Author: Antonio Cuni <[email protected]>
Branch: fastjson
Changeset: r64774:0c2d7c11a454
Date: 2013-06-04 17:40 +0200
http://bitbucket.org/pypy/pypy/changeset/0c2d7c11a454/
Log: implement decoding of objects
diff --git a/pypy/module/_fastjson/interp_decoder.py
b/pypy/module/_fastjson/interp_decoder.py
--- a/pypy/module/_fastjson/interp_decoder.py
+++ b/pypy/module/_fastjson/interp_decoder.py
@@ -6,15 +6,15 @@
def is_whitespace(ch):
return ch == ' ' or ch == '\t' or ch == '\r' or ch == '\n'
-TYPE_INVALID = 0
-TYPE_STRING = 0
+TYPE_UNKNOWN = 0
+TYPE_STRING = 1
class JSONDecoder(object):
def __init__(self, space, s):
self.space = space
self.s = s
self.i = 0
- self.last_type = TYPE_INVALID
+ self.last_type = TYPE_UNKNOWN
def eof(self):
return self.i == len(self.s)
@@ -30,6 +30,10 @@
def unget(self):
self.i -= 1
+ def getslice(self, start, end):
+ assert end > 0
+ return self.s[start:end]
+
def skip_whitespace(self):
while not self.eof():
ch = self.peek()
@@ -37,21 +41,56 @@
self.next()
else:
break
+
+ def _raise(self, msg, *args):
+ raise operationerrfmt(self.w_ValueError, msg, *args)
def decode_any(self):
self.skip_whitespace()
- ch = self.peek()
+ ch = self.next()
if ch == '"':
return self.decode_string()
+ elif ch == '{':
+ return self.decode_object()
else:
assert False, 'Unkown char: %s' % ch
- def getslice(self, start, end):
- assert end > 0
- return self.s[start:end]
+ def decode_object(self):
+ start = self.i
+ w_dict = self.space.newdict()
+ while not self.eof():
+ ch = self.peek()
+ if ch == '}':
+ self.next()
+ return w_dict
+ #
+ # parse a key: value
+ self.last_type = TYPE_UNKNOWN
+ w_name = self.decode_any()
+ if self.last_type != TYPE_STRING:
+ self._raise("Key name must be string")
+ self.skip_whitespace()
+ ch = self.next()
+ if ch != ':':
+ self._raise("No ':' found at char %d", self.i)
+ self.skip_whitespace()
+ #
+ w_value = self.decode_any()
+ self.space.setitem(w_dict, w_name, w_value)
+ self.skip_whitespace()
+ ch = self.next()
+ if ch == '}':
+ return w_dict
+ elif ch == ',':
+ pass
+ else:
+ self._raise("Unexpected '%s' when decoding object (char %d)",
+ ch, self.i)
+ self._raise("Unterminated object starting at char %d", start)
+
+
def decode_string(self):
- self.next()
start = self.i
while not self.eof():
# this loop is a fast path for strings which do not contain escape
@@ -66,8 +105,7 @@
content_so_far = self.getslice(start, self.i-1)
self.unget()
return self.decode_string_escaped(start, content_so_far)
- raise operationerrfmt(self.space.w_ValueError,
- "Unterminated string starting at char %d", start)
+ self._raise("Unterminated string starting at char %d", start)
def decode_string_escaped(self, start, content_so_far):
@@ -84,9 +122,8 @@
self.decode_escape_sequence(builder)
else:
builder.append_multiple_char(ch, 1) # we should implement
append_char
-
- raise operationerrfmt(self.space.w_ValueError,
- "Unterminated string starting at char %d", start)
+ #
+ self._raise("Unterminated string starting at char %d", start)
def decode_escape_sequence(self, builder):
put = builder.append_multiple_char
@@ -102,8 +139,7 @@
elif ch == 'u':
return self.decode_escape_sequence_unicode(builder)
else:
- raise operationerrfmt(self.space.w_ValueError,
- "Invalid \\escape: %s (char %d)", ch,
self.i-1)
+ self._raise("Invalid \\escape: %s (char %d)", ch, self.i-1)
def decode_escape_sequence_unicode(self, builder):
# at this point we are just after the 'u' of the \u1234 sequence.
@@ -112,8 +148,7 @@
try:
uchr = unichr(int(hexdigits, 16))
except ValueError:
- raise operationerrfmt(self.space.w_ValueError,
- "Invalid \uXXXX escape (char %d)", self.i-1)
+ self._raise("Invalid \uXXXX escape (char %d)", self.i-1)
#
utf8_ch = unicodehelper.encode_utf8(self.space, uchr)
builder.append(utf8_ch)
diff --git a/pypy/module/_fastjson/test/test__fastjson.py
b/pypy/module/_fastjson/test/test__fastjson.py
--- a/pypy/module/_fastjson/test/test__fastjson.py
+++ b/pypy/module/_fastjson/test/test__fastjson.py
@@ -68,3 +68,15 @@
import _fastjson
s = r'"\u1234"'
assert _fastjson.loads(s) == u'\u1234'
+
+ def test_decode_object(self):
+ import _fastjson
+ assert _fastjson.loads('{}') == {}
+ #
+ s = '{"hello": "world", "aaa": "bbb"}'
+ assert _fastjson.loads(s) == {'hello': 'world',
+ 'aaa': 'bbb'}
+
+ def test_decode_object_nonstring_key(self):
+ pass # write me when we have numbers
+
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit