mirror of
https://github.com/ultrajson/ultrajson.git
synced 2024-06-10 22:36:06 +02:00
- Optimized UTF-8 encoding and decoding
- Improved error reporting when encoding and decoding utf-8 - Change from tabs to spaces in most Python code - General code cleanup of C code - Added UTF-8 encoding/decoding to tests
This commit is contained in:
parent
d11844ad50
commit
9d6dd489ec
|
@ -17,7 +17,7 @@ extern "C"
|
|||
|
||||
//char indata[] = "R├ñksm├Ârg├Ñs ϺÏ│Ϻ┘àÏ® Ï¿┘å ┘àÏ¡┘àÏ» Ï¿┘å Ï╣┘êÏ Ͽ┘å ┘äϺϻ┘å";
|
||||
//char indata[] = "اسامة بن محمد بن عوض بن لادن,";
|
||||
char indata[] = "\xf3\xbf\xbf\xbfTRAILINGNORMAL";
|
||||
char indata[] = "\xf0\x91\x80\xb0TRAILINGNORMAL";
|
||||
/*
|
||||
\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e*/
|
||||
using namespace std;
|
||||
|
@ -518,6 +518,7 @@ void Object_releaseObject(JSOBJ obj)
|
|||
delete (BaseObject *) obj;
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
BaseObject *obj;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# coding=UTF-8
|
||||
# coding=UTF-8
|
||||
import simplejson
|
||||
import ujson
|
||||
import json
|
||||
|
@ -15,164 +15,190 @@ decodeData = ""
|
|||
"""=========================================================================="""
|
||||
|
||||
def ujsonEnc():
|
||||
x = ujson.encode(testObject)
|
||||
|
||||
x = ujson.encode(testObject)
|
||||
#print "ujsonEnc", x
|
||||
|
||||
def simplejsonEnc():
|
||||
x = simplejson.dumps(testObject)
|
||||
x = simplejson.dumps(testObject)
|
||||
#print "simplejsonEnc", x
|
||||
|
||||
def jsonEnc():
|
||||
x = json.dumps(testObject)
|
||||
x = json.dumps(testObject)
|
||||
#print "jsonEnc", x
|
||||
|
||||
def cjsonEnc():
|
||||
x = cjson.encode(testObject)
|
||||
x = cjson.encode(testObject)
|
||||
#print "cjsonEnc", x
|
||||
|
||||
"""=========================================================================="""
|
||||
|
||||
def ujsonDec():
|
||||
x = ujson.decode(decodeData)
|
||||
|
||||
x = ujson.decode(decodeData)
|
||||
#print "ujsonDec: ", x
|
||||
|
||||
def simplejsonDec():
|
||||
x = simplejson.loads(decodeData)
|
||||
x = simplejson.loads(decodeData)
|
||||
#print "simplejsonDec: ", x
|
||||
|
||||
def jsonDec():
|
||||
x = json.loads(decodeData)
|
||||
x = json.loads(decodeData)
|
||||
#print "jsonDec: ", x
|
||||
|
||||
def cjsonDec():
|
||||
x = cjson.decode(decodeData)
|
||||
|
||||
x = cjson.decode(decodeData)
|
||||
#print "cjsonDec: ", x
|
||||
|
||||
"""=========================================================================="""
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import timeit
|
||||
|
||||
print "Ready? Configure affinity and priority, starting in 20..."
|
||||
time.sleep(20)
|
||||
import timeit
|
||||
|
||||
print "Ready? Configure affinity and priority, starting in 20..."
|
||||
time.sleep(20)
|
||||
|
||||
print "Array with 256 utf-8 strings:"
|
||||
testObject = []
|
||||
|
||||
for x in xrange(256):
|
||||
testObject.append("نظام الحكم سلطاني وراثي في الذكور من ذرية السيد تركي بن سعيد بن سلطان ويشترط فيمن يختار لولاية الحكم من بينهم ان يكون مسلما رشيدا عاقلا ًوابنا شرعيا لابوين عمانيين ")
|
||||
|
||||
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 "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)), )
|
||||
|
||||
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 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 "Medium complex object:"
|
||||
testObject = [ [user, friends], [user, friends], [user, friends], [user, friends], [user, friends], [user, friends]]
|
||||
COUNT = 5000
|
||||
print "Array with 256 dict{string, int} pairs:"
|
||||
testObject = []
|
||||
|
||||
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)), )
|
||||
for x in xrange(256):
|
||||
testObject.append({str(random.random()*20): int(random.random()*1000000)})
|
||||
|
||||
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)), )
|
||||
COUNT = 5000
|
||||
|
||||
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)), )
|
||||
|
||||
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)
|
||||
|
||||
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 "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 = {}
|
||||
|
||||
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
|
||||
for y in xrange(256):
|
||||
arrays = []
|
||||
for x in xrange(256):
|
||||
arrays.append({str(random.random()*20): int(random.random()*1000000)})
|
||||
|
||||
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)), )
|
||||
testObject[str(random.random()*20)] = arrays
|
||||
|
||||
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)), )
|
||||
|
||||
|
||||
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.
993
python/tests.py
993
python/tests.py
|
@ -10,504 +10,497 @@ import datetime
|
|||
import calendar
|
||||
|
||||
class UltraJSONTests(TestCase):
|
||||
def test_encodeDoubleConversion(self):
|
||||
input = math.pi
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(round(input, 5), round(json.loads(output), 5))
|
||||
self.assertEquals(round(input, 5), round(ujson.decode(output), 5))
|
||||
pass
|
||||
|
||||
def test_encodeDoubleNegConversion(self):
|
||||
input = -math.pi
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(round(input, 5), round(json.loads(output), 5))
|
||||
self.assertEquals(round(input, 5), round(ujson.decode(output), 5))
|
||||
pass
|
||||
|
||||
def test_encodeArrayOfNestedArrays(self):
|
||||
input = [[[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]] ]
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
#self.assertEquals(output, json.dumps(input))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
|
||||
def test_encodeArrayOfDoubles(self):
|
||||
input = [ 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337 ]
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
#self.assertEquals(output, json.dumps(input))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
|
||||
|
||||
def test_encodeStringConversion(self):
|
||||
|
||||
input = "A string \\ \/ \b \f \n \r \t"
|
||||
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_decodeUnicodeConversion(self):
|
||||
pass
|
||||
|
||||
def test_encodeUnicodeConversion1(self):
|
||||
input = "Räksmörgås اسامة بن محمد بن عوض بن لادن"
|
||||
enc = ujson.encode(input)
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeUnicodeConversion2(self):
|
||||
input = "\xe6\x97\xa5\xd1\x88"
|
||||
enc = ujson.encode(input)
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeUnicodeSurrogatePair(self):
|
||||
input = "\xf0\x90\x8d\x86"
|
||||
enc = ujson.encode(input)
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeUnicode4BytesUTF8(self):
|
||||
input = "\xf0\xbf\xbf\xbfTRAILINGNORMAL"
|
||||
enc = ujson.encode(input)
|
||||
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeUnicode4BytesUTF8Highest(self):
|
||||
input = "\xf3\xbf\xbf\xbfTRAILINGNORMAL"
|
||||
enc = ujson.encode(input)
|
||||
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeArrayInArray(self):
|
||||
input = [[[[]]]]
|
||||
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_encodeIntConversion(self):
|
||||
input = 31337
|
||||
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_encodeIntNegConversion(self):
|
||||
input = -31337
|
||||
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_encodeLongNegConversion(self):
|
||||
input = -9223372036854775808
|
||||
output = ujson.encode(input)
|
||||
|
||||
outputjson = json.loads(output)
|
||||
outputujson = ujson.decode(output)
|
||||
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(output, json.dumps(input))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeListConversion(self):
|
||||
input = [ 1, 2, 3, 4 ]
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeDictConversion(self):
|
||||
input = { "k1": 1, "k2": 2, "k3": 3, "k4": 4 }
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeNoneConversion(self):
|
||||
input = None
|
||||
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_encodeTrueConversion(self):
|
||||
input = True
|
||||
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_encodeFalseConversion(self):
|
||||
input = False
|
||||
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_encodeDatetimeConversion(self):
|
||||
ts = time.time()
|
||||
input = datetime.datetime.fromtimestamp(ts)
|
||||
output = ujson.encode(input)
|
||||
expected = calendar.timegm(input.utctimetuple())
|
||||
self.assertEquals(int(expected), json.loads(output))
|
||||
self.assertEquals(int(expected), ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeDateConversion(self):
|
||||
ts = time.time()
|
||||
input = datetime.date.fromtimestamp(ts)
|
||||
|
||||
output = ujson.encode(input)
|
||||
tup = ( input.year, input.month, input.day, 0, 0, 0 )
|
||||
|
||||
expected = calendar.timegm(tup)
|
||||
self.assertEquals(int(expected), json.loads(output))
|
||||
self.assertEquals(int(expected), ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeRecursionMax(self):
|
||||
# 8 is the max recursion depth
|
||||
|
||||
class O2:
|
||||
member = 0
|
||||
pass
|
||||
|
||||
class O1:
|
||||
member = 0
|
||||
pass
|
||||
|
||||
input = O1()
|
||||
input.member = O2()
|
||||
input.member.member = input
|
||||
|
||||
try:
|
||||
output = ujson.encode(input)
|
||||
assert False, "Expected overflow exception"
|
||||
except(OverflowError):
|
||||
pass
|
||||
|
||||
|
||||
def test_decodeJibberish(self):
|
||||
input = "fdsa sda v9sa fdsa"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenArrayStart(self):
|
||||
input = "["
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenObjectStart(self):
|
||||
input = "{"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenArrayEnd(self):
|
||||
input = "]"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenObjectEnd(self):
|
||||
input = "}"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeStringUnterminated(self):
|
||||
input = "\"TESTING"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeStringUntermEscapeSequence(self):
|
||||
input = "\"TESTING\\\""
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeStringBadEscape(self):
|
||||
input = "\"TESTING\\\""
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeTrueBroken(self):
|
||||
input = "tru"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeFalseBroken(self):
|
||||
input = "fa"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeNullBroken(self):
|
||||
input = "n"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
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"
|
||||
|
||||
def test_decodeNumericIntPos(self):
|
||||
input = "31337"
|
||||
self.assertEquals (31337, ujson.decode(input))
|
||||
|
||||
def test_decodeNumericIntNeg(self):
|
||||
input = "-31337"
|
||||
self.assertEquals (-31337, ujson.decode(input))
|
||||
|
||||
"""
|
||||
# Should fail with exception
|
||||
def test_encodeUnicode4BytesUTF8Fail(self):
|
||||
input = "\xfd\xbf\xbf\xbf\xbf\xbf"
|
||||
enc = ujson.encode(input)
|
||||
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
|
||||
# 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>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntFrcExp(self):
|
||||
input = "<int>.<frc>E<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntFrcOverflow(self):
|
||||
input = "X.Y"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntPosOverflow(self):
|
||||
input = "9223372036854775807322"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeNumericIntNegOverflow(self):
|
||||
input = "-9223372036854775807322"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
|
||||
|
||||
#Exponent specific tests
|
||||
def test_decodeNumericIntExpEPLUS(self):
|
||||
input = "<int>E+<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpePLUS(self):
|
||||
input = "<int>e+<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpE(self):
|
||||
input = "<int>E<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpe(self):
|
||||
input = "<int>e<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpE(self):
|
||||
input = "<int>E<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpe(self):
|
||||
input = "<int>e<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpEMinus(self):
|
||||
input = "<int>E-<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpeMinus(self):
|
||||
input = "<int>e-<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeStringUnicodeEscape(self):
|
||||
input = "\u3131"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeStringUnicodeBrokenEscape(self):
|
||||
input = "\u3131"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeStringUnicodeInvalidEscape(self):
|
||||
input = "\u3131"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeStringUTF8(self):
|
||||
input = "someutfcharacters"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericFloatInf(self):
|
||||
pass
|
||||
|
||||
def test_decodeNumericFloatNan(self):
|
||||
pass
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def test_encodeDoubleConversion(self):
|
||||
input = math.pi
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(round(input, 5), round(json.loads(output), 5))
|
||||
self.assertEquals(round(input, 5), round(ujson.decode(output), 5))
|
||||
pass
|
||||
|
||||
def test_encodeDoubleNegConversion(self):
|
||||
input = -math.pi
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(round(input, 5), round(json.loads(output), 5))
|
||||
self.assertEquals(round(input, 5), round(ujson.decode(output), 5))
|
||||
pass
|
||||
|
||||
def test_encodeArrayOfNestedArrays(self):
|
||||
input = [[[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]], [[[]]] ]
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
#self.assertEquals(output, json.dumps(input))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
|
||||
def test_encodeArrayOfDoubles(self):
|
||||
input = [ 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337, 31337.31337 ]
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
#self.assertEquals(output, json.dumps(input))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
|
||||
def test_encodeStringConversion(self):
|
||||
input = "A string \\ \/ \b \f \n \r \t"
|
||||
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_decodeUnicodeConversion(self):
|
||||
pass
|
||||
|
||||
def test_encodeUnicodeConversion1(self):
|
||||
input = "Räksmörgås اسامة بن محمد بن عوض بن لادن"
|
||||
enc = ujson.encode(input)
|
||||
dec = ujson.decode(enc)
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeUnicodeConversion2(self):
|
||||
input = "\xe6\x97\xa5\xd1\x88"
|
||||
enc = ujson.encode(input)
|
||||
dec = ujson.decode(enc)
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeUnicodeSurrogatePair(self):
|
||||
input = "\xf0\x90\x8d\x86"
|
||||
enc = ujson.encode(input)
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeUnicode4BytesUTF8(self):
|
||||
input = "\xf0\x91\x80\xb0TRAILINGNORMAL"
|
||||
enc = ujson.encode(input)
|
||||
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeUnicode4BytesUTF8Highest(self):
|
||||
input = "\xf3\xbf\xbf\xbfTRAILINGNORMAL"
|
||||
enc = ujson.encode(input)
|
||||
|
||||
dec = ujson.decode(enc)
|
||||
|
||||
self.assertEquals(input, dec)
|
||||
self.assertEquals(enc, json.dumps(input, encoding="utf-8"))
|
||||
|
||||
def test_encodeArrayInArray(self):
|
||||
input = [[[[]]]]
|
||||
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_encodeIntConversion(self):
|
||||
input = 31337
|
||||
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_encodeIntNegConversion(self):
|
||||
input = -31337
|
||||
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_encodeLongNegConversion(self):
|
||||
input = -9223372036854775808
|
||||
output = ujson.encode(input)
|
||||
|
||||
outputjson = json.loads(output)
|
||||
outputujson = ujson.decode(output)
|
||||
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(output, json.dumps(input))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeListConversion(self):
|
||||
input = [ 1, 2, 3, 4 ]
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeDictConversion(self):
|
||||
input = { "k1": 1, "k2": 2, "k3": 3, "k4": 4 }
|
||||
output = ujson.encode(input)
|
||||
self.assertEquals(input, json.loads(output))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
self.assertEquals(input, ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeNoneConversion(self):
|
||||
input = None
|
||||
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_encodeTrueConversion(self):
|
||||
input = True
|
||||
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_encodeFalseConversion(self):
|
||||
input = False
|
||||
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_encodeDatetimeConversion(self):
|
||||
ts = time.time()
|
||||
input = datetime.datetime.fromtimestamp(ts)
|
||||
output = ujson.encode(input)
|
||||
expected = calendar.timegm(input.utctimetuple())
|
||||
self.assertEquals(int(expected), json.loads(output))
|
||||
self.assertEquals(int(expected), ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeDateConversion(self):
|
||||
ts = time.time()
|
||||
input = datetime.date.fromtimestamp(ts)
|
||||
|
||||
output = ujson.encode(input)
|
||||
tup = ( input.year, input.month, input.day, 0, 0, 0 )
|
||||
|
||||
expected = calendar.timegm(tup)
|
||||
self.assertEquals(int(expected), json.loads(output))
|
||||
self.assertEquals(int(expected), ujson.decode(output))
|
||||
pass
|
||||
|
||||
def test_encodeRecursionMax(self):
|
||||
# 8 is the max recursion depth
|
||||
|
||||
class O2:
|
||||
member = 0
|
||||
pass
|
||||
|
||||
class O1:
|
||||
member = 0
|
||||
pass
|
||||
|
||||
input = O1()
|
||||
input.member = O2()
|
||||
input.member.member = input
|
||||
|
||||
try:
|
||||
output = ujson.encode(input)
|
||||
assert False, "Expected overflow exception"
|
||||
except(OverflowError):
|
||||
pass
|
||||
|
||||
|
||||
def test_decodeJibberish(self):
|
||||
input = "fdsa sda v9sa fdsa"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenArrayStart(self):
|
||||
input = "["
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenObjectStart(self):
|
||||
input = "{"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenArrayEnd(self):
|
||||
input = "]"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeBrokenObjectEnd(self):
|
||||
input = "}"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeStringUnterminated(self):
|
||||
input = "\"TESTING"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeStringUntermEscapeSequence(self):
|
||||
input = "\"TESTING\\\""
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeStringBadEscape(self):
|
||||
input = "\"TESTING\\\""
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeTrueBroken(self):
|
||||
input = "tru"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeFalseBroken(self):
|
||||
input = "fa"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeNullBroken(self):
|
||||
input = "n"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
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"
|
||||
|
||||
def test_decodeNumericIntPos(self):
|
||||
input = "31337"
|
||||
self.assertEquals (31337, ujson.decode(input))
|
||||
|
||||
def test_decodeNumericIntNeg(self):
|
||||
input = "-31337"
|
||||
self.assertEquals (-31337, ujson.decode(input))
|
||||
|
||||
def test_encodeUnicode4BytesUTF8Fail(self):
|
||||
input = "\xfd\xbf\xbf\xbf\xbf\xbf"
|
||||
try:
|
||||
enc = ujson.encode(input)
|
||||
assert False, "Expected exception"
|
||||
except OverflowError:
|
||||
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_decodeNumericIntExp(self):
|
||||
input = "<int>E<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntFrcExp(self):
|
||||
input = "<int>.<frc>E<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntFrcOverflow(self):
|
||||
input = "X.Y"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntPosOverflow(self):
|
||||
input = "9223372036854775807322"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
def test_decodeNumericIntNegOverflow(self):
|
||||
input = "-9223372036854775807322"
|
||||
try:
|
||||
ujson.decode(input)
|
||||
assert False, "Expected exception!"
|
||||
except(ValueError):
|
||||
return
|
||||
assert False, "Wrong exception"
|
||||
|
||||
|
||||
|
||||
#Exponent specific tests
|
||||
def test_decodeNumericIntExpEPLUS(self):
|
||||
input = "<int>E+<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpePLUS(self):
|
||||
input = "<int>e+<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpE(self):
|
||||
input = "<int>E<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpe(self):
|
||||
input = "<int>e<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpE(self):
|
||||
input = "<int>E<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpe(self):
|
||||
input = "<int>e<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpEMinus(self):
|
||||
input = "<int>E-<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericIntExpeMinus(self):
|
||||
input = "<int>e-<exp>"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeStringUnicodeEscape(self):
|
||||
input = "\u3131"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeStringUnicodeBrokenEscape(self):
|
||||
input = "\u3131"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeStringUnicodeInvalidEscape(self):
|
||||
input = "\u3131"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeStringUTF8(self):
|
||||
input = "someutfcharacters"
|
||||
raise NotImplementedError("Implement this test!")
|
||||
|
||||
def test_decodeNumericFloatInf(self):
|
||||
pass
|
||||
|
||||
def test_decodeNumericFloatNan(self):
|
||||
pass
|
||||
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
|
18
ultrajson.h
18
ultrajson.h
|
@ -142,7 +142,7 @@ typedef unsigned __int64 JSUINT64;
|
|||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int32 JSINT32;
|
||||
typedef uint32_t JSUINT32;
|
||||
|
||||
typedef unsigned __int8 JSUINT8;
|
||||
typedef unsigned __int16 JSUTF16;
|
||||
typedef unsigned __int32 JSUTF32;
|
||||
|
||||
|
@ -153,14 +153,12 @@ typedef unsigned __int32 JSUTF32;
|
|||
#define FASTCALL_ATTR
|
||||
#define INLINE_PREFIX __inline
|
||||
|
||||
/*
|
||||
#define FASTCALL_MSVC
|
||||
#define FASTCALL_ATTR
|
||||
#define INLINE_PREFIX
|
||||
*/
|
||||
|
||||
#ifndef __LITTLE_ENDIAN__
|
||||
#define __LITTLE_ENDIAN__
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
typedef int64_t JSINT64;
|
||||
typedef u_int64_t JSUINT64;
|
||||
|
@ -174,12 +172,18 @@ typedef u_int32_t JSUINT32;
|
|||
|
||||
typedef u_int32_t uint32_t;
|
||||
|
||||
typedef u_int8_t JSUINT8;
|
||||
typedef u_int16_t JSUTF16;
|
||||
typedef u_int16_t JSUTF32;
|
||||
|
||||
#define EXPORTFUNCTION
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __LITTLE_ENDIAN__
|
||||
#error "Endianess not supported"
|
||||
#endif
|
||||
|
||||
enum JSTYPES
|
||||
{
|
||||
JT_NULL, // NULL
|
||||
|
|
|
@ -446,8 +446,6 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds)
|
|||
JSUTF32 u32chr;
|
||||
inputOffset ++;
|
||||
|
||||
//FIXME: Can't use this function in real life
|
||||
|
||||
for (index = 0; index < 4; index ++)
|
||||
{
|
||||
switch (*inputOffset)
|
||||
|
@ -499,15 +497,6 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds)
|
|||
iSur ++;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
else
|
||||
if ((sur[iSur] & 0xfc00) != 0xdc00)
|
||||
{
|
||||
// Unpaired surogate
|
||||
return SetError (ds, -1, "Unpaired low surrogate when decoding 'string'");
|
||||
}
|
||||
*/
|
||||
|
||||
u32chr = sur[iSur];
|
||||
iSur = 0;
|
||||
}
|
||||
|
@ -523,50 +512,54 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds)
|
|||
iSur = 0;
|
||||
}
|
||||
|
||||
// Convert UTF32 char to UTF-8 (gah!)
|
||||
if(u32chr < 0x80)
|
||||
if (u32chr < 0x80)
|
||||
{
|
||||
*(escOffset++) = u32chr;
|
||||
}
|
||||
else
|
||||
if(u32chr < 0x800)
|
||||
{
|
||||
*(escOffset++) = (MASK2BYTES | u32chr >> 6);
|
||||
*(escOffset++) = (MASKBYTE | u32chr & MASKBITS);
|
||||
}
|
||||
else
|
||||
if(u32chr < 0x10000)
|
||||
{
|
||||
*(escOffset++) = (MASK3BYTES | u32chr >> 12);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 6 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr & MASKBITS);
|
||||
*(escOffset++) = (char) u32chr;
|
||||
}
|
||||
else
|
||||
if(u32chr < 0x200000)
|
||||
if (u32chr < 0x0800)
|
||||
{
|
||||
*(escOffset++) = (MASK4BYTES | u32chr >> 18);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 12 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 6 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr & MASKBITS);
|
||||
(*escOffset++) = 0xC0 | ((u32chr >> 6) & 0x1F);
|
||||
(*escOffset++) = 0x80 | ((u32chr >> 0) & 0x3F);
|
||||
}
|
||||
else
|
||||
if (u32chr < 0x10000)
|
||||
{
|
||||
(*escOffset++) = 0xE0 | ((u32chr >> 12) & 0x0F);
|
||||
(*escOffset++) = 0x80 | ((u32chr >> 6) & 0x3F);
|
||||
(*escOffset++) = 0x80 | ((u32chr >> 0) & 0x3F);
|
||||
}
|
||||
else
|
||||
if (u32chr < 0x200000)
|
||||
{
|
||||
(*escOffset++) = 0xF0 | ((u32chr >> 18) & 0x07);
|
||||
(*escOffset++) = 0x80 | ((u32chr >> 12) & 0x3F);
|
||||
(*escOffset++) = 0x80 | ((u32chr >> 6) & 0x3F);
|
||||
(*escOffset++) = 0x80 | ((u32chr >> 0) & 0x3F);
|
||||
}
|
||||
else
|
||||
//FIXME: Does it even make sense supporting 4+ bytes UTF-8 sequences?
|
||||
if(u32chr < 0x4000000)
|
||||
{
|
||||
*(escOffset++) = (MASK5BYTES | u32chr >> 24);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 18 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 12 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 6 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr & MASKBITS);
|
||||
*(escOffset++) = 0xF8 | ((u32chr >> 24) & 0x03);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 18) & 0x3F);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 12) & 0x3F);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 6) & 0x3F);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 0) & 0x3F);
|
||||
}
|
||||
else
|
||||
if(u32chr < 0x8000000)
|
||||
{
|
||||
*(escOffset++) = (MASK6BYTES | u32chr >> 30);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 24 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 18 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 12 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr >> 6 & MASKBITS);
|
||||
*(escOffset++) = (MASKBYTE | u32chr & MASKBITS);
|
||||
*(escOffset++) = 0xFC | ((u32chr >> 30) & 0x01);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 24) & 0x3F);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 18) & 0x3F);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 12) & 0x3F);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 6) & 0x3F);
|
||||
*(escOffset++) = 0x80 | ((u32chr >> 0)& 0x3F);
|
||||
}
|
||||
else
|
||||
{
|
||||
return SetError (ds, -1, "Unicode code point of out bounds when decoding 'string'");
|
||||
}
|
||||
|
||||
|
||||
|
|
420
ultrajsonenc.c
420
ultrajsonenc.c
|
@ -47,35 +47,48 @@ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights rese
|
|||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
static const double g_pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
|
||||
|
||||
static const unsigned char g_utf8LengthLookup[256] =
|
||||
{
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
|
||||
};
|
||||
|
||||
//#define __LINE_PROFILER__
|
||||
|
||||
#ifdef __LINE_PROFILER__
|
||||
unsigned int g_profLines[1000] = { 0 };
|
||||
#define PROFILE_MARK() g_profLines[__LINE__] ++;
|
||||
|
||||
#else
|
||||
#define PROFILE_MARK()
|
||||
#endif
|
||||
static void SetError (JSOBJ obj, JSONObjectEncoder *enc, const char *message)
|
||||
{
|
||||
enc->errorMsg = message;
|
||||
enc->errorObj = obj;
|
||||
}
|
||||
|
||||
/*
|
||||
FIXME: Keep track of how big these get across several encoder calls and try to make an estimate
|
||||
Thay way we won't run our head into the wall each call */
|
||||
They way we won't run our head into the wall each call */
|
||||
void Buffer_Realloc (JSONObjectEncoder *enc, size_t cbNeeded)
|
||||
{
|
||||
size_t curSize = enc->end - enc->start;
|
||||
size_t newSize = curSize * 2;
|
||||
size_t offset = enc->offset - enc->start;
|
||||
|
||||
PROFILE_MARK();
|
||||
|
||||
while (newSize < curSize + cbNeeded)
|
||||
{
|
||||
newSize *= 2;
|
||||
}
|
||||
|
||||
|
||||
if (enc->heap)
|
||||
{
|
||||
enc->start = (char *) enc->realloc (enc->start, newSize);
|
||||
|
@ -98,155 +111,175 @@ FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_AppendShortHexUnchecked (c
|
|||
*(outputOffset++) = s_hexChars[(value & 0x0f00) >> 8];
|
||||
*(outputOffset++) = s_hexChars[(value & 0x00f0) >> 4];
|
||||
*(outputOffset++) = s_hexChars[(value & 0x000f) >> 0];
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
TODO:
|
||||
Performance hotspot. A lot of time is spent here */
|
||||
void Buffer_EscapeString (JSONObjectEncoder *enc, char *io)
|
||||
{
|
||||
char *of = enc->offset;
|
||||
PROFILE_MARK();
|
||||
FIXME:
|
||||
This function only works on Little Endian at the moment.
|
||||
There's a preprocessor check for this so you really can't compile on non little endian
|
||||
|
||||
FIXME: The JSON spec says escape "/" but non of the others do and we don't
|
||||
want to be left alone doing it so we don't :)
|
||||
|
||||
FIXME: I guess it would be possible to combine the UTF-8 length lookup with escaping lookup
|
||||
to make one bug super lookup table!
|
||||
*/
|
||||
|
||||
int Buffer_EscapeString (JSOBJ obj, JSONObjectEncoder *enc, char *io, char *end)
|
||||
{
|
||||
JSUTF32 ucs;
|
||||
char *of = enc->offset;
|
||||
|
||||
while (1)
|
||||
{
|
||||
unsigned char chr = (unsigned char) *io;
|
||||
int temp;
|
||||
unsigned char utflen;
|
||||
unsigned char chr;
|
||||
|
||||
if (chr >= 0x80)
|
||||
NEXT_CHARACTER:
|
||||
chr = (unsigned char) *io;
|
||||
|
||||
utflen = g_utf8LengthLookup[chr];
|
||||
|
||||
if (io + (utflen - 1) > end)
|
||||
{
|
||||
unsigned int len = 1;
|
||||
JSUTF32 u32chr = 0;
|
||||
enc->offset += (of - enc->offset);
|
||||
SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
io ++;
|
||||
|
||||
while (chr & (1 << (7 - len)) && len < 4)
|
||||
switch(utflen)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (*io == '\0')
|
||||
switch (chr)
|
||||
{
|
||||
//FIXME: Suppose this is decoding error, let's not take that crap
|
||||
return;
|
||||
case '\0': enc->offset += (of - enc->offset); return TRUE;
|
||||
case '\"': *(of++) = '\\'; *(of++) = '\"';break;
|
||||
case '\\': *(of++) = '\\'; *(of++) = '\\';break;
|
||||
//case '/': *(enc->offset++) = '\\'; *(enc->offset++) = '/';break;
|
||||
case '\b': *(of++) = '\\'; *(of++) = 'b';break;
|
||||
case '\f': *(of++) = '\\'; *(of++) = 'f';break;
|
||||
case '\n': *(of++) = '\\'; *(of++) = 'n';break;
|
||||
case '\r': *(of++) = '\\'; *(of++) = 'r';break;
|
||||
case '\t': *(of++) = '\\'; *(of++) = 't';break;
|
||||
case 0x01: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; break;
|
||||
case 0x02: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '2'; break;
|
||||
case 0x03: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '3'; break;
|
||||
case 0x04: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '4'; break;
|
||||
case 0x05: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '5'; break;
|
||||
case 0x06: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '6'; break;
|
||||
case 0x07: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '7'; break;
|
||||
case 0x0b: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = 'b'; break;
|
||||
case 0x0e: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = 'e'; break;
|
||||
case 0x0f: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = 'f'; break;
|
||||
case 0x10: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '0'; break;
|
||||
case 0x11: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '1'; break;
|
||||
case 0x12: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '2'; break;
|
||||
case 0x13: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '3'; break;
|
||||
case 0x14: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '4'; break;
|
||||
case 0x15: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '5'; break;
|
||||
case 0x16: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '6'; break;
|
||||
case 0x17: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '7'; break;
|
||||
case 0x18: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '8'; break;
|
||||
case 0x19: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '9'; break;
|
||||
case 0x1a: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'a'; break;
|
||||
case 0x1b: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'b'; break;
|
||||
case 0x1c: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'c'; break;
|
||||
case 0x1d: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'd'; break;
|
||||
case 0x1e: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'e'; break;
|
||||
case 0x1f: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'f'; break;
|
||||
default: *(of++)= chr; break;
|
||||
}
|
||||
io ++;
|
||||
|
||||
goto NEXT_CHARACTER;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
JSUTF32 in = *((JSUTF16 *) io);
|
||||
ucs = ((in & 0x1f) << 6) | ((in >> 8) & 0x3f);
|
||||
|
||||
if (ucs < 0x80)
|
||||
{
|
||||
enc->offset += (of - enc->offset);
|
||||
SetError (obj, enc, "Overlong 2 byte UTF-8 sequence detected when encoding string");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
temp = (*io & 0x3f);
|
||||
|
||||
u32chr <<= 6;
|
||||
u32chr |= (*io & 0x3f);
|
||||
|
||||
io ++;
|
||||
len ++;
|
||||
io += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
//u32chr >>= (len * 6);
|
||||
|
||||
/*
|
||||
FIXME: Performance issue
|
||||
I guess we can do this with a lookup of some sort */
|
||||
|
||||
switch (len)
|
||||
case 3:
|
||||
{
|
||||
case 2: u32chr |= (chr & 0x1f) << ((len - 1) * 6); break;
|
||||
case 3: u32chr |= (chr & 0x0f) << ((len - 1) * 6); break;
|
||||
case 4: u32chr |= (chr & 0x07) << ((len - 1) * 6); break;
|
||||
JSUTF32 in = *((JSUTF16 *) io);
|
||||
in |= *((JSUINT8 *) io + 2) << 16;
|
||||
|
||||
default:
|
||||
/*
|
||||
FIXME: This happens when a UTF-8 sequence which we can't encode it UTF-16 anyhow is encountered */
|
||||
return;
|
||||
//case 5: u32chr |= (chr & 0x03) << ((len - 1) * 6); break;
|
||||
//case 6: u32chr |= (chr & 0x01) << ((len - 1) * 6); break;
|
||||
ucs = ((in & 0x0f) << 12) | ((in & 0x3f00) >> 2) | ((in & 0x3f0000) >> 16);
|
||||
|
||||
if (ucs < 0x800)
|
||||
{
|
||||
enc->offset += (of - enc->offset);
|
||||
SetError (obj, enc, "Overlong 3 byte UTF-8 sequence detected when encoding string");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
io += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (u32chr > 0x10000)
|
||||
case 4:
|
||||
{
|
||||
JSUTF16 s1;
|
||||
JSUTF16 s2;
|
||||
u32chr -= 0x10000;
|
||||
JSUTF32 in = *((JSUTF32 *) io);
|
||||
ucs = ((in & 0x07) << 18) | ((in & 0x3f00) << 4) | ((in & 0x3f0000) >> 10) | ((in & 0x3f000000) >> 24);
|
||||
|
||||
s1 = (u32chr >> 10) + 0xd800;
|
||||
s2 = (u32chr & 0x3ff) + 0xdc00;
|
||||
if (ucs < 0x10000)
|
||||
{
|
||||
enc->offset += (of - enc->offset);
|
||||
SetError (obj, enc, "Overlong 4 byte UTF-8 sequence detected when encoding string");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(of++) = '\\';
|
||||
*(of++) = 'u';
|
||||
Buffer_AppendShortHexUnchecked(of, s1);
|
||||
of += 4;
|
||||
|
||||
*(of++) = '\\';
|
||||
*(of++) = 'u';
|
||||
Buffer_AppendShortHexUnchecked(of, s2);
|
||||
of += 4;
|
||||
io += 4;
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
case 5:
|
||||
case 6:
|
||||
default:
|
||||
{
|
||||
*(of++) = '\\';
|
||||
*(of++) = 'u';
|
||||
Buffer_AppendShortHexUnchecked(of, u32chr);
|
||||
of += 4;
|
||||
enc->offset += (of - enc->offset);
|
||||
SetError (obj, enc, "Unsupported UTF-8 sequence length when encoding string");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If the character is a UTF8 sequence of length > 1 we end up here */
|
||||
if (ucs > 0x10000)
|
||||
{
|
||||
ucs -= 0x10000;
|
||||
*(of++) = '\\';
|
||||
*(of++) = 'u';
|
||||
Buffer_AppendShortHexUnchecked(of, (ucs >> 10) + 0xd800);
|
||||
of += 4;
|
||||
|
||||
|
||||
|
||||
*(of++) = '\\';
|
||||
*(of++) = 'u';
|
||||
Buffer_AppendShortHexUnchecked(of, (ucs & 0x3ff) + 0xdc00);
|
||||
of += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (chr)
|
||||
{
|
||||
case '\0':
|
||||
enc->offset += (of - enc->offset);
|
||||
return;
|
||||
|
||||
case '\"': *(of++) = '\\'; *(of++) = '\"';break;
|
||||
case '\\': *(of++) = '\\'; *(of++) = '\\';break;
|
||||
|
||||
//NOTE: The RFC says escape solidus but none of the reference encoders does so.
|
||||
//We don't do it either now ;)
|
||||
//case '/': *(enc->offset++) = '\\'; *(enc->offset++) = '/';break;
|
||||
case '\b': *(of++) = '\\'; *(of++) = 'b';break;
|
||||
case '\f': *(of++) = '\\'; *(of++) = 'f';break;
|
||||
case '\n': *(of++) = '\\'; *(of++) = 'n';break;
|
||||
case '\r': *(of++) = '\\'; *(of++) = 'r';break;
|
||||
case '\t': *(of++) = '\\'; *(of++) = 't';break;
|
||||
|
||||
case 0x01: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; break;
|
||||
case 0x02: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '2'; break;
|
||||
case 0x03: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '3'; break;
|
||||
case 0x04: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '4'; break;
|
||||
case 0x05: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '5'; break;
|
||||
case 0x06: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '6'; break;
|
||||
case 0x07: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '7'; break;
|
||||
case 0x0b: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = 'b'; break;
|
||||
case 0x0e: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = 'e'; break;
|
||||
case 0x0f: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = 'f'; break;
|
||||
case 0x10: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '0'; break;
|
||||
case 0x11: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '1'; break;
|
||||
case 0x12: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '2'; break;
|
||||
case 0x13: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '3'; break;
|
||||
case 0x14: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '4'; break;
|
||||
case 0x15: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '5'; break;
|
||||
case 0x16: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '6'; break;
|
||||
case 0x17: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '7'; break;
|
||||
case 0x18: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '8'; break;
|
||||
case 0x19: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = '9'; break;
|
||||
case 0x1a: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'a'; break;
|
||||
case 0x1b: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'b'; break;
|
||||
case 0x1c: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'c'; break;
|
||||
case 0x1d: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'd'; break;
|
||||
case 0x1e: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'e'; break;
|
||||
case 0x1f: *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '1'; *(of++) = 'f'; break;
|
||||
default: *(of++)= chr; break;
|
||||
}
|
||||
io ++;
|
||||
*(of++) = '\\';
|
||||
*(of++) = 'u';
|
||||
Buffer_AppendShortHexUnchecked(of, ucs);
|
||||
of += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define Buffer_Reserve(__enc, __len) \
|
||||
if ((__enc)->offset + (__len) > (__enc)->end) \
|
||||
{ \
|
||||
|
@ -254,73 +287,20 @@ void Buffer_EscapeString (JSONObjectEncoder *enc, char *io)
|
|||
} \
|
||||
|
||||
|
||||
#define Buffer_AppendCharUnchecked(__enc, __chr) \
|
||||
*((__enc)->offset++) = __chr; \
|
||||
|
||||
/*
|
||||
FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_AppendEscape(JSONObjectEncoder *enc, const char *_pstr, size_t _len)
|
||||
{
|
||||
while (enc->offset + ((_len * 2) + 2) > enc->end)
|
||||
{
|
||||
Buffer_Realloc(enc);
|
||||
}
|
||||
|
||||
*(enc->offset++) = '\"';
|
||||
Buffer_Escape(enc, (char *)_pstr);
|
||||
*(enc->offset++) = '\"';
|
||||
}
|
||||
|
||||
FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_AppendEscapeUnchecked(JSONObjectEncoder *enc, const char *_pstr)
|
||||
{
|
||||
*(enc->offset++) = '\"';
|
||||
Buffer_Escape(enc, (char *)_pstr);
|
||||
*(enc->offset++) = '\"';
|
||||
}
|
||||
|
||||
|
||||
FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_Append(JSONObjectEncoder *enc, const char *_pstr, size_t _len)
|
||||
{
|
||||
while (enc->offset + _len > enc->end)
|
||||
{
|
||||
Buffer_Realloc(enc);
|
||||
}
|
||||
memcpy (enc->offset, _pstr, _len);
|
||||
enc->offset += _len;
|
||||
}
|
||||
|
||||
FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_Reserve(JSONObjectEncoder *enc, size_t _len)
|
||||
{
|
||||
while (enc->offset + _len > enc->end)
|
||||
{
|
||||
Buffer_Realloc(enc);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Powers of 10
|
||||
* 10^0 to 10^9
|
||||
*/
|
||||
static const double g_pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
|
||||
#define Buffer_AppendCharUnchecked(__enc, __chr) \
|
||||
*((__enc)->offset++) = __chr; \
|
||||
|
||||
FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC strreverse(char* begin, char* end)
|
||||
{
|
||||
char aux;
|
||||
PROFILE_MARK();
|
||||
while (end > begin)
|
||||
aux = *end, *end-- = *begin, *begin++ = aux;
|
||||
}
|
||||
|
||||
|
||||
void Buffer_AppendIntUnchecked(JSONObjectEncoder *enc, JSINT32 value)
|
||||
{
|
||||
char* wstr;
|
||||
JSUINT32 uvalue = (value < 0) ? -value : value;
|
||||
|
||||
PROFILE_MARK();
|
||||
|
||||
wstr = enc->offset;
|
||||
// Conversion. Number is reversed.
|
||||
|
@ -337,8 +317,6 @@ void Buffer_AppendLongUnchecked(JSONObjectEncoder *enc, JSINT64 value)
|
|||
{
|
||||
char* wstr;
|
||||
JSUINT64 uvalue = (value < 0) ? -value : value;
|
||||
|
||||
PROFILE_MARK();
|
||||
|
||||
wstr = enc->offset;
|
||||
// Conversion. Number is reversed.
|
||||
|
@ -364,7 +342,6 @@ void Buffer_AppendDoubleUnchecked(JSONObjectEncoder *enc, double value)
|
|||
uint32_t frac;
|
||||
int neg;
|
||||
|
||||
PROFILE_MARK();
|
||||
|
||||
/* Hacky test for NaN
|
||||
* under -fast-math this won't work, but then you also won't
|
||||
|
@ -499,19 +476,12 @@ FIXME:
|
|||
Perhaps implement recursion detection */
|
||||
|
||||
|
||||
static void SetError (JSOBJ obj, JSONObjectEncoder *enc, const char *message)
|
||||
{
|
||||
enc->errorMsg = message;
|
||||
enc->errorObj = obj;
|
||||
}
|
||||
|
||||
void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
||||
{
|
||||
JSONTypeContext tc;
|
||||
size_t szlen;
|
||||
|
||||
PROFILE_MARK();
|
||||
|
||||
if (enc->level > enc->recursionMax)
|
||||
{
|
||||
SetError (obj, enc, "Maximum recursion level reached");
|
||||
|
@ -525,21 +495,19 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
maxLength of double to string OR maxLength of JSLONG to string
|
||||
|
||||
Since input is assumed to be UTF-8 the worst character length is:
|
||||
|
||||
UTF-8: 6 bytes (31 bit real data) =>
|
||||
UCS-4: 4 bytes =>
|
||||
UTF-16: 2 surrogate pairs (4 bytes) =>
|
||||
Encoded: \uXXXX\uXXXX (12 bytes)
|
||||
|
||||
12 / 6 => 2
|
||||
4 bytes (of UTF-8) => "\uXXXX\uXXXX" (12 bytes)
|
||||
*/
|
||||
|
||||
Buffer_Reserve(enc, 256 + (cbName * 2));
|
||||
Buffer_Reserve(enc, 256 + (((cbName / 4) + 1) * 12));
|
||||
|
||||
if (name)
|
||||
{
|
||||
Buffer_AppendCharUnchecked(enc, '\"');
|
||||
Buffer_EscapeString(enc, name);
|
||||
if (!Buffer_EscapeString(obj, enc, name, name + cbName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Buffer_AppendCharUnchecked(enc, '\"');
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, ':');
|
||||
|
@ -560,9 +528,6 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
{
|
||||
int count = 0;
|
||||
JSOBJ iterObj;
|
||||
|
||||
PROFILE_MARK();
|
||||
|
||||
enc->iterBegin(obj, &tc);
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, '[');
|
||||
|
@ -595,8 +560,6 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
JSOBJ iterObj;
|
||||
char *objName;
|
||||
|
||||
PROFILE_MARK();
|
||||
|
||||
enc->iterBegin(obj, &tc);
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, '{');
|
||||
|
@ -626,24 +589,18 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
|
||||
case JT_LONG:
|
||||
{
|
||||
PROFILE_MARK();
|
||||
|
||||
Buffer_AppendLongUnchecked (enc, enc->getLongValue(obj, &tc));
|
||||
break;
|
||||
}
|
||||
|
||||
case JT_INT:
|
||||
{
|
||||
PROFILE_MARK();
|
||||
|
||||
Buffer_AppendIntUnchecked (enc, enc->getIntValue(obj, &tc));
|
||||
break;
|
||||
}
|
||||
|
||||
case JT_TRUE:
|
||||
{
|
||||
PROFILE_MARK();
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, 't');
|
||||
Buffer_AppendCharUnchecked (enc, 'r');
|
||||
Buffer_AppendCharUnchecked (enc, 'u');
|
||||
|
@ -653,9 +610,6 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
|
||||
case JT_FALSE:
|
||||
{
|
||||
//Buffer_AppendUnchecked (buffer, "false", 5);
|
||||
PROFILE_MARK();
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, 'f');
|
||||
Buffer_AppendCharUnchecked (enc, 'a');
|
||||
Buffer_AppendCharUnchecked (enc, 'l');
|
||||
|
@ -667,9 +621,6 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
|
||||
case JT_NULL:
|
||||
{
|
||||
//Buffer_AppendUnchecked(buffer, "null", 4);
|
||||
PROFILE_MARK();
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, 'n');
|
||||
Buffer_AppendCharUnchecked (enc, 'u');
|
||||
Buffer_AppendCharUnchecked (enc, 'l');
|
||||
|
@ -679,8 +630,6 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
|
||||
case JT_DOUBLE:
|
||||
{
|
||||
PROFILE_MARK();
|
||||
|
||||
Buffer_AppendDoubleUnchecked (enc, enc->getDoubleValue(obj, &tc));
|
||||
break;
|
||||
}
|
||||
|
@ -688,11 +637,16 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
case JT_UTF8:
|
||||
{
|
||||
const char *value = enc->getStringValue(obj, &tc, &szlen);
|
||||
PROFILE_MARK();
|
||||
|
||||
Buffer_Reserve(enc, (szlen * 2) + 2);
|
||||
Buffer_Reserve(enc, ((szlen / 4) + 1) * 12);
|
||||
Buffer_AppendCharUnchecked (enc, '\"');
|
||||
Buffer_EscapeString(enc, value);
|
||||
|
||||
if (!Buffer_EscapeString(obj, enc, value, value + szlen))
|
||||
{
|
||||
enc->endTypeContext(obj, &tc);
|
||||
enc->level --;
|
||||
return;
|
||||
}
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, '\"');
|
||||
break;
|
||||
}
|
||||
|
@ -703,9 +657,6 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//FIXME: Depending on performance make JSON_NO_EXTRA_WHITESPACE as configuration option
|
||||
char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char *_buffer, size_t _cbBuffer)
|
||||
{
|
||||
enc->malloc = enc->malloc ? enc->malloc : malloc;
|
||||
|
@ -747,18 +698,5 @@ char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char *_buffer, size_t
|
|||
Buffer_Reserve(enc, 1);
|
||||
Buffer_AppendCharUnchecked(enc, '\0');
|
||||
|
||||
#ifdef __LINE_PROFILER__
|
||||
{
|
||||
int index;
|
||||
for (index = 0; index < 1000; index ++)
|
||||
{
|
||||
if (g_profLines[index] > 0)
|
||||
fprintf (stderr, "%d %u\n", index, g_profLines[index]);
|
||||
}
|
||||
|
||||
getchar();
|
||||
}
|
||||
#endif
|
||||
|
||||
return enc->start;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue