//============================================================================= // 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); }
static void *NewObjPyStringToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { return PyStringToUTF8(GET_TC(tc)->newObj, tc, outValue, _outLen); }
//============================================================================= // 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; }
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); }
static 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 (!(GET_TC(tc)->itemName = PyIter_Next(GET_TC(tc)->iterator))) { PRINTMARK(); return 0; } if (!(GET_TC(tc)->itemValue = PyObject_GetItem(GET_TC(tc)->dictObj, GET_TC(tc)->itemName))) { 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)) { if (UNLIKELY(GET_TC(tc)->itemName == Py_None)) { GET_TC(tc)->itemName = PyString_FromString("null"); return 1; } 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; }
//============================================================================= // 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 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; }
double Object_getDoubleValue(JSOBJ obj, JSONTypeContext *tc) { double ret; GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL); return ret; }
int Object_iterNext(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->iterNext(obj, tc); }
JSUINT64 Object_getUnsignedLongValue(JSOBJ obj, JSONTypeContext *tc) { JSUINT64 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; }
const char *Object_getStringValue(JSOBJ obj, JSONTypeContext *tc, size_t *_outLen) { return GET_TC(tc)->PyTypeToJSON (obj, tc, NULL, _outLen); }
int SortedDict_iterNext(JSOBJ obj, JSONTypeContext *tc) { PyObject *items = NULL, *item = NULL, *key = NULL, *value = NULL; Py_ssize_t i, nitems; #if PY_MAJOR_VERSION >= 3 PyObject* keyTmp; #endif // Upon first call, obtain a list of the keys and sort them. This follows the same logic as the // stanard library's _json.c sort_keys handler. if (GET_TC(tc)->newObj == NULL) { // Obtain the list of keys from the dictionary. items = PyMapping_Keys(GET_TC(tc)->dictObj); if (items == NULL) { goto error; } else if (!PyList_Check(items)) { PyErr_SetString(PyExc_ValueError, "keys must return list"); goto error; } // Sort the list. if (PyList_Sort(items) < 0) { goto error; } // Obtain the value for each key, and pack a list of (key, value) 2-tuples. nitems = PyList_GET_SIZE(items); for (i = 0; i < nitems; i++) { key = PyList_GET_ITEM(items, i); value = PyDict_GetItem(GET_TC(tc)->dictObj, key); // Subject the key to the same type restrictions and conversions as in Dict_iterGetValue. if (PyUnicode_Check(key)) { key = PyUnicode_AsUTF8String(key); } else if (!PyString_Check(key)) { key = PyObject_Str(key); #if PY_MAJOR_VERSION >= 3 keyTmp = key; key = PyUnicode_AsUTF8String(key); Py_DECREF(keyTmp); #endif } else { Py_INCREF(key); } item = PyTuple_Pack(2, key, value); if (item == NULL) { goto error; } PyList_SET_ITEM(items, i, item); Py_DECREF(key); } // Store the sorted list of tuples in the newObj slot. GET_TC(tc)->newObj = items; GET_TC(tc)->size = nitems; } if (GET_TC(tc)->index >= GET_TC(tc)->size) { PRINTMARK(); return 0; } item = PyList_GET_ITEM(GET_TC(tc)->newObj, GET_TC(tc)->index); GET_TC(tc)->itemName = PyTuple_GET_ITEM(item, 0); GET_TC(tc)->itemValue = PyTuple_GET_ITEM(item, 1); GET_TC(tc)->index++; return 1; error: Py_XDECREF(item); Py_XDECREF(key); Py_XDECREF(value); Py_XDECREF(items); return -1; }
static void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObjectEncoder *enc) { PyObject *obj, *objRepr, *exc; 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->iterator = NULL; pc->attrList = NULL; pc->index = 0; pc->size = 0; pc->longValue = 0; pc->rawJSONValue = NULL; 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) { return; } if (exc && PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_Clear(); pc->PyTypeToJSON = PyLongToUINT64; tc->type = JT_ULONG; GET_TC(tc)->unsignedLongValue = PyLong_AsUnsignedLongLong(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) || (type_decimal && PyObject_IsInstance(obj, type_decimal))) { PRINTMARK(); pc->PyTypeToJSON = PyFloatToDOUBLE; tc->type = JT_DOUBLE; return; } else if (obj == Py_None) { PRINTMARK(); tc->type = JT_NULL; return; } ISITERABLE: if (PyDict_Check(obj)) { PRINTMARK(); tc->type = JT_OBJECT; SetupDictIter(obj, pc, enc); Py_INCREF(obj); return; } else if (PyList_Check(obj)) { PRINTMARK(); tc->type = JT_ARRAY; pc->iterEnd = List_iterEnd; pc->iterNext = List_iterNext; pc->iterGetValue = List_iterGetValue; pc->iterGetName = List_iterGetName; GET_TC(tc)->index = 0; GET_TC(tc)->size = PyList_GET_SIZE( (PyObject *) obj); return; } else if (PyTuple_Check(obj)) { PRINTMARK(); tc->type = JT_ARRAY; pc->iterEnd = Tuple_iterEnd; pc->iterNext = Tuple_iterNext; pc->iterGetValue = Tuple_iterGetValue; pc->iterGetName = Tuple_iterGetName; GET_TC(tc)->index = 0; GET_TC(tc)->size = PyTuple_GET_SIZE( (PyObject *) obj); GET_TC(tc)->itemValue = NULL; return; } if (UNLIKELY(PyObject_HasAttrString(obj, "toDict"))) { PyObject* toDictFunc = PyObject_GetAttrString(obj, "toDict"); PyObject* tuple = PyTuple_New(0); PyObject* toDictResult = PyObject_Call(toDictFunc, tuple, NULL); Py_DECREF(tuple); Py_DECREF(toDictFunc); if (toDictResult == NULL) { goto INVALID; } if (!PyDict_Check(toDictResult)) { Py_DECREF(toDictResult); tc->type = JT_NULL; return; } PRINTMARK(); tc->type = JT_OBJECT; SetupDictIter(toDictResult, pc, enc); return; } else if (UNLIKELY(PyObject_HasAttrString(obj, "__json__"))) { PyObject* toJSONFunc = PyObject_GetAttrString(obj, "__json__"); PyObject* tuple = PyTuple_New(0); PyObject* toJSONResult = PyObject_Call(toJSONFunc, tuple, NULL); Py_DECREF(tuple); Py_DECREF(toJSONFunc); if (toJSONResult == NULL) { goto INVALID; } if (PyErr_Occurred()) { Py_DECREF(toJSONResult); goto INVALID; } if (!PyString_Check(toJSONResult) && !PyUnicode_Check(toJSONResult)) { Py_DECREF(toJSONResult); PyErr_Format (PyExc_TypeError, "expected string"); goto INVALID; } PRINTMARK(); pc->PyTypeToJSON = PyRawJSONToUTF8; tc->type = JT_RAW; GET_TC(tc)->rawJSONValue = toJSONResult; return; } PRINTMARK(); PyErr_Clear(); objRepr = PyObject_Repr(obj); PyErr_Format (PyExc_TypeError, "%s is not JSON serializable", PyString_AS_STRING(objRepr)); Py_DECREF(objRepr); INVALID: PRINTMARK(); tc->type = JT_INVALID; PyObject_Free(tc->prv); tc->prv = NULL; return; }
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; }
void Object_iterEnd(JSOBJ obj, JSONTypeContext *tc) { GET_TC(tc)->iterEnd(obj, tc); }
JSOBJ Dir_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { PRINTMARK(); return GET_TC(tc)->itemValue; }
JSOBJ Object_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->iterGetValue(obj, tc); }
//============================================================================= // 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(); }
char *Object_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) { return GET_TC(tc)->iterGetName(obj, tc, outLen); }
JSOBJ Dict_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->itemValue; }
static void *PyLongToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_t *_outLen) { *((JSINT64 *) outValue) = GET_TC(tc)->longValue; return NULL; }
void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc) { PyObject *obj, *exc, *toFunc; 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) || (type_decimal && 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; } toFunc = PyObject_GetAttrString(obj, "toDict"); if (toFunc) { PyObject* tuple = PyTuple_New(0); PyObject* toDictResult = PyObject_Call(toFunc, tuple, NULL); Py_DECREF(tuple); Py_DECREF(toFunc); 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(); toFunc = PyObject_GetAttrString(obj, "toJson"); if (toFunc) { PyObject* tuple = PyTuple_New(0); PyObject* toJsonResult = PyObject_Call(toFunc, tuple, NULL); Py_DECREF(tuple); Py_DECREF(toFunc); if (toJsonResult == NULL) { PyErr_Clear(); tc->type = JT_NULL; return; } if (PyString_Check(toJsonResult)) { PRINTMARK(); pc->PyTypeToJSON = NewObjPyStringToUTF8; pc->newObj = toJsonResult; tc->type = JT_JSON; return; } else if (PyUnicode_Check(toJsonResult)) { PRINTMARK(); pc->PyTypeToJSON = NewObjPyUnicodeToUTF8; pc->newObj = toJsonResult; tc->type = JT_JSON; return; } else { Py_DECREF(toJsonResult); tc->type = JT_NULL; 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; }
static JSOBJ Tuple_iterGetValue(JSOBJ obj, JSONTypeContext *tc) { return GET_TC(tc)->itemValue; }