1
0
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:
Jonas Tärnström 2011-03-08 00:23:42 +01:00
parent 1ed0bc18ec
commit 86ebbb6a97
10 changed files with 240 additions and 140 deletions

@ -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);
}

@ -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;

@ -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