mirror of
https://github.com/ultrajson/ultrajson.git
synced 2024-05-29 23:16:07 +02:00
Fixed style of .c and .h files to use 2 spaces instead of 4 spaces and tabs and added some braces for easier code reading.
This commit is contained in:
parent
af4644b4a6
commit
e098bd1ce9
204
lib/ultrajson.h
204
lib/ultrajson.h
|
@ -16,7 +16,7 @@ modification, are permitted provided that the following conditions are met:
|
|||
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
|
||||
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
|
||||
|
@ -43,8 +43,8 @@ Encoder notes:
|
|||
------------------
|
||||
|
||||
:: Cyclic references ::
|
||||
Cyclic referenced objects are not detected.
|
||||
Set JSONObjectEncoder.recursionMax to suitable value or make sure input object
|
||||
Cyclic referenced objects are not detected.
|
||||
Set JSONObjectEncoder.recursionMax to suitable value or make sure input object
|
||||
tree doesn't have cyclic references.
|
||||
|
||||
*/
|
||||
|
@ -89,7 +89,7 @@ typedef __int64 JSLONG;
|
|||
#define EXPORTFUNCTION __declspec(dllexport)
|
||||
|
||||
#define FASTCALL_MSVC __fastcall
|
||||
#define FASTCALL_ATTR
|
||||
#define FASTCALL_ATTR
|
||||
#define INLINE_PREFIX __inline
|
||||
|
||||
#else
|
||||
|
@ -101,7 +101,7 @@ typedef uint64_t JSUINT64;
|
|||
typedef int32_t JSINT32;
|
||||
typedef uint32_t JSUINT32;
|
||||
|
||||
#define FASTCALL_MSVC
|
||||
#define FASTCALL_MSVC
|
||||
#define FASTCALL_ATTR __attribute__((fastcall))
|
||||
#define INLINE_PREFIX inline
|
||||
|
||||
|
@ -130,16 +130,16 @@ typedef int64_t JSLONG;
|
|||
|
||||
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
|
||||
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;
|
||||
|
@ -147,8 +147,8 @@ typedef void * JSITER;
|
|||
|
||||
typedef struct __JSONTypeContext
|
||||
{
|
||||
int type;
|
||||
void *prv;
|
||||
int type;
|
||||
void *prv;
|
||||
} JSONTypeContext;
|
||||
|
||||
/*
|
||||
|
@ -164,82 +164,82 @@ 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);
|
||||
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;
|
||||
/*
|
||||
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;
|
||||
/*
|
||||
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;
|
||||
/*
|
||||
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;
|
||||
/*
|
||||
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;
|
||||
/*
|
||||
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);
|
||||
/*
|
||||
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;
|
||||
/* 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 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;
|
||||
/*
|
||||
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 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;
|
||||
/*
|
||||
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;
|
||||
/*
|
||||
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;
|
||||
/* Buffer stuff */
|
||||
char *start;
|
||||
char *offset;
|
||||
char *end;
|
||||
int heap;
|
||||
int level;
|
||||
|
||||
} JSONObjectEncoder;
|
||||
|
||||
|
@ -254,11 +254,11 @@ buffer - Preallocated buffer to store result in. If NULL function allocates own
|
|||
cbBuffer - Length of buffer (ignored if buffer is NULL)
|
||||
|
||||
Returns:
|
||||
Encoded JSON object as a null terminated char string.
|
||||
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 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.
|
||||
|
@ -269,28 +269,26 @@ EXPORTFUNCTION char *JSON_EncodeObject(JSOBJ obj, JSONObjectEncoder *enc, char *
|
|||
|
||||
typedef struct __JSONObjectDecoder
|
||||
{
|
||||
JSOBJ (*newString)(wchar_t *start, wchar_t *end);
|
||||
void (*objectAddKey)(JSOBJ obj, JSOBJ name, JSOBJ value);
|
||||
void (*arrayAddItem)(JSOBJ obj, JSOBJ value);
|
||||
JSOBJ (*newTrue)(void);
|
||||
JSOBJ (*newFalse)(void);
|
||||
JSOBJ (*newNull)(void);
|
||||
JSOBJ (*newObject)(void);
|
||||
JSOBJ (*newArray)(void);
|
||||
JSOBJ (*newInt)(JSINT32 value);
|
||||
JSOBJ (*newLong)(JSINT64 value);
|
||||
JSOBJ (*newDouble)(double value);
|
||||
void (*releaseObject)(JSOBJ obj);
|
||||
JSPFN_MALLOC malloc;
|
||||
JSPFN_FREE free;
|
||||
JSPFN_REALLOC realloc;
|
||||
|
||||
char *errorStr;
|
||||
char *errorOffset;
|
||||
|
||||
int preciseFloat;
|
||||
JSOBJ (*newString)(wchar_t *start, wchar_t *end);
|
||||
void (*objectAddKey)(JSOBJ obj, JSOBJ name, JSOBJ value);
|
||||
void (*arrayAddItem)(JSOBJ obj, JSOBJ value);
|
||||
JSOBJ (*newTrue)(void);
|
||||
JSOBJ (*newFalse)(void);
|
||||
JSOBJ (*newNull)(void);
|
||||
JSOBJ (*newObject)(void);
|
||||
JSOBJ (*newArray)(void);
|
||||
JSOBJ (*newInt)(JSINT32 value);
|
||||
JSOBJ (*newLong)(JSINT64 value);
|
||||
JSOBJ (*newDouble)(double value);
|
||||
void (*releaseObject)(JSOBJ obj);
|
||||
JSPFN_MALLOC malloc;
|
||||
JSPFN_FREE free;
|
||||
JSPFN_REALLOC realloc;
|
||||
|
||||
char *errorStr;
|
||||
char *errorOffset;
|
||||
|
||||
int preciseFloat;
|
||||
} JSONObjectDecoder;
|
||||
|
||||
EXPORTFUNCTION JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuffer);
|
||||
|
|
1399
lib/ultrajsondec.c
1399
lib/ultrajsondec.c
|
@ -16,7 +16,7 @@ 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
|
||||
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
|
||||
|
@ -54,13 +54,13 @@ http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
|
|||
|
||||
struct DecoderState
|
||||
{
|
||||
char *start;
|
||||
char *end;
|
||||
wchar_t *escStart;
|
||||
wchar_t *escEnd;
|
||||
int escHeap;
|
||||
int lastType;
|
||||
JSONObjectDecoder *dec;
|
||||
char *start;
|
||||
char *end;
|
||||
wchar_t *escStart;
|
||||
wchar_t *escEnd;
|
||||
int escHeap;
|
||||
int lastType;
|
||||
JSONObjectDecoder *dec;
|
||||
};
|
||||
|
||||
JSOBJ FASTCALL_MSVC decode_any( struct DecoderState *ds) FASTCALL_ATTR;
|
||||
|
@ -68,810 +68,815 @@ 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;
|
||||
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(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 < 0)
|
||||
{
|
||||
intNeg = 1;
|
||||
}
|
||||
|
||||
if ( (intValue >> 31))
|
||||
{
|
||||
return ds->dec->newLong( (JSINT64) (intValue * (JSINT64) intNeg));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ds->dec->newInt( (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:
|
||||
|
||||
if (intValue < 0)
|
||||
{
|
||||
intNeg = 1;
|
||||
}
|
||||
|
||||
//FIXME: Check for arithemtic overflow here
|
||||
ds->lastType = JT_DOUBLE;
|
||||
ds->start = offset;
|
||||
return ds->dec->newDouble (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:
|
||||
|
||||
#ifdef JSON_DECODE_NUMERIC_AS_DOUBLE
|
||||
#else
|
||||
if (intValue < 0)
|
||||
{
|
||||
intNeg = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//FIXME: Check for arithemtic overflow here
|
||||
ds->lastType = JT_DOUBLE;
|
||||
ds->start = offset;
|
||||
return ds->dec->newDouble (createDouble( (double) intNeg, (double) intValue , frcValue, decimalCount) * pow(10.0, expValue * expNeg));
|
||||
ds->dec->errorOffset = 0;
|
||||
ds->dec->errorStr = NULL;
|
||||
}
|
||||
|
||||
FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_true ( struct DecoderState *ds)
|
||||
double createDouble(double intNeg, double intValue, double frcValue, int frcDecimalCount)
|
||||
{
|
||||
char *offset = ds->start;
|
||||
offset ++;
|
||||
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;
|
||||
}
|
||||
|
||||
if (*(offset++) != 'r')
|
||||
goto SETERROR;
|
||||
if (*(offset++) != 'u')
|
||||
goto SETERROR;
|
||||
if (*(offset++) != 'e')
|
||||
goto SETERROR;
|
||||
FASTCALL_ATTR JSOBJ FASTCALL_MSVC decodePreciseFloat(struct DecoderState *ds)
|
||||
{
|
||||
char *end;
|
||||
double value;
|
||||
errno = 0;
|
||||
|
||||
ds->lastType = JT_TRUE;
|
||||
ds->start = offset;
|
||||
return ds->dec->newTrue();
|
||||
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(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 < 0)
|
||||
{
|
||||
intNeg = 1;
|
||||
}
|
||||
|
||||
if ((intValue >> 31))
|
||||
{
|
||||
return ds->dec->newLong( (JSINT64) (intValue * (JSINT64) intNeg));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ds->dec->newInt( (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:
|
||||
|
||||
if (intValue < 0)
|
||||
{
|
||||
intNeg = 1;
|
||||
}
|
||||
|
||||
//FIXME: Check for arithemtic overflow here
|
||||
ds->lastType = JT_DOUBLE;
|
||||
ds->start = offset;
|
||||
return ds->dec->newDouble (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:
|
||||
|
||||
#ifdef JSON_DECODE_NUMERIC_AS_DOUBLE
|
||||
#else
|
||||
if (intValue < 0)
|
||||
{
|
||||
intNeg = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//FIXME: Check for arithemtic overflow here
|
||||
ds->lastType = JT_DOUBLE;
|
||||
ds->start = offset;
|
||||
return ds->dec->newDouble (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();
|
||||
|
||||
SETERROR:
|
||||
return SetError(ds, -1, "Unexpected character found when decoding 'true'");
|
||||
return SetError(ds, -1, "Unexpected character found when decoding 'true'");
|
||||
}
|
||||
|
||||
FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_false ( struct DecoderState *ds)
|
||||
FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_false ( struct DecoderState *ds)
|
||||
{
|
||||
char *offset = ds->start;
|
||||
offset ++;
|
||||
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;
|
||||
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->lastType = JT_FALSE;
|
||||
ds->start = offset;
|
||||
return ds->dec->newFalse();
|
||||
|
||||
SETERROR:
|
||||
return SetError(ds, -1, "Unexpected character found when decoding 'false'");
|
||||
|
||||
return SetError(ds, -1, "Unexpected character found when decoding 'false'");
|
||||
}
|
||||
|
||||
|
||||
FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_null ( struct DecoderState *ds)
|
||||
FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_null ( struct DecoderState *ds)
|
||||
{
|
||||
char *offset = ds->start;
|
||||
offset ++;
|
||||
char *offset = ds->start;
|
||||
offset ++;
|
||||
|
||||
if (*(offset++) != 'u')
|
||||
goto SETERROR;
|
||||
if (*(offset++) != 'l')
|
||||
goto SETERROR;
|
||||
if (*(offset++) != 'l')
|
||||
goto SETERROR;
|
||||
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->lastType = JT_NULL;
|
||||
ds->start = offset;
|
||||
return ds->dec->newNull();
|
||||
|
||||
SETERROR:
|
||||
return SetError(ds, -1, "Unexpected character found when decoding 'null'");
|
||||
return SetError(ds, -1, "Unexpected character found when decoding 'null'");
|
||||
}
|
||||
|
||||
FASTCALL_ATTR void FASTCALL_MSVC SkipWhitespace(struct DecoderState *ds)
|
||||
FASTCALL_ATTR void FASTCALL_MSVC SkipWhitespace(struct DecoderState *ds)
|
||||
{
|
||||
char *offset = ds->start;
|
||||
char *offset = ds->start;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch (*offset)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
offset ++;
|
||||
break;
|
||||
for (;;)
|
||||
{
|
||||
switch (*offset)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
offset ++;
|
||||
break;
|
||||
|
||||
default:
|
||||
ds->start = offset;
|
||||
return;
|
||||
}
|
||||
}
|
||||
default:
|
||||
ds->start = offset;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum DECODESTRINGSTATE
|
||||
{
|
||||
DS_ISNULL = 0x32,
|
||||
DS_ISQUOTE,
|
||||
DS_ISESCAPE,
|
||||
DS_UTFLENERROR,
|
||||
DS_ISNULL = 0x32,
|
||||
DS_ISQUOTE,
|
||||
DS_ISESCAPE,
|
||||
DS_UTFLENERROR,
|
||||
|
||||
};
|
||||
|
||||
static const JSUINT8 g_decoderLookup[256] =
|
||||
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,
|
||||
/* 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;
|
||||
size_t escLen = (ds->escEnd - ds->escStart);
|
||||
JSUINT8 *inputOffset;
|
||||
JSUINT8 oct;
|
||||
JSUTF32 ucs;
|
||||
ds->lastType = JT_INVALID;
|
||||
ds->start ++;
|
||||
JSUTF16 sur[2] = { 0 };
|
||||
int iSur = 0;
|
||||
int index;
|
||||
wchar_t *escOffset;
|
||||
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 ( (size_t) (ds->end - ds->start) > escLen)
|
||||
{
|
||||
size_t newSize = (ds->end - ds->start);
|
||||
|
||||
if (ds->escHeap)
|
||||
{
|
||||
ds->escStart = (wchar_t *) ds->dec->realloc (ds->escStart, newSize * sizeof(wchar_t));
|
||||
if (!ds->escStart)
|
||||
{
|
||||
return SetError(ds, -1, "Could not reserve memory block");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *oldStart = ds->escStart;
|
||||
ds->escHeap = 1;
|
||||
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));
|
||||
}
|
||||
if (ds->escHeap)
|
||||
{
|
||||
ds->escStart = (wchar_t *) ds->dec->realloc (ds->escStart, newSize * sizeof(wchar_t));
|
||||
if (!ds->escStart)
|
||||
{
|
||||
return SetError(ds, -1, "Could not reserve memory block");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *oldStart = ds->escStart;
|
||||
ds->escHeap = 1;
|
||||
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;
|
||||
}
|
||||
ds->escEnd = ds->escStart + newSize;
|
||||
}
|
||||
|
||||
escOffset = ds->escStart;
|
||||
inputOffset = (JSUINT8 *) ds->start;
|
||||
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'");
|
||||
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->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 DS_ISQUOTE:
|
||||
ds->lastType = JT_UTF8;
|
||||
inputOffset ++;
|
||||
ds->start += ( (char *) inputOffset - (ds->start));
|
||||
return ds->dec->newString(ds->escStart, escOffset);
|
||||
case 'u':
|
||||
{
|
||||
int index;
|
||||
inputOffset ++;
|
||||
|
||||
case DS_UTFLENERROR:
|
||||
return SetError (ds, -1, "Invalid UTF-8 sequence length when decoding 'string'");
|
||||
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 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 '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 'u':
|
||||
{
|
||||
int index;
|
||||
inputOffset ++;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
sur[iSur] = (sur[iSur] << 4) + 10 + (JSUTF16) (*inputOffset - 'a');
|
||||
break;
|
||||
|
||||
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 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
sur[iSur] = (sur[iSur] << 4) + 10 + (JSUTF16) (*inputOffset - 'A');
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
inputOffset ++;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
sur[iSur] = (sur[iSur] << 4) + 10 + (JSUTF16) (*inputOffset - 'a');
|
||||
break;
|
||||
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 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
sur[iSur] = (sur[iSur] << 4) + 10 + (JSUTF16) (*inputOffset - 'A');
|
||||
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;
|
||||
|
||||
inputOffset ++;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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'");
|
||||
}
|
||||
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
|
||||
(*escOffset++) = (wchar_t) sur[0];
|
||||
(*escOffset++) = (wchar_t) sur[1];
|
||||
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) 0x10000 + (((sur[0] - 0xd800) << 10) | (sur[1] - 0xdc00));
|
||||
*(escOffset++) = (wchar_t) ucs;
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_array( struct DecoderState *ds)
|
||||
{
|
||||
JSOBJ itemValue;
|
||||
JSOBJ newObj = ds->dec->newArray();
|
||||
int len = 0;
|
||||
JSOBJ itemValue;
|
||||
JSOBJ newObj = ds->dec->newArray();
|
||||
int len = 0;
|
||||
|
||||
ds->lastType = JT_INVALID;
|
||||
ds->start ++;
|
||||
ds->lastType = JT_INVALID;
|
||||
ds->start ++;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SkipWhitespace(ds);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SkipWhitespace(ds);
|
||||
if ((*ds->start) == ']')
|
||||
{
|
||||
if (len == 0)
|
||||
{
|
||||
ds->start ++;
|
||||
return newObj;
|
||||
}
|
||||
|
||||
if ((*ds->start) == ']')
|
||||
{
|
||||
if (len == 0)
|
||||
{
|
||||
ds->start ++;
|
||||
return newObj;
|
||||
}
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unexpected character found when decoding array value (1)");
|
||||
}
|
||||
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unexpected character found when decoding array value (1)");
|
||||
}
|
||||
itemValue = decode_any(ds);
|
||||
|
||||
itemValue = decode_any(ds);
|
||||
if (itemValue == NULL)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (itemValue == NULL)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
return NULL;
|
||||
}
|
||||
ds->dec->arrayAddItem (newObj, itemValue);
|
||||
|
||||
ds->dec->arrayAddItem (newObj, itemValue);
|
||||
SkipWhitespace(ds);
|
||||
|
||||
SkipWhitespace(ds);
|
||||
switch (*(ds->start++))
|
||||
{
|
||||
case ']':
|
||||
return newObj;
|
||||
|
||||
switch (*(ds->start++))
|
||||
{
|
||||
case ']':
|
||||
return newObj;
|
||||
case ',':
|
||||
break;
|
||||
|
||||
case ',':
|
||||
break;
|
||||
default:
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unexpected character found when decoding array value (2)");
|
||||
}
|
||||
|
||||
default:
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unexpected character found when decoding array value (2)");
|
||||
}
|
||||
|
||||
len ++;
|
||||
}
|
||||
len ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds)
|
||||
{
|
||||
JSOBJ itemName;
|
||||
JSOBJ itemValue;
|
||||
JSOBJ newObj = ds->dec->newObject();
|
||||
JSOBJ itemName;
|
||||
JSOBJ itemValue;
|
||||
JSOBJ newObj = ds->dec->newObject();
|
||||
|
||||
ds->start ++;
|
||||
ds->start ++;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SkipWhitespace(ds);
|
||||
for (;;)
|
||||
{
|
||||
SkipWhitespace(ds);
|
||||
|
||||
if ((*ds->start) == '}')
|
||||
{
|
||||
ds->start ++;
|
||||
return newObj;
|
||||
}
|
||||
if ((*ds->start) == '}')
|
||||
{
|
||||
ds->start ++;
|
||||
return newObj;
|
||||
}
|
||||
|
||||
ds->lastType = JT_INVALID;
|
||||
itemName = decode_any(ds);
|
||||
ds->lastType = JT_INVALID;
|
||||
itemName = decode_any(ds);
|
||||
|
||||
if (itemName == NULL)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
return NULL;
|
||||
}
|
||||
if (itemName == NULL)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ds->lastType != JT_UTF8)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return SetError(ds, -1, "Key name of object must be 'string' when decoding 'object'");
|
||||
}
|
||||
if (ds->lastType != JT_UTF8)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return SetError(ds, -1, "Key name of object must be 'string' when decoding 'object'");
|
||||
}
|
||||
|
||||
SkipWhitespace(ds);
|
||||
SkipWhitespace(ds);
|
||||
|
||||
if (*(ds->start++) != ':')
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return SetError(ds, -1, "No ':' found when decoding object value");
|
||||
}
|
||||
if (*(ds->start++) != ':')
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return SetError(ds, -1, "No ':' found when decoding object value");
|
||||
}
|
||||
|
||||
SkipWhitespace(ds);
|
||||
SkipWhitespace(ds);
|
||||
|
||||
itemValue = decode_any(ds);
|
||||
itemValue = decode_any(ds);
|
||||
|
||||
if (itemValue == NULL)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return NULL;
|
||||
}
|
||||
if (itemValue == NULL)
|
||||
{
|
||||
ds->dec->releaseObject(newObj);
|
||||
ds->dec->releaseObject(itemName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ds->dec->objectAddKey (newObj, itemName, itemValue);
|
||||
ds->dec->objectAddKey (newObj, itemName, itemValue);
|
||||
|
||||
SkipWhitespace(ds);
|
||||
SkipWhitespace(ds);
|
||||
|
||||
switch (*(ds->start++))
|
||||
{
|
||||
case '}':
|
||||
return newObj;
|
||||
switch (*(ds->start++))
|
||||
{
|
||||
case '}':
|
||||
return newObj;
|
||||
|
||||
case ',':
|
||||
break;
|
||||
case ',':
|
||||
break;
|
||||
|
||||
default:
|
||||
ds->dec->releaseObject(newObj);
|
||||
return SetError(ds, -1, "Unexpected character in found when decoding object value");
|
||||
}
|
||||
}
|
||||
default:
|
||||
ds->dec->releaseObject(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);
|
||||
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 '[': 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;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
// White space
|
||||
ds->start ++;
|
||||
break;
|
||||
|
||||
default:
|
||||
return SetError(ds, -1, "Expected object or value");
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
/*
|
||||
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.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.dec = dec;
|
||||
ds.dec->errorStr = NULL;
|
||||
ds.dec->errorOffset = NULL;
|
||||
|
||||
ds.escStart = escBuffer;
|
||||
ds.escEnd = ds.escStart + (JSON_MAX_STACK_BUFFER_SIZE / sizeof(wchar_t));
|
||||
ds.escHeap = 0;
|
||||
ds.dec = dec;
|
||||
ds.dec->errorStr = NULL;
|
||||
ds.dec->errorOffset = NULL;
|
||||
ds.dec = dec;
|
||||
|
||||
ds.dec = dec;
|
||||
ret = decode_any (&ds);
|
||||
|
||||
ret = decode_any (&ds);
|
||||
if (ds.escHeap)
|
||||
{
|
||||
dec->free(ds.escStart);
|
||||
}
|
||||
|
||||
if (ds.escHeap)
|
||||
{
|
||||
dec->free(ds.escStart);
|
||||
}
|
||||
SkipWhitespace(&ds);
|
||||
|
||||
SkipWhitespace(&ds);
|
||||
if (ds.start != ds.end && ret)
|
||||
{
|
||||
dec->releaseObject(ret);
|
||||
return SetError(&ds, -1, "Trailing data");
|
||||
}
|
||||
|
||||
if (ds.start != ds.end && ret)
|
||||
{
|
||||
dec->releaseObject(ret);
|
||||
return SetError(&ds, -1, "Trailing data");
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
1373
lib/ultrajsonenc.c
1373
lib/ultrajsonenc.c
|
@ -16,7 +16,7 @@ modification, are permitted provided that the following conditions are met:
|
|||
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
|
||||
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
|
||||
|
@ -61,31 +61,30 @@ Needs a cleanup and more documentation */
|
|||
|
||||
/*
|
||||
Table for pure ascii output escaping all characters above 127 to \uXXXX */
|
||||
static const JSUINT8 g_asciiOutputTable[256] =
|
||||
static const JSUINT8 g_asciiOutputTable[256] =
|
||||
{
|
||||
/* 0x00 */ 0, 30, 30, 30, 30, 30, 30, 30, 10, 12, 14, 30, 16, 18, 30, 30,
|
||||
/* 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,
|
||||
/* 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,
|
||||
/* 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,
|
||||
/* 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,
|
||||
/* 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,
|
||||
/* 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,
|
||||
/* 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,
|
||||
/* 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;
|
||||
enc->errorMsg = message;
|
||||
enc->errorObj = obj;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -93,350 +92,357 @@ FIXME: Keep track of how big these get across several encoder calls and try to m
|
|||
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;
|
||||
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;
|
||||
}
|
||||
while (newSize < curSize + cbNeeded)
|
||||
{
|
||||
newSize *= 2;
|
||||
}
|
||||
|
||||
if (enc->heap)
|
||||
if (enc->heap)
|
||||
{
|
||||
enc->start = (char *) enc->realloc (enc->start, newSize);
|
||||
if (!enc->start)
|
||||
{
|
||||
enc->start = (char *) enc->realloc (enc->start, newSize);
|
||||
if (!enc->start)
|
||||
{
|
||||
SetError (NULL, enc, "Could not reserve memory block");
|
||||
return;
|
||||
}
|
||||
SetError (NULL, enc, "Could not reserve memory block");
|
||||
return;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
char *oldStart = enc->start;
|
||||
enc->heap = 1;
|
||||
enc->start = (char *) enc->malloc (newSize);
|
||||
if (!enc->start)
|
||||
{
|
||||
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);
|
||||
SetError (NULL, enc, "Could not reserve memory block");
|
||||
return;
|
||||
}
|
||||
enc->offset = enc->start + offset;
|
||||
enc->end = enc->start + newSize;
|
||||
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];
|
||||
*(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;
|
||||
char *of = (char *) enc->offset;
|
||||
|
||||
for (;;)
|
||||
for (;;)
|
||||
{
|
||||
switch (*io)
|
||||
{
|
||||
switch (*io)
|
||||
case 0x00:
|
||||
{
|
||||
if (io < end)
|
||||
{
|
||||
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;
|
||||
*(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;
|
||||
|
||||
io++;
|
||||
}
|
||||
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;
|
||||
JSUTF32 ucs;
|
||||
char *of = (char *) enc->offset;
|
||||
|
||||
for (;;)
|
||||
for (;;)
|
||||
{
|
||||
JSUINT8 utflen = g_asciiOutputTable[(unsigned char) *io];
|
||||
|
||||
switch (utflen)
|
||||
{
|
||||
|
||||
//JSUINT8 chr = (unsigned char) *io;
|
||||
JSUINT8 utflen = g_asciiOutputTable[(unsigned char) *io];
|
||||
|
||||
switch (utflen)
|
||||
case 0:
|
||||
{
|
||||
if (io < end)
|
||||
{
|
||||
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;
|
||||
*(of++) = '\\';
|
||||
*(of++) = 'u';
|
||||
*(of++) = '0';
|
||||
*(of++) = '0';
|
||||
*(of++) = '0';
|
||||
*(of++) = '0';
|
||||
io ++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(of++) = '\\';
|
||||
*(of++) = 'u';
|
||||
Buffer_AppendShortHexUnchecked(of, (unsigned short) ucs);
|
||||
of += 4;
|
||||
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));\
|
||||
Buffer_Realloc((__enc), (__len));\
|
||||
} \
|
||||
|
||||
|
||||
|
@ -445,180 +451,180 @@ int Buffer_EscapeStringValidated (JSOBJ obj, JSONObjectEncoder *enc, const char
|
|||
|
||||
FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC strreverse(char* begin, char* end)
|
||||
{
|
||||
char aux;
|
||||
while (end > begin)
|
||||
aux = *end, *end-- = *begin, *begin++ = aux;
|
||||
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;
|
||||
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++ = '-';
|
||||
wstr = enc->offset;
|
||||
// Conversion. Number is reversed.
|
||||
|
||||
// Reverse string
|
||||
strreverse(enc->offset,wstr - 1);
|
||||
enc->offset += (wstr - (enc->offset));
|
||||
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;
|
||||
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++ = '-';
|
||||
wstr = enc->offset;
|
||||
// Conversion. Number is reversed.
|
||||
|
||||
// Reverse string
|
||||
strreverse(enc->offset,wstr - 1);
|
||||
enc->offset += (wstr - (enc->offset));
|
||||
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 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)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* 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);
|
||||
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);
|
||||
enc->offset += snprintf(str, enc->end - enc->offset, "%.15e", neg ? -value : value);
|
||||
#endif
|
||||
return TRUE;
|
||||
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;
|
||||
}
|
||||
|
||||
if (enc->doublePrecision == 0)
|
||||
//vvvvvvvvvvvvvvvvvvv Diff from modp_dto2
|
||||
}
|
||||
else
|
||||
if (frac)
|
||||
{
|
||||
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 = 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
|
||||
}
|
||||
//^^^^^^^^^^^^^^^^^^^ 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++ = '.';
|
||||
// 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++ = '.';
|
||||
*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)
|
||||
|
||||
if (neg)
|
||||
{
|
||||
*wstr++ = '-';
|
||||
*wstr++ = '-';
|
||||
}
|
||||
strreverse(str, wstr-1);
|
||||
enc->offset += (wstr - (enc->offset));
|
||||
|
@ -626,11 +632,6 @@ int Buffer_AppendDoubleUnchecked(JSOBJ obj, JSONObjectEncoder *enc, double value
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
FIXME:
|
||||
Handle integration functions returning NULL here */
|
||||
|
@ -641,61 +642,60 @@ 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;
|
||||
const char *value;
|
||||
char *objName;
|
||||
int count;
|
||||
JSOBJ iterObj;
|
||||
size_t szlen;
|
||||
JSONTypeContext tc;
|
||||
|
||||
if (enc->level > enc->recursionMax)
|
||||
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
|
||||
|
||||
Since input is assumed to be UTF-8 the worst character length is:
|
||||
|
||||
4 bytes (of UTF-8) => "\uXXXX\uXXXX" (12 bytes)
|
||||
*/
|
||||
|
||||
Buffer_Reserve(enc, 256 + (((cbName / 4) + 1) * 12));
|
||||
if (enc->errorMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (name)
|
||||
{
|
||||
Buffer_AppendCharUnchecked(enc, '\"');
|
||||
|
||||
if (enc->forceASCII)
|
||||
{
|
||||
SetError (obj, enc, "Maximum recursion level reached");
|
||||
if (!Buffer_EscapeStringValidated(obj, enc, name, name + cbName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Buffer_EscapeStringUnvalidated(enc, name, name + cbName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This reservation must hold
|
||||
Buffer_AppendCharUnchecked(enc, '\"');
|
||||
|
||||
length of _name as encoded worst case +
|
||||
maxLength of double to string OR maxLength of JSLONG to string
|
||||
|
||||
Since input is assumed to be UTF-8 the worst character length is:
|
||||
|
||||
4 bytes (of UTF-8) => "\uXXXX\uXXXX" (12 bytes)
|
||||
*/
|
||||
|
||||
Buffer_Reserve(enc, 256 + (((cbName / 4) + 1) * 12));
|
||||
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, ':');
|
||||
Buffer_AppendCharUnchecked (enc, ':');
|
||||
#ifndef JSON_NO_EXTRA_WHITESPACE
|
||||
Buffer_AppendCharUnchecked (enc, ' ');
|
||||
Buffer_AppendCharUnchecked (enc, ' ');
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -703,210 +703,209 @@ void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t cbName)
|
|||
|
||||
switch (tc.type)
|
||||
{
|
||||
case JT_INVALID:
|
||||
return;
|
||||
case JT_INVALID:
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
case JT_ARRAY:
|
||||
case JT_ARRAY:
|
||||
{
|
||||
count = 0;
|
||||
enc->iterBegin(obj, &tc);
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, '[');
|
||||
|
||||
while (enc->iterNext(obj, &tc))
|
||||
{
|
||||
count = 0;
|
||||
enc->iterBegin(obj, &tc);
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, '[');
|
||||
|
||||
while (enc->iterNext(obj, &tc))
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
Buffer_AppendCharUnchecked (enc, ',');
|
||||
if (count > 0)
|
||||
{
|
||||
Buffer_AppendCharUnchecked (enc, ',');
|
||||
#ifndef JSON_NO_EXTRA_WHITESPACE
|
||||
Buffer_AppendCharUnchecked (buffer, ' ');
|
||||
Buffer_AppendCharUnchecked (buffer, ' ');
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
iterObj = enc->iterGetValue(obj, &tc);
|
||||
iterObj = enc->iterGetValue(obj, &tc);
|
||||
|
||||
enc->level ++;
|
||||
encode (iterObj, enc, NULL, 0);
|
||||
count ++;
|
||||
}
|
||||
enc->level ++;
|
||||
encode (iterObj, enc, NULL, 0);
|
||||
count ++;
|
||||
}
|
||||
|
||||
enc->iterEnd(obj, &tc);
|
||||
Buffer_AppendCharUnchecked (enc, ']');
|
||||
break;
|
||||
}
|
||||
enc->iterEnd(obj, &tc);
|
||||
Buffer_AppendCharUnchecked (enc, ']');
|
||||
break;
|
||||
}
|
||||
|
||||
case JT_OBJECT:
|
||||
{
|
||||
count = 0;
|
||||
enc->iterBegin(obj, &tc);
|
||||
case JT_OBJECT:
|
||||
{
|
||||
count = 0;
|
||||
enc->iterBegin(obj, &tc);
|
||||
|
||||
Buffer_AppendCharUnchecked (enc, '{');
|
||||
Buffer_AppendCharUnchecked (enc, '{');
|
||||
|
||||
while (enc->iterNext(obj, &tc))
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
Buffer_AppendCharUnchecked (enc, ',');
|
||||
while (enc->iterNext(obj, &tc))
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
Buffer_AppendCharUnchecked (enc, ',');
|
||||
#ifndef JSON_NO_EXTRA_WHITESPACE
|
||||
Buffer_AppendCharUnchecked (enc, ' ');
|
||||
Buffer_AppendCharUnchecked (enc, ' ');
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
iterObj = enc->iterGetValue(obj, &tc);
|
||||
objName = enc->iterGetName(obj, &tc, &szlen);
|
||||
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, ((szlen / 4) + 1) * 12);
|
||||
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->level ++;
|
||||
encode (iterObj, enc, objName, szlen);
|
||||
count ++;
|
||||
}
|
||||
|
||||
enc->endTypeContext(obj, &tc);
|
||||
enc->level --;
|
||||
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, ((szlen / 4) + 1) * 12);
|
||||
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;
|
||||
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)
|
||||
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)
|
||||
{
|
||||
enc->recursionMax = JSON_MAX_RECURSION_DEPTH;
|
||||
SetError(obj, enc, "Could not reserve memory block");
|
||||
return NULL;
|
||||
}
|
||||
enc->heap = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
enc->start = _buffer;
|
||||
enc->heap = 0;
|
||||
}
|
||||
|
||||
if (enc->doublePrecision < 0 ||
|
||||
enc->doublePrecision > JSON_DOUBLE_MAX_DECIMALS)
|
||||
{
|
||||
enc->doublePrecision = JSON_DOUBLE_MAX_DECIMALS;
|
||||
}
|
||||
enc->end = enc->start + _cbBuffer;
|
||||
enc->offset = enc->start;
|
||||
|
||||
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;
|
||||
}
|
||||
encode (obj, enc, NULL, 0);
|
||||
|
||||
enc->end = enc->start + _cbBuffer;
|
||||
enc->offset = enc->start;
|
||||
Buffer_Reserve(enc, 1);
|
||||
if (enc->errorMsg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
Buffer_AppendCharUnchecked(enc, '\0');
|
||||
|
||||
|
||||
encode (obj, enc, NULL, 0);
|
||||
|
||||
Buffer_Reserve(enc, 1);
|
||||
if (enc->errorMsg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
Buffer_AppendCharUnchecked(enc, '\0');
|
||||
|
||||
return enc->start;
|
||||
return enc->start;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ modification, are permitted provided that the following conditions are met:
|
|||
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
|
||||
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
|
||||
|
@ -44,202 +44,201 @@ http://www.opensource.apple.com/source/tcl/tcl-14/tcl/license.terms
|
|||
|
||||
void Object_objectAddKey(JSOBJ obj, JSOBJ name, JSOBJ value)
|
||||
{
|
||||
PyDict_SetItem (obj, name, value);
|
||||
Py_DECREF( (PyObject *) name);
|
||||
Py_DECREF( (PyObject *) value);
|
||||
return;
|
||||
PyDict_SetItem (obj, name, value);
|
||||
Py_DECREF( (PyObject *) name);
|
||||
Py_DECREF( (PyObject *) value);
|
||||
return;
|
||||
}
|
||||
|
||||
void Object_arrayAddItem(JSOBJ obj, JSOBJ value)
|
||||
{
|
||||
PyList_Append(obj, value);
|
||||
Py_DECREF( (PyObject *) value);
|
||||
return;
|
||||
PyList_Append(obj, value);
|
||||
Py_DECREF( (PyObject *) value);
|
||||
return;
|
||||
}
|
||||
|
||||
JSOBJ Object_newString(wchar_t *start, wchar_t *end)
|
||||
{
|
||||
return PyUnicode_FromWideChar (start, (end - start));
|
||||
return PyUnicode_FromWideChar (start, (end - start));
|
||||
}
|
||||
|
||||
JSOBJ Object_newTrue(void)
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
|
||||
JSOBJ Object_newFalse(void)
|
||||
{
|
||||
Py_RETURN_FALSE;
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
JSOBJ Object_newNull(void)
|
||||
{
|
||||
Py_RETURN_NONE;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
JSOBJ Object_newObject(void)
|
||||
{
|
||||
return PyDict_New();
|
||||
return PyDict_New();
|
||||
}
|
||||
|
||||
JSOBJ Object_newArray(void)
|
||||
{
|
||||
return PyList_New(0);
|
||||
return PyList_New(0);
|
||||
}
|
||||
|
||||
JSOBJ Object_newInteger(JSINT32 value)
|
||||
{
|
||||
return PyInt_FromLong( (long) value);
|
||||
return PyInt_FromLong( (long) value);
|
||||
}
|
||||
|
||||
JSOBJ Object_newLong(JSINT64 value)
|
||||
{
|
||||
return PyLong_FromLongLong (value);
|
||||
return PyLong_FromLongLong (value);
|
||||
}
|
||||
|
||||
JSOBJ Object_newDouble(double value)
|
||||
{
|
||||
return PyFloat_FromDouble(value);
|
||||
{
|
||||
return PyFloat_FromDouble(value);
|
||||
}
|
||||
|
||||
static void Object_releaseObject(JSOBJ obj)
|
||||
{
|
||||
Py_DECREF( ((PyObject *)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
|
||||
};
|
||||
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.preciseFloat = 0;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", g_kwlist, &arg, &opreciseFloat))
|
||||
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)
|
||||
{
|
||||
return 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);
|
||||
}
|
||||
|
||||
if (opreciseFloat && PyObject_IsTrue(opreciseFloat))
|
||||
{
|
||||
decoder.preciseFloat = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject* JSONFileToObj(PyObject* self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
PyObject *read;
|
||||
PyObject *string;
|
||||
PyObject *result;
|
||||
PyObject *file = NULL;
|
||||
PyObject *argtuple;
|
||||
PyObject *read;
|
||||
PyObject *string;
|
||||
PyObject *result;
|
||||
PyObject *file = NULL;
|
||||
PyObject *argtuple;
|
||||
|
||||
if (!PyArg_ParseTuple (args, "O", &file))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple (args, "O", &file))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyObject_HasAttrString (file, "read"))
|
||||
{
|
||||
PyErr_Format (PyExc_TypeError, "expected file");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyObject_HasAttrString (file, "read"))
|
||||
{
|
||||
PyErr_Format (PyExc_TypeError, "expected file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
read = PyObject_GetAttrString (file, "read");
|
||||
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);
|
||||
if (!PyCallable_Check (read)) {
|
||||
Py_XDECREF(read);
|
||||
PyErr_Format (PyExc_TypeError, "expected file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (string == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
string = PyObject_CallObject (read, NULL);
|
||||
Py_XDECREF(read);
|
||||
|
||||
argtuple = PyTuple_Pack(1, string);
|
||||
if (string == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = JSONToObj (self, argtuple, kwargs);
|
||||
argtuple = PyTuple_Pack(1, string);
|
||||
|
||||
Py_XDECREF(argtuple);
|
||||
Py_XDECREF(string);
|
||||
result = JSONToObj (self, argtuple, kwargs);
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Py_XDECREF(argtuple);
|
||||
Py_XDECREF(string);
|
||||
|
||||
return result;
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ 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
|
||||
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
|
||||
|
@ -45,168 +45,164 @@ 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;
|
||||
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;
|
||||
PyObject *keys;
|
||||
size_t i;
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
|
||||
//#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__)
|
||||
#define PRINTMARK()
|
||||
//#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);
|
||||
PyObject* mod_decimal = PyImport_ImportModule("decimal");
|
||||
type_decimal = PyObject_GetAttrString(mod_decimal, "Decimal");
|
||||
Py_INCREF(type_decimal);
|
||||
Py_DECREF(mod_decimal);
|
||||
|
||||
PyDateTime_IMPORT;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
*((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;
|
||||
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);
|
||||
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);
|
||||
PyObject *obj = (PyObject *) _obj;
|
||||
PyObject *newObj = PyUnicode_EncodeUTF8 (PyUnicode_AS_UNICODE(obj), PyUnicode_GET_SIZE(obj), NULL);
|
||||
|
||||
GET_TC(tc)->newObj = newObj;
|
||||
GET_TC(tc)->newObj = newObj;
|
||||
|
||||
*_outLen = PyString_GET_SIZE(newObj);
|
||||
return PyString_AS_STRING(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;
|
||||
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);
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Tuple iteration functions
|
||||
// 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;
|
||||
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;
|
||||
PyObject *item;
|
||||
|
||||
if (GET_TC(tc)->index >= GET_TC(tc)->size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (GET_TC(tc)->index >= GET_TC(tc)->size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = PyTuple_GET_ITEM (obj, GET_TC(tc)->index);
|
||||
item = PyTuple_GET_ITEM (obj, GET_TC(tc)->index);
|
||||
|
||||
GET_TC(tc)->itemValue = item;
|
||||
GET_TC(tc)->index ++;
|
||||
return 1;
|
||||
GET_TC(tc)->itemValue = item;
|
||||
GET_TC(tc)->index ++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Tuple_iterEnd(JSOBJ obj, JSONTypeContext *tc)
|
||||
|
@ -215,217 +211,212 @@ void Tuple_iterEnd(JSOBJ obj, JSONTypeContext *tc)
|
|||
|
||||
JSOBJ Tuple_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
|
||||
{
|
||||
return GET_TC(tc)->itemValue;
|
||||
return GET_TC(tc)->itemValue;
|
||||
}
|
||||
|
||||
char *Tuple_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
|
||||
{
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Iterator iteration functions
|
||||
// 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);
|
||||
GET_TC(tc)->itemValue = NULL;
|
||||
GET_TC(tc)->iterator = PyObject_GetIter(obj);
|
||||
}
|
||||
|
||||
int Iter_iterNext(JSOBJ obj, JSONTypeContext *tc)
|
||||
{
|
||||
PyObject *item;
|
||||
PyObject *item;
|
||||
|
||||
if (GET_TC(tc)->itemValue)
|
||||
{
|
||||
Py_DECREF(GET_TC(tc)->itemValue);
|
||||
GET_TC(tc)->itemValue = NULL;
|
||||
}
|
||||
if (GET_TC(tc)->itemValue)
|
||||
{
|
||||
Py_DECREF(GET_TC(tc)->itemValue);
|
||||
GET_TC(tc)->itemValue = NULL;
|
||||
}
|
||||
|
||||
item = PyIter_Next(GET_TC(tc)->iterator);
|
||||
item = PyIter_Next(GET_TC(tc)->iterator);
|
||||
|
||||
if (item == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (item == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GET_TC(tc)->itemValue = item;
|
||||
return 1;
|
||||
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)->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;
|
||||
}
|
||||
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;
|
||||
return GET_TC(tc)->itemValue;
|
||||
}
|
||||
|
||||
char *Iter_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
|
||||
{
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Dir iteration functions
|
||||
// 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();
|
||||
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)->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;
|
||||
}
|
||||
if (GET_TC(tc)->itemName)
|
||||
{
|
||||
Py_DECREF(GET_TC(tc)->itemName);
|
||||
GET_TC(tc)->itemName = NULL;
|
||||
}
|
||||
|
||||
Py_DECREF( (PyObject *) GET_TC(tc)->attrList);
|
||||
PRINTMARK();
|
||||
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;
|
||||
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 (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;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
attr = PyUnicode_AsUTF8String(attrName);
|
||||
#else
|
||||
attr = attrName;
|
||||
Py_INCREF(attr);
|
||||
#endif
|
||||
attrStr = PyString_AS_STRING(attr);
|
||||
attrStr = PyString_AS_STRING(attr);
|
||||
|
||||
if (attrStr[0] == '_')
|
||||
{
|
||||
PRINTMARK();
|
||||
Py_DECREF(attr);
|
||||
continue;
|
||||
}
|
||||
if (attrStr[0] == '_')
|
||||
{
|
||||
PRINTMARK();
|
||||
Py_DECREF(attr);
|
||||
continue;
|
||||
}
|
||||
|
||||
itemValue = PyObject_GetAttr(obj, attrName);
|
||||
if (itemValue == NULL)
|
||||
{
|
||||
PyErr_Clear();
|
||||
Py_DECREF(attr);
|
||||
PRINTMARK();
|
||||
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;
|
||||
}
|
||||
if (PyCallable_Check(itemValue))
|
||||
{
|
||||
Py_DECREF(itemValue);
|
||||
Py_DECREF(attr);
|
||||
PRINTMARK();
|
||||
continue;
|
||||
}
|
||||
|
||||
PRINTMARK();
|
||||
itemName = attr;
|
||||
break;
|
||||
}
|
||||
PRINTMARK();
|
||||
itemName = attr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (itemName == NULL)
|
||||
{
|
||||
GET_TC(tc)->index = GET_TC(tc)->size;
|
||||
GET_TC(tc)->itemValue = NULL;
|
||||
return 0;
|
||||
}
|
||||
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 ++;
|
||||
GET_TC(tc)->itemName = itemName;
|
||||
GET_TC(tc)->itemValue = itemValue;
|
||||
GET_TC(tc)->index ++;
|
||||
|
||||
PRINTMARK();
|
||||
return 1;
|
||||
PRINTMARK();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
JSOBJ Dir_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
|
||||
{
|
||||
PRINTMARK();
|
||||
return GET_TC(tc)->itemValue;
|
||||
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);
|
||||
PRINTMARK();
|
||||
*outLen = PyString_GET_SIZE(GET_TC(tc)->itemName);
|
||||
return PyString_AS_STRING(GET_TC(tc)->itemName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
// List iteration functions
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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)
|
||||
|
@ -434,218 +425,216 @@ void List_iterEnd(JSOBJ obj, JSONTypeContext *tc)
|
|||
|
||||
JSOBJ List_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
|
||||
{
|
||||
return GET_TC(tc)->itemValue;
|
||||
return GET_TC(tc)->itemValue;
|
||||
}
|
||||
|
||||
char *List_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
|
||||
{
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Dict iteration functions
|
||||
// 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();
|
||||
GET_TC(tc)->index = 0;
|
||||
PRINTMARK();
|
||||
}
|
||||
|
||||
int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc)
|
||||
{
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject* itemNameTmp;
|
||||
PyObject* itemNameTmp;
|
||||
#endif
|
||||
|
||||
if (GET_TC(tc)->itemName)
|
||||
{
|
||||
Py_DECREF(GET_TC(tc)->itemName);
|
||||
GET_TC(tc)->itemName = NULL;
|
||||
}
|
||||
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 (!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 (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);
|
||||
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;
|
||||
}
|
||||
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();
|
||||
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;
|
||||
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);
|
||||
*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;
|
||||
}
|
||||
PyObject *obj, *exc, *toDictFunc;
|
||||
TypeContext *pc;
|
||||
PRINTMARK();
|
||||
if (!_obj) {
|
||||
tc->type = JT_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
obj = (PyObject*) _obj;
|
||||
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;
|
||||
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 (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);
|
||||
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();
|
||||
exc = PyErr_Occurred();
|
||||
|
||||
if (exc && PyErr_ExceptionMatches(PyExc_OverflowError))
|
||||
{
|
||||
PRINTMARK();
|
||||
goto INVALID;
|
||||
}
|
||||
if (exc && PyErr_ExceptionMatches(PyExc_OverflowError))
|
||||
{
|
||||
PRINTMARK();
|
||||
goto INVALID;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (PyInt_Check(obj))
|
||||
{
|
||||
PRINTMARK();
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (PyInt_Check(obj))
|
||||
{
|
||||
PRINTMARK();
|
||||
#ifdef _LP64
|
||||
pc->PyTypeToJSON = PyIntToINT64; tc->type = JT_LONG;
|
||||
pc->PyTypeToJSON = PyIntToINT64; tc->type = JT_LONG;
|
||||
#else
|
||||
pc->PyTypeToJSON = PyIntToINT32; tc->type = JT_INT;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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))
|
||||
{
|
||||
|
@ -681,10 +670,8 @@ ISITERABLE:
|
|||
pc->iterGetValue = Iter_iterGetValue;
|
||||
pc->iterGetName = Iter_iterGetName;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
toDictFunc = PyObject_GetAttrString(obj, "toDict");
|
||||
|
||||
if (toDictFunc)
|
||||
|
@ -721,14 +708,13 @@ ISITERABLE:
|
|||
|
||||
PyErr_Clear();
|
||||
|
||||
PRINTMARK();
|
||||
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:
|
||||
|
@ -738,7 +724,6 @@ INVALID:
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
void Object_endTypeContext(JSOBJ obj, JSONTypeContext *tc)
|
||||
{
|
||||
Py_XDECREF(GET_TC(tc)->newObj);
|
||||
|
@ -756,7 +741,6 @@ JSINT64 Object_getLongValue(JSOBJ obj, JSONTypeContext *tc)
|
|||
{
|
||||
JSINT64 ret;
|
||||
GET_TC(tc)->PyTypeToJSON (obj, tc, &ret, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -767,7 +751,6 @@ JSINT32 Object_getIntValue(JSOBJ obj, JSONTypeContext *tc)
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
double Object_getDoubleValue(JSOBJ obj, JSONTypeContext *tc)
|
||||
{
|
||||
double ret;
|
||||
|
@ -780,8 +763,6 @@ static void Object_releaseObject(JSOBJ _obj)
|
|||
Py_DECREF( (PyObject *) _obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Object_iterBegin(JSOBJ obj, JSONTypeContext *tc)
|
||||
{
|
||||
GET_TC(tc)->iterBegin(obj, tc);
|
||||
|
@ -807,7 +788,6 @@ 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};
|
||||
|
@ -820,7 +800,7 @@ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs)
|
|||
int idoublePrecision = 10; // default double precision setting
|
||||
PyObject *oencodeHTMLChars = NULL;
|
||||
|
||||
JSONObjectEncoder encoder =
|
||||
JSONObjectEncoder encoder =
|
||||
{
|
||||
Object_beginTypeContext, //void (*beginTypeContext)(JSOBJ obj, JSONTypeContext *tc);
|
||||
Object_endTypeContext, //void (*endTypeContext)(JSOBJ obj, JSONTypeContext *tc);
|
||||
|
@ -851,7 +831,6 @@ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (oensureAscii != NULL && !PyObject_IsTrue(oensureAscii))
|
||||
{
|
||||
encoder.forceASCII = 0;
|
||||
|
@ -957,7 +936,4 @@ PyObject* objToJSONFile(PyObject* self, PyObject *args, PyObject *kwargs)
|
|||
PRINTMARK();
|
||||
|
||||
Py_RETURN_NONE;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ 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
|
||||
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
|
||||
|
@ -55,27 +55,27 @@ 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 */
|
||||
{"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 */
|
||||
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)
|
||||
|
@ -92,21 +92,21 @@ static struct PyModuleDef moduledef = {
|
|||
|
||||
PYMODINITFUNC
|
||||
{
|
||||
PyObject *module;
|
||||
PyObject *version_string;
|
||||
PyObject *module;
|
||||
PyObject *version_string;
|
||||
|
||||
initObjToJSON();
|
||||
module = PYMODULE_CREATE();
|
||||
initObjToJSON();
|
||||
module = PYMODULE_CREATE();
|
||||
|
||||
if (module == NULL)
|
||||
{
|
||||
MODINITERROR;
|
||||
}
|
||||
if (module == NULL)
|
||||
{
|
||||
MODINITERROR;
|
||||
}
|
||||
|
||||
version_string = PyString_FromString (UJSON_VERSION);
|
||||
PyModule_AddObject (module, "__version__", version_string);
|
||||
version_string = PyString_FromString (UJSON_VERSION);
|
||||
PyModule_AddObject (module, "__version__", version_string);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return module;
|
||||
return module;
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue