1 /*
2   Copyright (c) 2009 Dave Gamble
3 
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:
10 
11   The above copyright notice and this permission notice shall be included in
12   all copies or substantial portions of the Software.
13 
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
20   THE SOFTWARE.
21 */
22 
23 /* cJSON */
24 /* JSON parser in C. */
25 
26 #include <string.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <stdlib.h>
30 #include <float.h>
31 #include <limits.h>
32 #include <ctype.h>
33 #include "cJSON.h"
34 
35 static const char *ep;
36 
cJSON_GetErrorPtr(void)37 const char *cJSON_GetErrorPtr(void) {return ep;}
38 
cJSON_strcasecmp(const char * s1,const char * s2)39 static int cJSON_strcasecmp(const char *s1,const char *s2)
40 {
41 	if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
42 	for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)	if(*s1 == 0)	return 0;
43 	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
44 }
45 
46 static void *(*cJSON_malloc)(size_t sz) = malloc;
47 static void (*cJSON_free)(void *ptr) = free;
48 
cJSON_strdup(const char * str)49 static char* cJSON_strdup(const char* str)
50 {
51       size_t len;
52       char* copy;
53 
54       len = strlen(str) + 1;
55       if (!(copy = (char*)cJSON_malloc(len))) return 0;
56       memcpy(copy,str,len);
57       return copy;
58 }
59 
cJSON_InitHooks(cJSON_Hooks * hooks)60 void cJSON_InitHooks(cJSON_Hooks* hooks)
61 {
62     if (!hooks) { /* Reset hooks */
63         cJSON_malloc = malloc;
64         cJSON_free = free;
65         return;
66     }
67 
68 	cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
69 	cJSON_free	 = (hooks->free_fn)?hooks->free_fn:free;
70 }
71 
72 /* Internal constructor. */
cJSON_New_Item(void)73 static cJSON *cJSON_New_Item(void)
74 {
75 	cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
76 	if (node) memset(node,0,sizeof(cJSON));
77 	return node;
78 }
79 
80 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * c)81 void cJSON_Delete(cJSON *c)
82 {
83 	cJSON *next;
84 	while (c)
85 	{
86 		next=c->next;
87 		if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
88 		if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
89 		if (c->string) cJSON_free(c->string);
90 		cJSON_free(c);
91 		c=next;
92 	}
93 }
94 
95 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * item,const char * num)96 static const char *parse_number(cJSON *item,const char *num)
97 {
98 	double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
99 
100 	if (*num=='-') sign=-1,num++;	/* Has sign? */
101 	if (*num=='0') num++;			/* is zero */
102 	if (*num>='1' && *num<='9')	do	n=(n*10.0)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
103 	if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;		do	n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}	/* Fractional part? */
104 	if (*num=='e' || *num=='E')		/* Exponent? */
105 	{	num++;if (*num=='+') num++;	else if (*num=='-') signsubscale=-1,num++;		/* With sign? */
106 		while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');	/* Number? */
107 	}
108 
109 	n=sign*n*pow(10.0,(scale+subscale*signsubscale));	/* number = +/- number.fraction * 10^+/- exponent */
110 
111 	item->valuedouble=n;
112 	item->valueint=(int)n;
113 	item->type=cJSON_Number;
114 	return num;
115 }
116 
117 /* Render the number nicely from the given item into a string. */
print_number(cJSON * item)118 static char *print_number(cJSON *item)
119 {
120 	char *str;
121 	double d=item->valuedouble;
122 	if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
123 	{
124 		str=(char*)cJSON_malloc(21);	/* 2^64+1 can be represented in 21 chars. */
125 		if (str) sprintf(str,"%d",item->valueint);
126 	}
127 	else
128 	{
129 		str=(char*)cJSON_malloc(64);	/* This is a nice tradeoff. */
130 		if (str)
131 		{
132 			if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
133 			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)			sprintf(str,"%e",d);
134 			else												sprintf(str,"%f",d);
135 		}
136 	}
137 	return str;
138 }
139 
parse_hex4(const char * str)140 static unsigned parse_hex4(const char *str)
141 {
142 	unsigned h=0;
143 	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;
144 	h=h<<4;str++;
145 	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;
146 	h=h<<4;str++;
147 	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;
148 	h=h<<4;str++;
149 	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;
150 	return h;
151 }
152 
153 /* Parse the input text into an unescaped cstring, and populate item. */
154 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
parse_string(cJSON * item,const char * str)155 static const char *parse_string(cJSON *item,const char *str)
156 {
157 	const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
158 	if (*str!='\"') {ep=str;return 0;}	/* not a string! */
159 
160 	while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;	/* Skip escaped quotes. */
161 
162 	out=(char*)cJSON_malloc(len+1);	/* This is how long we need for the string, roughly. */
163 	if (!out) return 0;
164 
165 	ptr=str+1;ptr2=out;
166 	while (*ptr!='\"' && *ptr)
167 	{
168 		if (*ptr!='\\') *ptr2++=*ptr++;
169 		else
170 		{
171 			ptr++;
172 			switch (*ptr)
173 			{
174 				case 'b': *ptr2++='\b';	break;
175 				case 'f': *ptr2++='\f';	break;
176 				case 'n': *ptr2++='\n';	break;
177 				case 'r': *ptr2++='\r';	break;
178 				case 't': *ptr2++='\t';	break;
179 				case 'u':	 /* transcode utf16 to utf8. */
180 					uc=parse_hex4(ptr+1);ptr+=4;	/* get the unicode char. */
181 
182 					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)	break;	/* check for invalid.	*/
183 
184 					if (uc>=0xD800 && uc<=0xDBFF)	/* UTF16 surrogate pairs.	*/
185 					{
186 						if (ptr[1]!='\\' || ptr[2]!='u')	break;	/* missing second-half of surrogate.	*/
187 						uc2=parse_hex4(ptr+3);ptr+=6;
188 						if (uc2<0xDC00 || uc2>0xDFFF)		break;	/* invalid second-half of surrogate.	*/
189 						uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
190 					}
191 
192 					len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
193 
194 					switch (len) {
195 						case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
196 						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
197 						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
198 						case 1: *--ptr2 =(uc | firstByteMark[len]);
199 					}
200 					ptr2+=len;
201 					break;
202 				default:  *ptr2++=*ptr; break;
203 			}
204 			ptr++;
205 		}
206 	}
207 	*ptr2=0;
208 	if (*ptr=='\"') ptr++;
209 	item->valuestring=out;
210 	item->type=cJSON_String;
211 	return ptr;
212 }
213 
214 /* Render the cstring provided to an escaped version that can be printed. */
print_string_ptr(const char * str)215 static char *print_string_ptr(const char *str)
216 {
217 	const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
218 
219 	if (!str) return cJSON_strdup("");
220 	ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
221 
222 	out=(char*)cJSON_malloc(len+3);
223 	if (!out) return 0;
224 
225 	ptr2=out;ptr=str;
226 	*ptr2++='\"';
227 	while (*ptr)
228 	{
229 		if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
230 		else
231 		{
232 			*ptr2++='\\';
233 			switch (token=*ptr++)
234 			{
235 				case '\\':	*ptr2++='\\';	break;
236 				case '\"':	*ptr2++='\"';	break;
237 				case '\b':	*ptr2++='b';	break;
238 				case '\f':	*ptr2++='f';	break;
239 				case '\n':	*ptr2++='n';	break;
240 				case '\r':	*ptr2++='r';	break;
241 				case '\t':	*ptr2++='t';	break;
242 				default: sprintf(ptr2,"u%04x",token);ptr2+=5;	break;	/* escape and print */
243 			}
244 		}
245 	}
246 	*ptr2++='\"';*ptr2++=0;
247 	return out;
248 }
249 /* Invote print_string_ptr (which is useful) on an item. */
print_string(cJSON * item)250 static char *print_string(cJSON *item)	{return print_string_ptr(item->valuestring);}
251 
252 /* Predeclare these prototypes. */
253 static const char *parse_value(cJSON *item,const char *value);
254 static char *print_value(cJSON *item,int depth,int fmt);
255 static const char *parse_array(cJSON *item,const char *value);
256 static char *print_array(cJSON *item,int depth,int fmt);
257 static const char *parse_object(cJSON *item,const char *value);
258 static char *print_object(cJSON *item,int depth,int fmt);
259 
260 /* Utility to jump whitespace and cr/lf */
skip(const char * in)261 static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
262 
263 /* Parse an object - create a new root, and populate. */
cJSON_ParseWithOpts(const char * value,const char ** return_parse_end,int require_null_terminated)264 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
265 {
266 	const char *end=0;
267 	cJSON *c=cJSON_New_Item();
268 	ep=0;
269 	if (!c) return 0;       /* memory fail */
270 
271 	end=parse_value(c,skip(value));
272 	if (!end)	{cJSON_Delete(c);return 0;}	/* parse failure. ep is set. */
273 
274 	/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
275 	if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
276 	if (return_parse_end) *return_parse_end=end;
277 	return c;
278 }
279 /* Default options for cJSON_Parse */
cJSON_Parse(const char * value)280 cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
281 
282 /* Render a cJSON item/entity/structure to text. */
cJSON_Print(cJSON * item)283 char *cJSON_Print(cJSON *item)				{return print_value(item,0,1);}
cJSON_PrintUnformatted(cJSON * item)284 char *cJSON_PrintUnformatted(cJSON *item)	{return print_value(item,0,0);}
285 
286 /* Parser core - when encountering text, process appropriately. */
parse_value(cJSON * item,const char * value)287 static const char *parse_value(cJSON *item,const char *value)
288 {
289 	if (!value)						return 0;	/* Fail on null. */
290 	if (!strncmp(value,"null",4))	{ item->type=cJSON_NULL;  return value+4; }
291 	if (!strncmp(value,"false",5))	{ item->type=cJSON_False; return value+5; }
292 	if (!strncmp(value,"true",4))	{ item->type=cJSON_True; item->valueint=1;	return value+4; }
293 	if (*value=='\"')				{ return parse_string(item,value); }
294 	if (*value=='-' || (*value>='0' && *value<='9'))	{ return parse_number(item,value); }
295 	if (*value=='[')				{ return parse_array(item,value); }
296 	if (*value=='{')				{ return parse_object(item,value); }
297 
298 	ep=value;return 0;	/* failure. */
299 }
300 
301 /* Render a value to text. */
print_value(cJSON * item,int depth,int fmt)302 static char *print_value(cJSON *item,int depth,int fmt)
303 {
304 	char *out=0;
305 	if (!item) return 0;
306 	switch ((item->type)&255)
307 	{
308 		case cJSON_NULL:	out=cJSON_strdup("null");	break;
309 		case cJSON_False:	out=cJSON_strdup("false");break;
310 		case cJSON_True:	out=cJSON_strdup("true"); break;
311 		case cJSON_Number:	out=print_number(item);break;
312 		case cJSON_String:	out=print_string(item);break;
313 		case cJSON_Array:	out=print_array(item,depth,fmt);break;
314 		case cJSON_Object:	out=print_object(item,depth,fmt);break;
315 	}
316 	return out;
317 }
318 
319 /* Build an array from input text. */
parse_array(cJSON * item,const char * value)320 static const char *parse_array(cJSON *item,const char *value)
321 {
322 	cJSON *child;
323 	if (*value!='[')	{ep=value;return 0;}	/* not an array! */
324 
325 	item->type=cJSON_Array;
326 	value=skip(value+1);
327 	if (*value==']') return value+1;	/* empty array. */
328 
329 	item->child=child=cJSON_New_Item();
330 	if (!item->child) return 0;		 /* memory fail */
331 	value=skip(parse_value(child,skip(value)));	/* skip any spacing, get the value. */
332 	if (!value) return 0;
333 
334 	while (*value==',')
335 	{
336 		cJSON *new_item;
337 		if (!(new_item=cJSON_New_Item())) return 0; 	/* memory fail */
338 		child->next=new_item;new_item->prev=child;child=new_item;
339 		value=skip(parse_value(child,skip(value+1)));
340 		if (!value) return 0;	/* memory fail */
341 	}
342 
343 	if (*value==']') return value+1;	/* end of array */
344 	ep=value;return 0;	/* malformed. */
345 }
346 
347 /* Render an array to text */
print_array(cJSON * item,int depth,int fmt)348 static char *print_array(cJSON *item,int depth,int fmt)
349 {
350 	char **entries;
351 	char *out=0,*ptr,*ret;int len=5;
352 	cJSON *child=item->child;
353 	int numentries=0,i=0,fail=0;
354 
355 	/* How many entries in the array? */
356 	while (child) numentries++,child=child->next;
357 	/* Explicitly handle numentries==0 */
358 	if (!numentries)
359 	{
360 		out=(char*)cJSON_malloc(3);
361 		if (out) strcpy(out,"[]");
362 		return out;
363 	}
364 	/* Allocate an array to hold the values for each */
365 	entries=(char**)cJSON_malloc(numentries*sizeof(char*));
366 	if (!entries) return 0;
367 	memset(entries,0,numentries*sizeof(char*));
368 	/* Retrieve all the results: */
369 	child=item->child;
370 	while (child && !fail)
371 	{
372 		ret=print_value(child,depth+1,fmt);
373 		entries[i++]=ret;
374 		if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
375 		child=child->next;
376 	}
377 
378 	/* If we didn't fail, try to malloc the output string */
379 	if (!fail) out=(char*)cJSON_malloc(len);
380 	/* If that fails, we fail. */
381 	if (!out) fail=1;
382 
383 	/* Handle failure. */
384 	if (fail)
385 	{
386 		for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
387 		cJSON_free(entries);
388 		return 0;
389 	}
390 
391 	/* Compose the output array. */
392 	*out='[';
393 	ptr=out+1;*ptr=0;
394 	for (i=0;i<numentries;i++)
395 	{
396 		strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
397 		if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
398 		cJSON_free(entries[i]);
399 	}
400 	cJSON_free(entries);
401 	*ptr++=']';*ptr++=0;
402 	return out;
403 }
404 
405 /* Build an object from the text. */
parse_object(cJSON * item,const char * value)406 static const char *parse_object(cJSON *item,const char *value)
407 {
408 	cJSON *child;
409 	if (*value!='{')	{ep=value;return 0;}	/* not an object! */
410 
411 	item->type=cJSON_Object;
412 	value=skip(value+1);
413 	if (*value=='}') return value+1;	/* empty array. */
414 
415 	item->child=child=cJSON_New_Item();
416 	if (!item->child) return 0;
417 	value=skip(parse_string(child,skip(value)));
418 	if (!value) return 0;
419 	child->string=child->valuestring;child->valuestring=0;
420 	if (*value!=':') {ep=value;return 0;}	/* fail! */
421 	value=skip(parse_value(child,skip(value+1)));	/* skip any spacing, get the value. */
422 	if (!value) return 0;
423 
424 	while (*value==',')
425 	{
426 		cJSON *new_item;
427 		if (!(new_item=cJSON_New_Item()))	return 0; /* memory fail */
428 		child->next=new_item;new_item->prev=child;child=new_item;
429 		value=skip(parse_string(child,skip(value+1)));
430 		if (!value) return 0;
431 		child->string=child->valuestring;child->valuestring=0;
432 		if (*value!=':') {ep=value;return 0;}	/* fail! */
433 		value=skip(parse_value(child,skip(value+1)));	/* skip any spacing, get the value. */
434 		if (!value) return 0;
435 	}
436 
437 	if (*value=='}') return value+1;	/* end of array */
438 	ep=value;return 0;	/* malformed. */
439 }
440 
441 /* Render an object to text. */
print_object(cJSON * item,int depth,int fmt)442 static char *print_object(cJSON *item,int depth,int fmt)
443 {
444 	char **entries=0,**names=0;
445 	char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
446 	cJSON *child=item->child;
447 	int numentries=0,fail=0;
448 	/* Count the number of entries. */
449 	while (child) numentries++,child=child->next;
450 	/* Explicitly handle empty object case */
451 	if (!numentries)
452 	{
453 		out=(char*)cJSON_malloc(fmt?depth+4:3);
454 		if (!out)	return 0;
455 		ptr=out;*ptr++='{';
456 		if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
457 		*ptr++='}';*ptr++=0;
458 		return out;
459 	}
460 	/* Allocate space for the names and the objects */
461 	entries=(char**)cJSON_malloc(numentries*sizeof(char*));
462 	if (!entries) return 0;
463 	names=(char**)cJSON_malloc(numentries*sizeof(char*));
464 	if (!names) {cJSON_free(entries);return 0;}
465 	memset(entries,0,sizeof(char*)*numentries);
466 	memset(names,0,sizeof(char*)*numentries);
467 
468 	/* Collect all the results into our arrays: */
469 	child=item->child;depth++;if (fmt) len+=depth;
470 	while (child)
471 	{
472 		names[i]=str=print_string_ptr(child->string);
473 		entries[i++]=ret=print_value(child,depth,fmt);
474 		if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
475 		child=child->next;
476 	}
477 
478 	/* Try to allocate the output string */
479 	if (!fail) out=(char*)cJSON_malloc(len);
480 	if (!out) fail=1;
481 
482 	/* Handle failure */
483 	if (fail)
484 	{
485 		for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
486 		cJSON_free(names);cJSON_free(entries);
487 		return 0;
488 	}
489 
490 	/* Compose the output: */
491 	*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
492 	for (i=0;i<numentries;i++)
493 	{
494 		if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
495 		strcpy(ptr,names[i]);ptr+=strlen(names[i]);
496 		*ptr++=':';if (fmt) *ptr++='\t';
497 		strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
498 		if (i!=numentries-1) *ptr++=',';
499 		if (fmt) *ptr++='\n';*ptr=0;
500 		cJSON_free(names[i]);cJSON_free(entries[i]);
501 	}
502 
503 	cJSON_free(names);cJSON_free(entries);
504 	if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
505 	*ptr++='}';*ptr++=0;
506 	return out;
507 }
508 
509 /* Get Array size/item / object item. */
cJSON_GetArraySize(cJSON * array)510 int    cJSON_GetArraySize(cJSON *array)							{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON_GetArrayItem(cJSON * array,int item)511 cJSON *cJSON_GetArrayItem(cJSON *array,int item)				{cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
cJSON_GetObjectItem(cJSON * object,const char * string)512 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)	{cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
513 
514 /* Utility for array list handling. */
suffix_object(cJSON * prev,cJSON * item)515 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
516 /* Utility for handling references. */
create_reference(cJSON * item)517 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;}
518 
519 /* Add item to array/object. */
cJSON_AddItemToArray(cJSON * array,cJSON * item)520 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);}}
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)521 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);}
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)522 void	cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)						{cJSON_AddItemToArray(array,create_reference(item));}
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)523 void	cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)	{cJSON_AddItemToObject(object,string,create_reference(item));}
524 
cJSON_DetachItemFromArray(cJSON * array,int which)525 cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)			{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
526 	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;}
cJSON_DeleteItemFromArray(cJSON * array,int which)527 void   cJSON_DeleteItemFromArray(cJSON *array,int which)			{cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON_DetachItemFromObject(cJSON * object,const char * string)528 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;}
cJSON_DeleteItemFromObject(cJSON * object,const char * string)529 void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
530 
531 /* Replace array/object items with new ones. */
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)532 void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)		{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
533 	newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
534 	if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)535 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);}}
536 
537 /* Create basic types: */
cJSON_CreateNull(void)538 cJSON *cJSON_CreateNull(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON_CreateTrue(void)539 cJSON *cJSON_CreateTrue(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON_CreateFalse(void)540 cJSON *cJSON_CreateFalse(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON_CreateBool(int b)541 cJSON *cJSON_CreateBool(int b)					{cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON_CreateNumber(double num)542 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_CreateString(const char * string)543 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_CreateArray(void)544 cJSON *cJSON_CreateArray(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON_CreateObject(void)545 cJSON *cJSON_CreateObject(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
546 
547 /* Create Arrays: */
cJSON_CreateIntArray(const int * numbers,int count)548 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;}
cJSON_CreateFloatArray(const float * numbers,int count)549 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;}
cJSON_CreateDoubleArray(const double * numbers,int count)550 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;}
cJSON_CreateStringArray(const char ** strings,int count)551 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;}
552 
553 /* Duplication */
cJSON_Duplicate(cJSON * item,int recurse)554 cJSON *cJSON_Duplicate(cJSON *item,int recurse)
555 {
556 	cJSON *newitem,*cptr,*nptr=0,*newchild;
557 	/* Bail on bad ptr */
558 	if (!item) return 0;
559 	/* Create new item */
560 	newitem=cJSON_New_Item();
561 	if (!newitem) return 0;
562 	/* Copy over all vars */
563 	newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
564 	if (item->valuestring)	{newitem->valuestring=cJSON_strdup(item->valuestring);	if (!newitem->valuestring)	{cJSON_Delete(newitem);return 0;}}
565 	if (item->string)		{newitem->string=cJSON_strdup(item->string);			if (!newitem->string)		{cJSON_Delete(newitem);return 0;}}
566 	/* If non-recursive, then we're done! */
567 	if (!recurse) return newitem;
568 	/* Walk the ->next chain for the child. */
569 	cptr=item->child;
570 	while (cptr)
571 	{
572 		newchild=cJSON_Duplicate(cptr,1);		/* Duplicate (with recurse) each item in the ->next chain */
573 		if (!newchild) {cJSON_Delete(newitem);return 0;}
574 		if (nptr)	{nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}	/* If newitem->child already set, then crosswire ->prev and ->next and move on */
575 		else		{newitem->child=newchild;nptr=newchild;}					/* Set newitem->child and move to it */
576 		cptr=cptr->next;
577 	}
578 	return newitem;
579 }
580 
cJSON_Minify(char * json)581 void cJSON_Minify(char *json)
582 {
583 	char *into=json;
584 	while (*json)
585 	{
586 		if (*json==' ') json++;
587 		else if (*json=='\t') json++;	// Whitespace characters.
588 		else if (*json=='\r') json++;
589 		else if (*json=='\n') json++;
590 		else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;	// double-slash comments, to end of line.
591 		else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}	// multiline comments.
592 		else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
593 		else *into++=*json++;			// All other characters.
594 	}
595 	*into=0;	// and null-terminate.
596 }