ujson-1.33/0000755000175100017510000000000012544263027011641 5ustar morphmorphujson-1.33/python/0000755000175100017510000000000012544263027013162 5ustar morphmorphujson-1.33/python/version.h0000666000175100017510000000376712155611544015040 0ustar morphmorph/* Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ESN Social Software AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved. Numeric decoder derived from from TCL library http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. */ #define UJSON_VERSION "1.33" ujson-1.33/python/objToJSON.c0000666000175100017510000005442412155377246015121 0ustar morphmorph/* Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ESN Social Software AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved. Numeric decoder derived from from TCL library http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. */ #include "py_defines.h" #include #include #include #define EPOCH_ORD 719163 static PyObject* type_decimal; typedef void *(*PFN_PyTypeToJSON)(JSOBJ obj, JSONTypeContext *ti, void *outValue, size_t *_outLen); #if (PY_VERSION_HEX < 0x02050000) typedef ssize_t Py_ssize_t; #endif typedef struct __TypeContext { JSPFN_ITERBEGIN iterBegin; JSPFN_ITEREND iterEnd; JSPFN_ITERNEXT iterNext; JSPFN_ITERGETNAME iterGetName; JSPFN_ITERGETVALUE iterGetValue; PFN_PyTypeToJSON PyTypeToJSON; PyObject *newObj; PyObject *dictObj; Py_ssize_t index; Py_ssize_t size; PyObject *itemValue; PyObject *itemName; PyObject *attrList; PyObject *iterator; JSINT64 longValue; } TypeContext; #define GET_TC(__ptrtc) ((TypeContext *)((__ptrtc)->prv)) struct PyDictIterState { PyObject *keys; size_t i; size_t sz; }; //#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__) #define PRINTMARK() void initObjToJSON(void) { PyObject* mod_decimal = PyImport_ImportModule("decimal"); type_decimal = PyObject_GetAttrString(mod_decimal, "Decimal"); Py_INCREF(type_decimal); Py_DECREF(mod_decimal); PyDateTime_IMPORT; } static void *PyIntToINT32(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { PyObject *obj = (PyObject *) _obj; *((JSINT32 *) outValue) = PyInt_AS_LONG (obj); return NULL; } static void *PyIntToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { PyObject *obj = (PyObject *) _obj; *((JSINT64 *) outValue) = PyInt_AS_LONG (obj); return NULL; } static void *PyLongToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { *((JSINT64 *) outValue) = GET_TC(tc)->longValue; return NULL; } static void *PyFloatToDOUBLE(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { PyObject *obj = (PyObject *) _obj; *((double *) outValue) = PyFloat_AsDouble (obj); return NULL; } static void *PyStringToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { PyObject *obj = (PyObject *) _obj; *_outLen = PyString_GET_SIZE(obj); return PyString_AS_STRING(obj); } static void *PyUnicodeToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { PyObject *obj = (PyObject *) _obj; PyObject *newObj = PyUnicode_EncodeUTF8 (PyUnicode_AS_UNICODE(obj), PyUnicode_GET_SIZE(obj), NULL); GET_TC(tc)->newObj = newObj; *_outLen = PyString_GET_SIZE(newObj); return PyString_AS_STRING(newObj); } static void *PyDateTimeToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { PyObject *obj = (PyObject *) _obj; PyObject *date, *ord; int y, m, d, h, mn, s, days; y = PyDateTime_GET_YEAR(obj); m = PyDateTime_GET_MONTH(obj); d = PyDateTime_GET_DAY(obj); h = PyDateTime_DATE_GET_HOUR(obj); mn = PyDateTime_DATE_GET_MINUTE(obj); s = PyDateTime_DATE_GET_SECOND(obj); date = PyDate_FromDate(y, m, 1); ord = PyObject_CallMethod(date, "toordinal", NULL); days = PyInt_AS_LONG(ord) - EPOCH_ORD + d - 1; Py_DECREF(date); Py_DECREF(ord); *( (JSINT64 *) outValue) = (((JSINT64) ((days * 24 + h) * 60 + mn)) * 60 + s); return NULL; } static void *PyDateToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { PyObject *obj = (PyObject *) _obj; PyObject *date, *ord; int y, m, d, days; y = PyDateTime_GET_YEAR(obj); m = PyDateTime_GET_MONTH(obj); d = PyDateTime_GET_DAY(obj); date = PyDate_FromDate(y, m, 1); ord = PyObject_CallMethod(date, "toordinal", NULL); days = PyInt_AS_LONG(ord) - EPOCH_ORD + d - 1; Py_DECREF(date); Py_DECREF(ord); *( (JSINT64 *) outValue) = ((JSINT64) days * 86400); return NULL; } //============================================================================= // Tuple iteration functions // itemValue is borrowed reference, no ref counting //============================================================================= void Tuple_iterBegin(JSOBJ obj, JSONTypeContext *tc) { GET_TC(tc)->index = 0; GET_TC(tc)->size = PyTuple_GET_SIZE( (PyObject *) obj); GET_TC(tc)->itemValue = NULL; } int Tuple_iterNext(JSOBJ obj, JSONTypeContext *tc) { PyObject *item; if (GET_TC(tc)->index >= GET_TC(tc)->size) { return 0; } item = PyTuple_GET_ITEM (obj, GET_TC(tc)->index); GET_TC(tc)->itemValue = item; GET_TC(tc)->index ++; return 1; } void Tuple_iterEnd(JSOBJ obj, JSONTypeContext *tc) { } JSOBJ Tuple_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->itemValue; } char *Tuple_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) { return NULL; } //============================================================================= // Iterator iteration functions // itemValue is borrowed reference, no ref counting //============================================================================= void Iter_iterBegin(JSOBJ obj, JSONTypeContext *tc) { GET_TC(tc)->itemValue = NULL; GET_TC(tc)->iterator = PyObject_GetIter(obj); } int Iter_iterNext(JSOBJ obj, JSONTypeContext *tc) { PyObject *item; if (GET_TC(tc)->itemValue) { Py_DECREF(GET_TC(tc)->itemValue); GET_TC(tc)->itemValue = NULL; } item = PyIter_Next(GET_TC(tc)->iterator); if (item == NULL) { return 0; } GET_TC(tc)->itemValue = item; return 1; } void Iter_iterEnd(JSOBJ obj, JSONTypeContext *tc) { if (GET_TC(tc)->itemValue) { Py_DECREF(GET_TC(tc)->itemValue); GET_TC(tc)->itemValue = NULL; } if (GET_TC(tc)->iterator) { Py_DECREF(GET_TC(tc)->iterator); GET_TC(tc)->iterator = NULL; } } JSOBJ Iter_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->itemValue; } char *Iter_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) { return NULL; } //============================================================================= // Dir iteration functions // itemName ref is borrowed from PyObject_Dir (attrList). No refcount // itemValue ref is from PyObject_GetAttr. Ref counted //============================================================================= void Dir_iterBegin(JSOBJ obj, JSONTypeContext *tc) { GET_TC(tc)->attrList = PyObject_Dir(obj); GET_TC(tc)->index = 0; GET_TC(tc)->size = PyList_GET_SIZE(GET_TC(tc)->attrList); PRINTMARK(); } void Dir_iterEnd(JSOBJ obj, JSONTypeContext *tc) { if (GET_TC(tc)->itemValue) { Py_DECREF(GET_TC(tc)->itemValue); GET_TC(tc)->itemValue = NULL; } if (GET_TC(tc)->itemName) { Py_DECREF(GET_TC(tc)->itemName); GET_TC(tc)->itemName = NULL; } Py_DECREF( (PyObject *) GET_TC(tc)->attrList); PRINTMARK(); } int Dir_iterNext(JSOBJ _obj, JSONTypeContext *tc) { PyObject *obj = (PyObject *) _obj; PyObject *itemValue = GET_TC(tc)->itemValue; PyObject *itemName = GET_TC(tc)->itemName; PyObject* attr; PyObject* attrName; char* attrStr; if (itemValue) { Py_DECREF(GET_TC(tc)->itemValue); GET_TC(tc)->itemValue = itemValue = NULL; } if (itemName) { Py_DECREF(GET_TC(tc)->itemName); GET_TC(tc)->itemName = itemName = NULL; } for (; GET_TC(tc)->index < GET_TC(tc)->size; GET_TC(tc)->index ++) { attrName = PyList_GET_ITEM(GET_TC(tc)->attrList, GET_TC(tc)->index); #if PY_MAJOR_VERSION >= 3 attr = PyUnicode_AsUTF8String(attrName); #else attr = attrName; Py_INCREF(attr); #endif attrStr = PyString_AS_STRING(attr); if (attrStr[0] == '_') { PRINTMARK(); Py_DECREF(attr); continue; } itemValue = PyObject_GetAttr(obj, attrName); if (itemValue == NULL) { PyErr_Clear(); Py_DECREF(attr); PRINTMARK(); continue; } if (PyCallable_Check(itemValue)) { Py_DECREF(itemValue); Py_DECREF(attr); PRINTMARK(); continue; } PRINTMARK(); itemName = attr; break; } if (itemName == NULL) { GET_TC(tc)->index = GET_TC(tc)->size; GET_TC(tc)->itemValue = NULL; return 0; } GET_TC(tc)->itemName = itemName; GET_TC(tc)->itemValue = itemValue; GET_TC(tc)->index ++; PRINTMARK(); return 1; } JSOBJ Dir_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { PRINTMARK(); return GET_TC(tc)->itemValue; } char *Dir_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) { PRINTMARK(); *outLen = PyString_GET_SIZE(GET_TC(tc)->itemName); return PyString_AS_STRING(GET_TC(tc)->itemName); } //============================================================================= // List iteration functions // itemValue is borrowed from object (which is list). No refcounting //============================================================================= void List_iterBegin(JSOBJ obj, JSONTypeContext *tc) { GET_TC(tc)->index = 0; GET_TC(tc)->size = PyList_GET_SIZE( (PyObject *) obj); } int List_iterNext(JSOBJ obj, JSONTypeContext *tc) { if (GET_TC(tc)->index >= GET_TC(tc)->size) { PRINTMARK(); return 0; } GET_TC(tc)->itemValue = PyList_GET_ITEM (obj, GET_TC(tc)->index); GET_TC(tc)->index ++; return 1; } void List_iterEnd(JSOBJ obj, JSONTypeContext *tc) { } JSOBJ List_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->itemValue; } char *List_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) { return NULL; } //============================================================================= // Dict iteration functions // itemName might converted to string (Python_Str). Do refCounting // itemValue is borrowed from object (which is dict). No refCounting //============================================================================= void Dict_iterBegin(JSOBJ obj, JSONTypeContext *tc) { GET_TC(tc)->index = 0; PRINTMARK(); } int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc) { #if PY_MAJOR_VERSION >= 3 PyObject* itemNameTmp; #endif if (GET_TC(tc)->itemName) { Py_DECREF(GET_TC(tc)->itemName); GET_TC(tc)->itemName = NULL; } if (!PyDict_Next ( (PyObject *)GET_TC(tc)->dictObj, &GET_TC(tc)->index, &GET_TC(tc)->itemName, &GET_TC(tc)->itemValue)) { PRINTMARK(); return 0; } if (PyUnicode_Check(GET_TC(tc)->itemName)) { GET_TC(tc)->itemName = PyUnicode_AsUTF8String (GET_TC(tc)->itemName); } else if (!PyString_Check(GET_TC(tc)->itemName)) { GET_TC(tc)->itemName = PyObject_Str(GET_TC(tc)->itemName); #if PY_MAJOR_VERSION >= 3 itemNameTmp = GET_TC(tc)->itemName; GET_TC(tc)->itemName = PyUnicode_AsUTF8String (GET_TC(tc)->itemName); Py_DECREF(itemNameTmp); #endif } else { Py_INCREF(GET_TC(tc)->itemName); } PRINTMARK(); return 1; } void Dict_iterEnd(JSOBJ obj, JSONTypeContext *tc) { if (GET_TC(tc)->itemName) { Py_DECREF(GET_TC(tc)->itemName); GET_TC(tc)->itemName = NULL; } Py_DECREF(GET_TC(tc)->dictObj); PRINTMARK(); } JSOBJ Dict_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->itemValue; } char *Dict_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) { *outLen = PyString_GET_SIZE(GET_TC(tc)->itemName); return PyString_AS_STRING(GET_TC(tc)->itemName); } void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc) { PyObject *obj, *exc, *toDictFunc; TypeContext *pc; PRINTMARK(); if (!_obj) { tc->type = JT_INVALID; return; } obj = (PyObject*) _obj; tc->prv = PyObject_Malloc(sizeof(TypeContext)); pc = (TypeContext *) tc->prv; if (!pc) { tc->type = JT_INVALID; PyErr_NoMemory(); return; } pc->newObj = NULL; pc->dictObj = NULL; pc->itemValue = NULL; pc->itemName = NULL; pc->attrList = NULL; pc->index = 0; pc->size = 0; pc->longValue = 0; if (PyIter_Check(obj)) { PRINTMARK(); goto ISITERABLE; } if (PyBool_Check(obj)) { PRINTMARK(); tc->type = (obj == Py_True) ? JT_TRUE : JT_FALSE; return; } else if (PyLong_Check(obj)) { PRINTMARK(); pc->PyTypeToJSON = PyLongToINT64; tc->type = JT_LONG; GET_TC(tc)->longValue = PyLong_AsLongLong(obj); exc = PyErr_Occurred(); if (exc && PyErr_ExceptionMatches(PyExc_OverflowError)) { PRINTMARK(); goto INVALID; } return; } else if (PyInt_Check(obj)) { PRINTMARK(); #ifdef _LP64 pc->PyTypeToJSON = PyIntToINT64; tc->type = JT_LONG; #else pc->PyTypeToJSON = PyIntToINT32; tc->type = JT_INT; #endif return; } else if (PyString_Check(obj)) { PRINTMARK(); pc->PyTypeToJSON = PyStringToUTF8; tc->type = JT_UTF8; return; } else if (PyUnicode_Check(obj)) { PRINTMARK(); pc->PyTypeToJSON = PyUnicodeToUTF8; tc->type = JT_UTF8; return; } else if (PyFloat_Check(obj) || PyObject_IsInstance(obj, type_decimal)) { PRINTMARK(); pc->PyTypeToJSON = PyFloatToDOUBLE; tc->type = JT_DOUBLE; return; } else if (PyDateTime_Check(obj)) { PRINTMARK(); pc->PyTypeToJSON = PyDateTimeToINT64; tc->type = JT_LONG; return; } else if (PyDate_Check(obj)) { PRINTMARK(); pc->PyTypeToJSON = PyDateToINT64; tc->type = JT_LONG; return; } else if (obj == Py_None) { PRINTMARK(); tc->type = JT_NULL; return; } ISITERABLE: if (PyDict_Check(obj)) { PRINTMARK(); tc->type = JT_OBJECT; pc->iterBegin = Dict_iterBegin; pc->iterEnd = Dict_iterEnd; pc->iterNext = Dict_iterNext; pc->iterGetValue = Dict_iterGetValue; pc->iterGetName = Dict_iterGetName; pc->dictObj = obj; Py_INCREF(obj); return; } else if (PyList_Check(obj)) { PRINTMARK(); tc->type = JT_ARRAY; pc->iterBegin = List_iterBegin; pc->iterEnd = List_iterEnd; pc->iterNext = List_iterNext; pc->iterGetValue = List_iterGetValue; pc->iterGetName = List_iterGetName; return; } else if (PyTuple_Check(obj)) { PRINTMARK(); tc->type = JT_ARRAY; pc->iterBegin = Tuple_iterBegin; pc->iterEnd = Tuple_iterEnd; pc->iterNext = Tuple_iterNext; pc->iterGetValue = Tuple_iterGetValue; pc->iterGetName = Tuple_iterGetName; return; } else if (PyAnySet_Check(obj)) { PRINTMARK(); tc->type = JT_ARRAY; pc->iterBegin = Iter_iterBegin; pc->iterEnd = Iter_iterEnd; pc->iterNext = Iter_iterNext; pc->iterGetValue = Iter_iterGetValue; pc->iterGetName = Iter_iterGetName; return; } toDictFunc = PyObject_GetAttrString(obj, "toDict"); if (toDictFunc) { PyObject* tuple = PyTuple_New(0); PyObject* toDictResult = PyObject_Call(toDictFunc, tuple, NULL); Py_DECREF(tuple); Py_DECREF(toDictFunc); if (toDictResult == NULL) { PyErr_Clear(); tc->type = JT_NULL; return; } if (!PyDict_Check(toDictResult)) { Py_DECREF(toDictResult); tc->type = JT_NULL; return; } PRINTMARK(); tc->type = JT_OBJECT; pc->iterBegin = Dict_iterBegin; pc->iterEnd = Dict_iterEnd; pc->iterNext = Dict_iterNext; pc->iterGetValue = Dict_iterGetValue; pc->iterGetName = Dict_iterGetName; pc->dictObj = toDictResult; return; } PyErr_Clear(); PRINTMARK(); tc->type = JT_OBJECT; pc->iterBegin = Dir_iterBegin; pc->iterEnd = Dir_iterEnd; pc->iterNext = Dir_iterNext; pc->iterGetValue = Dir_iterGetValue; pc->iterGetName = Dir_iterGetName; return; INVALID: tc->type = JT_INVALID; PyObject_Free(tc->prv); tc->prv = NULL; return; } void Object_endTypeContext(JSOBJ obj, JSONTypeContext *tc) { Py_XDECREF(GET_TC(tc)->newObj); PyObject_Free(tc->prv); tc->prv = NULL; } const char *Object_getStringValue(JSOBJ obj, JSONTypeContext *tc, size_t *_outLen) { return GET_TC(tc)->PyTypeToJSON (obj, tc, NULL, _outLen); } JSINT64 Object_getLongValue(JSOBJ obj, JSONTypeContext *tc) { JSINT64 ret; GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL); return ret; } JSINT32 Object_getIntValue(JSOBJ obj, JSONTypeContext *tc) { JSINT32 ret; GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL); return ret; } double Object_getDoubleValue(JSOBJ obj, JSONTypeContext *tc) { double ret; GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL); return ret; } static void Object_releaseObject(JSOBJ _obj) { Py_DECREF( (PyObject *) _obj); } void Object_iterBegin(JSOBJ obj, JSONTypeContext *tc) { GET_TC(tc)->iterBegin(obj, tc); } int Object_iterNext(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->iterNext(obj, tc); } void Object_iterEnd(JSOBJ obj, JSONTypeContext *tc) { GET_TC(tc)->iterEnd(obj, tc); } JSOBJ Object_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->iterGetValue(obj, tc); } char *Object_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) { return GET_TC(tc)->iterGetName(obj, tc, outLen); } PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "obj", "ensure_ascii", "double_precision", "encode_html_chars", NULL}; char buffer[65536]; char *ret; PyObject *newobj; PyObject *oinput = NULL; PyObject *oensureAscii = NULL; int idoublePrecision = 10; // default double precision setting PyObject *oencodeHTMLChars = NULL; JSONObjectEncoder encoder = { Object_beginTypeContext, Object_endTypeContext, Object_getStringValue, Object_getLongValue, Object_getIntValue, Object_getDoubleValue, Object_iterBegin, Object_iterNext, Object_iterEnd, Object_iterGetValue, Object_iterGetName, Object_releaseObject, PyObject_Malloc, PyObject_Realloc, PyObject_Free, -1, //recursionMax idoublePrecision, 1, //forceAscii 0, //encodeHTMLChars }; PRINTMARK(); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OiO", kwlist, &oinput, &oensureAscii, &idoublePrecision, &oencodeHTMLChars)) { return NULL; } if (oensureAscii != NULL && !PyObject_IsTrue(oensureAscii)) { encoder.forceASCII = 0; } if (oencodeHTMLChars != NULL && PyObject_IsTrue(oencodeHTMLChars)) { encoder.encodeHTMLChars = 1; } encoder.doublePrecision = idoublePrecision; PRINTMARK(); ret = JSON_EncodeObject (oinput, &encoder, buffer, sizeof (buffer)); PRINTMARK(); if (PyErr_Occurred()) { return NULL; } if (encoder.errorMsg) { if (ret != buffer) { encoder.free (ret); } PyErr_Format (PyExc_OverflowError, "%s", encoder.errorMsg); return NULL; } newobj = PyString_FromString (ret); if (ret != buffer) { encoder.free (ret); } PRINTMARK(); return newobj; } PyObject* objToJSONFile(PyObject* self, PyObject *args, PyObject *kwargs) { PyObject *data; PyObject *file; PyObject *string; PyObject *write; PyObject *argtuple; PRINTMARK(); if (!PyArg_ParseTuple (args, "OO", &data, &file)) { return NULL; } if (!PyObject_HasAttrString (file, "write")) { PyErr_Format (PyExc_TypeError, "expected file"); return NULL; } write = PyObject_GetAttrString (file, "write"); if (!PyCallable_Check (write)) { Py_XDECREF(write); PyErr_Format (PyExc_TypeError, "expected file"); return NULL; } argtuple = PyTuple_Pack(1, data); string = objToJSON (self, argtuple, kwargs); if (string == NULL) { Py_XDECREF(write); Py_XDECREF(argtuple); return NULL; } Py_XDECREF(argtuple); argtuple = PyTuple_Pack (1, string); if (argtuple == NULL) { Py_XDECREF(write); return NULL; } if (PyObject_CallObject (write, argtuple) == NULL) { Py_XDECREF(write); Py_XDECREF(argtuple); return NULL; } Py_XDECREF(write); Py_DECREF(argtuple); Py_XDECREF(string); PRINTMARK(); Py_RETURN_NONE; } ujson-1.33/python/py_defines.h0000666000175100017510000000454512075616026015474 0ustar morphmorph/* Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ESN Social Software AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved. Numeric decoder derived from from TCL library http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. */ #include #if PY_MAJOR_VERSION >= 3 #define PyInt_Check PyLong_Check #define PyInt_AS_LONG PyLong_AsLong #define PyInt_FromLong PyLong_FromLong #define PyString_Check PyBytes_Check #define PyString_GET_SIZE PyBytes_GET_SIZE #define PyString_AS_STRING PyBytes_AS_STRING #define PyString_FromString PyUnicode_FromString #endif ujson-1.33/python/JSONtoObj.c0000666000175100017510000001331712155377716015117 0ustar morphmorph/* Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ESN Social Software AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved. Numeric decoder derived from from TCL library http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. */ #include "py_defines.h" #include //#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__) #define PRINTMARK() void Object_objectAddKey(void *prv, JSOBJ obj, JSOBJ name, JSOBJ value) { PyDict_SetItem (obj, name, value); Py_DECREF( (PyObject *) name); Py_DECREF( (PyObject *) value); return; } void Object_arrayAddItem(void *prv, JSOBJ obj, JSOBJ value) { PyList_Append(obj, value); Py_DECREF( (PyObject *) value); return; } JSOBJ Object_newString(void *prv, wchar_t *start, wchar_t *end) { return PyUnicode_FromWideChar (start, (end - start)); } JSOBJ Object_newTrue(void *prv) { Py_RETURN_TRUE; } JSOBJ Object_newFalse(void *prv) { Py_RETURN_FALSE; } JSOBJ Object_newNull(void *prv) { Py_RETURN_NONE; } JSOBJ Object_newObject(void *prv) { return PyDict_New(); } JSOBJ Object_newArray(void *prv) { return PyList_New(0); } JSOBJ Object_newInteger(void *prv, JSINT32 value) { return PyInt_FromLong( (long) value); } JSOBJ Object_newLong(void *prv, JSINT64 value) { return PyLong_FromLongLong (value); } JSOBJ Object_newDouble(void *prv, double value) { return PyFloat_FromDouble(value); } static void Object_releaseObject(void *prv, JSOBJ obj) { Py_DECREF( ((PyObject *)obj)); } static char *g_kwlist[] = {"obj", "precise_float", NULL}; PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs) { PyObject *ret; PyObject *sarg; PyObject *arg; PyObject *opreciseFloat = NULL; JSONObjectDecoder decoder = { Object_newString, Object_objectAddKey, Object_arrayAddItem, Object_newTrue, Object_newFalse, Object_newNull, Object_newObject, Object_newArray, Object_newInteger, Object_newLong, Object_newDouble, Object_releaseObject, PyObject_Malloc, PyObject_Free, PyObject_Realloc }; decoder.preciseFloat = 0; decoder.prv = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", g_kwlist, &arg, &opreciseFloat)) { return NULL; } if (opreciseFloat && PyObject_IsTrue(opreciseFloat)) { decoder.preciseFloat = 1; } if (PyString_Check(arg)) { sarg = arg; } else if (PyUnicode_Check(arg)) { sarg = PyUnicode_AsUTF8String(arg); if (sarg == NULL) { //Exception raised above us by codec according to docs return NULL; } } else { PyErr_Format(PyExc_TypeError, "Expected String or Unicode"); return NULL; } decoder.errorStr = NULL; decoder.errorOffset = NULL; ret = JSON_DecodeObject(&decoder, PyString_AS_STRING(sarg), PyString_GET_SIZE(sarg)); if (sarg != arg) { Py_DECREF(sarg); } if (decoder.errorStr) { /* FIXME: It's possible to give a much nicer error message here with actual failing element in input etc*/ PyErr_Format (PyExc_ValueError, "%s", decoder.errorStr); if (ret) { Py_DECREF( (PyObject *) ret); } return NULL; } return ret; } PyObject* JSONFileToObj(PyObject* self, PyObject *args, PyObject *kwargs) { PyObject *read; PyObject *string; PyObject *result; PyObject *file = NULL; PyObject *argtuple; if (!PyArg_ParseTuple (args, "O", &file)) { return NULL; } if (!PyObject_HasAttrString (file, "read")) { PyErr_Format (PyExc_TypeError, "expected file"); return NULL; } read = PyObject_GetAttrString (file, "read"); if (!PyCallable_Check (read)) { Py_XDECREF(read); PyErr_Format (PyExc_TypeError, "expected file"); return NULL; } string = PyObject_CallObject (read, NULL); Py_XDECREF(read); if (string == NULL) { return NULL; } argtuple = PyTuple_Pack(1, string); result = JSONToObj (self, argtuple, kwargs); Py_XDECREF(argtuple); Py_XDECREF(string); if (result == NULL) { return NULL; } return result; } ujson-1.33/python/ujson.c0000666000175100017510000001110412155373442014466 0ustar morphmorph/* Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ESN Social Software AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved. Numeric decoder derived from from TCL library http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. */ #include "py_defines.h" #include "version.h" /* objToJSON */ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs); void initObjToJSON(void); /* JSONToObj */ PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs); /* objToJSONFile */ PyObject* objToJSONFile(PyObject* self, PyObject *args, PyObject *kwargs); /* JSONFileToObj */ PyObject* JSONFileToObj(PyObject* self, PyObject *args, PyObject *kwargs); #define ENCODER_HELP_TEXT "Use ensure_ascii=false to output UTF-8. Pass in double_precision to alter the maximum digit precision of doubles. Set encode_html_chars=True to encode < > & as unicode escape sequences." static PyMethodDef ujsonMethods[] = { {"encode", (PyCFunction) objToJSON, METH_VARARGS | METH_KEYWORDS, "Converts arbitrary object recursivly into JSON. " ENCODER_HELP_TEXT}, {"decode", (PyCFunction) JSONToObj, METH_VARARGS | METH_KEYWORDS, "Converts JSON as string to dict object structure. Use precise_float=True to use high precision float decoder."}, {"dumps", (PyCFunction) objToJSON, METH_VARARGS | METH_KEYWORDS, "Converts arbitrary object recursivly into JSON. " ENCODER_HELP_TEXT}, {"loads", (PyCFunction) JSONToObj, METH_VARARGS | METH_KEYWORDS, "Converts JSON as string to dict object structure. Use precise_float=True to use high precision float decoder."}, {"dump", (PyCFunction) objToJSONFile, METH_VARARGS | METH_KEYWORDS, "Converts arbitrary object recursively into JSON file. " ENCODER_HELP_TEXT}, {"load", (PyCFunction) JSONFileToObj, METH_VARARGS | METH_KEYWORDS, "Converts JSON as file to dict object structure. Use precise_float=True to use high precision float decoder."}, {NULL, NULL, 0, NULL} /* Sentinel */ }; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "ujson", 0, /* m_doc */ -1, /* m_size */ ujsonMethods, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ }; #define PYMODINITFUNC PyObject *PyInit_ujson(void) #define PYMODULE_CREATE() PyModule_Create(&moduledef) #define MODINITERROR return NULL #else #define PYMODINITFUNC PyMODINIT_FUNC initujson(void) #define PYMODULE_CREATE() Py_InitModule("ujson", ujsonMethods) #define MODINITERROR return #endif PYMODINITFUNC { PyObject *module; PyObject *version_string; initObjToJSON(); module = PYMODULE_CREATE(); if (module == NULL) { MODINITERROR; } version_string = PyString_FromString (UJSON_VERSION); PyModule_AddObject (module, "__version__", version_string); #if PY_MAJOR_VERSION >= 3 return module; #endif } ujson-1.33/lib/0000755000175100017510000000000012544263027012407 5ustar morphmorphujson-1.33/lib/ultrajsonenc.c0000666000175100017510000005364312155611660015277 0ustar morphmorph/* Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ESN Social Software AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved. Numeric decoder derived from from TCL library http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. */ #include "ultrajson.h" #include #include #include #include #include #include #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /* Worst cases being: Control characters (ASCII < 32) 0x00 (1 byte) input => \u0000 output (6 bytes) 1 * 6 => 6 (6 bytes required) or UTF-16 surrogate pairs 4 bytes input in UTF-8 => \uXXXX\uYYYY (12 bytes). 4 * 6 => 24 bytes (12 bytes required) The extra 2 bytes are for the quotes around the string */ #define RESERVE_STRING(_len) (2 + ((_len) * 6)) static const double g_pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000}; static const char g_hexChars[] = "0123456789abcdef"; static const char g_escapeChars[] = "0123456789\\b\\t\\n\\f\\r\\\"\\\\\\/"; /* FIXME: While this is fine dandy and working it's a magic value mess which probably only the author understands. Needs a cleanup and more documentation */ /* Table for pure ascii output escaping all characters above 127 to \uXXXX */ static const JSUINT8 g_asciiOutputTable[256] = { /* 0x00 */ 0, 30, 30, 30, 30, 30, 30, 30, 10, 12, 14, 30, 16, 18, 30, 30, /* 0x10 */ 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, /* 0x20 */ 1, 1, 20, 1, 1, 1, 29, 1, 1, 1, 1, 1, 1, 1, 1, 24, /* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 1, 29, 1, /* 0x40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 1, 1, 1, /* 0x60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xf0 */ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 }; 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 That 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; while (newSize < curSize + cbNeeded) { newSize *= 2; } if (enc->heap) { enc->start = (char *) enc->realloc (enc->start, newSize); if (!enc->start) { SetError (NULL, enc, "Could not reserve memory block"); return; } } else { char *oldStart = enc->start; enc->heap = 1; enc->start = (char *) enc->malloc (newSize); if (!enc->start) { SetError (NULL, enc, "Could not reserve memory block"); return; } memcpy (enc->start, oldStart, offset); } enc->offset = enc->start + offset; enc->end = enc->start + newSize; } FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_AppendShortHexUnchecked (char *outputOffset, unsigned short value) { *(outputOffset++) = g_hexChars[(value & 0xf000) >> 12]; *(outputOffset++) = g_hexChars[(value & 0x0f00) >> 8]; *(outputOffset++) = g_hexChars[(value & 0x00f0) >> 4]; *(outputOffset++) = g_hexChars[(value & 0x000f) >> 0]; } int Buffer_EscapeStringUnvalidated (JSONObjectEncoder *enc, const char *io, const char *end) { char *of = (char *) enc->offset; for (;;) { switch (*io) { case 0x00: { if (io < end) { *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; break; } else { enc->offset += (of - enc->offset); return TRUE; } } case '\"': (*of++) = '\\'; (*of++) = '\"'; break; case '\\': (*of++) = '\\'; (*of++) = '\\'; break; case '/': (*of++) = '\\'; (*of++) = '/'; 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 0x26: // '/' case 0x3c: // '<' case 0x3e: // '>' { if (enc->encodeHTMLChars) { // Fall through to \u00XX case below. } else { // Same as default case below. (*of++) = (*io); break; } } case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x0b: case 0x0e: case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: { *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = g_hexChars[ (unsigned char) (((*io) & 0xf0) >> 4)]; *(of++) = g_hexChars[ (unsigned char) ((*io) & 0x0f)]; break; } default: (*of++) = (*io); break; } io++; } } int Buffer_EscapeStringValidated (JSOBJ obj, JSONObjectEncoder *enc, const char *io, const char *end) { JSUTF32 ucs; char *of = (char *) enc->offset; for (;;) { JSUINT8 utflen = g_asciiOutputTable[(unsigned char) *io]; switch (utflen) { case 0: { if (io < end) { *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; *(of++) = '0'; io ++; continue; } else { enc->offset += (of - enc->offset); return TRUE; } } case 1: { *(of++)= (*io++); continue; } case 2: { JSUTF32 in; JSUTF16 in16; if (end - io < 1) { enc->offset += (of - enc->offset); SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string"); return FALSE; } memcpy(&in16, io, sizeof(JSUTF16)); in = (JSUTF32) in16; #ifdef __LITTLE_ENDIAN__ ucs = ((in & 0x1f) << 6) | ((in >> 8) & 0x3f); #else ucs = ((in & 0x1f00) >> 2) | (in & 0x3f); #endif if (ucs < 0x80) { enc->offset += (of - enc->offset); SetError (obj, enc, "Overlong 2 byte UTF-8 sequence detected when encoding string"); return FALSE; } io += 2; break; } case 3: { JSUTF32 in; JSUTF16 in16; JSUINT8 in8; if (end - io < 2) { enc->offset += (of - enc->offset); SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string"); return FALSE; } memcpy(&in16, io, sizeof(JSUTF16)); memcpy(&in8, io + 2, sizeof(JSUINT8)); #ifdef __LITTLE_ENDIAN__ in = (JSUTF32) in16; in |= in8 << 16; ucs = ((in & 0x0f) << 12) | ((in & 0x3f00) >> 2) | ((in & 0x3f0000) >> 16); #else in = in16 << 8; in |= in8; ucs = ((in & 0x0f0000) >> 4) | ((in & 0x3f00) >> 2) | (in & 0x3f); #endif 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; } case 4: { JSUTF32 in; if (end - io < 3) { enc->offset += (of - enc->offset); SetError (obj, enc, "Unterminated UTF-8 sequence when encoding string"); return FALSE; } memcpy(&in, io, sizeof(JSUTF32)); #ifdef __LITTLE_ENDIAN__ ucs = ((in & 0x07) << 18) | ((in & 0x3f00) << 4) | ((in & 0x3f0000) >> 10) | ((in & 0x3f000000) >> 24); #else ucs = ((in & 0x07000000) >> 6) | ((in & 0x3f0000) >> 4) | ((in & 0x3f00) >> 2) | (in & 0x3f); #endif if (ucs < 0x10000) { enc->offset += (of - enc->offset); SetError (obj, enc, "Overlong 4 byte UTF-8 sequence detected when encoding string"); return FALSE; } io += 4; break; } case 5: case 6: { enc->offset += (of - enc->offset); SetError (obj, enc, "Unsupported UTF-8 sequence length when encoding string"); return FALSE; } case 29: { if (enc->encodeHTMLChars) { // Fall through to \u00XX case 30 below. } else { // Same as case 1 above. *(of++) = (*io++); continue; } } case 30: { // \uXXXX encode *(of++) = '\\'; *(of++) = 'u'; *(of++) = '0'; *(of++) = '0'; *(of++) = g_hexChars[ (unsigned char) (((*io) & 0xf0) >> 4)]; *(of++) = g_hexChars[ (unsigned char) ((*io) & 0x0f)]; io ++; continue; } case 10: case 12: case 14: case 16: case 18: case 20: case 22: case 24: { *(of++) = *( (char *) (g_escapeChars + utflen + 0)); *(of++) = *( (char *) (g_escapeChars + utflen + 1)); io ++; continue; } // This can never happen, it's here to make L4 VC++ happy default: { ucs = 0; break; } } /* 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, (unsigned short) (ucs >> 10) + 0xd800); of += 4; *(of++) = '\\'; *(of++) = 'u'; Buffer_AppendShortHexUnchecked(of, (unsigned short) (ucs & 0x3ff) + 0xdc00); of += 4; } else { *(of++) = '\\'; *(of++) = 'u'; Buffer_AppendShortHexUnchecked(of, (unsigned short) ucs); of += 4; } } } #define Buffer_Reserve(__enc, __len) \ if ( (size_t) ((__enc)->end - (__enc)->offset) < (size_t) (__len)) \ { \ Buffer_Realloc((__enc), (__len));\ } \ #define Buffer_AppendCharUnchecked(__enc, __chr) \ *((__enc)->offset++) = __chr; \ FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC strreverse(char* begin, char* end) { char aux; while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux; } void Buffer_AppendIntUnchecked(JSONObjectEncoder *enc, JSINT32 value) { char* wstr; JSUINT32 uvalue = (value < 0) ? -value : value; wstr = enc->offset; // Conversion. Number is reversed. do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10); if (value < 0) *wstr++ = '-'; // Reverse string strreverse(enc->offset,wstr - 1); enc->offset += (wstr - (enc->offset)); } void Buffer_AppendLongUnchecked(JSONObjectEncoder *enc, JSINT64 value) { char* wstr; JSUINT64 uvalue = (value < 0) ? -value : value; wstr = enc->offset; // Conversion. Number is reversed. do *wstr++ = (char)(48 + (uvalue % 10ULL)); while(uvalue /= 10ULL); if (value < 0) *wstr++ = '-'; // Reverse string strreverse(enc->offset,wstr - 1); enc->offset += (wstr - (enc->offset)); } int Buffer_AppendDoubleUnchecked(JSOBJ obj, JSONObjectEncoder *enc, double value) { /* if input is larger than thres_max, revert to exponential */ const double thres_max = (double) 1e16 - 1; int count; double diff = 0.0; char* str = enc->offset; char* wstr = str; unsigned long long whole; double tmp; unsigned long long frac; int neg; double pow10; if (value == HUGE_VAL || value == -HUGE_VAL) { SetError (obj, enc, "Invalid Inf value when encoding double"); return FALSE; } if (!(value == value)) { SetError (obj, enc, "Invalid Nan value when encoding double"); return FALSE; } /* we'll work in positive values and deal with the negative sign issue later */ neg = 0; if (value < 0) { neg = 1; value = -value; } pow10 = g_pow10[enc->doublePrecision]; whole = (unsigned long long) value; tmp = (value - whole) * pow10; frac = (unsigned long long)(tmp); diff = tmp - frac; if (diff > 0.5) { ++frac; /* handle rollover, e.g. case 0.99 with prec 1 is 1.0 */ if (frac >= pow10) { frac = 0; ++whole; } } else if (diff == 0.5 && ((frac == 0) || (frac & 1))) { /* if halfway, round up if odd, OR if last digit is 0. That last part is strange */ ++frac; } /* for very large numbers switch back to native sprintf for exponentials. anyone want to write code to replace this? */ /* normal printf behavior is to print EVERY whole number digit which can be 100s of characters overflowing your buffers == bad */ if (value > thres_max) { #ifdef _WIN32 enc->offset += sprintf_s(str, enc->end - enc->offset, "%.15e", neg ? -value : value); #else enc->offset += snprintf(str, enc->end - enc->offset, "%.15e", neg ? -value : value); #endif return TRUE; } if (enc->doublePrecision == 0) { diff = value - whole; if (diff > 0.5) { /* greater than 0.5, round up, e.g. 1.6 -> 2 */ ++whole; } else if (diff == 0.5 && (whole & 1)) { /* exactly 0.5 and ODD, then round up */ /* 1.5 -> 2, but 2.5 -> 2 */ ++whole; } //vvvvvvvvvvvvvvvvvvv Diff from modp_dto2 } else if (frac) { count = enc->doublePrecision; // now do fractional part, as an unsigned number // we know it is not 0 but we can have leading zeros, these // should be removed while (!(frac % 10)) { --count; frac /= 10; } //^^^^^^^^^^^^^^^^^^^ Diff from modp_dto2 // now do fractional part, as an unsigned number do { --count; *wstr++ = (char)(48 + (frac % 10)); } while (frac /= 10); // add extra 0s while (count-- > 0) { *wstr++ = '0'; } // add decimal *wstr++ = '.'; } else { *wstr++ = '0'; *wstr++ = '.'; } // do whole part // Take care of sign // Conversion. Number is reversed. do *wstr++ = (char)(48 + (whole % 10)); while (whole /= 10); if (neg) { *wstr++ = '-'; } strreverse(str, wstr-1); enc->offset += (wstr - (enc->offset)); return TRUE; } /* FIXME: Handle integration functions returning NULL here */ /* FIXME: Perhaps implement recursion detection */ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName) { const char *value; char *objName; int count; JSOBJ iterObj; size_t szlen; JSONTypeContext tc; if (enc->level > enc->recursionMax) { SetError (obj, enc, "Maximum recursion level reached"); return; } /* This reservation must hold length of _name as encoded worst case + maxLength of double to string OR maxLength of JSLONG to string */ Buffer_Reserve(enc, 256 + RESERVE_STRING(cbName)); if (enc->errorMsg) { return; } if (name) { Buffer_AppendCharUnchecked(enc, '\"'); if (enc->forceASCII) { if (!Buffer_EscapeStringValidated(obj, enc, name, name + cbName)) { return; } } else { if (!Buffer_EscapeStringUnvalidated(enc, name, name + cbName)) { return; } } Buffer_AppendCharUnchecked(enc, '\"'); Buffer_AppendCharUnchecked (enc, ':'); #ifndef JSON_NO_EXTRA_WHITESPACE Buffer_AppendCharUnchecked (enc, ' '); #endif } enc->beginTypeContext(obj, &tc); switch (tc.type) { case JT_INVALID: { return; } case JT_ARRAY: { count = 0; enc->iterBegin(obj, &tc); Buffer_AppendCharUnchecked (enc, '['); while (enc->iterNext(obj, &tc)) { if (count > 0) { Buffer_AppendCharUnchecked (enc, ','); #ifndef JSON_NO_EXTRA_WHITESPACE Buffer_AppendCharUnchecked (buffer, ' '); #endif } iterObj = enc->iterGetValue(obj, &tc); enc->level ++; encode (iterObj, enc, NULL, 0); count ++; } enc->iterEnd(obj, &tc); Buffer_AppendCharUnchecked (enc, ']'); break; } case JT_OBJECT: { count = 0; enc->iterBegin(obj, &tc); Buffer_AppendCharUnchecked (enc, '{'); while (enc->iterNext(obj, &tc)) { if (count > 0) { Buffer_AppendCharUnchecked (enc, ','); #ifndef JSON_NO_EXTRA_WHITESPACE Buffer_AppendCharUnchecked (enc, ' '); #endif } iterObj = enc->iterGetValue(obj, &tc); objName = enc->iterGetName(obj, &tc, &szlen); enc->level ++; encode (iterObj, enc, objName, szlen); count ++; } enc->iterEnd(obj, &tc); Buffer_AppendCharUnchecked (enc, '}'); break; } case JT_LONG: { Buffer_AppendLongUnchecked (enc, enc->getLongValue(obj, &tc)); break; } case JT_INT: { Buffer_AppendIntUnchecked (enc, enc->getIntValue(obj, &tc)); break; } case JT_TRUE: { Buffer_AppendCharUnchecked (enc, 't'); Buffer_AppendCharUnchecked (enc, 'r'); Buffer_AppendCharUnchecked (enc, 'u'); Buffer_AppendCharUnchecked (enc, 'e'); break; } case JT_FALSE: { Buffer_AppendCharUnchecked (enc, 'f'); Buffer_AppendCharUnchecked (enc, 'a'); Buffer_AppendCharUnchecked (enc, 'l'); Buffer_AppendCharUnchecked (enc, 's'); Buffer_AppendCharUnchecked (enc, 'e'); break; } case JT_NULL: { Buffer_AppendCharUnchecked (enc, 'n'); Buffer_AppendCharUnchecked (enc, 'u'); Buffer_AppendCharUnchecked (enc, 'l'); Buffer_AppendCharUnchecked (enc, 'l'); break; } case JT_DOUBLE: { if (!Buffer_AppendDoubleUnchecked (obj, enc, enc->getDoubleValue(obj, &tc))) { enc->endTypeContext(obj, &tc); enc->level --; return; } break; } case JT_UTF8: { value = enc->getStringValue(obj, &tc, &szlen); Buffer_Reserve(enc, RESERVE_STRING(szlen)); if (enc->errorMsg) { enc->endTypeContext(obj, &tc); return; } Buffer_AppendCharUnchecked (enc, '\"'); if (enc->forceASCII) { if (!Buffer_EscapeStringValidated(obj, enc, value, value + szlen)) { enc->endTypeContext(obj, &tc); enc->level --; return; } } else { if (!Buffer_EscapeStringUnvalidated(enc, value, value + szlen)) { enc->endTypeContext(obj, &tc); enc->level --; return; } } Buffer_AppendCharUnchecked (enc, '\"'); break; } } enc->endTypeContext(obj, &tc); enc->level --; } char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char *_buffer, size_t _cbBuffer) { enc->malloc = enc->malloc ? enc->malloc : malloc; enc->free = enc->free ? enc->free : free; enc->realloc = enc->realloc ? enc->realloc : realloc; enc->errorMsg = NULL; enc->errorObj = NULL; enc->level = 0; if (enc->recursionMax < 1) { enc->recursionMax = JSON_MAX_RECURSION_DEPTH; } if (enc->doublePrecision < 0 || enc->doublePrecision > JSON_DOUBLE_MAX_DECIMALS) { enc->doublePrecision = JSON_DOUBLE_MAX_DECIMALS; } if (_buffer == NULL) { _cbBuffer = 32768; enc->start = (char *) enc->malloc (_cbBuffer); if (!enc->start) { SetError(obj, enc, "Could not reserve memory block"); return NULL; } enc->heap = 1; } else { enc->start = _buffer; enc->heap = 0; } enc->end = enc->start + _cbBuffer; enc->offset = enc->start; encode (obj, enc, NULL, 0); Buffer_Reserve(enc, 1); if (enc->errorMsg) { return NULL; } Buffer_AppendCharUnchecked(enc, '\0'); return enc->start; } ujson-1.33/lib/ultrajsondec.c0000666000175100017510000005247112155377624015274 0ustar morphmorph/* Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ESN Social Software AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved. Numeric decoder derived from from TCL library http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. */ #include "ultrajson.h" #include #include #include #include #include #include #include #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef NULL #define NULL 0 #endif struct DecoderState { char *start; char *end; wchar_t *escStart; wchar_t *escEnd; int escHeap; int lastType; JSUINT32 objDepth; void *prv; JSONObjectDecoder *dec; }; JSOBJ FASTCALL_MSVC decode_any( struct DecoderState *ds) FASTCALL_ATTR; typedef JSOBJ (*PFN_DECODER)( struct DecoderState *ds); static JSOBJ SetError( struct DecoderState *ds, int offset, const char *message) { ds->dec->errorOffset = ds->start + offset; ds->dec->errorStr = (char *) message; return NULL; } static void ClearError( struct DecoderState *ds) { ds->dec->errorOffset = 0; ds->dec->errorStr = NULL; } double createDouble(double intNeg, double intValue, double frcValue, int frcDecimalCount) { static const double g_pow10[] = {1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001,0.0000001, 0.00000001, 0.000000001, 0.0000000001, 0.00000000001, 0.000000000001, 0.0000000000001, 0.00000000000001, 0.000000000000001}; return (intValue + (frcValue * g_pow10[frcDecimalCount])) * intNeg; } FASTCALL_ATTR JSOBJ FASTCALL_MSVC decodePreciseFloat(struct DecoderState *ds) { char *end; double value; errno = 0; value = strtod(ds->start, &end); if (errno == ERANGE) { return SetError(ds, -1, "Range error when decoding numeric as double"); } ds->start = end; return ds->dec->newDouble(ds->prv, value); } FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_numeric (struct DecoderState *ds) { int intNeg = 1; int mantSize = 0; JSUINT64 intValue; int chr; int decimalCount = 0; double frcValue = 0.0; double expNeg; double expValue; char *offset = ds->start; JSUINT64 overflowLimit = LLONG_MAX; if (*(offset) == '-') { offset ++; intNeg = -1; overflowLimit = LLONG_MIN; } // Scan integer part intValue = 0; while (1) { chr = (int) (unsigned char) *(offset); switch (chr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { //FIXME: Check for arithemtic overflow here //PERF: Don't do 64-bit arithmetic here unless we know we have to intValue = intValue * 10ULL + (JSLONG) (chr - 48); if (intValue > overflowLimit) { return SetError(ds, -1, overflowLimit == LLONG_MAX ? "Value is too big" : "Value is too small"); } offset ++; mantSize ++; break; } case '.': { offset ++; goto DECODE_FRACTION; break; } case 'e': case 'E': { offset ++; goto DECODE_EXPONENT; break; } default: { goto BREAK_INT_LOOP; break; } } } BREAK_INT_LOOP: ds->lastType = JT_INT; ds->start = offset; if ((intValue >> 31)) { return ds->dec->newLong(ds->prv, (JSINT64) (intValue * (JSINT64) intNeg)); } else { return ds->dec->newInt(ds->prv, (JSINT32) (intValue * intNeg)); } DECODE_FRACTION: if (ds->dec->preciseFloat) { return decodePreciseFloat(ds); } // Scan fraction part frcValue = 0.0; for (;;) { chr = (int) (unsigned char) *(offset); switch (chr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { if (decimalCount < JSON_DOUBLE_MAX_DECIMALS) { frcValue = frcValue * 10.0 + (double) (chr - 48); decimalCount ++; } offset ++; break; } case 'e': case 'E': { offset ++; goto DECODE_EXPONENT; break; } default: { goto BREAK_FRC_LOOP; } } } BREAK_FRC_LOOP: //FIXME: Check for arithemtic overflow here ds->lastType = JT_DOUBLE; ds->start = offset; return ds->dec->newDouble (ds->prv, createDouble( (double) intNeg, (double) intValue, frcValue, decimalCount)); DECODE_EXPONENT: if (ds->dec->preciseFloat) { return decodePreciseFloat(ds); } expNeg = 1.0; if (*(offset) == '-') { expNeg = -1.0; offset ++; } else if (*(offset) == '+') { expNeg = +1.0; offset ++; } expValue = 0.0; for (;;) { chr = (int) (unsigned char) *(offset); switch (chr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { expValue = expValue * 10.0 + (double) (chr - 48); offset ++; break; } default: { goto BREAK_EXP_LOOP; } } } BREAK_EXP_LOOP: //FIXME: Check for arithemtic overflow here ds->lastType = JT_DOUBLE; ds->start = offset; return ds->dec->newDouble (ds->prv, createDouble( (double) intNeg, (double) intValue , frcValue, decimalCount) * pow(10.0, expValue * expNeg)); } FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_true ( struct DecoderState *ds) { char *offset = ds->start; offset ++; if (*(offset++) != 'r') goto SETERROR; if (*(offset++) != 'u') goto SETERROR; if (*(offset++) != 'e') goto SETERROR; ds->lastType = JT_TRUE; ds->start = offset; return ds->dec->newTrue(ds->prv); SETERROR: return SetError(ds, -1, "Unexpected character found when decoding 'true'"); } FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_false ( struct DecoderState *ds) { char *offset = ds->start; offset ++; if (*(offset++) != 'a') goto SETERROR; if (*(offset++) != 'l') goto SETERROR; if (*(offset++) != 's') goto SETERROR; if (*(offset++) != 'e') goto SETERROR; ds->lastType = JT_FALSE; ds->start = offset; return ds->dec->newFalse(ds->prv); SETERROR: return SetError(ds, -1, "Unexpected character found when decoding 'false'"); } FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_null ( struct DecoderState *ds) { char *offset = ds->start; offset ++; if (*(offset++) != 'u') goto SETERROR; if (*(offset++) != 'l') goto SETERROR; if (*(offset++) != 'l') goto SETERROR; ds->lastType = JT_NULL; ds->start = offset; return ds->dec->newNull(ds->prv); SETERROR: return SetError(ds, -1, "Unexpected character found when decoding 'null'"); } FASTCALL_ATTR void FASTCALL_MSVC SkipWhitespace(struct DecoderState *ds) { char *offset = ds->start; for (;;) { switch (*offset) { case ' ': case '\t': case '\r': case '\n': offset ++; break; default: ds->start = offset; return; } } } enum DECODESTRINGSTATE { DS_ISNULL = 0x32, DS_ISQUOTE, DS_ISESCAPE, DS_UTFLENERROR, }; static const JSUINT8 g_decoderLookup[256] = { /* 0x00 */ DS_ISNULL, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x20 */ 1, 1, DS_ISQUOTE, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, DS_ISESCAPE, 1, 1, 1, /* 0x60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xc0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xe0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xf0 */ 4, 4, 4, 4, 4, 4, 4, 4, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, DS_UTFLENERROR, }; FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_string ( struct DecoderState *ds) { JSUTF16 sur[2] = { 0 }; int iSur = 0; int index; wchar_t *escOffset; wchar_t *escStart; size_t escLen = (ds->escEnd - ds->escStart); JSUINT8 *inputOffset; JSUINT8 oct; JSUTF32 ucs; ds->lastType = JT_INVALID; ds->start ++; if ( (size_t) (ds->end - ds->start) > escLen) { size_t newSize = (ds->end - ds->start); if (ds->escHeap) { if (newSize > (UINT_MAX / sizeof(wchar_t))) { return SetError(ds, -1, "Could not reserve memory block"); } escStart = (wchar_t *)ds->dec->realloc(ds->escStart, newSize * sizeof(wchar_t)); if (!escStart) { ds->dec->free(ds->escStart); return SetError(ds, -1, "Could not reserve memory block"); } ds->escStart = escStart; } else { wchar_t *oldStart = ds->escStart; ds->escHeap = 1; if (newSize > (UINT_MAX / sizeof(wchar_t))) { return SetError(ds, -1, "Could not reserve memory block"); } ds->escStart = (wchar_t *) ds->dec->malloc(newSize * sizeof(wchar_t)); if (!ds->escStart) { return SetError(ds, -1, "Could not reserve memory block"); } memcpy(ds->escStart, oldStart, escLen * sizeof(wchar_t)); } ds->escEnd = ds->escStart + newSize; } escOffset = ds->escStart; inputOffset = (JSUINT8 *) ds->start; for (;;) { switch (g_decoderLookup[(JSUINT8)(*inputOffset)]) { case DS_ISNULL: { return SetError(ds, -1, "Unmatched ''\"' when when decoding 'string'"); } case DS_ISQUOTE: { ds->lastType = JT_UTF8; inputOffset ++; ds->start += ( (char *) inputOffset - (ds->start)); return ds->dec->newString(ds->prv, ds->escStart, escOffset); } case DS_UTFLENERROR: { return SetError (ds, -1, "Invalid UTF-8 sequence length when decoding 'string'"); } case DS_ISESCAPE: inputOffset ++; switch (*inputOffset) { case '\\': *(escOffset++) = L'\\'; inputOffset++; continue; case '\"': *(escOffset++) = L'\"'; inputOffset++; continue; case '/': *(escOffset++) = L'/'; inputOffset++; continue; case 'b': *(escOffset++) = L'\b'; inputOffset++; continue; case 'f': *(escOffset++) = L'\f'; inputOffset++; continue; case 'n': *(escOffset++) = L'\n'; inputOffset++; continue; case 'r': *(escOffset++) = L'\r'; inputOffset++; continue; case 't': *(escOffset++) = L'\t'; inputOffset++; continue; case 'u': { int index; inputOffset ++; for (index = 0; index < 4; index ++) { switch (*inputOffset) { case '\0': return SetError (ds, -1, "Unterminated unicode escape sequence when decoding 'string'"); default: return SetError (ds, -1, "Unexpected character in unicode escape sequence when decoding 'string'"); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': sur[iSur] = (sur[iSur] << 4) + (JSUTF16) (*inputOffset - '0'); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': sur[iSur] = (sur[iSur] << 4) + 10 + (JSUTF16) (*inputOffset - 'a'); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': sur[iSur] = (sur[iSur] << 4) + 10 + (JSUTF16) (*inputOffset - 'A'); break; } inputOffset ++; } if (iSur == 0) { if((sur[iSur] & 0xfc00) == 0xd800) { // First of a surrogate pair, continue parsing iSur ++; break; } (*escOffset++) = (wchar_t) sur[iSur]; iSur = 0; } else { // Decode pair if ((sur[1] & 0xfc00) != 0xdc00) { return SetError (ds, -1, "Unpaired high surrogate when decoding 'string'"); } #if WCHAR_MAX == 0xffff (*escOffset++) = (wchar_t) sur[0]; (*escOffset++) = (wchar_t) sur[1]; #else (*escOffset++) = (wchar_t) 0x10000 + (((sur[0] - 0xd800) << 10) | (sur[1] - 0xdc00)); #endif iSur = 0; } break; } case '\0': return SetError(ds, -1, "Unterminated escape sequence when decoding 'string'"); default: return SetError(ds, -1, "Unrecognized escape sequence when decoding 'string'"); } break; case 1: { *(escOffset++) = (wchar_t) (*inputOffset++); break; } case 2: { ucs = (*inputOffset++) & 0x1f; ucs <<= 6; if (((*inputOffset) & 0x80) != 0x80) { return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'"); } ucs |= (*inputOffset++) & 0x3f; if (ucs < 0x80) return SetError (ds, -1, "Overlong 2 byte UTF-8 sequence detected when decoding 'string'"); *(escOffset++) = (wchar_t) ucs; break; } case 3: { JSUTF32 ucs = 0; ucs |= (*inputOffset++) & 0x0f; for (index = 0; index < 2; index ++) { ucs <<= 6; oct = (*inputOffset++); if ((oct & 0x80) != 0x80) { return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'"); } ucs |= oct & 0x3f; } if (ucs < 0x800) return SetError (ds, -1, "Overlong 3 byte UTF-8 sequence detected when encoding string"); *(escOffset++) = (wchar_t) ucs; break; } case 4: { JSUTF32 ucs = 0; ucs |= (*inputOffset++) & 0x07; for (index = 0; index < 3; index ++) { ucs <<= 6; oct = (*inputOffset++); if ((oct & 0x80) != 0x80) { return SetError(ds, -1, "Invalid octet in UTF-8 sequence when decoding 'string'"); } ucs |= oct & 0x3f; } if (ucs < 0x10000) return SetError (ds, -1, "Overlong 4 byte UTF-8 sequence detected when decoding 'string'"); #if WCHAR_MAX == 0xffff if (ucs >= 0x10000) { ucs -= 0x10000; *(escOffset++) = (wchar_t) (ucs >> 10) + 0xd800; *(escOffset++) = (wchar_t) (ucs & 0x3ff) + 0xdc00; } else { *(escOffset++) = (wchar_t) ucs; } #else *(escOffset++) = (wchar_t) ucs; #endif break; } } } } FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_array(struct DecoderState *ds) { JSOBJ itemValue; JSOBJ newObj; int len; ds->objDepth++; if (ds->objDepth > JSON_MAX_OBJECT_DEPTH) { return SetError(ds, -1, "Reached object decoding depth limit"); } newObj = ds->dec->newArray(ds->prv); len = 0; ds->lastType = JT_INVALID; ds->start ++; for (;;) { SkipWhitespace(ds); if ((*ds->start) == ']') { ds->objDepth--; if (len == 0) { ds->start ++; return newObj; } ds->dec->releaseObject(ds->prv, newObj); return SetError(ds, -1, "Unexpected character found when decoding array value (1)"); } itemValue = decode_any(ds); if (itemValue == NULL) { ds->dec->releaseObject(ds->prv, newObj); return NULL; } ds->dec->arrayAddItem (ds->prv, newObj, itemValue); SkipWhitespace(ds); switch (*(ds->start++)) { case ']': { ds->objDepth--; return newObj; } case ',': break; default: ds->dec->releaseObject(ds->prv, newObj); return SetError(ds, -1, "Unexpected character found when decoding array value (2)"); } len ++; } } FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds) { JSOBJ itemName; JSOBJ itemValue; JSOBJ newObj; ds->objDepth++; if (ds->objDepth > JSON_MAX_OBJECT_DEPTH) { return SetError(ds, -1, "Reached object decoding depth limit"); } newObj = ds->dec->newObject(ds->prv); ds->start ++; for (;;) { SkipWhitespace(ds); if ((*ds->start) == '}') { ds->objDepth--; ds->start ++; return newObj; } ds->lastType = JT_INVALID; itemName = decode_any(ds); if (itemName == NULL) { ds->dec->releaseObject(ds->prv, newObj); return NULL; } if (ds->lastType != JT_UTF8) { ds->dec->releaseObject(ds->prv, newObj); ds->dec->releaseObject(ds->prv, itemName); return SetError(ds, -1, "Key name of object must be 'string' when decoding 'object'"); } SkipWhitespace(ds); if (*(ds->start++) != ':') { ds->dec->releaseObject(ds->prv, newObj); ds->dec->releaseObject(ds->prv, itemName); return SetError(ds, -1, "No ':' found when decoding object value"); } SkipWhitespace(ds); itemValue = decode_any(ds); if (itemValue == NULL) { ds->dec->releaseObject(ds->prv, newObj); ds->dec->releaseObject(ds->prv, itemName); return NULL; } ds->dec->objectAddKey (ds->prv, newObj, itemName, itemValue); SkipWhitespace(ds); switch (*(ds->start++)) { case '}': { ds->objDepth--; return newObj; } case ',': break; default: ds->dec->releaseObject(ds->prv, newObj); return SetError(ds, -1, "Unexpected character in found when decoding object value"); } } } FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_any(struct DecoderState *ds) { for (;;) { switch (*ds->start) { case '\"': return decode_string (ds); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': return decode_numeric (ds); case '[': return decode_array (ds); case '{': return decode_object (ds); case 't': return decode_true (ds); case 'f': return decode_false (ds); case 'n': return decode_null (ds); case ' ': case '\t': case '\r': case '\n': // White space ds->start ++; break; default: return SetError(ds, -1, "Expected object or value"); } } } JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuffer) { /* FIXME: Base the size of escBuffer of that of cbBuffer so that the unicode escaping doesn't run into the wall each time */ struct DecoderState ds; wchar_t escBuffer[(JSON_MAX_STACK_BUFFER_SIZE / sizeof(wchar_t))]; JSOBJ ret; ds.start = (char *) buffer; ds.end = ds.start + cbBuffer; ds.escStart = escBuffer; ds.escEnd = ds.escStart + (JSON_MAX_STACK_BUFFER_SIZE / sizeof(wchar_t)); ds.escHeap = 0; ds.prv = dec->prv; ds.dec = dec; ds.dec->errorStr = NULL; ds.dec->errorOffset = NULL; ds.objDepth = 0; ds.dec = dec; ret = decode_any (&ds); if (ds.escHeap) { dec->free(ds.escStart); } SkipWhitespace(&ds); if (ds.start != ds.end && ret) { dec->releaseObject(ds.prv, ret); return SetError(&ds, -1, "Trailing data"); } return ret; } ujson-1.33/lib/ultrajson.h0000666000175100017510000002246212155377446014624 0ustar morphmorph/* Copyright (c) 2011-2013, ESN Social Software AB and Jonas Tarnstrom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ESN Social Software AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESN SOCIAL SOFTWARE AB OR JONAS TARNSTROM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc) http://code.google.com/p/stringencoders/ Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved. Numeric decoder derived from from TCL library http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. */ /* Ultra fast JSON encoder and decoder Developed by Jonas Tarnstrom (jonas@esn.me). Encoder notes: ------------------ :: Cyclic references :: Cyclic referenced objects are not detected. Set JSONObjectEncoder.recursionMax to suitable value or make sure input object tree doesn't have cyclic references. */ #ifndef __ULTRAJSON_H__ #define __ULTRAJSON_H__ #include #include // Don't output any extra whitespaces when encoding #define JSON_NO_EXTRA_WHITESPACE // Max decimals to encode double floating point numbers with #ifndef JSON_DOUBLE_MAX_DECIMALS #define JSON_DOUBLE_MAX_DECIMALS 15 #endif // Max recursion depth, default for encoder #ifndef JSON_MAX_RECURSION_DEPTH #define JSON_MAX_RECURSION_DEPTH 1024 #endif // Max recursion depth, default for decoder #ifndef JSON_MAX_OBJECT_DEPTH #define JSON_MAX_OBJECT_DEPTH 1024 #endif /* Dictates and limits how much stack space for buffers UltraJSON will use before resorting to provided heap functions */ #ifndef JSON_MAX_STACK_BUFFER_SIZE #define JSON_MAX_STACK_BUFFER_SIZE 131072 #endif #ifdef _WIN32 typedef __int64 JSINT64; typedef unsigned __int64 JSUINT64; typedef __int32 JSINT32; typedef unsigned __int32 JSUINT32; typedef unsigned __int8 JSUINT8; typedef unsigned __int16 JSUTF16; typedef unsigned __int32 JSUTF32; typedef __int64 JSLONG; #define EXPORTFUNCTION __declspec(dllexport) #define FASTCALL_MSVC __fastcall #define FASTCALL_ATTR #define INLINE_PREFIX __inline #else #include typedef int64_t JSINT64; typedef uint64_t JSUINT64; typedef int32_t JSINT32; typedef uint32_t JSUINT32; #define FASTCALL_MSVC #if !defined __x86_64__ #define FASTCALL_ATTR __attribute__((fastcall)) #else #define FASTCALL_ATTR #endif #define INLINE_PREFIX inline typedef uint8_t JSUINT8; typedef uint16_t JSUTF16; typedef uint32_t JSUTF32; typedef int64_t JSLONG; #define EXPORTFUNCTION #endif #if !(defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__)) #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define __LITTLE_ENDIAN__ #else #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define __BIG_ENDIAN__ #endif #endif #endif #if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) #error "Endianess not supported" #endif enum JSTYPES { JT_NULL, // NULL JT_TRUE, //boolean true JT_FALSE, //boolean false JT_INT, //(JSINT32 (signed 32-bit)) JT_LONG, //(JSINT64 (signed 64-bit)) JT_DOUBLE, //(double) JT_UTF8, //(char 8-bit) JT_ARRAY, // Array structure JT_OBJECT, // Key/Value structure JT_INVALID, // Internal, do not return nor expect }; typedef void * JSOBJ; typedef void * JSITER; typedef struct __JSONTypeContext { int type; void *prv; } JSONTypeContext; /* Function pointer declarations, suitable for implementing UltraJSON */ typedef void (*JSPFN_ITERBEGIN)(JSOBJ obj, JSONTypeContext *tc); typedef int (*JSPFN_ITERNEXT)(JSOBJ obj, JSONTypeContext *tc); typedef void (*JSPFN_ITEREND)(JSOBJ obj, JSONTypeContext *tc); typedef JSOBJ (*JSPFN_ITERGETVALUE)(JSOBJ obj, JSONTypeContext *tc); typedef char *(*JSPFN_ITERGETNAME)(JSOBJ obj, JSONTypeContext *tc, size_t *outLen); typedef void *(*JSPFN_MALLOC)(size_t size); typedef void (*JSPFN_FREE)(void *pptr); typedef void *(*JSPFN_REALLOC)(void *base, size_t size); typedef struct __JSONObjectEncoder { void (*beginTypeContext)(JSOBJ obj, JSONTypeContext *tc); void (*endTypeContext)(JSOBJ obj, JSONTypeContext *tc); const char *(*getStringValue)(JSOBJ obj, JSONTypeContext *tc, size_t *_outLen); JSINT64 (*getLongValue)(JSOBJ obj, JSONTypeContext *tc); JSINT32 (*getIntValue)(JSOBJ obj, JSONTypeContext *tc); double (*getDoubleValue)(JSOBJ obj, JSONTypeContext *tc); /* Begin iteration of an iteratable object (JS_ARRAY or JS_OBJECT) Implementor should setup iteration state in ti->prv */ JSPFN_ITERBEGIN iterBegin; /* Retrieve next object in an iteration. Should return 0 to indicate iteration has reached end or 1 if there are more items. Implementor is responsible for keeping state of the iteration. Use ti->prv fields for this */ JSPFN_ITERNEXT iterNext; /* Ends the iteration of an iteratable object. Any iteration state stored in ti->prv can be freed here */ JSPFN_ITEREND iterEnd; /* Returns a reference to the value object of an iterator The is responsible for the life-cycle of the returned string. Use iterNext/iterEnd and ti->prv to keep track of current object */ JSPFN_ITERGETVALUE iterGetValue; /* Return name of iterator. The is responsible for the life-cycle of the returned string. Use iterNext/iterEnd and ti->prv to keep track of current object */ JSPFN_ITERGETNAME iterGetName; /* Release a value as indicated by setting ti->release = 1 in the previous getValue call. The ti->prv array should contain the necessary context to release the value */ void (*releaseObject)(JSOBJ obj); /* Library functions Set to NULL to use STDLIB malloc,realloc,free */ JSPFN_MALLOC malloc; JSPFN_REALLOC realloc; JSPFN_FREE free; /* Configuration for max recursion, set to 0 to use default (see JSON_MAX_RECURSION_DEPTH)*/ int recursionMax; /* Configuration for max decimals of double floating poiunt numbers to encode (0-9) */ int doublePrecision; /* If true output will be ASCII with all characters above 127 encoded as \uXXXX. If false output will be UTF-8 or what ever charset strings are brought as */ int forceASCII; /* If true, '<', '>', and '&' characters will be encoded as \u003c, \u003e, and \u0026, respectively. If false, no special encoding will be used. */ int encodeHTMLChars; /* Set to an error message if error occured */ const char *errorMsg; JSOBJ errorObj; /* Buffer stuff */ char *start; char *offset; char *end; int heap; int level; } JSONObjectEncoder; /* Encode an object structure into JSON. Arguments: obj - An anonymous type representing the object enc - Function definitions for querying JSOBJ type buffer - Preallocated buffer to store result in. If NULL function allocates own buffer cbBuffer - Length of buffer (ignored if buffer is NULL) Returns: Encoded JSON object as a null terminated char string. NOTE: If the supplied buffer wasn't enough to hold the result the function will allocate a new buffer. Life cycle of the provided buffer must still be handled by caller. If the return value doesn't equal the specified buffer caller must release the memory using JSONObjectEncoder.free or free() as specified when calling this function. */ EXPORTFUNCTION char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char *buffer, size_t cbBuffer); typedef struct __JSONObjectDecoder { JSOBJ (*newString)(void *prv, wchar_t *start, wchar_t *end); void (*objectAddKey)(void *prv, JSOBJ obj, JSOBJ name, JSOBJ value); void (*arrayAddItem)(void *prv, JSOBJ obj, JSOBJ value); JSOBJ (*newTrue)(void *prv); JSOBJ (*newFalse)(void *prv); JSOBJ (*newNull)(void *prv); JSOBJ (*newObject)(void *prv); JSOBJ (*newArray)(void *prv); JSOBJ (*newInt)(void *prv, JSINT32 value); JSOBJ (*newLong)(void *prv, JSINT64 value); JSOBJ (*newDouble)(void *prv, double value); void (*releaseObject)(void *prv, JSOBJ obj); JSPFN_MALLOC malloc; JSPFN_FREE free; JSPFN_REALLOC realloc; char *errorStr; char *errorOffset; int preciseFloat; void *prv; } JSONObjectDecoder; EXPORTFUNCTION JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuffer); #endif ujson-1.33/PKG-INFO0000666000175100017510000002601512155614640012745 0ustar morphmorphMetadata-Version: 1.0 Name: ujson Version: 1.33 Summary: Ultra fast JSON encoder and decoder for Python Home-page: http://www.esn.me Author: Jonas Tarnstrom Author-email: jonas.tarnstrom@esn.me License: BSD License Download-URL: http://github.com/esnme/ultrajson Description: UltraJSON ============= UltraJSON is an ultra fast JSON encoder and decoder written in pure C with bindings for Python 2.5+ and 3. For a more painless day to day C/C++ JSON decoder experience please checkout ujson4c_, based on UltraJSON. .. _ujson4c: http://github.com/esnme/ujson4c/ | Please checkout the rest of the projects in the Ultra series: | http://github.com/esnme/ultramemcache | http://github.com/esnme/ultramysql To install it just run Pip as usual:: $ pip install ujson ============ Usage ============ May be used as a drop in replacement for most other JSON parsers for Python:: >>> import ujson >>> ujson.dumps([{"key": "value"}, 81, True]) '[{"key":"value"},81,true]' >>> ujson.loads("""[{"key": "value"}, 81, true]""") [{u'key': u'value'}, 81, True] ~~~~~~~~~~~~~~~ Encoder options ~~~~~~~~~~~~~~~ encode_html_chars ----------------- Used to enable special encoding of "unsafe" HTML characters into safer Unicode sequences. Default is false:: >>> ujson.dumps(" &" not_html_encoded = '"A string \\\\ \\/ \\b \\f \\n \\r \\t <\\/script> &"' html_encoded = '"A string \\\\ \\/ \\b \\f \\n \\r \\t \\u003c\\/script\\u003e \\u0026"' def helper(expected_output, **encode_kwargs): output = ujson.encode(input, **encode_kwargs) self.assertEquals(input, json.loads(output)) self.assertEquals(output, expected_output) self.assertEquals(input, ujson.decode(output)) # Default behavior assumes encode_html_chars=False. helper(not_html_encoded, ensure_ascii=True) helper(not_html_encoded, ensure_ascii=False) # Make sure explicit encode_html_chars=False works. helper(not_html_encoded, ensure_ascii=True, encode_html_chars=False) helper(not_html_encoded, ensure_ascii=False, encode_html_chars=False) # Make sure explicit encode_html_chars=True does the encoding. helper(html_encoded, ensure_ascii=True, encode_html_chars=True) helper(html_encoded, ensure_ascii=False, encode_html_chars=True) def test_doubleLongIssue(self): sut = {u'a': -4342969734183514} encoded = json.dumps(sut) decoded = json.loads(encoded) self.assertEqual(sut, decoded) encoded = ujson.encode(sut, double_precision=100) decoded = ujson.decode(encoded) self.assertEqual(sut, decoded) def test_doubleLongDecimalIssue(self): sut = {u'a': -12345678901234.56789012} encoded = json.dumps(sut) decoded = json.loads(encoded) self.assertEqual(sut, decoded) encoded = ujson.encode(sut, double_precision=100) decoded = ujson.decode(encoded) self.assertEqual(sut, decoded) def test_encodeDecodeLongDecimal(self): sut = {u'a': -528656961.4399388} encoded = ujson.dumps(sut, double_precision=15) ujson.decode(encoded) def test_decimalDecodeTest(self): sut = {u'a': 4.56} encoded = ujson.encode(sut) decoded = ujson.decode(encoded) self.assertNotEqual(sut, decoded) def test_decimalDecodeTestPrecise(self): sut = {u'a': 4.56} encoded = ujson.encode(sut) decoded = ujson.decode(encoded, precise_float=True) self.assertEqual(sut, decoded) def test_encodeDictWithUnicodeKeys(self): input = { u"key1": u"value1", u"key1": u"value1", u"key1": u"value1", u"key1": u"value1", u"key1": u"value1", u"key1": u"value1" } output = ujson.encode(input) input = { u"بن": u"value1", u"بن": u"value1", u"بن": u"value1", u"بن": u"value1", u"بن": u"value1", u"بن": u"value1", u"بن": u"value1" } output = ujson.encode(input) 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)) def test_encodeWithDecimal(self): input = 1.0 output = ujson.encode(input) self.assertEquals(output, "1.0") 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)) def test_encodeArrayOfNestedArrays(self): input = [[[[]]]] * 20 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] * 10 output = ujson.encode(input) self.assertEquals(input, json.loads(output)) #self.assertEquals(output, json.dumps(input)) self.assertEquals(input, ujson.decode(output)) def test_doublePrecisionTest(self): input = 30.012345678901234 output = ujson.encode(input, double_precision = 15) self.assertEquals(input, json.loads(output)) self.assertEquals(input, ujson.decode(output)) output = ujson.encode(input, double_precision = 9) self.assertEquals(round(input, 9), json.loads(output)) self.assertEquals(round(input, 9), ujson.decode(output)) output = ujson.encode(input, double_precision = 3) self.assertEquals(round(input, 3), json.loads(output)) self.assertEquals(round(input, 3), ujson.decode(output)) def test_invalidDoublePrecision(self): input = 30.12345678901234567890 output = ujson.encode(input, double_precision = 20) # should snap to the max, which is 15 self.assertEquals(round(input, 15), json.loads(output)) self.assertEquals(round(input, 15), ujson.decode(output)) output = ujson.encode(input, double_precision = -1) # also should snap to the max, which is 15 self.assertEquals(round(input, 15), json.loads(output)) self.assertEquals(round(input, 15), ujson.decode(output)) # will throw typeError self.assertRaises(TypeError, ujson.encode, input, double_precision = '9') # will throw typeError self.assertRaises(TypeError, ujson.encode, input, double_precision = None) 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, '"A string \\\\ \\/ \\b \\f \\n \\r \\t"') 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(enc, json_unicode(input)) self.assertEquals(dec, json.loads(enc)) def test_encodeControlEscaping(self): input = "\x19" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEquals(input, dec) self.assertEquals(enc, json_unicode(input)) def test_encodeUnicodeConversion2(self): input = "\xe6\x97\xa5\xd1\x88" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEquals(enc, json_unicode(input)) self.assertEquals(dec, json.loads(enc)) def test_encodeUnicodeSurrogatePair(self): input = "\xf0\x90\x8d\x86" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEquals(enc, json_unicode(input)) self.assertEquals(dec, json.loads(enc)) def test_encodeUnicode4BytesUTF8(self): input = "\xf0\x91\x80\xb0TRAILINGNORMAL" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEquals(enc, json_unicode(input)) self.assertEquals(dec, json.loads(enc)) def test_encodeUnicode4BytesUTF8Highest(self): input = "\xf3\xbf\xbf\xbfTRAILINGNORMAL" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEquals(enc, json_unicode(input)) self.assertEquals(dec, json.loads(enc)) 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_encodeToUTF8(self): input = "\xe6\x97\xa5\xd1\x88" enc = ujson.encode(input, ensure_ascii=False) dec = ujson.decode(enc) self.assertEquals(enc, json_unicode(input, ensure_ascii=False)) self.assertEquals(dec, json.loads(enc)) def test_decodeFromUnicode(self): input = u"{\"obj\": 31337}" dec1 = ujson.decode(input) dec2 = ujson.decode(str(input)) self.assertEquals(dec1, dec2) 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_encodeDoubleNan(self): input = float('nan') try: ujson.encode(input) assert False, "Expected exception!" except(OverflowError): return assert False, "Wrong exception" def test_encodeDoubleInf(self): input = float('inf') try: ujson.encode(input) assert False, "Expected exception!" except(OverflowError): return assert False, "Wrong exception" def test_encodeDoubleNegInf(self): input = -float('inf') try: ujson.encode(input) assert False, "Expected exception!" except(OverflowError): return assert False, "Wrong exception" 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_decodeArrayDepthTooBig(self): input = '[' * (1024 * 1024) 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_decodeObjectDepthTooBig(self): input = '{' * (1024 * 1024) 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)) #@unittest.skipIf(_python_ver(3), "No exception in Python 3") def test_encodeUnicode4BytesUTF8Fail(self): input = "\xfd\xbf\xbf\xbf\xbf\xbf" try: enc = ujson.encode(input) assert False, "Expected exception" except OverflowError: pass def test_encodeNullCharacter(self): input = "31337 \x00 1337" output = ujson.encode(input) self.assertEquals(input, json.loads(output)) self.assertEquals(output, json.dumps(input)) self.assertEquals(input, ujson.decode(output)) input = "\x00" output = ujson.encode(input) self.assertEquals(input, json.loads(output)) self.assertEquals(output, json.dumps(input)) self.assertEquals(input, ujson.decode(output)) self.assertEquals('" \\u0000\\r\\n "', ujson.dumps(u" \u0000\r\n ")) pass def test_decodeNullCharacter(self): input = "\"31337 \\u0000 31337\"" self.assertEquals(ujson.decode(input), json.loads(input)) 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 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_numericIntExp(self): input = "1337E40" output = ujson.decode(input) self.assertEquals(output, json.loads(input)) def test_numericIntFrcExp(self): input = "1.337E40" output = ujson.decode(input) self.assertEquals(output, json.loads(input)) def test_decodeNumericIntExpEPLUS(self): input = "1337E+9" output = ujson.decode(input) self.assertEquals(output, json.loads(input)) def test_decodeNumericIntExpePLUS(self): input = "1.337e+40" output = ujson.decode(input) self.assertEquals(output, json.loads(input)) def test_decodeNumericIntExpE(self): input = "1337E40" output = ujson.decode(input) self.assertEquals(output, json.loads(input)) def test_decodeNumericIntExpe(self): input = "1337e40" output = ujson.decode(input) self.assertEquals(output, json.loads(input)) def test_decodeNumericIntExpEMinus(self): input = "1.337E-4" output = ujson.decode(input) self.assertEquals(output, json.loads(input)) def test_decodeNumericIntExpeMinus(self): input = "1.337e-4" output = ujson.decode(input) self.assertEquals(output, json.loads(input)) def test_dumpToFile(self): f = StringIO.StringIO() ujson.dump([1, 2, 3], f) self.assertEquals("[1,2,3]", f.getvalue()) def test_dumpToFileLikeObject(self): class filelike: def __init__(self): self.bytes = '' def write(self, bytes): self.bytes += bytes f = filelike() ujson.dump([1, 2, 3], f) self.assertEquals("[1,2,3]", f.bytes) def test_dumpFileArgsError(self): try: ujson.dump([], '') except TypeError: pass else: assert False, 'expected TypeError' def test_loadFile(self): f = StringIO.StringIO("[1,2,3,4]") self.assertEquals([1, 2, 3, 4], ujson.load(f)) def test_loadFileLikeObject(self): class filelike: def read(self): try: self.end except AttributeError: self.end = True return "[1,2,3,4]" f = filelike() self.assertEquals([1, 2, 3, 4], ujson.load(f)) def test_loadFileArgsError(self): try: ujson.load("[]") except TypeError: pass else: assert False, "expected TypeError" def test_version(self): assert re.match(r'^\d+\.\d+(\.\d+)?$', ujson.__version__), \ "ujson.__version__ must be a string like '1.4.0'" def test_encodeNumericOverflow(self): try: ujson.encode(12839128391289382193812939) except OverflowError: pass else: assert False, "expected OverflowError" def test_encodeNumericOverflowNested(self): for n in xrange(0, 100): class Nested: x = 12839128391289382193812939 nested = Nested() try: ujson.encode(nested) except OverflowError: pass else: assert False, "expected OverflowError" def test_decodeNumberWith32bitSignBit(self): #Test that numbers that fit within 32 bits but would have the # sign bit set (2**31 <= x < 2**32) are decoded properly. boundary1 = 2**31 boundary2 = 2**32 docs = ( '{"id": 3590016419}', '{"id": %s}' % 2**31, '{"id": %s}' % 2**32, '{"id": %s}' % ((2**32)-1), ) results = (3590016419, 2**31, 2**32, 2**32-1) for doc,result in zip(docs, results): self.assertEqual(ujson.decode(doc)['id'], result) def test_encodeBigEscape(self): for x in xrange(10): if PY3: base = '\u00e5'.encode('utf-8') else: base = "\xc3\xa5" input = base * 1024 * 1024 * 2 output = ujson.encode(input) def test_decodeBigEscape(self): for x in xrange(10): if PY3: base = '\u00e5'.encode('utf-8') quote = "\"".encode() else: base = "\xc3\xa5" quote = "\"" input = quote + (base * 1024 * 1024 * 2) + quote output = ujson.decode(input) def test_toDict(self): d = {u"key": 31337} class DictTest: def toDict(self): return d o = DictTest() output = ujson.encode(o) dec = ujson.decode(output) self.assertEquals(dec, d) def test_decodeArrayTrailingCommaFail(self): input = "[31337,]" try: ujson.decode(input) except ValueError: pass else: assert False, "expected ValueError" def test_decodeArrayLeadingCommaFail(self): input = "[,31337]" try: ujson.decode(input) except ValueError: pass else: assert False, "expected ValueError" def test_decodeArrayOnlyCommaFail(self): input = "[,]" try: ujson.decode(input) except ValueError: pass else: assert False, "expected ValueError" def test_decodeArrayUnmatchedBracketFail(self): input = "[]]" try: ujson.decode(input) except ValueError: pass else: assert False, "expected ValueError" def test_decodeArrayEmpty(self): input = "[]" ujson.decode(input) def test_decodeArrayOneItem(self): input = "[31337]" ujson.decode(input) def test_decodeBigValue(self): input = "9223372036854775807" ujson.decode(input) def test_decodeSmallValue(self): input = "-9223372036854775808" ujson.decode(input) def test_decodeTooBigValue(self): try: input = "9223372036854775808" ujson.decode(input) except ValueError, e: pass else: assert False, "expected ValueError" def test_decodeTooSmallValue(self): try: input = "-90223372036854775809" ujson.decode(input) except ValueError,e: pass else: assert False, "expected ValueError" def test_decodeVeryTooBigValue(self): try: input = "9223372036854775808" ujson.decode(input) except ValueError: pass else: assert False, "expected ValueError" def test_decodeVeryTooSmallValue(self): try: input = "-90223372036854775809" ujson.decode(input) except ValueError: pass else: assert False, "expected ValueError" def test_decodeWithTrailingWhitespaces(self): input = "{}\n\t " ujson.decode(input) def test_decodeWithTrailingNonWhitespaces(self): try: input = "{}\n\t a" ujson.decode(input) except ValueError: pass else: assert False, "expected ValueError" def test_decodeArrayWithBigInt(self): try: ujson.loads('[18446098363113800555]') except ValueError: pass else: assert False, "expected ValueError" def test_decodeArrayFaultyUnicode(self): try: ujson.loads('[18446098363113800555]') except ValueError: pass else: assert False, "expected ValueError" def test_decodeFloatingPointAdditionalTests(self): self.assertEquals(-1.1234567893, ujson.loads("-1.1234567893")) self.assertEquals(-1.234567893, ujson.loads("-1.234567893")) self.assertEquals(-1.34567893, ujson.loads("-1.34567893")) self.assertEquals(-1.4567893, ujson.loads("-1.4567893")) self.assertEquals(-1.567893, ujson.loads("-1.567893")) self.assertEquals(-1.67893, ujson.loads("-1.67893")) self.assertEquals(-1.7893, ujson.loads("-1.7893")) self.assertEquals(-1.893, ujson.loads("-1.893")) self.assertEquals(-1.3, ujson.loads("-1.3")) self.assertEquals(1.1234567893, ujson.loads("1.1234567893")) self.assertEquals(1.234567893, ujson.loads("1.234567893")) self.assertEquals(1.34567893, ujson.loads("1.34567893")) self.assertEquals(1.4567893, ujson.loads("1.4567893")) self.assertEquals(1.567893, ujson.loads("1.567893")) self.assertEquals(1.67893, ujson.loads("1.67893")) self.assertEquals(1.7893, ujson.loads("1.7893")) self.assertEquals(1.893, ujson.loads("1.893")) self.assertEquals(1.3, ujson.loads("1.3")) def test_encodeBigSet(self): s = set() for x in xrange(0, 100000): s.add(x) ujson.encode(s) def test_encodeEmptySet(self): s = set() self.assertEquals("[]", ujson.encode(s)) def test_encodeSet(self): s = set([1,2,3,4,5,6,7,8,9]) enc = ujson.encode(s) dec = ujson.decode(enc) for v in dec: self.assertTrue(v in s) """ def test_decodeNumericIntFrcOverflow(self): input = "X.Y" 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!") """ if __name__ == "__main__": unittest.main() # Use this to look for memory leaks """ if __name__ == '__main__': from guppy import hpy hp = hpy() hp.setrelheap() while True: try: unittest.main() except SystemExit: pass heap = hp.heapu() print heap """ ujson-1.33/setup.py0000666000175100017510000000430312155373442013360 0ustar morphmorphtry: from setuptools import setup, Extension except ImportError: from distutils.core import setup, Extension import distutils.sysconfig import shutil import os.path import re import sys CLASSIFIERS = filter(None, map(str.strip, """ Development Status :: 5 - Production/Stable Intended Audience :: Developers License :: OSI Approved :: BSD License Programming Language :: C Programming Language :: Python :: 2.4 Programming Language :: Python :: 2.5 Programming Language :: Python :: 2.6 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.2 """.splitlines())) try: shutil.rmtree("./build") except(OSError): pass module1 = Extension('ujson', sources = ['./python/ujson.c', './python/objToJSON.c', './python/JSONtoObj.c', './lib/ultrajsonenc.c', './lib/ultrajsondec.c'], include_dirs = ['./python', './lib'], extra_compile_args=['-D_GNU_SOURCE']) def get_version(): filename = os.path.join(os.path.dirname(__file__), './python/version.h') file = None try: file = open(filename) header = file.read() finally: if file: file.close() m = re.search(r'#define\s+UJSON_VERSION\s+"(\d+\.\d+(?:\.\d+)?)"', header) assert m, "version.h must contain UJSON_VERSION macro" return m.group(1) f = open('README.rst') try: README = f.read() finally: f.close() setup (name = 'ujson', version = get_version(), description = "Ultra fast JSON encoder and decoder for Python", long_description = README, ext_modules = [module1], author="Jonas Tarnstrom", author_email="jonas.tarnstrom@esn.me", download_url="http://github.com/esnme/ultrajson", license="BSD License", platforms=['any'], url="http://www.esn.me", classifiers=CLASSIFIERS, ) if sys.version_info[0] >= 3: print( "*" * 100) print("If you want to run the tests be sure to run 2to3 on them first, " "e.g. `2to3 -w tests/tests.py`.") print("*" * 100)