2 Copyright (c) 2009 Dave Gamble
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 static int cJSON_strcasecmp(const char *s1,const char *s2)
37 if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
38 for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
39 return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
42 static void *(*cJSON_malloc)(size_t sz) = malloc;
43 static void (*cJSON_free)(void *ptr) = free;
45 static char* cJSON_strdup(const char* str)
50 len = strlen(str) + 1;
51 if (!(copy = (char*)cJSON_malloc(len))) return 0;
56 void cJSON_InitHooks(cJSON_Hooks* hooks)
58 if (!hooks) { /* Reset hooks */
59 cJSON_malloc = malloc;
64 cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
65 cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
68 // Internal constructor.
69 static cJSON *cJSON_New_Item()
71 cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
72 if (node) memset(node,0,sizeof(cJSON));
76 // Delete a cJSON structure.
77 void cJSON_Delete(cJSON *c)
83 if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
84 if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
85 if (c->string) cJSON_free(c->string);
91 // Parse the input text to generate a number, and populate the result into item.
92 static const char *parse_number(cJSON *item,const char *num)
94 double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
96 // Could use sscanf for this?
97 if (*num=='-') sign=-1,num++; // Has sign?
98 if (*num=='0') num++; // is zero
99 if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); // Number?
100 if (*num=='.') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} // Fractional part?
101 if (*num=='e' || *num=='E') // Exponent?
102 { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; // With sign?
103 while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); // Number?
106 n=sign*n*pow(10.0,(scale+subscale*signsubscale)); // number = +/- number.fraction * 10^+/- exponent
109 item->valueint=(int)n;
110 item->type=cJSON_Number;
114 // Render the number nicely from the given item into a string.
115 static char *print_number(cJSON *item)
118 double d=item->valuedouble;
119 if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
121 str=(char*)cJSON_malloc(21); // 2^64+1 can be represented in 21 chars.
122 if (str) sprintf(str,"%d",item->valueint);
126 str=(char*)cJSON_malloc(64); // This is a nice tradeoff.
129 if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
130 else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
131 else sprintf(str,"%f",d);
137 // Parse the input text into an unescaped cstring, and populate item.
138 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
139 static const char *parse_string(cJSON *item,const char *str)
141 const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc;
142 if (*str!='\"') return 0; // not a string!
144 while (*ptr!='\"' && (unsigned char)*ptr>31 && ++len) if (*ptr++ == '\\') ptr++; // Skip escaped quotes.
146 out=(char*)cJSON_malloc(len+1); // This is how long we need for the string, roughly.
150 while (*ptr!='\"' && (unsigned char)*ptr>31)
152 if (*ptr!='\\') *ptr2++=*ptr++;
158 case 'b': *ptr2++='\b'; break;
159 case 'f': *ptr2++='\f'; break;
160 case 'n': *ptr2++='\n'; break;
161 case 'r': *ptr2++='\r'; break;
162 case 't': *ptr2++='\t'; break;
163 case 'u': // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY.
164 sscanf(ptr+1,"%4x",&uc); // get the unicode char.
165 len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
168 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
169 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
170 case 1: *--ptr2 =(uc | firstByteMark[len]);
174 default: *ptr2++=*ptr; break;
180 if (*ptr=='\"') ptr++;
181 item->valuestring=out;
182 item->type=cJSON_String;
186 // Render the cstring provided to an escaped version that can be printed.
187 static char *print_string_ptr(const char *str)
189 const char *ptr;char *ptr2,*out;int len=0;
191 if (!str) return cJSON_strdup("");
192 ptr=str;while (*ptr && ++len) {if ((unsigned char)*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;}
194 out=(char*)cJSON_malloc(len+3);
201 if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
207 case '\\': *ptr2++='\\'; break;
208 case '\"': *ptr2++='\"'; break;
209 case '\b': *ptr2++='b'; break;
210 case '\f': *ptr2++='f'; break;
211 case '\n': *ptr2++='n'; break;
212 case '\r': *ptr2++='r'; break;
213 case '\t': *ptr2++='t'; break;
214 default: ptr2--; break; // eviscerate with prejudice.
218 *ptr2++='\"';*ptr2++=0;
221 // Invote print_string_ptr (which is useful) on an item.
222 static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
224 // Predeclare these prototypes.
225 static const char *parse_value(cJSON *item,const char *value);
226 static char *print_value(cJSON *item,int depth,int fmt);
227 static const char *parse_array(cJSON *item,const char *value);
228 static char *print_array(cJSON *item,int depth,int fmt);
229 static const char *parse_object(cJSON *item,const char *value);
230 static char *print_object(cJSON *item,int depth,int fmt);
232 // Utility to jump whitespace and cr/lf
233 static const char *skip(const char *in) {while (in && (unsigned char)*in<=32) in++; return in;}
235 // Parse an object - create a new root, and populate.
236 cJSON *cJSON_Parse(const char *value)
238 cJSON *c=cJSON_New_Item();
239 if (!c) return 0; /* memory fail */
241 if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
245 // Render a cJSON item/entity/structure to text.
246 char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
247 char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
249 // Parser core - when encountering text, process appropriately.
250 static const char *parse_value(cJSON *item,const char *value)
252 if (!value) return 0; // Fail on null.
253 if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
254 if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
255 if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
256 if (*value=='\"') { return parse_string(item,value); }
257 if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
258 if (*value=='[') { return parse_array(item,value); }
259 if (*value=='{') { return parse_object(item,value); }
261 return 0; // failure.
264 // Render a value to text.
265 static char *print_value(cJSON *item,int depth,int fmt)
269 switch ((item->type)&255)
271 case cJSON_NULL: out=cJSON_strdup("null"); break;
272 case cJSON_False: out=cJSON_strdup("false");break;
273 case cJSON_True: out=cJSON_strdup("true"); break;
274 case cJSON_Number: out=print_number(item);break;
275 case cJSON_String: out=print_string(item);break;
276 case cJSON_Array: out=print_array(item,depth,fmt);break;
277 case cJSON_Object: out=print_object(item,depth,fmt);break;
282 // Build an array from input text.
283 static const char *parse_array(cJSON *item,const char *value)
286 if (*value!='[') return 0; // not an array!
288 item->type=cJSON_Array;
290 if (*value==']') return value+1; // empty array.
292 item->child=child=cJSON_New_Item();
293 if (!item->child) return 0; // memory fail
294 value=skip(parse_value(child,skip(value))); // skip any spacing, get the value.
295 if (!value) return 0;
300 if (!(new_item=cJSON_New_Item())) return 0; // memory fail
301 child->next=new_item;new_item->prev=child;child=new_item;
302 value=skip(parse_value(child,skip(value+1)));
303 if (!value) return 0; // memory fail
306 if (*value==']') return value+1; // end of array
307 return 0; // malformed.
310 // Render an array to text
311 static char *print_array(cJSON *item,int depth,int fmt)
314 char *out=0,*ptr,*ret;int len=5;
315 cJSON *child=item->child;
316 int numentries=0,i=0,fail=0;
318 // How many entries in the array?
319 while (child) numentries++,child=child->next;
320 // Allocate an array to hold the values for each
321 entries=(char**)cJSON_malloc(numentries*sizeof(char*));
322 if (!entries) return 0;
323 memset(entries,0,numentries*sizeof(char*));
324 // Retrieve all the results:
326 while (child && !fail)
328 ret=print_value(child,depth+1,fmt);
330 if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
334 // If we didn't fail, try to malloc the output string
335 if (!fail) out=cJSON_malloc(len);
336 // If that fails, we fail.
342 for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
347 // Compose the output array.
350 for (i=0;i<numentries;i++)
352 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
353 if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
354 cJSON_free(entries[i]);
361 // Build an object from the text.
362 static const char *parse_object(cJSON *item,const char *value)
365 if (*value!='{') return 0; // not an object!
367 item->type=cJSON_Object;
369 if (*value=='}') return value+1; // empty array.
371 item->child=child=cJSON_New_Item();
372 if (!item->child) return 0;
373 value=skip(parse_string(child,skip(value)));
374 if (!value) return 0;
375 child->string=child->valuestring;child->valuestring=0;
376 if (*value!=':') return 0; // fail!
377 value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value.
378 if (!value) return 0;
383 if (!(new_item=cJSON_New_Item())) return 0; // memory fail
384 child->next=new_item;new_item->prev=child;child=new_item;
385 value=skip(parse_string(child,skip(value+1)));
386 if (!value) return 0;
387 child->string=child->valuestring;child->valuestring=0;
388 if (*value!=':') return 0; // fail!
389 value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value.
390 if (!value) return 0;
393 if (*value=='}') return value+1; // end of array
394 return 0; // malformed.
397 // Render an object to text.
398 static char *print_object(cJSON *item,int depth,int fmt)
400 char **entries=0,**names=0;
401 char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
402 cJSON *child=item->child;
403 int numentries=0,fail=0;
404 // Count the number of entries.
405 while (child) numentries++,child=child->next;
406 // Allocate space for the names and the objects
407 entries=(char**)cJSON_malloc(numentries*sizeof(char*));
408 if (!entries) return 0;
409 names=(char**)cJSON_malloc(numentries*sizeof(char*));
410 if (!names) {cJSON_free(entries);return 0;}
411 memset(entries,0,sizeof(char*)*numentries);
412 memset(names,0,sizeof(char*)*numentries);
414 // Collect all the results into our arrays:
415 child=item->child;depth++;if (fmt) len+=depth;
418 names[i]=str=print_string_ptr(child->string);
419 entries[i++]=ret=print_value(child,depth,fmt);
420 if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
424 // Try to allocate the output string
425 if (!fail) out=(char*)cJSON_malloc(len);
431 for (i=0;i<numentries;i++) {if (names[i]) free(names[i]);if (entries[i]) free(entries[i]);}
432 free(names);free(entries);
436 // Compose the output:
437 *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
438 for (i=0;i<numentries;i++)
440 if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
441 strcpy(ptr,names[i]);ptr+=strlen(names[i]);
442 *ptr++=':';if (fmt) *ptr++='\t';
443 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
444 if (i!=numentries-1) *ptr++=',';
445 if (fmt) *ptr++='\n';*ptr=0;
446 cJSON_free(names[i]);cJSON_free(entries[i]);
449 cJSON_free(names);cJSON_free(entries);
450 if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
455 // Get Array size/item / object item.
456 int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
457 cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
458 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
460 // Utility for array list handling.
461 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
462 // Utility for handling references.
463 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;}
465 // Add item to array/object.
466 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);}}
467 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);}
468 void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
469 void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
471 cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
472 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;}
473 void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
474 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;}
475 void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
477 // Replace array/object items with new ones.
478 void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
479 newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
480 if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
481 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);}}
483 // Create basic types:
484 cJSON *cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
485 cJSON *cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
486 cJSON *cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
487 cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
488 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;}
489 cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
490 cJSON *cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
491 cJSON *cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
494 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;}
495 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;}
496 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;}
497 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;}