3 Copyright (c) 2009 Dave Gamble
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 /* JSON parser in C. */
31 #define DBL_EPSILON 2.2204460492503131E-16
34 static const char *ep;
36 long stripquotes(char *str)
42 if ( str[0] == '"' && str[len-1] == '"' )
43 str[len-1] = 0, offset = 1;
48 const char *cJSON_GetErrorPtr(void) {return ep;}
50 static int32_t cJSON_strcasecmp(const char *s1,const char *s2)
52 if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
53 for(; tolower((int32_t)(*s1)) == tolower((int32_t)(*s2)); ++s1, ++s2) if(*s1 == 0) return 0;
54 return tolower((int32_t)(*(const unsigned char *)s1)) - tolower((int32_t)(*(const unsigned char *)s2));
57 static void *(*cJSON_malloc)(size_t sz) = malloc;
58 static void (*cJSON_free)(void *ptr) = free;
60 static char* cJSON_strdup(const char* str)
65 len = strlen(str) + 1;
66 if (!(copy = (char*)cJSON_malloc(len+1))) return 0;
71 void cJSON_InitHooks(cJSON_Hooks* hooks)
73 if (!hooks) { /* Reset hooks */
74 cJSON_malloc = malloc;
79 cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
80 cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
83 /* Internal constructor. */
84 static cJSON *cJSON_New_Item(void)
86 cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
87 if (node) memset(node,0,sizeof(cJSON));
91 /* Delete a cJSON structure. */
92 void cJSON_Delete(cJSON *c)
98 if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
99 if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
100 if (c->string) cJSON_free(c->string);
106 /* Parse the input text to generate a number, and populate the result into item. */
107 static const char *parse_number(cJSON *item,const char *num)
109 double n=0,sign=1,scale=0;int32_t subscale=0,signsubscale=1;
111 if (*num=='-') sign=-1,num++; /* Has sign? */
112 if (*num=='0') num++; /* is zero */
113 if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
114 if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
115 if (*num=='e' || *num=='E') /* Exponent? */
116 { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
117 while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
120 n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
123 item->valueint=(int64_t)n;
124 item->type=cJSON_Number;
128 /* Render the number nicely from the given item into a string. */
129 static char *print_number(cJSON *item)
132 double d = item->valuedouble;
133 if ( fabs(((double)item->valueint) - d) <= DBL_EPSILON && d >= (1. - DBL_EPSILON) && d < (1LL << 62) )//d <= INT_MAX && d >= INT_MIN )
135 str = (char *)cJSON_malloc(24); /* 2^64+1 can be represented in 21 chars + sign. */
137 sprintf(str,"%lld",(long long)item->valueint);
141 str = (char *)cJSON_malloc(66); /* This is a nice tradeoff. */
144 if ( fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60 )
145 sprintf(str,"%.0f",d);
146 //else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
148 sprintf(str,"%.8f",d);
154 static unsigned parse_hex4(const char *str)
157 if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
159 if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
161 if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
163 if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
167 /* Parse the input text into an unescaped cstring, and populate item. */
168 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
169 static const char *parse_string(cJSON *item,const char *str)
171 const char *ptr=str+1;char *ptr2;char *out;int32_t len=0;unsigned uc,uc2;
172 if (*str!='\"') {ep=str;return 0;} /* not a string! */
174 while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; // Skip escaped quotes
176 out=(char*)cJSON_malloc(len+2); /* This is how long we need for the string, roughly. */
180 while (*ptr!='\"' && *ptr)
184 if ( *ptr == '%' && is_hexstr((char *)&ptr[1],2) && isprint(_decode_hex((char *)&ptr[1])) != 0 )
185 *ptr2++ = _decode_hex((char *)&ptr[1]), ptr += 3;
186 else *ptr2++ = *ptr++;
193 case 'b': *ptr2++='\b'; break;
194 case 'f': *ptr2++='\f'; break;
195 case 'n': *ptr2++='\n'; break;
196 case 'r': *ptr2++='\r'; break;
197 case 't': *ptr2++='\t'; break;
198 case 'u': // transcode utf16 to utf8
199 uc=parse_hex4(ptr+1);ptr+=4; // get the unicode char
201 if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid
203 if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs
205 if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate.
206 uc2=parse_hex4(ptr+3);ptr+=6;
207 if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate
208 uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
211 len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
214 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
215 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
216 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
217 case 1: *--ptr2 =(uc | firstByteMark[len]);
221 default: *ptr2++=*ptr; break;
227 if (*ptr=='\"') ptr++;
228 item->valuestring=out;
229 item->type=cJSON_String;
233 /* Render the cstring provided to an escaped version that can be printed. */
234 static char *print_string_ptr(const char *str)
236 const char *ptr;char *ptr2,*out;int32_t len=0;unsigned char token;
238 if (!str) return cJSON_strdup("");
239 ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
241 out=(char*)cJSON_malloc(len+3+1);
248 if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
252 switch (token=*ptr++)
254 case '\\': *ptr2++='\\'; break;
255 case '\"': *ptr2++='\"'; break;
256 case '\b': *ptr2++='b'; break;
257 case '\f': *ptr2++='f'; break;
258 case '\n': *ptr2++='n'; break;
259 case '\r': *ptr2++='r'; break;
260 case '\t': *ptr2++='t'; break;
261 default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
265 *ptr2++='\"';*ptr2++=0;
268 /* Invote print_string_ptr (which is useful) on an item. */
269 static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
271 /* Predeclare these prototypes. */
272 static const char *parse_value(cJSON *item,const char *value);
273 static char *print_value(cJSON *item,int32_t depth,int32_t fmt);
274 static const char *parse_array(cJSON *item,const char *value);
275 static char *print_array(cJSON *item,int32_t depth,int32_t fmt);
276 static const char *parse_object(cJSON *item,const char *value);
277 static char *print_object(cJSON *item,int32_t depth,int32_t fmt);
279 /* Utility to jump whitespace and cr/lf */
280 static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
282 /* Parse an object - create a new root, and populate. */
283 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int32_t require_null_terminated)
286 cJSON *c=cJSON_New_Item();
288 if (!c) return 0; /* memory fail */
290 end=parse_value(c,skip(value));
291 if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
293 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
294 if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
295 if (return_parse_end) *return_parse_end=end;
298 /* Default options for cJSON_Parse */
299 cJSON *cJSON_Parse(const char *value)
301 return(cJSON_ParseWithOpts(value,0,0));
304 /* Render a cJSON item/entity/structure to text. */
305 char *cJSON_Print(cJSON *item)
307 return(print_value(item,0,1));
309 char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
311 /* Parser core - when encountering text, process appropriately. */
312 static const char *parse_value(cJSON *item,const char *value)
314 if (!value) return 0; /* Fail on null. */
315 if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
316 if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
317 if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
318 if (*value=='\"') { return parse_string(item,value); }
319 if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
320 if (*value=='[') { return parse_array(item,value); }
321 if (*value=='{') { return parse_object(item,value); }
323 ep=value;return 0; /* failure. */
326 /* Render a value to text. */
327 static char *print_value(cJSON *item,int32_t depth,int32_t fmt)
331 switch ((item->type)&255)
333 case cJSON_NULL: out=cJSON_strdup("null"); break;
334 case cJSON_False: out=cJSON_strdup("false");break;
335 case cJSON_True: out=cJSON_strdup("true"); break;
336 case cJSON_Number: out=print_number(item);break;
337 case cJSON_String: out=print_string(item);break;
338 case cJSON_Array: out=print_array(item,depth,fmt);break;
339 case cJSON_Object: out=print_object(item,depth,fmt);break;
344 /* Build an array from input text. */
345 static const char *parse_array(cJSON *item,const char *value)
348 if (*value!='[') {ep=value;return 0;} /* not an array! */
350 item->type=cJSON_Array;
352 if (*value==']') return value+1; /* empty array. */
354 item->child=child=cJSON_New_Item();
355 if (!item->child) return 0; /* memory fail */
356 value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
357 if (!value) return 0;
362 if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
363 child->next=new_item;new_item->prev=child;child=new_item;
364 value=skip(parse_value(child,skip(value+1)));
365 if (!value) return 0; /* memory fail */
368 if (*value==']') return value+1; /* end of array */
369 ep=value;return 0; /* malformed. */
372 /* Render an array to text */
373 static char *print_array(cJSON *item,int32_t depth,int32_t fmt)
376 char *out=0,*ptr,*ret;int32_t len=5;
377 cJSON *child=item->child;
378 int32_t numentries=0,i=0,fail=0;
380 /* How many entries in the array? */
381 while (child) numentries++,child=child->next;
382 /* Explicitly handle numentries==0 */
385 out=(char*)cJSON_malloc(3+1);
386 if (out) strcpy(out,"[]");
389 /* Allocate an array to hold the values for each */
390 entries=(char**)cJSON_malloc((1+numentries)*sizeof(char*));
391 if (!entries) return 0;
392 memset(entries,0,numentries*sizeof(char*));
393 /* Retrieve all the results: */
395 while (child && !fail)
397 ret=print_value(child,depth+1,fmt);
399 if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
403 /* If we didn't fail, try to malloc the output string */
404 if (!fail) out=(char*)cJSON_malloc(len+1);
405 /* If that fails, we fail. */
408 /* Handle failure. */
411 for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
416 /* Compose the output array. */
419 for (i=0;i<numentries;i++)
421 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
422 if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
423 cJSON_free(entries[i]);
430 /* Build an object from the text. */
431 static const char *parse_object(cJSON *item,const char *value)
434 if (*value!='{') {ep=value;return 0;} /* not an object! */
436 item->type=cJSON_Object;
438 if (*value=='}') return value+1; /* empty array. */
440 item->child=child=cJSON_New_Item();
441 if (!item->child) return 0;
442 value=skip(parse_string(child,skip(value)));
443 if (!value) return 0;
444 child->string=child->valuestring;child->valuestring=0;
445 if (*value!=':') {ep=value;return 0;} /* fail! */
446 value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
447 if (!value) return 0;
452 if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
453 child->next=new_item;new_item->prev=child;child=new_item;
454 value=skip(parse_string(child,skip(value+1)));
455 if (!value) return 0;
456 child->string=child->valuestring;child->valuestring=0;
457 if (*value!=':') {ep=value;return 0;} /* fail! */
458 value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
459 if (!value) return 0;
462 if (*value=='}') return value+1; /* end of array */
463 ep=value;return 0; /* malformed. */
466 /* Render an object to text. */
467 static char *print_object(cJSON *item,int32_t depth,int32_t fmt)
469 char **entries=0,**names=0;
470 char *out=0,*ptr,*ret,*str;int32_t len=7,i=0,j;
471 cJSON *child=item->child,*firstchild;
472 int32_t numentries=0,fail=0;
473 // Count the number of entries
479 if ( child == firstchild )
481 printf("cJSON infinite loop detected\n");
485 /* Explicitly handle empty object case */
488 out=(char*)cJSON_malloc(fmt?depth+4+1:3+1);
491 if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
495 /* Allocate space for the names and the objects */
496 entries=(char**)cJSON_malloc(numentries*sizeof(char*));
497 if (!entries) return 0;
498 names=(char**)cJSON_malloc(numentries*sizeof(char*));
499 if (!names) {cJSON_free(entries);return 0;}
500 memset(entries,0,sizeof(char*)*numentries);
501 memset(names,0,sizeof(char*)*numentries);
503 /* Collect all the results into our arrays: */
504 child=item->child;depth++;if (fmt) len+=depth;
507 names[i]=str=print_string_ptr(child->string);
508 entries[i++]=ret=print_value(child,depth,fmt);
509 if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
511 if ( child == firstchild )
515 /* Try to allocate the output string */
516 if (!fail) out=(char*)cJSON_malloc(len+1);
522 for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
523 cJSON_free(names);cJSON_free(entries);
527 /* Compose the output: */
528 *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
529 for (i=0;i<numentries;i++)
531 if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
532 strcpy(ptr,names[i]);ptr+=strlen(names[i]);
533 *ptr++=':';if (fmt) *ptr++='\t';
534 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
535 if (i!=numentries-1) *ptr++=',';
536 if (fmt) *ptr++='\n';*ptr=0;
537 cJSON_free(names[i]);cJSON_free(entries[i]);
540 cJSON_free(names);cJSON_free(entries);
541 if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
546 /* Get Array size/item / object item. */
547 int32_t cJSON_GetArraySize(cJSON *array) {cJSON *c; if ( array == 0 ) return(0); c=array->child;int32_t i=0;while(c)i++,c=c->next;return i;}
548 cJSON *cJSON_GetArrayItem(cJSON *array,int32_t item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
549 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
551 /* Utility for array list handling. */
552 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
553 /* Utility for handling references. */
554 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;}
556 /* Add item to array/object. */
557 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);}}
558 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);}
559 void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
560 void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
562 cJSON *cJSON_DetachItemFromArray(cJSON *array,int32_t which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
563 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;}
564 void cJSON_DeleteItemFromArray(cJSON *array,int32_t which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
565 cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int32_t 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;}
566 void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
568 /* Replace array/object items with new ones. */
569 void cJSON_ReplaceItemInArray(cJSON *array,int32_t which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
570 newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
571 if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
572 void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int32_t 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);}}
574 /* Create basic types: */
575 cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
576 cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
577 cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
578 cJSON *cJSON_CreateBool(int32_t b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
579 cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int64_t)num;}return item;}
580 cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
581 cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
582 cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
585 cJSON *cJSON_CreateIntArray(int64_t *numbers,int32_t count) {int32_t i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber((double)numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
586 cJSON *cJSON_CreateFloatArray(float *numbers,int32_t count) {int32_t 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;}
587 cJSON *cJSON_CreateDoubleArray(double *numbers,int32_t count) {int32_t 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;}
588 cJSON *cJSON_CreateStringArray(char **strings,int32_t count) {int32_t 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;}
591 cJSON *cJSON_Duplicate(cJSON *item,int32_t recurse)
593 cJSON *newitem,*cptr,*nptr=0,*newchild;
594 /* Bail on bad ptr */
596 /* Create new item */
597 newitem=cJSON_New_Item();
598 if (!newitem) return 0;
599 /* Copy over all vars */
600 newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
601 if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
602 if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
603 /* If non-recursive, then we're done! */
604 if (!recurse) return newitem;
605 /* Walk the ->next chain for the child. */
609 newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
610 if (!newchild) {cJSON_Delete(newitem);return 0;}
611 if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
612 else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
618 void cJSON_Minify(char *json)
623 if (*json==' ') json++;
624 else if (*json=='\t') json++; // Whitespace characters.
625 else if (*json=='\r') json++;
626 else if (*json=='\n') json++;
627 else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line.
628 else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments.
629 else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
630 else *into++=*json++; // All other characters.
632 *into=0; // and null-terminate.
635 // the following written by jl777
636 /******************************************************************************
637 * Copyright © 2014-2017 The SuperNET Developers. *
639 * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
640 * the top-level directory of this distribution for the individual copyright *
641 * holder information and the developer policies on copyright and licensing. *
643 * Unless otherwise agreed in a custom licensing agreement, no part of the *
644 * SuperNET software, including this file may be copied, modified, propagated *
645 * or distributed except according to the terms contained in the LICENSE file *
647 * Removal or modification of this copyright notice is prohibited. *
649 ******************************************************************************/
651 void copy_cJSON(struct destbuf *dest,cJSON *obj)
659 str = cJSON_Print(obj);
662 offset = stripquotes(str);
663 //strcpy(dest,str+offset);
664 for (i=0; i<MAX_JSON_FIELD-1; i++)
665 if ( (dest->buf[i]= str[offset+i]) == 0 )
673 void copy_cJSON2(char *dest,int32_t maxlen,cJSON *obj)
678 if ( maxlen > sizeof(tmp.buf) )
679 maxlen = sizeof(tmp.buf);
680 copy_cJSON(&tmp,obj);
681 if ( strlen(tmp.buf) < maxlen )
682 strcpy(dest,tmp.buf);
686 int64_t _get_cJSON_int(cJSON *json)
691 copy_cJSON(&tmp,json);
692 if ( tmp.buf[0] != 0 )
693 return(calc_nxt64bits(tmp.buf));
698 int64_t get_cJSON_int(cJSON *json,char *field)
703 numjson = cJSON_GetObjectItem(json,field);
705 return(_get_cJSON_int(numjson));
710 int64_t conv_floatstr(char *numstr)
714 corr = (val < 0.) ? -0.50000000001 : 0.50000000001;
715 return((int64_t)(val * SATOSHIDEN + corr));
718 int64_t _conv_cJSON_float(cJSON *json)
720 int64_t conv_floatstr(char *);
724 copy_cJSON(&tmp,json);
725 return(conv_floatstr(tmp.buf));
730 int64_t conv_cJSON_float(cJSON *json,char *field)
733 return(_conv_cJSON_float(cJSON_GetObjectItem(json,field)));
737 int32_t extract_cJSON_str(char *dest,int32_t max,cJSON *json,char *field)
739 int32_t safecopy(char *dest,char *src,long len);
745 obj = cJSON_GetObjectItem(json,field);
748 str = cJSON_Print(obj);
749 offset = stripquotes(str);
750 len = safecopy(dest,str+offset,max);
757 cJSON *gen_list_json(char **list)
760 array = cJSON_CreateArray();
761 while ( list != 0 && *list != 0 && *list[0] != 0 )
763 item = cJSON_CreateString(*list++);
764 cJSON_AddItemToArray(array,item);
769 uint64_t get_API_nxt64bits(cJSON *obj)
771 uint64_t nxt64bits = 0;
775 if ( is_cJSON_Number(obj) != 0 )
776 return((uint64_t)obj->valuedouble);
777 copy_cJSON(&tmp,obj);
778 nxt64bits = calc_nxt64bits(tmp.buf);
782 uint64_t j64bits(cJSON *json,char *field) { if ( field == 0 ) return(get_API_nxt64bits(json)); return(get_API_nxt64bits(cJSON_GetObjectItem(json,field))); }
783 uint64_t j64bitsi(cJSON *json,int32_t i) { return(get_API_nxt64bits(cJSON_GetArrayItem(json,i))); }
785 uint64_t get_satoshi_obj(cJSON *json,char *field)
788 uint64_t prev,satoshis,mult = 1;
789 struct destbuf numstr,checkstr;
791 numjson = cJSON_GetObjectItem(json,field);
792 copy_cJSON(&numstr,numjson);
793 satoshis = prev = 0; mult = 1; n = (int32_t)strlen(numstr.buf);
794 for (i=n-1; i>=0; i--,mult*=10)
796 satoshis += (mult * (numstr.buf[i] - '0'));
797 if ( satoshis < prev )
798 printf("get_satoshi_obj numstr.(%s) i.%d prev.%llu vs satoshis.%llu\n",numstr.buf,i,(unsigned long long)prev,(unsigned long long)satoshis);
801 sprintf(checkstr.buf,"%llu",(long long)satoshis);
802 if ( strcmp(checkstr.buf,numstr.buf) != 0 )
804 printf("SATOSHI GREMLIN?? numstr.(%s) -> %.8f -> (%s)\n",numstr.buf,dstr(satoshis),checkstr.buf);
809 void add_satoshis_json(cJSON *json,char *field,uint64_t satoshis)
813 sprintf(numstr,"%lld",(long long)satoshis);
814 obj = cJSON_CreateString(numstr);
815 cJSON_AddItemToObject(json,field,obj);
816 if ( satoshis != get_satoshi_obj(json,field) )
817 printf("error adding satoshi obj %ld -> %ld\n",(unsigned long)satoshis,(unsigned long)get_satoshi_obj(json,field));
820 char *cJSON_str(cJSON *json)
822 if ( json != 0 && is_cJSON_String(json) != 0 )
823 return(json->valuestring);
827 void jadd(cJSON *json,char *field,cJSON *item) { if ( json != 0 )cJSON_AddItemToObject(json,field,item); }
828 void jaddstr(cJSON *json,char *field,char *str) { if ( json != 0 && str != 0 ) cJSON_AddItemToObject(json,field,cJSON_CreateString(str)); }
829 void jaddnum(cJSON *json,char *field,double num) { if ( json != 0 )cJSON_AddItemToObject(json,field,cJSON_CreateNumber(num)); }
830 void jadd64bits(cJSON *json,char *field,uint64_t nxt64bits) { char numstr[64]; sprintf(numstr,"%llu",(long long)nxt64bits), jaddstr(json,field,numstr); }
831 void jaddi(cJSON *json,cJSON *item) { if ( json != 0 ) cJSON_AddItemToArray(json,item); }
832 void jaddistr(cJSON *json,char *str) { if ( json != 0 ) cJSON_AddItemToArray(json,cJSON_CreateString(str)); }
833 void jaddinum(cJSON *json,double num) { if ( json != 0 ) cJSON_AddItemToArray(json,cJSON_CreateNumber(num)); }
834 void jaddi64bits(cJSON *json,uint64_t nxt64bits) { char numstr[64]; sprintf(numstr,"%llu",(long long)nxt64bits), jaddistr(json,numstr); }
835 char *jstr(cJSON *json,char *field) { if ( json == 0 ) return(0); if ( field == 0 ) return(cJSON_str(json)); return(cJSON_str(cJSON_GetObjectItem(json,field))); }
837 char *jstri(cJSON *json,int32_t i) { return(cJSON_str(cJSON_GetArrayItem(json,i))); }
838 char *jprint(cJSON *json,int32_t freeflag)
841 /*static portable_mutex_t mutex; static int32_t initflag;
844 portable_mutex_init(&mutex);
848 return(clonestr((char *)"{}"));
849 //portable_mutex_lock(&mutex);
851 str = cJSON_Print(json), _stripwhite(str,' ');
854 //portable_mutex_unlock(&mutex);
858 bits256 get_API_bits256(cJSON *obj)
860 bits256 hash; char *str;
861 memset(hash.bytes,0,sizeof(hash));
864 if ( is_cJSON_String(obj) != 0 && (str= obj->valuestring) != 0 && strlen(str) == 64 )
865 decode_hex(hash.bytes,sizeof(hash),str);
869 bits256 jbits256(cJSON *json,char *field) { if ( field == 0 ) return(get_API_bits256(json)); return(get_API_bits256(cJSON_GetObjectItem(json,field))); }
870 bits256 jbits256i(cJSON *json,int32_t i) { return(get_API_bits256(cJSON_GetArrayItem(json,i))); }
871 void jaddbits256(cJSON *json,char *field,bits256 hash) { char str[65]; bits256_str(str,hash), jaddstr(json,field,str); }
872 void jaddibits256(cJSON *json,bits256 hash) { char str[65]; bits256_str(str,hash), jaddistr(json,str); }
874 char *get_cJSON_fieldname(cJSON *obj)
878 if ( obj->child != 0 && obj->child->string != 0 )
879 return(obj->child->string);
880 else if ( obj->string != 0 )
883 return((char *)"<no cJSON string field>");
886 int32_t jnum(cJSON *obj,char *field)
888 char *str; int32_t polarity = 1;
890 obj = jobj(obj,field);
893 if ( is_cJSON_Number(obj) != 0 )
894 return(obj->valuedouble);
895 else if ( is_cJSON_String(obj) != 0 && (str= jstr(obj,0)) != 0 )
898 polarity = -1, str++;
899 return(polarity * (int32_t)calc_nxt64bits(str));
905 void ensure_jsonitem(cJSON *json,char *field,char *value)
907 cJSON *obj = cJSON_GetObjectItem(json,field);
909 cJSON_AddItemToObject(json,field,cJSON_CreateString(value));
910 else cJSON_ReplaceItemInObject(json,field,cJSON_CreateString(value));
913 int32_t in_jsonarray(cJSON *array,char *value)
916 struct destbuf remote;
917 if ( array != 0 && is_cJSON_Array(array) != 0 )
919 n = cJSON_GetArraySize(array);
922 if ( array == 0 || n == 0 )
924 copy_cJSON(&remote,cJSON_GetArrayItem(array,i));
925 if ( strcmp(remote.buf,value) == 0 )
932 int32_t myatoi(char *str,int32_t range)
935 x = strtol(str,&ptr,10);
936 if ( range != 0 && x >= range )
941 int32_t get_API_int(cJSON *obj,int32_t val)
946 if ( is_cJSON_Number(obj) != 0 )
947 return((int32_t)obj->valuedouble);
948 copy_cJSON(&buf,obj);
949 val = myatoi(buf.buf,0);
955 int32_t jint(cJSON *json,char *field) { if ( json == 0 ) return(0); if ( field == 0 ) return(get_API_int(json,0)); return(get_API_int(cJSON_GetObjectItem(json,field),0)); }
956 int32_t jinti(cJSON *json,int32_t i) { if ( json == 0 ) return(0); return(get_API_int(cJSON_GetArrayItem(json,i),0)); }
958 uint32_t get_API_uint(cJSON *obj,uint32_t val)
963 if ( is_cJSON_Number(obj) != 0 )
964 return((uint32_t)obj->valuedouble);
965 copy_cJSON(&buf,obj);
966 val = myatoi(buf.buf,0);
970 uint32_t juint(cJSON *json,char *field) { if ( json == 0 ) return(0); if ( field == 0 ) return(get_API_uint(json,0)); return(get_API_uint(cJSON_GetObjectItem(json,field),0)); }
971 uint32_t juinti(cJSON *json,int32_t i) { if ( json == 0 ) return(0); return(get_API_uint(cJSON_GetArrayItem(json,i),0)); }
973 double get_API_float(cJSON *obj)
979 if ( is_cJSON_Number(obj) != 0 )
980 return(obj->valuedouble);
981 copy_cJSON(&buf,obj);
987 double jdouble(cJSON *json,char *field)
992 return(get_API_float(json));
993 else return(get_API_float(cJSON_GetObjectItem(json,field)));
997 double jdoublei(cJSON *json,int32_t i)
1000 return(get_API_float(cJSON_GetArrayItem(json,i)));
1004 cJSON *jobj(cJSON *json,char *field) { if ( json != 0 ) return(cJSON_GetObjectItem(json,field)); return(0); }
1006 void jdelete(cJSON *json,char *field)
1008 if ( jobj(json,field) != 0 )
1009 cJSON_DeleteItemFromObject(json,field);
1012 cJSON *jduplicate(cJSON *json) { return(cJSON_Duplicate(json,1)); }
1014 cJSON *jitem(cJSON *array,int32_t i) { if ( array != 0 && is_cJSON_Array(array) != 0 && cJSON_GetArraySize(array) > i ) return(cJSON_GetArrayItem(array,i)); return(0); }
1015 cJSON *jarray(int32_t *nump,cJSON *json,char *field)
1022 else array = cJSON_GetObjectItem(json,field);
1023 if ( array != 0 && is_cJSON_Array(array) != 0 && (*nump= cJSON_GetArraySize(array)) > 0 )
1030 int32_t expand_nxt64bits(char *NXTaddr,uint64_t nxt64bits)
1035 for (i=0; nxt64bits!=0; i++)
1037 modval = nxt64bits % 10;
1038 rev[i] = (char)(modval + '0');
1043 NXTaddr[i] = rev[n-1-i];
1048 char *nxt64str(uint64_t nxt64bits)
1050 static char NXTaddr[64];
1051 expand_nxt64bits(NXTaddr,nxt64bits);
1055 char *nxt64str2(uint64_t nxt64bits)
1057 static char NXTaddr[64];
1058 expand_nxt64bits(NXTaddr,nxt64bits);
1062 int32_t cmp_nxt64bits(const char *str,uint64_t nxt64bits)
1065 if ( str == 0 )//|| str[0] == 0 || nxt64bits == 0 )
1067 if ( nxt64bits == 0 && str[0] == 0 )
1069 expand_nxt64bits(expanded,nxt64bits);
1070 return(strcmp(str,expanded));
1073 uint64_t calc_nxt64bits(const char *NXTaddr)
1076 int64_t n,i,polarity = 1;
1077 uint64_t lastval,mult,nxt64bits = 0;
1080 printf("calling calc_nxt64bits with null ptr!\n");
1083 n = strlen(NXTaddr);
1086 printf("calc_nxt64bits: illegal NXTaddr.(%s) too long\n",NXTaddr);
1089 else if ( strcmp(NXTaddr,"0") == 0 || strcmp(NXTaddr,"false") == 0 )
1091 // printf("zero address?\n"); getchar();
1094 if ( NXTaddr[0] == '-' )
1095 polarity = -1, NXTaddr++, n--;
1098 for (i=n-1; i>=0; i--,mult*=10)
1101 if ( c < '0' || c > '9' )
1103 printf("calc_nxt64bits: illegal char.(%c %d) in (%s).%d\n",c,c,NXTaddr,(int32_t)i);
1108 printf("calc_nxt64bits: illegal char.(%c %d) in (%s).%d\n",c,c,NXTaddr,(int32_t)i);
1113 nxt64bits += mult * (c - '0');
1114 if ( nxt64bits < lastval )
1115 printf("calc_nxt64bits: warning: 64bit overflow %llx < %llx\n",(long long)nxt64bits,(long long)lastval);
1116 lastval = nxt64bits;
1118 while ( *NXTaddr == '0' && *NXTaddr != 0 )
1120 if ( cmp_nxt64bits(NXTaddr,nxt64bits) != 0 )
1121 printf("error calculating nxt64bits: %s -> %llx -> %s\n",NXTaddr,(long long)nxt64bits,nxt64str(nxt64bits));
1123 return(-(int64_t)nxt64bits);
1127 cJSON *addrs_jsonarray(uint64_t *addrs,int32_t num)
1129 int32_t j; cJSON *array;
1130 array = cJSON_CreateArray();
1131 for (j=0; j<num; j++)
1132 jaddi64bits(array,addrs[j]);
1136 void free_json(cJSON *json) { if ( json != 0 ) cJSON_Delete(json); }