@ -20,8 +20,8 @@
THE SOFTWARE .
*/
// cJSON
// JSON parser in C.
/* cJSON */
/* JSON parser in C. */
# include <string.h>
# include <stdio.h>
@ -65,7 +65,7 @@ void cJSON_InitHooks(cJSON_Hooks* hooks)
cJSON_free = ( hooks - > free_fn ) ? hooks - > free_fn : free ;
}
// Internal constructor.
/* Internal constructor. */
static cJSON * cJSON_New_Item ( )
{
cJSON * node = ( cJSON * ) cJSON_malloc ( sizeof ( cJSON ) ) ;
@ -73,7 +73,7 @@ static cJSON *cJSON_New_Item()
return node ;
}
// Delete a cJSON structure.
/* Delete a cJSON structure. */
void cJSON_Delete ( cJSON * c )
{
cJSON * next ;
@ -88,22 +88,22 @@ void cJSON_Delete(cJSON *c)
}
}
// Parse the input text to generate a number, and populate the result into item.
/* Parse the input text to generate a number, and populate the result into item. */
static const char * parse_number ( cJSON * item , const char * num )
{
double n = 0 , sign = 1 , scale = 0 ; int subscale = 0 , signsubscale = 1 ;
// Could use sscanf for this?
if ( * num = = ' - ' ) sign = - 1 , num + + ; // Has sign?
if ( * num = = ' 0 ' ) num + + ; // is zero
if ( * num > = ' 1 ' & & * num < = ' 9 ' ) do n = ( n * 10.0 ) + ( * num + + - ' 0 ' ) ; while ( * num > = ' 0 ' & & * num < = ' 9 ' ) ; // Number?
if ( * num = = ' . ' ) { num + + ; do n = ( n * 10.0 ) + ( * num + + - ' 0 ' ) , scale - - ; while ( * num > = ' 0 ' & & * num < = ' 9 ' ) ; } // Fractional part?
if ( * num = = ' e ' | | * num = = ' E ' ) // Exponent?
{ num + + ; if ( * num = = ' + ' ) num + + ; else if ( * num = = ' - ' ) signsubscale = - 1 , num + + ; // With sign?
while ( * num > = ' 0 ' & & * num < = ' 9 ' ) subscale = ( subscale * 10 ) + ( * num + + - ' 0 ' ) ; // Number?
/* Could use sscanf for this? */
if ( * num = = ' - ' ) sign = - 1 , num + + ; /* Has sign? */
if ( * num = = ' 0 ' ) num + + ; /* is zero */
if ( * num > = ' 1 ' & & * num < = ' 9 ' ) do n = ( n * 10.0 ) + ( * num + + - ' 0 ' ) ; while ( * num > = ' 0 ' & & * num < = ' 9 ' ) ; /* Number? */
if ( * num = = ' . ' ) { num + + ; do n = ( n * 10.0 ) + ( * num + + - ' 0 ' ) , scale - - ; while ( * num > = ' 0 ' & & * num < = ' 9 ' ) ; } /* Fractional part? */
if ( * num = = ' e ' | | * num = = ' E ' ) /* Exponent? */
{ num + + ; if ( * num = = ' + ' ) num + + ; else if ( * num = = ' - ' ) signsubscale = - 1 , num + + ; /* With sign? */
while ( * num > = ' 0 ' & & * num < = ' 9 ' ) subscale = ( subscale * 10 ) + ( * num + + - ' 0 ' ) ; /* Number? */
}
n = sign * n * pow ( 10.0 , ( scale + subscale * signsubscale ) ) ; // number = +/- number.fraction * 10^+/- exponent
n = sign * n * pow ( 10.0 , ( scale + subscale * signsubscale ) ) ; /* number = +/- number.fraction * 10^+/- exponent */
item - > valuedouble = n ;
item - > valueint = ( int ) n ;
@ -111,19 +111,19 @@ static const char *parse_number(cJSON *item,const char *num)
return num ;
}
// Render the number nicely from the given item into a string.
/* Render the number nicely from the given item into a string. */
static char * print_number ( cJSON * item )
{
char * str ;
double d = item - > valuedouble ;
if ( fabs ( ( ( double ) item - > valueint ) - d ) < = DBL_EPSILON & & d < = INT_MAX & & d > = INT_MIN )
{
str = ( char * ) cJSON_malloc ( 21 ) ; // 2^64+1 can be represented in 21 chars.
str = ( char * ) cJSON_malloc ( 21 ) ; /* 2^64+1 can be represented in 21 chars. */
if ( str ) sprintf ( str , " %d " , item - > valueint ) ;
}
else
{
str = ( char * ) cJSON_malloc ( 64 ) ; // This is a nice tradeoff.
str = ( char * ) cJSON_malloc ( 64 ) ; /* This is a nice tradeoff. */
if ( str )
{
if ( fabs ( floor ( d ) - d ) < = DBL_EPSILON ) sprintf ( str , " %.0f " , d ) ;
@ -134,16 +134,16 @@ static char *print_number(cJSON *item)
return str ;
}
// Parse the input text into an unescaped cstring, and populate item.
/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark [ 7 ] = { 0x00 , 0x00 , 0xC0 , 0xE0 , 0xF0 , 0xF8 , 0xFC } ;
static const char * parse_string ( cJSON * item , const char * str )
{
const char * ptr = str + 1 ; char * ptr2 ; char * out ; int len = 0 ; unsigned uc ;
if ( * str ! = ' \" ' ) return 0 ; // not a string!
if ( * str ! = ' \" ' ) return 0 ; /* not a string! */
while ( * ptr ! = ' \" ' & & ( unsigned char ) * ptr > 31 & & + + len ) if ( * ptr + + = = ' \\ ' ) ptr + + ; // Skip escaped quotes.
while ( * ptr ! = ' \" ' & & ( unsigned char ) * ptr > 31 & & + + len ) if ( * ptr + + = = ' \\ ' ) ptr + + ; /* Skip escaped quotes. */
out = ( char * ) cJSON_malloc ( len + 1 ) ; // This is how long we need for the string, roughly.
out = ( char * ) cJSON_malloc ( len + 1 ) ; /* This is how long we need for the string, roughly. */
if ( ! out ) return 0 ;
ptr = str + 1 ; ptr2 = out ;
@ -160,8 +160,8 @@ static const char *parse_string(cJSON *item,const char *str)
case ' n ' : * ptr2 + + = ' \n ' ; break ;
case ' r ' : * ptr2 + + = ' \r ' ; break ;
case ' t ' : * ptr2 + + = ' \t ' ; break ;
case ' u ' : // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY.
sscanf ( ptr + 1 , " %4x " , & uc ) ; // get the unicode char.
case ' u ' : /* transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY. */
sscanf ( ptr + 1 , " %4x " , & uc ) ; /* get the unicode char. */
len = 3 ; if ( uc < 0x80 ) len = 1 ; else if ( uc < 0x800 ) len = 2 ; ptr2 + = len ;
switch ( len ) {
@ -183,7 +183,7 @@ static const char *parse_string(cJSON *item,const char *str)
return ptr ;
}
// Render the cstring provided to an escaped version that can be printed.
/* Render the cstring provided to an escaped version that can be printed. */
static char * print_string_ptr ( const char * str )
{
const char * ptr ; char * ptr2 , * out ; int len = 0 ;
@ -211,17 +211,17 @@ static char *print_string_ptr(const char *str)
case ' \n ' : * ptr2 + + = ' n ' ; break ;
case ' \r ' : * ptr2 + + = ' r ' ; break ;
case ' \t ' : * ptr2 + + = ' t ' ; break ;
default : ptr2 - - ; break ; // eviscerate with prejudice.
default : ptr2 - - ; break ; /* eviscerate with prejudice. */
}
}
}
* ptr2 + + = ' \" ' ; * ptr2 + + = 0 ;
return out ;
}
// Invote print_string_ptr (which is useful) on an item.
/* Invote print_string_ptr (which is useful) on an item. */
static char * print_string ( cJSON * item ) { return print_string_ptr ( item - > valuestring ) ; }
// Predeclare these prototypes.
/* Predeclare these prototypes. */
static const char * parse_value ( cJSON * item , const char * value ) ;
static char * print_value ( cJSON * item , int depth , int fmt ) ;
static const char * parse_array ( cJSON * item , const char * value ) ;
@ -229,10 +229,10 @@ static char *print_array(cJSON *item,int depth,int fmt);
static const char * parse_object ( cJSON * item , const char * value ) ;
static char * print_object ( cJSON * item , int depth , int fmt ) ;
// Utility to jump whitespace and cr/lf
/* Utility to jump whitespace and cr/lf */
static const char * skip ( const char * in ) { while ( in & & ( unsigned char ) * in < = 32 ) in + + ; return in ; }
// Parse an object - create a new root, and populate.
/* Parse an object - create a new root, and populate. */
cJSON * cJSON_Parse ( const char * value )
{
cJSON * c = cJSON_New_Item ( ) ;
@ -242,14 +242,14 @@ cJSON *cJSON_Parse(const char *value)
return c ;
}
// Render a cJSON item/entity/structure to text.
/* Render a cJSON item/entity/structure to text. */
char * cJSON_Print ( cJSON * item ) { return print_value ( item , 0 , 1 ) ; }
char * cJSON_PrintUnformatted ( cJSON * item ) { return print_value ( item , 0 , 0 ) ; }
// Parser core - when encountering text, process appropriately.
/* Parser core - when encountering text, process appropriately. */
static const char * parse_value ( cJSON * item , const char * value )
{
if ( ! value ) return 0 ; // Fail on null.
if ( ! value ) return 0 ; /* Fail on null. */
if ( ! strncmp ( value , " null " , 4 ) ) { item - > type = cJSON_NULL ; return value + 4 ; }
if ( ! strncmp ( value , " false " , 5 ) ) { item - > type = cJSON_False ; return value + 5 ; }
if ( ! strncmp ( value , " true " , 4 ) ) { item - > type = cJSON_True ; item - > valueint = 1 ; return value + 4 ; }
@ -258,10 +258,10 @@ static const char *parse_value(cJSON *item,const char *value)
if ( * value = = ' [ ' ) { return parse_array ( item , value ) ; }
if ( * value = = ' { ' ) { return parse_object ( item , value ) ; }
return 0 ; // failure.
return 0 ; /* failure. */
}
// Render a value to text.
/* Render a value to text. */
static char * print_value ( cJSON * item , int depth , int fmt )
{
char * out = 0 ;
@ -279,35 +279,35 @@ static char *print_value(cJSON *item,int depth,int fmt)
return out ;
}
// Build an array from input text.
/* Build an array from input text. */
static const char * parse_array ( cJSON * item , const char * value )
{
cJSON * child ;
if ( * value ! = ' [ ' ) return 0 ; // not an array!
if ( * value ! = ' [ ' ) return 0 ; /* not an array! */
item - > type = cJSON_Array ;
value = skip ( value + 1 ) ;
if ( * value = = ' ] ' ) return value + 1 ; // empty array.
if ( * value = = ' ] ' ) return value + 1 ; /* empty array. */
item - > child = child = cJSON_New_Item ( ) ;
if ( ! item - > child ) return 0 ; // memory fail
value = skip ( parse_value ( child , skip ( value ) ) ) ; // skip any spacing, get the value.
if ( ! item - > child ) return 0 ; /* memory fail */
value = skip ( parse_value ( child , skip ( value ) ) ) ; /* skip any spacing, get the value. */
if ( ! value ) return 0 ;
while ( * value = = ' , ' )
{
cJSON * new_item ;
if ( ! ( new_item = cJSON_New_Item ( ) ) ) return 0 ; // memory fail
if ( ! ( new_item = cJSON_New_Item ( ) ) ) return 0 ; /* memory fail */
child - > next = new_item ; new_item - > prev = child ; child = new_item ;
value = skip ( parse_value ( child , skip ( value + 1 ) ) ) ;
if ( ! value ) return 0 ; // memory fail
if ( ! value ) return 0 ; /* memory fail */
}
if ( * value = = ' ] ' ) return value + 1 ; // end of array
return 0 ; // malformed.
if ( * value = = ' ] ' ) return value + 1 ; /* end of array */
return 0 ; /* malformed. */
}
// Render an array to text
/* Render an array to text */
static char * print_array ( cJSON * item , int depth , int fmt )
{
char * * entries ;
@ -315,13 +315,13 @@ static char *print_array(cJSON *item,int depth,int fmt)
cJSON * child = item - > child ;
int numentries = 0 , i = 0 , fail = 0 ;
// How many entries in the array?
/* How many entries in the array? */
while ( child ) numentries + + , child = child - > next ;
// Allocate an array to hold the values for each
/* Allocate an array to hold the values for each */
entries = ( char * * ) cJSON_malloc ( numentries * sizeof ( char * ) ) ;
if ( ! entries ) return 0 ;
memset ( entries , 0 , numentries * sizeof ( char * ) ) ;
// Retrieve all the results:
/* Retrieve all the results: */
child = item - > child ;
while ( child & & ! fail )
{
@ -331,12 +331,12 @@ static char *print_array(cJSON *item,int depth,int fmt)
child = child - > next ;
}
// If we didn't fail, try to malloc the output string
/* If we didn't fail, try to malloc the output string */
if ( ! fail ) out = cJSON_malloc ( len ) ;
// If that fails, we fail.
/* If that fails, we fail. */
if ( ! out ) fail = 1 ;
// Handle failure.
/* Handle failure. */
if ( fail )
{
for ( i = 0 ; i < numentries ; i + + ) if ( entries [ i ] ) cJSON_free ( entries [ i ] ) ;
@ -344,7 +344,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
return 0 ;
}
// Compose the output array.
/* Compose the output array. */
* out = ' [ ' ;
ptr = out + 1 ; * ptr = 0 ;
for ( i = 0 ; i < numentries ; i + + )
@ -358,52 +358,52 @@ static char *print_array(cJSON *item,int depth,int fmt)
return out ;
}
// Build an object from the text.
/* Build an object from the text. */
static const char * parse_object ( cJSON * item , const char * value )
{
cJSON * child ;
if ( * value ! = ' { ' ) return 0 ; // not an object!
if ( * value ! = ' { ' ) return 0 ; /* not an object! */
item - > type = cJSON_Object ;
value = skip ( value + 1 ) ;
if ( * value = = ' } ' ) return value + 1 ; // empty array.
if ( * value = = ' } ' ) return value + 1 ; /* empty array. */
item - > child = child = cJSON_New_Item ( ) ;
if ( ! item - > child ) return 0 ;
value = skip ( parse_string ( child , skip ( value ) ) ) ;
if ( ! value ) return 0 ;
child - > string = child - > valuestring ; child - > valuestring = 0 ;
if ( * value ! = ' : ' ) return 0 ; // fail!
value = skip ( parse_value ( child , skip ( value + 1 ) ) ) ; // skip any spacing, get the value.
if ( * value ! = ' : ' ) return 0 ; /* fail! */
value = skip ( parse_value ( child , skip ( value + 1 ) ) ) ; /* skip any spacing, get the value. */
if ( ! value ) return 0 ;
while ( * value = = ' , ' )
{
cJSON * new_item ;
if ( ! ( new_item = cJSON_New_Item ( ) ) ) return 0 ; // memory fail
if ( ! ( new_item = cJSON_New_Item ( ) ) ) return 0 ; /* memory fail */
child - > next = new_item ; new_item - > prev = child ; child = new_item ;
value = skip ( parse_string ( child , skip ( value + 1 ) ) ) ;
if ( ! value ) return 0 ;
child - > string = child - > valuestring ; child - > valuestring = 0 ;
if ( * value ! = ' : ' ) return 0 ; // fail!
value = skip ( parse_value ( child , skip ( value + 1 ) ) ) ; // skip any spacing, get the value.
if ( * value ! = ' : ' ) return 0 ; /* fail! */
value = skip ( parse_value ( child , skip ( value + 1 ) ) ) ; /* skip any spacing, get the value. */
if ( ! value ) return 0 ;
}
if ( * value = = ' } ' ) return value + 1 ; // end of array
return 0 ; // malformed.
if ( * value = = ' } ' ) return value + 1 ; /* end of array */
return 0 ; /* malformed. */
}
// Render an object to text.
/* Render an object to text. */
static char * print_object ( cJSON * item , int depth , int fmt )
{
char * * entries = 0 , * * names = 0 ;
char * out = 0 , * ptr , * ret , * str ; int len = 7 , i = 0 , j ;
cJSON * child = item - > child ;
int numentries = 0 , fail = 0 ;
// Count the number of entries.
/* Count the number of entries. */
while ( child ) numentries + + , child = child - > next ;
// Allocate space for the names and the objects
/* Allocate space for the names and the objects */
entries = ( char * * ) cJSON_malloc ( numentries * sizeof ( char * ) ) ;
if ( ! entries ) return 0 ;
names = ( char * * ) cJSON_malloc ( numentries * sizeof ( char * ) ) ;
@ -411,7 +411,7 @@ static char *print_object(cJSON *item,int depth,int fmt)
memset ( entries , 0 , sizeof ( char * ) * numentries ) ;
memset ( names , 0 , sizeof ( char * ) * numentries ) ;
// Collect all the results into our arrays:
/* Collect all the results into our arrays: */
child = item - > child ; depth + + ; if ( fmt ) len + = depth ;
while ( child )
{
@ -421,11 +421,11 @@ static char *print_object(cJSON *item,int depth,int fmt)
child = child - > next ;
}
// Try to allocate the output string
/* Try to allocate the output string */
if ( ! fail ) out = ( char * ) cJSON_malloc ( len ) ;
if ( ! out ) fail = 1 ;
// Handle failure
/* Handle failure */
if ( fail )
{
for ( i = 0 ; i < numentries ; i + + ) { if ( names [ i ] ) free ( names [ i ] ) ; if ( entries [ i ] ) free ( entries [ i ] ) ; }
@ -433,7 +433,7 @@ static char *print_object(cJSON *item,int depth,int fmt)
return 0 ;
}
// Compose the output:
/* Compose the output: */
* out = ' { ' ; ptr = out + 1 ; if ( fmt ) * ptr + + = ' \n ' ; * ptr = 0 ;
for ( i = 0 ; i < numentries ; i + + )
{
@ -452,17 +452,17 @@ static char *print_object(cJSON *item,int depth,int fmt)
return out ;
}
// Get Array size/item / object item.
/* Get Array size/item / object item. */
int cJSON_GetArraySize ( cJSON * array ) { cJSON * c = array - > child ; int i = 0 ; while ( c ) i + + , c = c - > next ; return i ; }
cJSON * cJSON_GetArrayItem ( cJSON * array , int item ) { cJSON * c = array - > child ; while ( c & & item > 0 ) item - - , c = c - > next ; return c ; }
cJSON * cJSON_GetObjectItem ( cJSON * object , const char * string ) { cJSON * c = object - > child ; while ( c & & cJSON_strcasecmp ( c - > string , string ) ) c = c - > next ; return c ; }
// Utility for array list handling.
/* Utility for array list handling. */
static void suffix_object ( cJSON * prev , cJSON * item ) { prev - > next = item ; item - > prev = prev ; }
// Utility for handling references.
/* Utility for handling references. */
static cJSON * create_reference ( cJSON * item ) { cJSON * ref = cJSON_New_Item ( ) ; if ( ! ref ) return 0 ; memcpy ( ref , item , sizeof ( cJSON ) ) ; ref - > string = 0 ; ref - > type | = cJSON_IsReference ; ref - > next = ref - > prev = 0 ; return ref ; }
// Add item to array/object.
/* Add item to array/object. */
void cJSON_AddItemToArray ( cJSON * array , cJSON * item ) { cJSON * c = array - > child ; if ( ! item ) return ; if ( ! c ) { array - > child = item ; } else { while ( c & & c - > next ) c = c - > next ; suffix_object ( c , item ) ; } }
void cJSON_AddItemToObject ( cJSON * object , const char * string , cJSON * item ) { if ( ! item ) return ; if ( item - > string ) cJSON_free ( item - > string ) ; item - > string = cJSON_strdup ( string ) ; cJSON_AddItemToArray ( object , item ) ; }
void cJSON_AddItemReferenceToArray ( cJSON * array , cJSON * item ) { cJSON_AddItemToArray ( array , create_reference ( item ) ) ; }
@ -474,13 +474,13 @@ void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_D
cJSON * cJSON_DetachItemFromObject ( cJSON * object , const char * string ) { int i = 0 ; cJSON * c = object - > child ; while ( c & & cJSON_strcasecmp ( c - > string , string ) ) i + + , c = c - > next ; if ( c ) return cJSON_DetachItemFromArray ( object , i ) ; return 0 ; }
void cJSON_DeleteItemFromObject ( cJSON * object , const char * string ) { cJSON_Delete ( cJSON_DetachItemFromObject ( object , string ) ) ; }
// Replace array/object items with new ones.
/* Replace array/object items with new ones. */
void cJSON_ReplaceItemInArray ( cJSON * array , int which , cJSON * newitem ) { cJSON * c = array - > child ; while ( c & & which > 0 ) c = c - > next , which - - ; if ( ! c ) return ;
newitem - > next = c - > next ; newitem - > prev = c - > prev ; if ( newitem - > next ) newitem - > next - > prev = newitem ;
if ( c = = array - > child ) array - > child = newitem ; else newitem - > prev - > next = newitem ; c - > next = c - > prev = 0 ; cJSON_Delete ( c ) ; }
void cJSON_ReplaceItemInObject ( cJSON * object , const char * string , cJSON * newitem ) { int i = 0 ; cJSON * c = object - > child ; while ( c & & cJSON_strcasecmp ( c - > string , string ) ) i + + , c = c - > next ; if ( c ) { newitem - > string = cJSON_strdup ( string ) ; cJSON_ReplaceItemInArray ( object , i , newitem ) ; } }
// Create basic types:
/* Create basic types: */
cJSON * cJSON_CreateNull ( ) { cJSON * item = cJSON_New_Item ( ) ; if ( item ) item - > type = cJSON_NULL ; return item ; }
cJSON * cJSON_CreateTrue ( ) { cJSON * item = cJSON_New_Item ( ) ; if ( item ) item - > type = cJSON_True ; return item ; }
cJSON * cJSON_CreateFalse ( ) { cJSON * item = cJSON_New_Item ( ) ; if ( item ) item - > type = cJSON_False ; return item ; }
@ -490,7 +490,7 @@ cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(i
cJSON * cJSON_CreateArray ( ) { cJSON * item = cJSON_New_Item ( ) ; if ( item ) item - > type = cJSON_Array ; return item ; }
cJSON * cJSON_CreateObject ( ) { cJSON * item = cJSON_New_Item ( ) ; if ( item ) item - > type = cJSON_Object ; return item ; }
// Create Arrays:
/* Create Arrays: */
cJSON * cJSON_CreateIntArray ( int * numbers , int count ) { int i ; cJSON * n = 0 , * p = 0 , * a = cJSON_CreateArray ( ) ; for ( i = 0 ; a & & i < count ; i + + ) { n = cJSON_CreateNumber ( numbers [ i ] ) ; if ( ! i ) a - > child = n ; else suffix_object ( p , n ) ; p = n ; } return a ; }
cJSON * cJSON_CreateFloatArray ( float * numbers , int count ) { int i ; cJSON * n = 0 , * p = 0 , * a = cJSON_CreateArray ( ) ; for ( i = 0 ; a & & i < count ; i + + ) { n = cJSON_CreateNumber ( numbers [ i ] ) ; if ( ! i ) a - > child = n ; else suffix_object ( p , n ) ; p = n ; } return a ; }
cJSON * cJSON_CreateDoubleArray ( double * numbers , int count ) { int i ; cJSON * n = 0 , * p = 0 , * a = cJSON_CreateArray ( ) ; for ( i = 0 ; a & & i < count ; i + + ) { n = cJSON_CreateNumber ( numbers [ i ] ) ; if ( ! i ) a - > child = n ; else suffix_object ( p , n ) ; p = n ; } return a ; }