update json lib in core and ESL and re-apply old patches

This commit is contained in:
Anthony Minessale 2012-09-13 12:54:25 -05:00
parent 4c3c4c5a28
commit 5a956890af
4 changed files with 393 additions and 321 deletions

View File

@ -20,12 +20,22 @@
THE SOFTWARE. THE SOFTWARE.
*/ */
// cJSON /* cJSON */
// JSON parser in C. /* JSON parser in C. */
#include "esl.h" #include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h> #include <float.h>
#include <limits.h> #include <limits.h>
#include <ctype.h>
#include "esl_json.h"
#include "esl.h"
static const char *ep;
ESL_DECLARE(const char *)cJSON_GetErrorPtr() {return ep;}
static int cJSON_strcasecmp(const char *s1,const char *s2) static int cJSON_strcasecmp(const char *s1,const char *s2)
{ {
@ -51,14 +61,15 @@ static char* cJSON_strdup(const char* str)
{ {
size_t len; size_t len;
char* copy; char* copy;
const char *s = str ? str : "";
len = strlen(str) + 1; len = strlen(s) + 1;
if (!(copy = (char*)cJSON_malloc(len))) return 0; if (!(copy = (char*)cJSON_malloc(len))) return 0;
memcpy(copy,str,len); memcpy(copy,s,len);
return copy; return copy;
} }
void cJSON_InitHooks(cJSON_Hooks* hooks) ESL_DECLARE(void)cJSON_InitHooks(cJSON_Hooks* hooks)
{ {
if (!hooks) { /* Reset hooks */ if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc; cJSON_malloc = malloc;
@ -70,16 +81,16 @@ void cJSON_InitHooks(cJSON_Hooks* hooks)
cJSON_free = (hooks->free_fn)?hooks->free_fn:free; cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
} }
// Internal constructor. /* Internal constructor. */
static cJSON *cJSON_New_Item(void) static cJSON *cJSON_New_Item()
{ {
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
if (node) memset(node,0,sizeof(cJSON)); if (node) memset(node,0,sizeof(cJSON));
return node; return node;
} }
// Delete a cJSON structure. /* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c) ESL_DECLARE(void)cJSON_Delete(cJSON *c)
{ {
cJSON *next; cJSON *next;
while (c) while (c)
@ -93,22 +104,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) static const char *parse_number(cJSON *item,const char *num)
{ {
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
// Could use sscanf for this? /* Could use sscanf for this? */
if (*num=='-') sign=-1,num++; // Has sign? if (*num=='-') sign=-1,num++; /* Has sign? */
if (*num=='0') num++; // is zero 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>='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=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
if (*num=='e' || *num=='E') // Exponent? if (*num=='e' || *num=='E') /* Exponent? */
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; // With sign? { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); // Number? 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->valuedouble=n;
item->valueint=(int)n; item->valueint=(int)n;
@ -116,40 +127,43 @@ static const char *parse_number(cJSON *item,const char *num)
return 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) static char *print_number(cJSON *item)
{ {
char *str; char *str;
double d=item->valuedouble; double d=item->valuedouble;
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 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. */
sprintf(str,"%d",item->valueint); if (str) sprintf(str,"%d",item->valueint);
} }
else else
{ {
str=(char*)cJSON_malloc(64); // This is a nice tradeoff. str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d); if (str)
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); {
else sprintf(str,"%f",d); if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
} }
return str; 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 unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str) static const char *parse_string(cJSON *item,const char *str)
{ {
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc; const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') return 0; // not a string! if (*str!='\"') {ep=str;return 0;} /* not a string! */
while (*ptr!='\"' && (unsigned char)*ptr>31 && ++len) if (*ptr++ == '\\') ptr++; // Skip escaped quotes. while (*ptr!='\"' && *ptr && ++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; if (!out) return 0;
ptr=str+1;ptr2=out; ptr=str+1;ptr2=out;
while (*ptr!='\"' && (unsigned char)*ptr>31) while (*ptr!='\"' && *ptr)
{ {
if (*ptr!='\\') *ptr2++=*ptr++; if (*ptr!='\\') *ptr2++=*ptr++;
else else
@ -162,16 +176,31 @@ static const char *parse_string(cJSON *item,const char *str)
case 'n': *ptr2++='\n'; break; case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break; case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break; case 't': *ptr2++='\t'; break;
case 'u': // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY. case 'u': /* transcode utf16 to utf8. */
if (sscanf(ptr+1,"%4x",&uc) < 1) break; // get the unicode char. if (sscanf(ptr+1,"%4x",&uc) < 1) break;
len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
ptr+=4; /* get the unicode char. */
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid.
if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs.
{
if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate.
if (sscanf(ptr+3,"%4x",&uc2) < 1) break;
ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate.
uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF);
}
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
switch (len) { switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(char)(uc | firstByteMark[len]); case 1: *--ptr2 =(char)(uc | firstByteMark[len]);
} }
ptr2+=len;ptr+=4; ptr2+=len;
break; break;
default: *ptr2++=*ptr; break; default: *ptr2++=*ptr; break;
} }
@ -185,15 +214,17 @@ static const char *parse_string(cJSON *item,const char *str)
return ptr; 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) static char *print_string_ptr(const char *str)
{ {
const char *ptr;char *ptr2,*out;int len=0; const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
if (!str) return cJSON_strdup(""); if (!str) return cJSON_strdup("");
ptr=str;while (*ptr && ++len) {if ((unsigned char)*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;} ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
out=(char*)cJSON_malloc(len+3); out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;ptr=str; ptr2=out;ptr=str;
*ptr2++='\"'; *ptr2++='\"';
while (*ptr) while (*ptr)
@ -202,7 +233,7 @@ static char *print_string_ptr(const char *str)
else else
{ {
*ptr2++='\\'; *ptr2++='\\';
switch (*ptr++) switch (token=*ptr++)
{ {
case '\\': *ptr2++='\\'; break; case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break; case '\"': *ptr2++='\"'; break;
@ -211,17 +242,17 @@ static char *print_string_ptr(const char *str)
case '\n': *ptr2++='n'; break; case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break; case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break; case '\t': *ptr2++='t'; break;
default: ptr2--; break; // eviscerate with prejudice. default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
} }
} }
} }
*ptr2++='\"';*ptr2++=0; *ptr2++='\"';*ptr2++=0;
return out; 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);} 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 const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt); static char *print_value(cJSON *item,int depth,int fmt);
static const char *parse_array(cJSON *item,const char *value); static const char *parse_array(cJSON *item,const char *value);
@ -229,27 +260,28 @@ static char *print_array(cJSON *item,int depth,int fmt);
static const char *parse_object(cJSON *item,const char *value); static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt); 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;} static const char *skip(const char *in) {while (in && *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) ESL_DECLARE(cJSON *)cJSON_Parse(const char *value)
{ {
cJSON *c=cJSON_New_Item(); cJSON *c=cJSON_New_Item();
ep=0;
if (!c) return 0; /* memory fail */ if (!c) return 0; /* memory fail */
if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;} if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
return c; 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_Print(cJSON *item) {return print_value(item,0,1);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} 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) 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,"null",4)) { item->type=cJSON_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 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; } if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
@ -258,10 +290,10 @@ static const char *parse_value(cJSON *item,const char *value)
if (*value=='[') { return parse_array(item,value); } if (*value=='[') { return parse_array(item,value); }
if (*value=='{') { return parse_object(item,value); } if (*value=='{') { return parse_object(item,value); }
return 0; // failure. ep=value;return 0; /* failure. */
} }
// Render a value to text. /* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt) static char *print_value(cJSON *item,int depth,int fmt)
{ {
char *out=0; char *out=0;
@ -279,35 +311,35 @@ static char *print_value(cJSON *item,int depth,int fmt)
return out; return out;
} }
// Build an array from input text. /* Build an array from input text. */
static const char *parse_array(cJSON *item,const char *value) static const char *parse_array(cJSON *item,const char *value)
{ {
cJSON *child; cJSON *child;
if (*value!='[') return 0; // not an array! if (*value!='[') {ep=value;return 0;} /* not an array! */
item->type=cJSON_Array; item->type=cJSON_Array;
value=skip(value+1); value=skip(value+1);
if (*value==']') return value+1; // empty array. if (*value==']') return value+1; /* empty array. */
item->child=child=cJSON_New_Item(); item->child=child=cJSON_New_Item();
if (!item->child) return 0; // memory fail if (!item->child) return 0; /* memory fail */
value=skip(parse_value(child,skip(value))); // skip any spacing, get the value. value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
if (!value) return 0; if (!value) return 0;
while (*value==',') while (*value==',')
{ {
cJSON *new_item; 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; child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_value(child,skip(value+1))); 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 if (*value==']') return value+1; /* end of array */
return 0; // malformed. ep=value;return 0; /* malformed. */
} }
// Render an array to text /* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt) static char *print_array(cJSON *item,int depth,int fmt)
{ {
char **entries; char **entries;
@ -315,13 +347,13 @@ static char *print_array(cJSON *item,int depth,int fmt)
cJSON *child=item->child; cJSON *child=item->child;
int numentries=0,i=0,fail=0; 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; 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*)); entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0; if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*)); memset(entries,0,numentries*sizeof(char*));
// Retrieve all the results: /* Retrieve all the results: */
child=item->child; child=item->child;
while (child && !fail) while (child && !fail)
{ {
@ -331,12 +363,12 @@ static char *print_array(cJSON *item,int depth,int fmt)
child=child->next; 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 (!fail) out=(char*)cJSON_malloc(len);
// If that fails, we fail. /* If that fails, we fail. */
if (!out) fail=1; if (!out) fail=1;
// Handle failure. /* Handle failure. */
if (fail) if (fail)
{ {
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
@ -344,7 +376,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
return 0; return 0;
} }
// Compose the output array. /* Compose the output array. */
*out='['; *out='[';
ptr=out+1;*ptr=0; ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++) for (i=0;i<numentries;i++)
@ -358,51 +390,52 @@ static char *print_array(cJSON *item,int depth,int fmt)
return out; return out;
} }
// Build an object from the text. /* Build an object from the text. */
static const char *parse_object(cJSON *item,const char *value) static const char *parse_object(cJSON *item,const char *value)
{ {
cJSON *child; cJSON *child;
if (*value!='{') return 0; // not an object! if (*value!='{') {ep=value;return 0;} /* not an object! */
item->type=cJSON_Object; item->type=cJSON_Object;
value=skip(value+1); value=skip(value+1);
if (*value=='}') return value+1; // empty array. if (*value=='}') return value+1; /* empty array. */
item->child=child=cJSON_New_Item(); item->child=child=cJSON_New_Item();
if (!item->child) return 0;
value=skip(parse_string(child,skip(value))); value=skip(parse_string(child,skip(value)));
if (!value) return 0; if (!value) return 0;
child->string=child->valuestring;child->valuestring=0; child->string=child->valuestring;child->valuestring=0;
if (*value!=':') return 0; // fail! if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value. value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0; if (!value) return 0;
while (*value==',') while (*value==',')
{ {
cJSON *new_item; 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; child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_string(child,skip(value+1))); value=skip(parse_string(child,skip(value+1)));
if (!value) return 0; if (!value) return 0;
child->string=child->valuestring;child->valuestring=0; child->string=child->valuestring;child->valuestring=0;
if (*value!=':') return 0; // fail! if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value. value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0; if (!value) return 0;
} }
if (*value=='}') return value+1; // end of array if (*value=='}') return value+1; /* end of array */
return 0; // malformed. ep=value;return 0; /* malformed. */
} }
// Render an object to text. /* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt) static char *print_object(cJSON *item,int depth,int fmt)
{ {
char **entries=0,**names=0; char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j; char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
cJSON *child=item->child; cJSON *child=item->child;
int numentries=0,fail=0; int numentries=0,fail=0;
// Count the number of entries. /* Count the number of entries. */
while (child) numentries++,child=child->next; 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*)); entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0; if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*)); names=(char**)cJSON_malloc(numentries*sizeof(char*));
@ -410,7 +443,7 @@ static char *print_object(cJSON *item,int depth,int fmt)
memset(entries,0,sizeof(char*)*numentries); memset(entries,0,sizeof(char*)*numentries);
memset(names,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; child=item->child;depth++;if (fmt) len+=depth;
while (child) while (child)
{ {
@ -420,19 +453,19 @@ static char *print_object(cJSON *item,int depth,int fmt)
child=child->next; child=child->next;
} }
// Try to allocate the output string /* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len); if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1; if (!out) fail=1;
// Handle failure /* Handle failure */
if (fail) if (fail)
{ {
for (i=0;i<numentries;i++) {if (names[i]) free(names[i]);if (entries[i]) free(entries[i]);} for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
free(names);free(entries); cJSON_free(names);cJSON_free(entries);
return 0; return 0;
} }
// Compose the output: /* Compose the output: */
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++) for (i=0;i<numentries;i++)
{ {
@ -451,45 +484,46 @@ static char *print_object(cJSON *item,int depth,int fmt)
return out; 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;} ESL_DECLARE(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;} ESL_DECLARE(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;} ESL_DECLARE(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;} 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();memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} 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 (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} ESL_DECLARE(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->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} ESL_DECLARE(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));} ESL_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} ESL_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; ESL_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} ESL_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
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;} ESL_DECLARE(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));} ESL_DECLARE(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; ESL_DECLARE(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; 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);} 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);}} ESL_DECLARE(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();item->type=cJSON_NULL;return item;} ESL_DECLARE(cJSON *)cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();item->type=cJSON_True;return item;} ESL_DECLARE(cJSON *)cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();item->type=cJSON_False;return item;} ESL_DECLARE(cJSON *)cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;return item;} ESL_DECLARE(cJSON *)cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();item->type=cJSON_String;item->valuestring=cJSON_strdup(string);return item;} ESL_DECLARE(cJSON *)cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
cJSON *cJSON_CreateArray() {cJSON *item=cJSON_New_Item();item->type=cJSON_Array;return item;} ESL_DECLARE(cJSON *)cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateObject() {cJSON *item=cJSON_New_Item();item->type=cJSON_Object;return item;} ESL_DECLARE(cJSON *)cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
ESL_DECLARE(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;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} ESL_DECLARE(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;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} ESL_DECLARE(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;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} ESL_DECLARE(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;}
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} ESL_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}

View File

@ -19,9 +19,7 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
#include "esl.h" #include "esl.h"
#ifndef cJSON__h #ifndef cJSON__h
#define cJSON__h #define cJSON__h
@ -30,7 +28,7 @@ extern "C"
{ {
#endif #endif
// cJSON Types: /* cJSON Types: */
#define cJSON_False 0 #define cJSON_False 0
#define cJSON_True 1 #define cJSON_True 1
#define cJSON_NULL 2 #define cJSON_NULL 2
@ -41,18 +39,18 @@ extern "C"
#define cJSON_IsReference 256 #define cJSON_IsReference 256
// The cJSON structure: /* The cJSON structure: */
typedef struct cJSON { typedef struct cJSON {
struct cJSON *next,*prev; // next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; // An array or object item will have a child pointer pointing to a chain of the items in the array/object. struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; // The type of the item, as above. int type; /* The type of the item, as above. */
char *valuestring; // The item's string, if type==cJSON_String char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; // The item's number, if type==cJSON_Number int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; // The item's number, if type==cJSON_Number double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; // The item's name string, if this item is the child of, or is in the list of subitems of an object. char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON; } cJSON;
typedef struct cJSON_Hooks { typedef struct cJSON_Hooks {
@ -60,57 +58,61 @@ typedef struct cJSON_Hooks {
void (*free_fn)(void *ptr); void (*free_fn)(void *ptr);
} cJSON_Hooks; } cJSON_Hooks;
// Supply malloc, realloc and free functions to cJSON /* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks); ESL_DECLARE(void) cJSON_InitHooks(cJSON_Hooks* hooks);
// Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value); ESL_DECLARE(cJSON *)cJSON_Parse(const char *value);
// Render a cJSON entity to text for transfer/storage. Free the char* when finished. /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item); ESL_DECLARE(char *)cJSON_Print(cJSON *item);
// Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item); ESL_DECLARE(char *)cJSON_PrintUnformatted(cJSON *item);
// Delete a cJSON entity and all subentities. /* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c); ESL_DECLARE(void) cJSON_Delete(cJSON *c);
// Returns the number of items in an array (or object). /* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array); ESL_DECLARE(int) cJSON_GetArraySize(cJSON *array);
// Retrieve item number "item" from array "array". Returns NULL if unsuccessful. /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); ESL_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item);
// Get item "string" from object. Case insensitive. /* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); ESL_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
ESL_DECLARE(const char *)cJSON_GetErrorPtr();
// These calls create a cJSON item of the appropriate type. /* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void); ESL_DECLARE(cJSON *)cJSON_CreateNull();
extern cJSON *cJSON_CreateTrue(void); ESL_DECLARE(cJSON *)cJSON_CreateTrue();
extern cJSON *cJSON_CreateFalse(void); ESL_DECLARE(cJSON *)cJSON_CreateFalse();
extern cJSON *cJSON_CreateNumber(double num); ESL_DECLARE(cJSON *)cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateString(const char *string); ESL_DECLARE(cJSON *)cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateArray(void); ESL_DECLARE(cJSON *)cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateObject(void); ESL_DECLARE(cJSON *)cJSON_CreateArray();
ESL_DECLARE(cJSON *)cJSON_CreateObject();
// These utilities create an Array of count items. /* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(int *numbers,int count); ESL_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(float *numbers,int count); ESL_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count); ESL_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count); ESL_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count);
// Append item to the specified array/object. /* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); ESL_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); ESL_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
// Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); ESL_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); ESL_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
// Remove/Detatch items from Arrays/Objects. /* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); ESL_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which); ESL_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); ESL_DECLARE(cJSON *)cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); ESL_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string);
// Update array items. /* Update array items. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); ESL_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); ESL_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())

View File

@ -19,9 +19,7 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
#include "switch.h" #include "switch.h"
#ifndef cJSON__h #ifndef cJSON__h
#define cJSON__h #define cJSON__h
@ -30,7 +28,7 @@ extern "C"
{ {
#endif #endif
// cJSON Types: /* cJSON Types: */
#define cJSON_False 0 #define cJSON_False 0
#define cJSON_True 1 #define cJSON_True 1
#define cJSON_NULL 2 #define cJSON_NULL 2
@ -41,18 +39,18 @@ extern "C"
#define cJSON_IsReference 256 #define cJSON_IsReference 256
// The cJSON structure: /* The cJSON structure: */
typedef struct cJSON { typedef struct cJSON {
struct cJSON *next,*prev; // next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; // An array or object item will have a child pointer pointing to a chain of the items in the array/object. struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; // The type of the item, as above. int type; /* The type of the item, as above. */
char *valuestring; // The item's string, if type==cJSON_String char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; // The item's number, if type==cJSON_Number int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; // The item's number, if type==cJSON_Number double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; // The item's name string, if this item is the child of, or is in the list of subitems of an object. char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON; } cJSON;
typedef struct cJSON_Hooks { typedef struct cJSON_Hooks {
@ -60,55 +58,59 @@ typedef struct cJSON_Hooks {
void (*free_fn)(void *ptr); void (*free_fn)(void *ptr);
} cJSON_Hooks; } cJSON_Hooks;
// Supply malloc, realloc and free functions to cJSON /* Supply malloc, realloc and free functions to cJSON */
SWITCH_DECLARE(void) cJSON_InitHooks(cJSON_Hooks* hooks); SWITCH_DECLARE(void) cJSON_InitHooks(cJSON_Hooks* hooks);
// Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
SWITCH_DECLARE(cJSON *)cJSON_Parse(const char *value); SWITCH_DECLARE(cJSON *)cJSON_Parse(const char *value);
// Render a cJSON entity to text for transfer/storage. Free the char* when finished. /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
SWITCH_DECLARE(char *)cJSON_Print(cJSON *item); SWITCH_DECLARE(char *)cJSON_Print(cJSON *item);
// Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
SWITCH_DECLARE(char *)cJSON_PrintUnformatted(cJSON *item); SWITCH_DECLARE(char *)cJSON_PrintUnformatted(cJSON *item);
// Delete a cJSON entity and all subentities. /* Delete a cJSON entity and all subentities. */
SWITCH_DECLARE(void) cJSON_Delete(cJSON *c); SWITCH_DECLARE(void) cJSON_Delete(cJSON *c);
// Returns the number of items in an array (or object). /* Returns the number of items in an array (or object). */
SWITCH_DECLARE(int) cJSON_GetArraySize(cJSON *array); SWITCH_DECLARE(int) cJSON_GetArraySize(cJSON *array);
// Retrieve item number "item" from array "array". Returns NULL if unsuccessful. /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
SWITCH_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item); SWITCH_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item);
// Get item "string" from object. Case insensitive. /* Get item "string" from object. Case insensitive. */
SWITCH_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string); SWITCH_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
SWITCH_DECLARE(const char *)cJSON_GetErrorPtr();
// These calls create a cJSON item of the appropriate type. /* These calls create a cJSON item of the appropriate type. */
SWITCH_DECLARE(cJSON *)cJSON_CreateNull(void); SWITCH_DECLARE(cJSON *)cJSON_CreateNull();
SWITCH_DECLARE(cJSON *)cJSON_CreateTrue(void); SWITCH_DECLARE(cJSON *)cJSON_CreateTrue();
SWITCH_DECLARE(cJSON *)cJSON_CreateFalse(void); SWITCH_DECLARE(cJSON *)cJSON_CreateFalse();
SWITCH_DECLARE(cJSON *)cJSON_CreateBool(int b);
SWITCH_DECLARE(cJSON *)cJSON_CreateNumber(double num); SWITCH_DECLARE(cJSON *)cJSON_CreateNumber(double num);
SWITCH_DECLARE(cJSON *)cJSON_CreateString(const char *string); SWITCH_DECLARE(cJSON *)cJSON_CreateString(const char *string);
SWITCH_DECLARE(cJSON *)cJSON_CreateArray(void); SWITCH_DECLARE(cJSON *)cJSON_CreateArray();
SWITCH_DECLARE(cJSON *)cJSON_CreateObject(void); SWITCH_DECLARE(cJSON *)cJSON_CreateObject();
// These utilities create an Array of count items. /* These utilities create an Array of count items. */
SWITCH_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count); SWITCH_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count);
SWITCH_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count); SWITCH_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count);
SWITCH_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count); SWITCH_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count);
SWITCH_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count); SWITCH_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count);
// Append item to the specified array/object. /* Append item to the specified array/object. */
SWITCH_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); SWITCH_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
SWITCH_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); SWITCH_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
// Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
SWITCH_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); SWITCH_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
SWITCH_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); SWITCH_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
// Remove/Detatch items from Arrays/Objects. /* Remove/Detatch items from Arrays/Objects. */
SWITCH_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which); SWITCH_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which);
SWITCH_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which); SWITCH_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which);
SWITCH_DECLARE(cJSON *)cJSON_DetachItemFromObject(cJSON *object,const char *string); SWITCH_DECLARE(cJSON *)cJSON_DetachItemFromObject(cJSON *object,const char *string);
SWITCH_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string); SWITCH_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string);
// Update array items. /* Update array items. */
SWITCH_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); SWITCH_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
SWITCH_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); SWITCH_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);

View File

@ -20,11 +20,22 @@
THE SOFTWARE. THE SOFTWARE.
*/ */
// cJSON /* cJSON */
// JSON parser in C. /* JSON parser in C. */
#include "switch.h" #include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h> #include <float.h>
#include <limits.h>
#include <ctype.h>
#include "switch_json.h"
#include "switch.h"
static const char *ep;
SWITCH_DECLARE(const char *)cJSON_GetErrorPtr() {return ep;}
static int cJSON_strcasecmp(const char *s1,const char *s2) static int cJSON_strcasecmp(const char *s1,const char *s2)
{ {
@ -58,7 +69,7 @@ static char* cJSON_strdup(const char* str)
return copy; return copy;
} }
SWITCH_DECLARE(void) cJSON_InitHooks(cJSON_Hooks* hooks) SWITCH_DECLARE(void)cJSON_InitHooks(cJSON_Hooks* hooks)
{ {
if (!hooks) { /* Reset hooks */ if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc; cJSON_malloc = malloc;
@ -70,16 +81,16 @@ SWITCH_DECLARE(void) cJSON_InitHooks(cJSON_Hooks* hooks)
cJSON_free = (hooks->free_fn)?hooks->free_fn:free; cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
} }
// Internal constructor. /* Internal constructor. */
static cJSON *cJSON_New_Item(void) static cJSON *cJSON_New_Item()
{ {
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
if (node) memset(node,0,sizeof(cJSON)); if (node) memset(node,0,sizeof(cJSON));
return node; return node;
} }
// Delete a cJSON structure. /* Delete a cJSON structure. */
SWITCH_DECLARE(void) cJSON_Delete(cJSON *c) SWITCH_DECLARE(void)cJSON_Delete(cJSON *c)
{ {
cJSON *next; cJSON *next;
while (c) while (c)
@ -93,22 +104,22 @@ SWITCH_DECLARE(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) static const char *parse_number(cJSON *item,const char *num)
{ {
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
// Could use sscanf for this? /* Could use sscanf for this? */
if (*num=='-') sign=-1,num++; // Has sign? if (*num=='-') sign=-1,num++; /* Has sign? */
if (*num=='0') num++; // is zero 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>='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=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
if (*num=='e' || *num=='E') // Exponent? if (*num=='e' || *num=='E') /* Exponent? */
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; // With sign? { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); // Number? 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->valuedouble=n;
item->valueint=(int)n; item->valueint=(int)n;
@ -116,40 +127,43 @@ static const char *parse_number(cJSON *item,const char *num)
return 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) static char *print_number(cJSON *item)
{ {
char *str; char *str;
double d=item->valuedouble; double d=item->valuedouble;
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 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. */
sprintf(str,"%d",item->valueint); if (str) sprintf(str,"%d",item->valueint);
} }
else else
{ {
str=(char*)cJSON_malloc(64); // This is a nice tradeoff. str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d); if (str)
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); {
else sprintf(str,"%f",d); if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
} }
return str; 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 unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str) static const char *parse_string(cJSON *item,const char *str)
{ {
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc; const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') return 0; // not a string! if (*str!='\"') {ep=str;return 0;} /* not a string! */
while (*ptr!='\"' && (unsigned char)*ptr>31 && ++len) if (*ptr++ == '\\') ptr++; // Skip escaped quotes. while (*ptr!='\"' && *ptr && ++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; if (!out) return 0;
ptr=str+1;ptr2=out; ptr=str+1;ptr2=out;
while (*ptr!='\"' && (unsigned char)*ptr>31) while (*ptr!='\"' && *ptr)
{ {
if (*ptr!='\\') *ptr2++=*ptr++; if (*ptr!='\\') *ptr2++=*ptr++;
else else
@ -162,16 +176,31 @@ static const char *parse_string(cJSON *item,const char *str)
case 'n': *ptr2++='\n'; break; case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break; case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break; case 't': *ptr2++='\t'; break;
case 'u': // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY. case 'u': /* transcode utf16 to utf8. */
if (sscanf(ptr+1,"%4x",&uc) < 1) break; // get the unicode char. if (sscanf(ptr+1,"%4x",&uc) < 1) break;
len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
ptr+=4; /* get the unicode char. */
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid.
if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs.
{
if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate.
if (sscanf(ptr+3,"%4x",&uc2) < 1) break;
ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate.
uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF);
}
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
switch (len) { switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(char)(uc | firstByteMark[len]); case 1: *--ptr2 =(char)(uc | firstByteMark[len]);
} }
ptr2+=len;ptr+=4; ptr2+=len;
break; break;
default: *ptr2++=*ptr; break; default: *ptr2++=*ptr; break;
} }
@ -185,15 +214,17 @@ static const char *parse_string(cJSON *item,const char *str)
return ptr; 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) static char *print_string_ptr(const char *str)
{ {
const char *ptr;char *ptr2,*out;int len=0; const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
if (!str) return cJSON_strdup(""); if (!str) return cJSON_strdup("");
ptr=str;while (*ptr && ++len) {if ((unsigned char)*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;} ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
out=(char*)cJSON_malloc(len+3); out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;ptr=str; ptr2=out;ptr=str;
*ptr2++='\"'; *ptr2++='\"';
while (*ptr) while (*ptr)
@ -202,7 +233,7 @@ static char *print_string_ptr(const char *str)
else else
{ {
*ptr2++='\\'; *ptr2++='\\';
switch (*ptr++) switch (token=*ptr++)
{ {
case '\\': *ptr2++='\\'; break; case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break; case '\"': *ptr2++='\"'; break;
@ -211,17 +242,17 @@ static char *print_string_ptr(const char *str)
case '\n': *ptr2++='n'; break; case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break; case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break; case '\t': *ptr2++='t'; break;
default: ptr2--; break; // eviscerate with prejudice. default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
} }
} }
} }
*ptr2++='\"';*ptr2++=0; *ptr2++='\"';*ptr2++=0;
return out; 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);} 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 const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt); static char *print_value(cJSON *item,int depth,int fmt);
static const char *parse_array(cJSON *item,const char *value); static const char *parse_array(cJSON *item,const char *value);
@ -229,27 +260,28 @@ static char *print_array(cJSON *item,int depth,int fmt);
static const char *parse_object(cJSON *item,const char *value); static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt); 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;} static const char *skip(const char *in) {while (in && *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. */
SWITCH_DECLARE(cJSON *)cJSON_Parse(const char *value) SWITCH_DECLARE(cJSON *)cJSON_Parse(const char *value)
{ {
cJSON *c=cJSON_New_Item(); cJSON *c=cJSON_New_Item();
ep=0;
if (!c) return 0; /* memory fail */ if (!c) return 0; /* memory fail */
if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;} if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
return c; return c;
} }
// Render a cJSON item/entity/structure to text. /* Render a cJSON item/entity/structure to text. */
SWITCH_DECLARE(char *)cJSON_Print(cJSON *item) {return print_value(item,0,1);} char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
SWITCH_DECLARE(char *)cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} 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) 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,"null",4)) { item->type=cJSON_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 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; } if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
@ -258,10 +290,10 @@ static const char *parse_value(cJSON *item,const char *value)
if (*value=='[') { return parse_array(item,value); } if (*value=='[') { return parse_array(item,value); }
if (*value=='{') { return parse_object(item,value); } if (*value=='{') { return parse_object(item,value); }
return 0; // failure. ep=value;return 0; /* failure. */
} }
// Render a value to text. /* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt) static char *print_value(cJSON *item,int depth,int fmt)
{ {
char *out=0; char *out=0;
@ -279,35 +311,35 @@ static char *print_value(cJSON *item,int depth,int fmt)
return out; return out;
} }
// Build an array from input text. /* Build an array from input text. */
static const char *parse_array(cJSON *item,const char *value) static const char *parse_array(cJSON *item,const char *value)
{ {
cJSON *child; cJSON *child;
if (*value!='[') return 0; // not an array! if (*value!='[') {ep=value;return 0;} /* not an array! */
item->type=cJSON_Array; item->type=cJSON_Array;
value=skip(value+1); value=skip(value+1);
if (*value==']') return value+1; // empty array. if (*value==']') return value+1; /* empty array. */
item->child=child=cJSON_New_Item(); item->child=child=cJSON_New_Item();
if (!item->child) return 0; // memory fail if (!item->child) return 0; /* memory fail */
value=skip(parse_value(child,skip(value))); // skip any spacing, get the value. value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
if (!value) return 0; if (!value) return 0;
while (*value==',') while (*value==',')
{ {
cJSON *new_item; 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; child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_value(child,skip(value+1))); 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 if (*value==']') return value+1; /* end of array */
return 0; // malformed. ep=value;return 0; /* malformed. */
} }
// Render an array to text /* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt) static char *print_array(cJSON *item,int depth,int fmt)
{ {
char **entries; char **entries;
@ -315,13 +347,13 @@ static char *print_array(cJSON *item,int depth,int fmt)
cJSON *child=item->child; cJSON *child=item->child;
int numentries=0,i=0,fail=0; 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; 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*)); entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0; if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*)); memset(entries,0,numentries*sizeof(char*));
// Retrieve all the results: /* Retrieve all the results: */
child=item->child; child=item->child;
while (child && !fail) while (child && !fail)
{ {
@ -331,12 +363,12 @@ static char *print_array(cJSON *item,int depth,int fmt)
child=child->next; 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 (!fail) out=(char*)cJSON_malloc(len);
// If that fails, we fail. /* If that fails, we fail. */
if (!out) fail=1; if (!out) fail=1;
// Handle failure. /* Handle failure. */
if (fail) if (fail)
{ {
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
@ -344,7 +376,7 @@ static char *print_array(cJSON *item,int depth,int fmt)
return 0; return 0;
} }
// Compose the output array. /* Compose the output array. */
*out='['; *out='[';
ptr=out+1;*ptr=0; ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++) for (i=0;i<numentries;i++)
@ -358,51 +390,52 @@ static char *print_array(cJSON *item,int depth,int fmt)
return out; return out;
} }
// Build an object from the text. /* Build an object from the text. */
static const char *parse_object(cJSON *item,const char *value) static const char *parse_object(cJSON *item,const char *value)
{ {
cJSON *child; cJSON *child;
if (*value!='{') return 0; // not an object! if (*value!='{') {ep=value;return 0;} /* not an object! */
item->type=cJSON_Object; item->type=cJSON_Object;
value=skip(value+1); value=skip(value+1);
if (*value=='}') return value+1; // empty array. if (*value=='}') return value+1; /* empty array. */
item->child=child=cJSON_New_Item(); item->child=child=cJSON_New_Item();
if (!item->child) return 0;
value=skip(parse_string(child,skip(value))); value=skip(parse_string(child,skip(value)));
if (!value) return 0; if (!value) return 0;
child->string=child->valuestring;child->valuestring=0; child->string=child->valuestring;child->valuestring=0;
if (*value!=':') return 0; // fail! if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value. value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0; if (!value) return 0;
while (*value==',') while (*value==',')
{ {
cJSON *new_item; 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; child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_string(child,skip(value+1))); value=skip(parse_string(child,skip(value+1)));
if (!value) return 0; if (!value) return 0;
child->string=child->valuestring;child->valuestring=0; child->string=child->valuestring;child->valuestring=0;
if (*value!=':') return 0; // fail! if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value. value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0; if (!value) return 0;
} }
if (*value=='}') return value+1; // end of array if (*value=='}') return value+1; /* end of array */
return 0; // malformed. ep=value;return 0; /* malformed. */
} }
// Render an object to text. /* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt) static char *print_object(cJSON *item,int depth,int fmt)
{ {
char **entries=0,**names=0; char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j; char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
cJSON *child=item->child; cJSON *child=item->child;
int numentries=0,fail=0; int numentries=0,fail=0;
// Count the number of entries. /* Count the number of entries. */
while (child) numentries++,child=child->next; 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*)); entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0; if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*)); names=(char**)cJSON_malloc(numentries*sizeof(char*));
@ -410,7 +443,7 @@ static char *print_object(cJSON *item,int depth,int fmt)
memset(entries,0,sizeof(char*)*numentries); memset(entries,0,sizeof(char*)*numentries);
memset(names,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; child=item->child;depth++;if (fmt) len+=depth;
while (child) while (child)
{ {
@ -420,19 +453,19 @@ static char *print_object(cJSON *item,int depth,int fmt)
child=child->next; child=child->next;
} }
// Try to allocate the output string /* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len); if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1; if (!out) fail=1;
// Handle failure /* Handle failure */
if (fail) if (fail)
{ {
for (i=0;i<numentries;i++) {if (names[i]) free(names[i]);if (entries[i]) free(entries[i]);} for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
free(names);free(entries); cJSON_free(names);cJSON_free(entries);
return 0; return 0;
} }
// Compose the output: /* Compose the output: */
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++) for (i=0;i<numentries;i++)
{ {
@ -451,45 +484,46 @@ static char *print_object(cJSON *item,int depth,int fmt)
return out; return out;
} }
// Get Array size/item / object item. /* Get Array size/item / object item. */
SWITCH_DECLARE(int) cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;} SWITCH_DECLARE(int) cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
SWITCH_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} SWITCH_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
SWITCH_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} SWITCH_DECLARE(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;} 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();memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} 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. */
SWITCH_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} SWITCH_DECLARE(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);}}
SWITCH_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} SWITCH_DECLARE(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);}
SWITCH_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} SWITCH_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
SWITCH_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} SWITCH_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
SWITCH_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; SWITCH_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
SWITCH_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} SWITCH_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
SWITCH_DECLARE(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;} SWITCH_DECLARE(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;}
SWITCH_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} SWITCH_DECLARE(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. */
SWITCH_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; SWITCH_DECLARE(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; 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);} if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
SWITCH_DECLARE(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);}} SWITCH_DECLARE(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: */
SWITCH_DECLARE(cJSON *)cJSON_CreateNull() {cJSON *item=cJSON_New_Item();item->type=cJSON_NULL;return item;} SWITCH_DECLARE(cJSON *)cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
SWITCH_DECLARE(cJSON *)cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();item->type=cJSON_True;return item;} SWITCH_DECLARE(cJSON *)cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
SWITCH_DECLARE(cJSON *)cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();item->type=cJSON_False;return item;} SWITCH_DECLARE(cJSON *)cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
SWITCH_DECLARE(cJSON *)cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;return item;} SWITCH_DECLARE(cJSON *)cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
SWITCH_DECLARE(cJSON *)cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();item->type=cJSON_String;item->valuestring=cJSON_strdup(string);return item;} SWITCH_DECLARE(cJSON *)cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
SWITCH_DECLARE(cJSON *)cJSON_CreateArray() {cJSON *item=cJSON_New_Item();item->type=cJSON_Array;return item;} SWITCH_DECLARE(cJSON *)cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
SWITCH_DECLARE(cJSON *)cJSON_CreateObject() {cJSON *item=cJSON_New_Item();item->type=cJSON_Object;return item;} SWITCH_DECLARE(cJSON *)cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
SWITCH_DECLARE(cJSON *)cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
// Create Arrays: /* Create Arrays: */
SWITCH_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} SWITCH_DECLARE(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;}
SWITCH_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} SWITCH_DECLARE(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;}
SWITCH_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} SWITCH_DECLARE(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;}
SWITCH_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} SWITCH_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}