2012-06-25 11:29:54 +02:00
|
|
|
/*
|
2014-04-14 13:45:50 +02:00
|
|
|
Developed by ESN, an Electronic Arts Inc. studio.
|
|
|
|
Copyright (c) 2014, Electronic Arts Inc.
|
2012-06-25 11:29:54 +02:00
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
2014-04-14 13:45:50 +02:00
|
|
|
* 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 ESN, Electronic Arts Inc. nor the
|
|
|
|
names of its contributors may be used to endorse or promote products
|
|
|
|
derived from this software without specific prior written permission.
|
2012-06-25 11:29:54 +02:00
|
|
|
|
|
|
|
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
|
2014-04-14 13:45:50 +02:00
|
|
|
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS INC. BE LIABLE
|
2012-06-25 11:29:54 +02:00
|
|
|
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.
|
|
|
|
|
2013-01-16 16:22:08 +01:00
|
|
|
|
|
|
|
Portions of code from MODP_ASCII - Ascii transformations (upper/lower, etc)
|
2012-06-25 11:29:54 +02:00
|
|
|
http://code.google.com/p/stringencoders/
|
|
|
|
Copyright (c) 2007 Nick Galbreath -- nickg [at] modp [dot] com. All rights reserved.
|
|
|
|
|
2013-01-16 16:22:08 +01:00
|
|
|
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.
|
2012-06-25 11:29:54 +02:00
|
|
|
*/
|
|
|
|
|
2012-06-12 00:27:04 +02:00
|
|
|
#include "py_defines.h"
|
2012-06-11 19:41:56 +02:00
|
|
|
#include <ultrajson.h>
|
|
|
|
|
|
|
|
|
2013-02-12 16:41:12 +01:00
|
|
|
//#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__)
|
|
|
|
#define PRINTMARK()
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
void Object_objectAddKey(void *prv, JSOBJ obj, JSOBJ name, JSOBJ value)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
PyDict_SetItem (obj, name, value);
|
|
|
|
Py_DECREF( (PyObject *) name);
|
|
|
|
Py_DECREF( (PyObject *) value);
|
|
|
|
return;
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
void Object_arrayAddItem(void *prv, JSOBJ obj, JSOBJ value)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
PyList_Append(obj, value);
|
|
|
|
Py_DECREF( (PyObject *) value);
|
|
|
|
return;
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newString(void *prv, wchar_t *start, wchar_t *end)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
return PyUnicode_FromWideChar (start, (end - start));
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newTrue(void *prv)
|
2013-05-08 22:52:53 +02:00
|
|
|
{
|
|
|
|
Py_RETURN_TRUE;
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newFalse(void *prv)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
Py_RETURN_FALSE;
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newNull(void *prv)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
Py_RETURN_NONE;
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newObject(void *prv)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
return PyDict_New();
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newArray(void *prv)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
return PyList_New(0);
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newInteger(void *prv, JSINT32 value)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
return PyInt_FromLong( (long) value);
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newLong(void *prv, JSINT64 value)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
return PyLong_FromLongLong (value);
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
JSOBJ Object_newDouble(void *prv, double value)
|
2013-05-08 22:52:53 +02:00
|
|
|
{
|
|
|
|
return PyFloat_FromDouble(value);
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-06-10 12:44:04 +02:00
|
|
|
static void Object_releaseObject(void *prv, JSOBJ obj)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
Py_DECREF( ((PyObject *)obj));
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-02-12 16:41:12 +01:00
|
|
|
static char *g_kwlist[] = {"obj", "precise_float", NULL};
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-02-12 16:41:12 +01:00
|
|
|
PyObject* JSONToObj(PyObject* self, PyObject *args, PyObject *kwargs)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
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;
|
2013-06-10 12:44:04 +02:00
|
|
|
decoder.prv = NULL;
|
2013-05-08 22:52:53 +02:00
|
|
|
|
|
|
|
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)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
//Exception raised above us by codec according to docs
|
|
|
|
return NULL;
|
2013-02-12 16:41:12 +01:00
|
|
|
}
|
2013-05-08 22:52:53 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PyErr_Format(PyExc_TypeError, "Expected String or Unicode");
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-02-12 16:41:12 +01:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
decoder.errorStr = NULL;
|
|
|
|
decoder.errorOffset = NULL;
|
2013-02-12 16:41:12 +01:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
ret = JSON_DecodeObject(&decoder, PyString_AS_STRING(sarg), PyString_GET_SIZE(sarg));
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
if (sarg != arg)
|
|
|
|
{
|
|
|
|
Py_DECREF(sarg);
|
|
|
|
}
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
if (decoder.errorStr)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
FIXME: It's possible to give a much nicer error message here with actual failing element in input etc*/
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
PyErr_Format (PyExc_ValueError, "%s", decoder.errorStr);
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
if (ret)
|
2012-06-11 19:41:56 +02:00
|
|
|
{
|
2013-05-08 22:52:53 +02:00
|
|
|
Py_DECREF( (PyObject *) ret);
|
2012-06-11 19:41:56 +02:00
|
|
|
}
|
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
return ret;
|
|
|
|
}
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
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)) {
|
2012-06-11 19:41:56 +02:00
|
|
|
Py_XDECREF(read);
|
2013-05-08 22:52:53 +02:00
|
|
|
PyErr_Format (PyExc_TypeError, "expected file");
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
string = PyObject_CallObject (read, NULL);
|
|
|
|
Py_XDECREF(read);
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
if (string == NULL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-02-12 16:41:12 +01:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
argtuple = PyTuple_Pack(1, string);
|
2013-02-12 16:41:12 +01:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
result = JSONToObj (self, argtuple, kwargs);
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
Py_XDECREF(argtuple);
|
|
|
|
Py_XDECREF(string);
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
if (result == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-06-11 19:41:56 +02:00
|
|
|
|
2013-05-08 22:52:53 +02:00
|
|
|
return result;
|
|
|
|
}
|