[pypy-commit] pypy fastjson: start to implement the json decoder: decode only strings so far

antocuni noreply at buildbot.pypy.org
Tue Jun 4 17:41:28 CEST 2013


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: fastjson
Changeset: r64768:6ec983152d16
Date: 2013-06-04 15:28 +0200
http://bitbucket.org/pypy/pypy/changeset/6ec983152d16/

Log:	start to implement the json decoder: decode only strings so far

diff --git a/pypy/module/_fastjson/__init__.py b/pypy/module/_fastjson/__init__.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_fastjson/__init__.py
@@ -0,0 +1,10 @@
+from pypy.interpreter.mixedmodule import MixedModule
+
+class Module(MixedModule):
+    """fast json implementation"""
+
+    appleveldefs = {}
+
+    interpleveldefs = {
+        'loads' : 'interp_decoder.loads',
+        }
diff --git a/pypy/module/_fastjson/interp_decoder.py b/pypy/module/_fastjson/interp_decoder.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_fastjson/interp_decoder.py
@@ -0,0 +1,65 @@
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.interpreter import unicodehelper
+
+def is_whitespace(ch):
+    return ch == ' ' or ch == '\t' or ch == '\r' or ch == '\n'
+
+TYPE_INVALID = 0
+TYPE_STRING = 0
+
+class JSONDecoder(object):
+    def __init__(self, space, s):
+        self.space = space
+        self.s = s
+        self.i = 0
+        self.last_type = TYPE_INVALID
+
+    def eof(self):
+        return self.i == len(self.s)
+
+    def peek(self):
+        return self.s[self.i]
+
+    def next(self):
+        ch = self.peek()
+        self.i += 1
+        return ch
+
+    def skip_whitespace(self):
+        while not self.eof():
+            ch = self.peek()
+            if is_whitespace(ch):
+                self.next()
+            else:
+                break
+
+    def decode_any(self):
+        self.skip_whitespace()
+        ch = self.peek()
+        if ch == '"':
+            return self.decode_string()
+        else:
+            assert False, 'Unkown char: %s' % ch
+
+    def decode_string(self):
+        self.next()
+        start = self.i
+        while True:
+            ch = self.next()
+            if ch == '"':
+                end = self.i-1
+                assert end > 0
+                content = self.s[start:end]
+                self.last_type = TYPE_STRING
+                return self.space.wrap(unicodehelper.decode_utf8(self.space, content))
+            elif ch == '\\':
+                raise Exception("escaped strings not supported yet")
+
+
+ at unwrap_spec(s=str)
+def loads(space, s):
+    decoder = JSONDecoder(space, s)
+    return decoder.decode_any()
+
+
diff --git a/pypy/module/_fastjson/test/test__fastjson.py b/pypy/module/_fastjson/test/test__fastjson.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_fastjson/test/test__fastjson.py
@@ -0,0 +1,32 @@
+# -*- encoding: utf-8 -*-
+import py
+from pypy.module._fastjson.interp_decoder import JSONDecoder
+
+def test_skip_whitespace():
+    dec = JSONDecoder('fake space', '   hello   ')
+    assert dec.i == 0
+    dec.skip_whitespace()
+    assert dec.next() == 'h'
+    assert dec.next() == 'e'
+    assert dec.next() == 'l'
+    assert dec.next() == 'l'
+    assert dec.next() == 'o'
+    dec.skip_whitespace()
+    assert dec.eof()
+
+    
+
+class AppTest(object):
+    spaceconfig = {"objspace.usemodules._fastjson": True}
+
+    def test_load_string(self):
+        import _fastjson
+        res = _fastjson.loads('"hello"')
+        assert res == u'hello'
+        assert type(res) is unicode
+
+    def test_load_string_utf8(self):
+        import _fastjson
+        s = u'àèìòù'
+        res = _fastjson.loads('"%s"' % s.encode('utf-8'))
+        assert res == s


More information about the pypy-commit mailing list