mirror of
https://github.com/ultrajson/ultrajson.git
synced 2024-11-24 05:12:02 +01:00
- Implemented proper releasing of JSOBJ instances in decoder when decoding fails inside Object or Array
- Brought a bunch of tests pack from the dead - Implemented leak tests for decoder releaseObject calls - Implemented simplified loads/dumps (one argument) protocol for ujson module - Code clean up in decoder - Fixed known OSX issue with non exist malloc.h (stdlib.h instead)
This commit is contained in:
parent
1ed0bc18ec
commit
86ebbb6a97
@ -475,7 +475,7 @@ char *Object_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
|
||||
|
||||
void Object_releaseObject(JSOBJ obj)
|
||||
{
|
||||
|
||||
delete (BaseObject *) obj;
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
@ -514,6 +514,7 @@ int main (int argc, char **argv)
|
||||
decoder.malloc = malloc;
|
||||
decoder.free = free;
|
||||
decoder.realloc = realloc;
|
||||
decoder.releaseObject = Object_releaseObject;
|
||||
|
||||
char buffer[65536];
|
||||
#define N 1000000
|
||||
|
@ -61,6 +61,11 @@ JSOBJ Object_newDouble(double value)
|
||||
return PyFloat_FromDouble(value);
|
||||
}
|
||||
|
||||
static void Object_releaseObject(JSOBJ obj)
|
||||
{
|
||||
Py_DECREF( ((PyObject *)obj));
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject* JSONToObj(PyObject* self, PyObject *arg)
|
||||
@ -78,6 +83,7 @@ PyObject* JSONToObj(PyObject* self, PyObject *arg)
|
||||
Object_newArray,
|
||||
Object_newInteger,
|
||||
Object_newDouble,
|
||||
Object_releaseObject,
|
||||
PyObject_Malloc,
|
||||
PyObject_Free,
|
||||
PyObject_Realloc
|
||||
|
@ -4,10 +4,11 @@ import ujson
|
||||
import json
|
||||
import cjson
|
||||
import time
|
||||
import sys
|
||||
import random
|
||||
|
||||
user = { "userId": 3381293, "age": 213, "username": "johndoe", "fullname": u"John Doe the Second", "isAuthorized": True, "liked": 31231.31231202, "approval": 31.1471, "jobs": [ 1, 2 ], "currJob": None }
|
||||
friends = [ user, user, user, user, user, user, user, user ]
|
||||
testObject = [ [user, friends], [user, friends], [user, friends], [user, friends], [user, friends], [user, friends]]
|
||||
|
||||
decodeData = ""
|
||||
|
||||
@ -47,18 +48,131 @@ if __name__ == "__main__":
|
||||
|
||||
print "Ready? Configure affinity and priority, starting in 20..."
|
||||
#time.sleep(20)
|
||||
|
||||
COUNT = 10000
|
||||
|
||||
|
||||
print "Medium complex object:"
|
||||
testObject = [ [user, friends], [user, friends], [user, friends], [user, friends], [user, friends], [user, friends]]
|
||||
COUNT = 5000
|
||||
|
||||
print "ujson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonEnc()", "from __main__ import ujsonEnc", time.clock,10, COUNT)), )
|
||||
print "simplejson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonEnc()", "from __main__ import simplejsonEnc", time.clock,10, COUNT)), )
|
||||
print "cjson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonEnc()", "from __main__ import cjsonEnc", time.clock, 10, COUNT)), )
|
||||
print "json encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonEnc()", "from __main__ import jsonEnc", time.clock, 3, COUNT)), )
|
||||
#print "json encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonEnc()", "from __main__ import jsonEnc", time.clock, 3, COUNT)), )
|
||||
|
||||
decodeData = json.dumps(testObject)
|
||||
|
||||
print "ujson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonDec()", "from __main__ import ujsonDec", time.clock,10, COUNT)), )
|
||||
print "cjson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonDec()", "from __main__ import cjsonDec", time.clock,10, COUNT)), )
|
||||
print "simplejson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonDec()", "from __main__ import simplejsonDec", time.clock,10, COUNT)), )
|
||||
print "json decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonDec()", "from __main__ import jsonDec", time.clock, 3, COUNT)), )
|
||||
#print "json decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonDec()", "from __main__ import jsonDec", time.clock, 3, COUNT)), )
|
||||
|
||||
print "Array with 256 strings:"
|
||||
testObject = []
|
||||
|
||||
for x in xrange(256):
|
||||
testObject.append("A pretty long string which is in a list")
|
||||
|
||||
COUNT = 10000
|
||||
|
||||
print "ujson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonEnc()", "from __main__ import ujsonEnc", time.clock,10, COUNT)), )
|
||||
print "simplejson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonEnc()", "from __main__ import simplejsonEnc", time.clock,10, COUNT)), )
|
||||
print "cjson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonEnc()", "from __main__ import cjsonEnc", time.clock, 10, COUNT)), )
|
||||
#print "json encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonEnc()", "from __main__ import jsonEnc", time.clock, 3, COUNT)), )
|
||||
|
||||
decodeData = json.dumps(testObject)
|
||||
|
||||
print "ujson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonDec()", "from __main__ import ujsonDec", time.clock,10, COUNT)), )
|
||||
print "cjson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonDec()", "from __main__ import cjsonDec", time.clock,10, COUNT)), )
|
||||
print "simplejson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonDec()", "from __main__ import simplejsonDec", time.clock,10, COUNT)), )
|
||||
#print "json decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonDec()", "from __main__ import jsonDec", time.clock, 3, COUNT)), )
|
||||
|
||||
print "Array with 256 doubles:"
|
||||
testObject = []
|
||||
|
||||
for x in xrange(256):
|
||||
testObject.append(sys.maxint * random.random())
|
||||
|
||||
COUNT = 10000
|
||||
|
||||
print "ujson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonEnc()", "from __main__ import ujsonEnc", time.clock,10, COUNT)), )
|
||||
print "simplejson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonEnc()", "from __main__ import simplejsonEnc", time.clock,10, COUNT)), )
|
||||
print "cjson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonEnc()", "from __main__ import cjsonEnc", time.clock, 10, COUNT)), )
|
||||
#print "json encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonEnc()", "from __main__ import jsonEnc", time.clock, 3, COUNT)), )
|
||||
|
||||
decodeData = json.dumps(testObject)
|
||||
|
||||
print "ujson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonDec()", "from __main__ import ujsonDec", time.clock,10, COUNT)), )
|
||||
print "cjson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonDec()", "from __main__ import cjsonDec", time.clock,10, COUNT)), )
|
||||
print "simplejson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonDec()", "from __main__ import simplejsonDec", time.clock,10, COUNT)), )
|
||||
#print "json decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonDec()", "from __main__ import jsonDec", time.clock, 3, COUNT)), )
|
||||
|
||||
print "Array with 256 True values:"
|
||||
testObject = []
|
||||
|
||||
for x in xrange(256):
|
||||
testObject.append(True)
|
||||
|
||||
COUNT = 50000
|
||||
|
||||
print "ujson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonEnc()", "from __main__ import ujsonEnc", time.clock,10, COUNT)), )
|
||||
print "simplejson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonEnc()", "from __main__ import simplejsonEnc", time.clock,10, COUNT)), )
|
||||
print "cjson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonEnc()", "from __main__ import cjsonEnc", time.clock, 10, COUNT)), )
|
||||
#print "json encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonEnc()", "from __main__ import jsonEnc", time.clock, 3, COUNT)), )
|
||||
|
||||
decodeData = json.dumps(testObject)
|
||||
|
||||
print "ujson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonDec()", "from __main__ import ujsonDec", time.clock,10, COUNT)), )
|
||||
print "cjson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonDec()", "from __main__ import cjsonDec", time.clock,10, COUNT)), )
|
||||
print "simplejson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonDec()", "from __main__ import simplejsonDec", time.clock,10, COUNT)), )
|
||||
#print "json decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonDec()", "from __main__ import jsonDec", time.clock, 3, COUNT)), )
|
||||
|
||||
|
||||
print "Array with 256 dict{string, int} pairs:"
|
||||
testObject = []
|
||||
|
||||
for x in xrange(256):
|
||||
testObject.append({str(random.random()*20): int(random.random()*1000000)})
|
||||
|
||||
COUNT = 5000
|
||||
|
||||
print "ujson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonEnc()", "from __main__ import ujsonEnc", time.clock,10, COUNT)), )
|
||||
print "simplejson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonEnc()", "from __main__ import simplejsonEnc", time.clock,10, COUNT)), )
|
||||
print "cjson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonEnc()", "from __main__ import cjsonEnc", time.clock, 10, COUNT)), )
|
||||
#print "json encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonEnc()", "from __main__ import jsonEnc", time.clock, 3, COUNT)), )
|
||||
|
||||
decodeData = json.dumps(testObject)
|
||||
|
||||
print "ujson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonDec()", "from __main__ import ujsonDec", time.clock,10, COUNT)), )
|
||||
print "cjson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonDec()", "from __main__ import cjsonDec", time.clock,10, COUNT)), )
|
||||
print "simplejson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonDec()", "from __main__ import simplejsonDec", time.clock,10, COUNT)), )
|
||||
#print "json decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonDec()", "from __main__ import jsonDec", time.clock, 3, COUNT)), )
|
||||
|
||||
|
||||
|
||||
print "Dict with 256 arrays with 256 dict{string, int} pairs:"
|
||||
testObject = {}
|
||||
|
||||
|
||||
for y in xrange(256):
|
||||
arrays = []
|
||||
for x in xrange(256):
|
||||
arrays.append({str(random.random()*20): int(random.random()*1000000)})
|
||||
|
||||
testObject[str(random.random()*20)] = arrays
|
||||
|
||||
|
||||
COUNT = 50
|
||||
|
||||
print "ujson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonEnc()", "from __main__ import ujsonEnc", time.clock,10, COUNT)), )
|
||||
print "simplejson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonEnc()", "from __main__ import simplejsonEnc", time.clock,10, COUNT)), )
|
||||
print "cjson encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonEnc()", "from __main__ import cjsonEnc", time.clock, 10, COUNT)), )
|
||||
#print "json encode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonEnc()", "from __main__ import jsonEnc", time.clock, 3, COUNT)), )
|
||||
|
||||
decodeData = json.dumps(testObject)
|
||||
|
||||
print "ujson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("ujsonDec()", "from __main__ import ujsonDec", time.clock,10, COUNT)), )
|
||||
print "cjson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("cjsonDec()", "from __main__ import cjsonDec", time.clock,10, COUNT)), )
|
||||
print "simplejson decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("simplejsonDec()", "from __main__ import simplejsonDec", time.clock,10, COUNT)), )
|
||||
#print "json decode : %.05f calls/sec" % (COUNT / min(timeit.repeat("jsonDec()", "from __main__ import jsonDec", time.clock, 3, COUNT)), )
|
||||
|
||||
|
Binary file not shown.
@ -611,7 +611,7 @@ double Object_getDoubleValue(JSOBJ obj, JSONTypeContext *tc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Object_releaseObject(JSOBJ *_obj)
|
||||
static void Object_releaseObject(JSOBJ *_obj)
|
||||
{
|
||||
Py_DECREF( (PyObject *) _obj);
|
||||
}
|
||||
|
131
python/tests.py
131
python/tests.py
@ -166,30 +166,6 @@ class UltraJSONTests(TestCase):
|
||||
pass
|
||||
|
||||
|
||||
"""
|
||||
# This test fails. I'm not sure it's an issue or not
|
||||
def test_encodeListLongConversion(self):
|
||||
input = [9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807 ]
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
# This test fails, I'm not sure it's an issue or not
|
||||
def test_encodeLongConversion(self):
|
||||
input = 9223372036854775807
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(output, json.dumps(input))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
|
||||
def test_encodeUTF8Conversion(self):
|
||||
input = u"A \"string\"\"\\\/\b\f\n\r\t"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
pass
|
||||
|
||||
def test_decodeJibberish(self):
|
||||
input = "fdsa sda v9sa fdsa"
|
||||
try:
|
||||
@ -288,6 +264,96 @@ class UltraJSONTests(TestCase):
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
|
||||
def test_decodeBrokenDictKeyTypeLeakTest(self):
|
||||
input = '{{1337:""}}'
|
||||
for x in xrange(1000):
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError),e:
|
||||
continue
|
||||
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenDictLeakTest(self):
|
||||
input = '{{"key":"}'
|
||||
for x in xrange(1000):
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
continue
|
||||
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenListLeakTest(self):
|
||||
input = '[[[true'
|
||||
for x in xrange(1000):
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
continue
|
||||
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeDictWithNoKey(self):
|
||||
input = "{{{{31337}}}}"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeDictWithNoColonOrValue(self):
|
||||
input = "{{{{\"key\"}}}}"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeDictWithNoValue(self):
|
||||
input = "{{{{\"key\":}}}}"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
|
||||
assert False, "Wrong exception"
|
||||
|
||||
|
||||
"""
|
||||
# This test fails. I'm not sure it's an issue or not
|
||||
def test_encodeListLongConversion(self):
|
||||
input = [9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807 ]
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
# This test fails, I'm not sure it's an issue or not
|
||||
def test_encodeLongConversion(self):
|
||||
input = 9223372036854775807
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(output, json.dumps(input))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
|
||||
def test_encodeUTF8Conversion(self):
|
||||
input = u"A \"string\"\"\\\/\b\f\n\r\t"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
pass
|
||||
|
||||
|
||||
def test_decodeNumericIntExp(self):
|
||||
input = "<int>E<exp>"
|
||||
@ -384,22 +450,7 @@ class UltraJSONTests(TestCase):
|
||||
def test_decodeNumericFloatNan(self):
|
||||
pass
|
||||
|
||||
# Should fail!
|
||||
def test_decodeDictWithNoKey(self):
|
||||
input = "{{{{31337}}}}"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
# Should fail!
|
||||
def test_decodeDictWithNoColonOrValue(self):
|
||||
input = "{{{{"key"}}}}"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
# Should fail!
|
||||
def test_decodeDictWithNoValue(self):
|
||||
input = "{{{{"key":}}}}"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
"""
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -9,8 +9,10 @@ PyObject* JSONToObj(PyObject* self, PyObject *arg);
|
||||
|
||||
|
||||
static PyMethodDef ujsonMethods[] = {
|
||||
{"encode", objToJSON, METH_O, "Converts arbitrary object recursivly into JSON as string"},
|
||||
{"encode", objToJSON, METH_O, "Converts arbitrary object recursivly into JSON"},
|
||||
{"decode", JSONToObj, METH_O, "Converts JSON as string to dict object structure"},
|
||||
{"dumps", objToJSON, METH_O, "Converts arbitrary object recursivly into JSON"},
|
||||
{"loads", JSONToObj, METH_O, "Converts JSON as string to dict object structure"},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
@ -328,6 +328,7 @@ typedef struct __JSONObjectDecoder
|
||||
JSOBJ (*newArray)();
|
||||
JSOBJ (*newInteger)(JSLONG value);
|
||||
JSOBJ (*newDouble)(double value);
|
||||
void (*releaseObject)(JSOBJ obj);
|
||||
JSPFN_MALLOC malloc;
|
||||
JSPFN_FREE free;
|
||||
JSPFN_REALLOC realloc;
|
||||
|
107
ultrajsondec.c
107
ultrajsondec.c
@ -55,6 +55,9 @@ JSOBJ FASTCALL_MSVC decode_any( struct DecoderState *ds) FASTCALL_ATTR;
|
||||
typedef JSOBJ (*PFN_DECODER)( struct DecoderState *ds);
|
||||
PFN_DECODER g_identTable[256] = { NULL };
|
||||
|
||||
/*
|
||||
FIXME: Maybe move this to inside of createDouble function. Might increase memory locality and worst case
|
||||
possibly polute the global namespace less */
|
||||
static const double g_pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
|
||||
|
||||
|
||||
@ -337,27 +340,6 @@ SETERROR:
|
||||
return SetError(ds, -1, "Unexpected character found when decoding 'null'");
|
||||
}
|
||||
|
||||
|
||||
static char g_unescapeLookup[] = {
|
||||
/* 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f */
|
||||
/* 0x00 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x10 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x20 */ '\0', '\0', '\"', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x30 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x40 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x50 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x60 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x70 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x80 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0x90 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0xa0 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0xb0 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0xc0 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0xd0 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0xe0 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
/* 0xf0 */ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||
};
|
||||
|
||||
FASTCALL_ATTR void FASTCALL_MSVC SkipWhitespace(struct DecoderState *ds)
|
||||
{
|
||||
while (1)
|
||||
@ -371,18 +353,6 @@ FASTCALL_ATTR void FASTCALL_MSVC SkipWhitespace(struct DecoderState *ds)
|
||||
ds->start ++;
|
||||
break;
|
||||
|
||||
/*
|
||||
case '\x00':
|
||||
case '\x01':
|
||||
case '\x02':
|
||||
case '\x03':
|
||||
case '\x04':
|
||||
case '\x05':
|
||||
case '\x06':
|
||||
case '\x07':
|
||||
return;
|
||||
*/
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -480,8 +450,8 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_array( struct DecoderState *ds)
|
||||
|
||||
if (itemValue == NULL)
|
||||
{
|
||||
ds->lastType = JT_ARRAY;
|
||||
return newObj;
|
||||
ds->dec->releaseObject(newObj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ds->dec->arrayAddItem (newObj, itemValue);
|
||||
@ -497,12 +467,12 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_array( struct DecoderState *ds)
|
||||
break;
|
||||
|
||||
default:
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unexpected character in found when decoding array value");
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: Must release newObj here!
|
||||
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unmatched ']' when decoding 'array'");
|
||||
}
|
||||
|
||||
@ -529,15 +499,16 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds)
|
||||
ds->lastType = JT_INVALID;
|
||||
itemName = decode_any(ds);
|
||||
|
||||
//FIXME: Why should we accept this?
|
||||
if (itemName == NULL)
|
||||
{
|
||||
ds->lastType = JT_OBJECT;
|
||||
ds->dec->releaseObject(newObj);
|
||||
return newObj;
|
||||
}
|
||||
|
||||
if (ds->lastType != JT_UTF8)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return SetError(ds, -1, "Key name of object must be 'string' when decoding 'object'");
|
||||
}
|
||||
|
||||
@ -545,6 +516,8 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds)
|
||||
|
||||
if (*(ds->start++) != ':')
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return SetError(ds, -1, "No ':' found when decoding object value");
|
||||
}
|
||||
|
||||
@ -552,9 +525,10 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds)
|
||||
|
||||
itemValue = decode_any(ds);
|
||||
|
||||
//FIXME: itemName will leak here
|
||||
if (itemValue == NULL)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return newObj;
|
||||
}
|
||||
|
||||
@ -571,12 +545,12 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds)
|
||||
break;
|
||||
|
||||
default:
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unexpected character in found when decoding object value");
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: newobj will leak here
|
||||
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unmatched '}' when decoding object");
|
||||
}
|
||||
|
||||
@ -641,55 +615,6 @@ JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuf
|
||||
ds.dec->errorStr = NULL;
|
||||
ds.dec->errorOffset = NULL;
|
||||
|
||||
if (s_once)
|
||||
{
|
||||
//FIXME: Move to static initialization instead
|
||||
/*
|
||||
g_identTable['\"'] = decode_string;
|
||||
g_identTable['0'] = decode_numeric;
|
||||
g_identTable['1'] = decode_numeric;
|
||||
g_identTable['2'] = decode_numeric;
|
||||
g_identTable['3'] = decode_numeric;
|
||||
g_identTable['4'] = decode_numeric;
|
||||
g_identTable['5'] = decode_numeric;
|
||||
g_identTable['6'] = decode_numeric;
|
||||
g_identTable['7'] = decode_numeric;
|
||||
g_identTable['8'] = decode_numeric;
|
||||
g_identTable['9'] = decode_numeric;
|
||||
g_identTable['0'] = decode_numeric;
|
||||
g_identTable['-'] = decode_numeric;
|
||||
g_identTable['['] = decode_array;
|
||||
g_identTable['{'] = decode_object;
|
||||
g_identTable['t'] = decode_true;
|
||||
g_identTable['f'] = decode_false;
|
||||
g_identTable['n'] = decode_null;
|
||||
g_identTable['}'] = decode_object_end;
|
||||
g_identTable[']'] = decode_array_end;
|
||||
g_identTable[','] = decode_item_separator;
|
||||
for (index = 0; index < 33; index ++)
|
||||
{
|
||||
g_identTable[index] = (PFN_DECODER) 1;
|
||||
}
|
||||
*/
|
||||
|
||||
for (index = 0; index < 256; index ++)
|
||||
{
|
||||
g_unescapeLookup[index] = '\0';
|
||||
}
|
||||
|
||||
g_unescapeLookup['\\'] = '\\';
|
||||
g_unescapeLookup['\"'] = '\"';
|
||||
g_unescapeLookup['/'] = '/';
|
||||
g_unescapeLookup['b'] = '\b';
|
||||
g_unescapeLookup['f'] = '\f';
|
||||
g_unescapeLookup['n'] = '\n';
|
||||
g_unescapeLookup['r'] = '\r';
|
||||
g_unescapeLookup['t'] = '\t';
|
||||
|
||||
//FIXME: Implement unicode decode here
|
||||
s_once = 0;
|
||||
}
|
||||
|
||||
ds.dec = dec;
|
||||
|
||||
ret = decode_any (&ds);
|
||||
|
@ -38,7 +38,7 @@ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights rese
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef TRUE
|
||||
|
Loading…
Reference in New Issue
Block a user