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