1
0
Fork 0
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:
Mikhail Sychev 2013-05-08 13:52:53 -07:00
parent af4644b4a6
commit e098bd1ce9
6 changed files with 2015 additions and 2038 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
}