yangyang
Fork of WIZnetInterface by
Embed:
(wiki syntax)
Show/hide line numbers
cJSON.c
00001 /* 00002 Copyright (c) 2009 Dave Gamble 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 */ 00022 00023 /* cJSON */ 00024 /* JSON parser in C. */ 00025 00026 #include <string.h> 00027 #include <stdio.h> 00028 #include <math.h> 00029 #include <stdlib.h> 00030 #include <float.h> 00031 #include <limits.h> 00032 #include <ctype.h> 00033 #include "cJSON.h" 00034 00035 static const char *ep; 00036 00037 const char *cJSON_GetErrorPtr(void) {return ep;} 00038 00039 static int cJSON_strcasecmp(const char *s1,const char *s2) 00040 { 00041 if (!s1) return (s1==s2)?0:1;if (!s2) return 1; 00042 for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; 00043 return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); 00044 } 00045 00046 static void *(*cJSON_malloc)(size_t sz) = malloc; 00047 static void (*cJSON_free)(void *ptr) = free; 00048 00049 static char* cJSON_strdup(const char* str) 00050 { 00051 size_t len; 00052 char* copy; 00053 00054 len = strlen(str) + 1; 00055 if (!(copy = (char*)cJSON_malloc(len))) return 0; 00056 memcpy(copy,str,len); 00057 return copy; 00058 } 00059 00060 void cJSON_InitHooks(cJSON_Hooks* hooks) 00061 { 00062 if (!hooks) { /* Reset hooks */ 00063 cJSON_malloc = malloc; 00064 cJSON_free = free; 00065 return; 00066 } 00067 00068 cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; 00069 cJSON_free = (hooks->free_fn)?hooks->free_fn:free; 00070 } 00071 00072 /* Internal constructor. */ 00073 static cJSON *cJSON_New_Item(void) 00074 { 00075 cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); 00076 if (node) memset(node,0,sizeof(cJSON)); 00077 return node; 00078 } 00079 00080 /* Delete a cJSON structure. */ 00081 void cJSON_Delete(cJSON *c) 00082 { 00083 cJSON *next; 00084 while (c) 00085 { 00086 next=c->next; 00087 if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); 00088 if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); 00089 if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); 00090 cJSON_free(c); 00091 c=next; 00092 } 00093 } 00094 00095 /* Parse the input text to generate a number, and populate the result into item. */ 00096 static const char *parse_number(cJSON *item,const char *num) 00097 { 00098 double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; 00099 00100 if (*num=='-') sign=-1,num++; /* Has sign? */ 00101 if (*num=='0') num++; /* is zero */ 00102 if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ 00103 if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ 00104 if (*num=='e' || *num=='E') /* Exponent? */ 00105 { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ 00106 while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ 00107 } 00108 00109 n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ 00110 00111 item->valuedouble=n; 00112 item->valueint=(int)n; 00113 item->type=cJSON_Number; 00114 return num; 00115 } 00116 00117 static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } 00118 00119 typedef struct {char *buffer; int length; int offset; } printbuffer; 00120 00121 static char* ensure(printbuffer *p,int needed) 00122 { 00123 char *newbuffer;int newsize; 00124 if (!p || !p->buffer) return 0; 00125 needed+=p->offset; 00126 if (needed<=p->length) return p->buffer+p->offset; 00127 00128 newsize=pow2gt(needed); 00129 newbuffer=(char*)cJSON_malloc(newsize); 00130 if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} 00131 if (newbuffer) memcpy(newbuffer,p->buffer,p->length); 00132 cJSON_free(p->buffer); 00133 p->length=newsize; 00134 p->buffer=newbuffer; 00135 return newbuffer+p->offset; 00136 } 00137 00138 static int update(printbuffer *p) 00139 { 00140 char *str; 00141 if (!p || !p->buffer) return 0; 00142 str=p->buffer+p->offset; 00143 return p->offset+strlen(str); 00144 } 00145 00146 /* Render the number nicely from the given item into a string. */ 00147 static char *print_number(cJSON *item,printbuffer *p) 00148 { 00149 char *str=0; 00150 double d=item->valuedouble; 00151 if (d==0) 00152 { 00153 if (p) str=ensure(p,2); 00154 else str=(char*)cJSON_malloc(2); /* special case for 0. */ 00155 if (str) strcpy(str,"0"); 00156 } 00157 else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) 00158 { 00159 if (p) str=ensure(p,21); 00160 else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ 00161 if (str) sprintf(str,"%d",item->valueint); 00162 } 00163 else 00164 { 00165 if (p) str=ensure(p,64); 00166 else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ 00167 if (str) 00168 { 00169 if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); 00170 else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); 00171 else sprintf(str,"%f",d); 00172 } 00173 } 00174 return str; 00175 } 00176 00177 static unsigned parse_hex4(const char *str) 00178 { 00179 unsigned h=0; 00180 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; 00181 h=h<<4;str++; 00182 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; 00183 h=h<<4;str++; 00184 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; 00185 h=h<<4;str++; 00186 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; 00187 return h; 00188 } 00189 00190 /* Parse the input text into an unescaped cstring, and populate item. */ 00191 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 00192 static const char *parse_string(cJSON *item,const char *str) 00193 { 00194 const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; 00195 if (*str!='\"') {ep=str;return 0;} /* not a string! */ 00196 00197 while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ 00198 00199 out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ 00200 if (!out) return 0; 00201 00202 ptr=str+1;ptr2=out; 00203 while (*ptr!='\"' && *ptr) 00204 { 00205 if (*ptr!='\\') *ptr2++=*ptr++; 00206 else 00207 { 00208 ptr++; 00209 switch (*ptr) 00210 { 00211 case 'b': *ptr2++='\b'; break; 00212 case 'f': *ptr2++='\f'; break; 00213 case 'n': *ptr2++='\n'; break; 00214 case 'r': *ptr2++='\r'; break; 00215 case 't': *ptr2++='\t'; break; 00216 case 'u': /* transcode utf16 to utf8. */ 00217 uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ 00218 00219 if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ 00220 00221 if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ 00222 { 00223 if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ 00224 uc2=parse_hex4(ptr+3);ptr+=6; 00225 if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ 00226 uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); 00227 } 00228 00229 len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; 00230 00231 switch (len) { 00232 case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 00233 case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 00234 case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; 00235 case 1: *--ptr2 =(uc | firstByteMark[len]); 00236 } 00237 ptr2+=len; 00238 break; 00239 default: *ptr2++=*ptr; break; 00240 } 00241 ptr++; 00242 } 00243 } 00244 *ptr2=0; 00245 if (*ptr=='\"') ptr++; 00246 item->valuestring=out; 00247 item->type=cJSON_String; 00248 return ptr; 00249 } 00250 00251 00252 static int escapable[256]={ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 00253 0,0,1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 00254 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 00255 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 00256 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 00257 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 00258 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 00259 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; 00260 00261 /* Render the cstring provided to an escaped version that can be printed. */ 00262 static char *print_string_ptr(const char *str,printbuffer *p) 00263 { 00264 const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; 00265 00266 ptr=str;while (*ptr) flag|=escapable[*ptr++]; 00267 if (!flag) 00268 { 00269 len=ptr-str; 00270 if (p) out=ensure(p,len+3); 00271 else out=(char*)cJSON_malloc(len+3); 00272 if (!out) return 0; 00273 ptr2=out;*ptr2++='\"'; 00274 strcpy(ptr2,str); 00275 ptr2[len]='\"'; 00276 ptr2[len+1]=0; 00277 return out; 00278 } 00279 00280 if (!str) 00281 { 00282 if (p) out=ensure(p,3); 00283 else out=(char*)cJSON_malloc(3); 00284 if (!out) return 0; 00285 strcpy(out,"\"\""); 00286 return out; 00287 } 00288 ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} 00289 00290 if (p) out=ensure(p,len+3); 00291 else out=(char*)cJSON_malloc(len+3); 00292 if (!out) return 0; 00293 00294 ptr2=out;ptr=str; 00295 *ptr2++='\"'; 00296 while (*ptr) 00297 { 00298 if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; 00299 else 00300 { 00301 *ptr2++='\\'; 00302 switch (token=*ptr++) 00303 { 00304 case '\\': *ptr2++='\\'; break; 00305 case '\"': *ptr2++='\"'; break; 00306 case '\b': *ptr2++='b'; break; 00307 case '\f': *ptr2++='f'; break; 00308 case '\n': *ptr2++='n'; break; 00309 case '\r': *ptr2++='r'; break; 00310 case '\t': *ptr2++='t'; break; 00311 default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ 00312 } 00313 } 00314 } 00315 *ptr2++='\"';*ptr2++=0; 00316 return out; 00317 } 00318 /* Invote print_string_ptr (which is useful) on an item. */ 00319 static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} 00320 00321 /* Predeclare these prototypes. */ 00322 static const char *parse_value(cJSON *item,const char *value); 00323 static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); 00324 static const char *parse_array(cJSON *item,const char *value); 00325 static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); 00326 static const char *parse_object(cJSON *item,const char *value); 00327 static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); 00328 00329 /* Utility to jump whitespace and cr/lf */ 00330 static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} 00331 00332 /* Parse an object - create a new root, and populate. */ 00333 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) 00334 { 00335 const char *end=0; 00336 cJSON *c=cJSON_New_Item(); 00337 ep=0; 00338 if (!c) return 0; /* memory fail */ 00339 00340 end=parse_value(c,skip(value)); 00341 if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ 00342 00343 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 00344 if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} 00345 if (return_parse_end) *return_parse_end=end; 00346 return c; 00347 } 00348 /* Default options for cJSON_Parse */ 00349 cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} 00350 00351 /* Render a cJSON item/entity/structure to text. */ 00352 char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} 00353 char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} 00354 00355 char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) 00356 { 00357 printbuffer p; 00358 p.buffer=(char*)cJSON_malloc(prebuffer); 00359 p.length=prebuffer; 00360 p.offset=0; 00361 return print_value(item,0,fmt,&p); 00362 return p.buffer; 00363 } 00364 00365 00366 /* Parser core - when encountering text, process appropriately. */ 00367 static const char *parse_value(cJSON *item,const char *value) 00368 { 00369 if (!value) return 0; /* Fail on null. */ 00370 if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } 00371 if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } 00372 if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } 00373 if (*value=='\"') { return parse_string(item,value); } 00374 if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } 00375 if (*value=='[') { return parse_array(item,value); } 00376 if (*value=='{') { return parse_object(item,value); } 00377 00378 ep=value;return 0; /* failure. */ 00379 } 00380 00381 /* Render a value to text. */ 00382 static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) 00383 { 00384 char *out=0; 00385 if (!item) return 0; 00386 if (p) 00387 { 00388 switch ((item->type)&255) 00389 { 00390 case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} 00391 case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} 00392 case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} 00393 case cJSON_Number: out=print_number(item,p);break; 00394 case cJSON_String: out=print_string(item,p);break; 00395 case cJSON_Array: out=print_array(item,depth,fmt,p);break; 00396 case cJSON_Object: out=print_object(item,depth,fmt,p);break; 00397 } 00398 } 00399 else 00400 { 00401 switch ((item->type)&255) 00402 { 00403 case cJSON_NULL: out=cJSON_strdup("null"); break; 00404 case cJSON_False: out=cJSON_strdup("false");break; 00405 case cJSON_True: out=cJSON_strdup("true"); break; 00406 case cJSON_Number: out=print_number(item,0);break; 00407 case cJSON_String: out=print_string(item,0);break; 00408 case cJSON_Array: out=print_array(item,depth,fmt,0);break; 00409 case cJSON_Object: out=print_object(item,depth,fmt,0);break; 00410 } 00411 } 00412 return out; 00413 } 00414 00415 /* Build an array from input text. */ 00416 static const char *parse_array(cJSON *item,const char *value) 00417 { 00418 cJSON *child; 00419 if (*value!='[') {ep=value;return 0;} /* not an array! */ 00420 00421 item->type=cJSON_Array; 00422 value=skip(value+1); 00423 if (*value==']') return value+1; /* empty array. */ 00424 00425 item->child=child=cJSON_New_Item(); 00426 if (!item->child) return 0; /* memory fail */ 00427 value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ 00428 if (!value) return 0; 00429 00430 while (*value==',') 00431 { 00432 cJSON *new_item; 00433 if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 00434 child->next=new_item;new_item->prev=child;child=new_item; 00435 value=skip(parse_value(child,skip(value+1))); 00436 if (!value) return 0; /* memory fail */ 00437 } 00438 00439 if (*value==']') return value+1; /* end of array */ 00440 ep=value;return 0; /* malformed. */ 00441 } 00442 00443 /* Render an array to text */ 00444 static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) 00445 { 00446 char **entries; 00447 char *out=0,*ptr,*ret;int len=5; 00448 cJSON *child=item->child; 00449 int numentries=0,i=0,fail=0; 00450 size_t tmplen=0; 00451 00452 /* How many entries in the array? */ 00453 while (child) numentries++,child=child->next; 00454 /* Explicitly handle numentries==0 */ 00455 if (!numentries) 00456 { 00457 if (p) out=ensure(p,3); 00458 else out=(char*)cJSON_malloc(3); 00459 if (out) strcpy(out,"[]"); 00460 return out; 00461 } 00462 00463 if (p) 00464 { 00465 /* Compose the output array. */ 00466 i=p->offset; 00467 ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; 00468 child=item->child; 00469 while (child && !fail) 00470 { 00471 print_value(child,depth+1,fmt,p); 00472 p->offset=update(p); 00473 if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} 00474 child=child->next; 00475 } 00476 ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; 00477 out=(p->buffer)+i; 00478 } 00479 else 00480 { 00481 /* Allocate an array to hold the values for each */ 00482 entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 00483 if (!entries) return 0; 00484 memset(entries,0,numentries*sizeof(char*)); 00485 /* Retrieve all the results: */ 00486 child=item->child; 00487 while (child && !fail) 00488 { 00489 ret=print_value(child,depth+1,fmt,0); 00490 entries[i++]=ret; 00491 if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; 00492 child=child->next; 00493 } 00494 00495 /* If we didn't fail, try to malloc the output string */ 00496 if (!fail) out=(char*)cJSON_malloc(len); 00497 /* If that fails, we fail. */ 00498 if (!out) fail=1; 00499 00500 /* Handle failure. */ 00501 if (fail) 00502 { 00503 for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); 00504 cJSON_free(entries); 00505 return 0; 00506 } 00507 00508 /* Compose the output array. */ 00509 *out='['; 00510 ptr=out+1;*ptr=0; 00511 for (i=0;i<numentries;i++) 00512 { 00513 tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen; 00514 if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;} 00515 cJSON_free(entries[i]); 00516 } 00517 cJSON_free(entries); 00518 *ptr++=']';*ptr++=0; 00519 } 00520 return out; 00521 } 00522 00523 /* Build an object from the text. */ 00524 static const char *parse_object(cJSON *item,const char *value) 00525 { 00526 cJSON *child; 00527 if (*value!='{') {ep=value;return 0;} /* not an object! */ 00528 00529 item->type=cJSON_Object; 00530 value=skip(value+1); 00531 if (*value=='}') return value+1; /* empty array. */ 00532 00533 item->child=child=cJSON_New_Item(); 00534 if (!item->child) return 0; 00535 value=skip(parse_string(child,skip(value))); 00536 if (!value) return 0; 00537 child->string=child->valuestring;child->valuestring=0; 00538 if (*value!=':') {ep=value;return 0;} /* fail! */ 00539 value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 00540 if (!value) return 0; 00541 00542 while (*value==',') 00543 { 00544 cJSON *new_item; 00545 if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ 00546 child->next=new_item;new_item->prev=child;child=new_item; 00547 value=skip(parse_string(child,skip(value+1))); 00548 if (!value) return 0; 00549 child->string=child->valuestring;child->valuestring=0; 00550 if (*value!=':') {ep=value;return 0;} /* fail! */ 00551 value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ 00552 if (!value) return 0; 00553 } 00554 00555 if (*value=='}') return value+1; /* end of array */ 00556 ep=value;return 0; /* malformed. */ 00557 } 00558 00559 /* Render an object to text. */ 00560 static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) 00561 { 00562 char **entries=0,**names=0; 00563 char *out=0,*ptr,*ret,*str;int len=7,i=0,j; 00564 cJSON *child=item->child; 00565 int numentries=0,fail=0; 00566 size_t tmplen=0; 00567 /* Count the number of entries. */ 00568 while (child) numentries++,child=child->next; 00569 /* Explicitly handle empty object case */ 00570 if (!numentries) 00571 { 00572 if (p) out=ensure(p,fmt?depth+4:3); 00573 else out=(char*)cJSON_malloc(fmt?depth+4:3); 00574 if (!out) return 0; 00575 ptr=out;*ptr++='{'; 00576 if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';} 00577 *ptr++='}';*ptr++=0; 00578 return out; 00579 } 00580 if (p) 00581 { 00582 /* Compose the output: */ 00583 i=p->offset; 00584 len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; 00585 *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; 00586 child=item->child;depth++; 00587 while (child) 00588 { 00589 if (fmt) 00590 { 00591 ptr=ensure(p,depth); if (!ptr) return 0; 00592 for (j=0;j<depth;j++) *ptr++='\t'; 00593 p->offset+=depth; 00594 } 00595 print_string_ptr(child->string,p); 00596 p->offset=update(p); 00597 00598 len=fmt?2:1; 00599 ptr=ensure(p,len); if (!ptr) return 0; 00600 *ptr++=':';if (fmt) *ptr++='\t'; 00601 p->offset+=len; 00602 00603 print_value(child,depth,fmt,p); 00604 p->offset=update(p); 00605 00606 len=(fmt?1:0)+(child->next?1:0); 00607 ptr=ensure(p,len+1); if (!ptr) return 0; 00608 if (child->next) *ptr++=','; 00609 if (fmt) *ptr++='\n';*ptr=0; 00610 p->offset+=len; 00611 child=child->next; 00612 } 00613 ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; 00614 if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; 00615 *ptr++='}';*ptr=0; 00616 out=(p->buffer)+i; 00617 } 00618 else 00619 { 00620 /* Allocate space for the names and the objects */ 00621 entries=(char**)cJSON_malloc(numentries*sizeof(char*)); 00622 if (!entries) return 0; 00623 names=(char**)cJSON_malloc(numentries*sizeof(char*)); 00624 if (!names) {cJSON_free(entries);return 0;} 00625 memset(entries,0,sizeof(char*)*numentries); 00626 memset(names,0,sizeof(char*)*numentries); 00627 00628 /* Collect all the results into our arrays: */ 00629 child=item->child;depth++;if (fmt) len+=depth; 00630 while (child) 00631 { 00632 names[i]=str=print_string_ptr(child->string,0); 00633 entries[i++]=ret=print_value(child,depth,fmt,0); 00634 if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; 00635 child=child->next; 00636 } 00637 00638 /* Try to allocate the output string */ 00639 if (!fail) out=(char*)cJSON_malloc(len); 00640 if (!out) fail=1; 00641 00642 /* Handle failure */ 00643 if (fail) 00644 { 00645 for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);} 00646 cJSON_free(names);cJSON_free(entries); 00647 return 0; 00648 } 00649 00650 /* Compose the output: */ 00651 *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; 00652 for (i=0;i<numentries;i++) 00653 { 00654 if (fmt) for (j=0;j<depth;j++) *ptr++='\t'; 00655 tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen; 00656 *ptr++=':';if (fmt) *ptr++='\t'; 00657 strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); 00658 if (i!=numentries-1) *ptr++=','; 00659 if (fmt) *ptr++='\n';*ptr=0; 00660 cJSON_free(names[i]);cJSON_free(entries[i]); 00661 } 00662 00663 cJSON_free(names);cJSON_free(entries); 00664 if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; 00665 *ptr++='}';*ptr++=0; 00666 } 00667 return out; 00668 } 00669 00670 /* Get Array size/item / object item. */ 00671 int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;} 00672 cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} 00673 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} 00674 00675 /* Utility for array list handling. */ 00676 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} 00677 /* Utility for handling references. */ 00678 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;} 00679 00680 /* Add item to array/object. */ 00681 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);}} 00682 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);} 00683 void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} 00684 void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} 00685 void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} 00686 00687 cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; 00688 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;} 00689 void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} 00690 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;} 00691 void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} 00692 00693 /* Replace array/object items with new ones. */ 00694 void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; 00695 newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; 00696 if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} 00697 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);}} 00698 00699 /* Create basic types: */ 00700 cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} 00701 cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} 00702 cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} 00703 cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} 00704 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;} 00705 cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} 00706 cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} 00707 cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} 00708 00709 /* Create Arrays: */ 00710 cJSON *cJSON_CreateIntArray(const 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;} 00711 cJSON *cJSON_CreateFloatArray(const 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;} 00712 cJSON *cJSON_CreateDoubleArray(const 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;} 00713 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;} 00714 00715 /* Duplication */ 00716 cJSON *cJSON_Duplicate(cJSON *item,int recurse) 00717 { 00718 cJSON *newitem,*cptr,*nptr=0,*newchild; 00719 /* Bail on bad ptr */ 00720 if (!item) return 0; 00721 /* Create new item */ 00722 newitem=cJSON_New_Item(); 00723 if (!newitem) return 0; 00724 /* Copy over all vars */ 00725 newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; 00726 if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} 00727 if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} 00728 /* If non-recursive, then we're done! */ 00729 if (!recurse) return newitem; 00730 /* Walk the ->next chain for the child. */ 00731 cptr=item->child; 00732 while (cptr) 00733 { 00734 newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ 00735 if (!newchild) {cJSON_Delete(newitem);return 0;} 00736 if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 00737 else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ 00738 cptr=cptr->next; 00739 } 00740 return newitem; 00741 } 00742 00743 void cJSON_Minify(char *json) 00744 { 00745 char *into=json; 00746 while (*json) 00747 { 00748 if (*json==' ') json++; 00749 else if (*json=='\t') json++; // Whitespace characters. 00750 else if (*json=='\r') json++; 00751 else if (*json=='\n') json++; 00752 else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line. 00753 else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments. 00754 else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive. 00755 else *into++=*json++; // All other characters. 00756 } 00757 *into=0; // and null-terminate. 00758 }
Generated on Thu Jul 14 2022 10:00:04 by 1.7.2