cJSON.c 22.6 KB
Newer Older
D
Dave Gamble 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
  Copyright (c) 2009 Dave Gamble

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

23 24
/* cJSON */
/* JSON parser in C. */
D
Dave Gamble 已提交
25 26 27 28 29 30

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
31
#include <limits.h>
D
Dave Gamble 已提交
32
#include <ctype.h>
D
Dave Gamble 已提交
33 34
#include "cJSON.h"

35 36
static const char *ep;

D
Dave Gamble 已提交
37
const char *cJSON_GetErrorPtr(void) {return ep;}
38

39 40
static int cJSON_strcasecmp(const char *s1,const char *s2)
{
41
	if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
42 43 44
	for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)	if(*s1 == 0)	return 0;
	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
static void *(*cJSON_malloc)(size_t sz) = malloc;
static void (*cJSON_free)(void *ptr) = free;

static char* cJSON_strdup(const char* str)
{
      size_t len;
      char* copy;

      len = strlen(str) + 1;
      if (!(copy = (char*)cJSON_malloc(len))) return 0;
      memcpy(copy,str,len);
      return copy;
}

void cJSON_InitHooks(cJSON_Hooks* hooks)
{
    if (!hooks) { /* Reset hooks */
        cJSON_malloc = malloc;
        cJSON_free = free;
        return;
    }

	cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
	cJSON_free	 = (hooks->free_fn)?hooks->free_fn:free;
}

72
/* Internal constructor. */
D
Dave Gamble 已提交
73
static cJSON *cJSON_New_Item(void)
74 75 76 77 78
{
	cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
	if (node) memset(node,0,sizeof(cJSON));
	return node;
}
D
Dave Gamble 已提交
79

80
/* Delete a cJSON structure. */
D
Dave Gamble 已提交
81 82 83 84 85 86
void cJSON_Delete(cJSON *c)
{
	cJSON *next;
	while (c)
	{
		next=c->next;
D
Dave Gamble 已提交
87 88
		if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
		if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
89 90
		if (c->string) cJSON_free(c->string);
		cJSON_free(c);
D
Dave Gamble 已提交
91 92 93 94
		c=next;
	}
}

95
/* Parse the input text to generate a number, and populate the result into item. */
D
Dave Gamble 已提交
96 97 98 99
static const char *parse_number(cJSON *item,const char *num)
{
	double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;

100 101 102
	if (*num=='-') sign=-1,num++;	/* Has sign? */
	if (*num=='0') num++;			/* is zero */
	if (*num>='1' && *num<='9')	do	n=(n*10.0)+(*num++ -'0');	while (*num>='0' && *num<='9');	/* Number? */
D
Dave Gamble 已提交
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 105 106
	if (*num=='e' || *num=='E')		/* Exponent? */
	{	num++;if (*num=='+') num++;	else if (*num=='-') signsubscale=-1,num++;		/* With sign? */
		while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');	/* Number? */
D
Dave Gamble 已提交
107 108
	}

109
	n=sign*n*pow(10.0,(scale+subscale*signsubscale));	/* number = +/- number.fraction * 10^+/- exponent */
D
Dave Gamble 已提交
110 111 112 113 114 115 116
	
	item->valuedouble=n;
	item->valueint=(int)n;
	item->type=cJSON_Number;
	return num;
}

117
/* Render the number nicely from the given item into a string. */
D
Dave Gamble 已提交
118 119 120 121
static char *print_number(cJSON *item)
{
	char *str;
	double d=item->valuedouble;
122
	if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
D
Dave Gamble 已提交
123
	{
124
		str=(char*)cJSON_malloc(21);	/* 2^64+1 can be represented in 21 chars. */
125
		if (str) sprintf(str,"%d",item->valueint);
D
Dave Gamble 已提交
126 127 128
	}
	else
	{
129
		str=(char*)cJSON_malloc(64);	/* This is a nice tradeoff. */
130 131
		if (str)
		{
132 133 134
			if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)			sprintf(str,"%e",d);
			else												sprintf(str,"%f",d);
135
		}
D
Dave Gamble 已提交
136 137 138 139
	}
	return str;
}

140 141 142 143
static unsigned parse_hex4(const char *str)
{
	unsigned h=0;
	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;
D
Dave Gamble 已提交
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;
D
Dave Gamble 已提交
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;
D
Dave Gamble 已提交
148
	h=h<<4;str++;
149 150 151 152
	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;
	return h;
}

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 };
D
Dave Gamble 已提交
155 156
static const char *parse_string(cJSON *item,const char *str)
{
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! */
D
Dave Gamble 已提交
159
	
D
Dave Gamble 已提交
160
	while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;	/* Skip escaped quotes. */
D
Dave Gamble 已提交
161
	
162
	out=(char*)cJSON_malloc(len+1);	/* This is how long we need for the string, roughly. */
163
	if (!out) return 0;
D
Dave Gamble 已提交
164 165
	
	ptr=str+1;ptr2=out;
D
Dave Gamble 已提交
166
	while (*ptr!='\"' && *ptr)
D
Dave Gamble 已提交
167 168 169 170 171 172 173 174 175 176 177 178
	{
		if (*ptr!='\\') *ptr2++=*ptr++;
		else
		{
			ptr++;
			switch (*ptr)
			{
				case 'b': *ptr2++='\b';	break;
				case 'f': *ptr2++='\f';	break;
				case 'n': *ptr2++='\n';	break;
				case 'r': *ptr2++='\r';	break;
				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

D
Dave Gamble 已提交
182
					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)	break;	/* check for invalid.	*/
183

D
Dave Gamble 已提交
184
					if (uc>=0xD800 && uc<=0xDBFF)	/* UTF16 surrogate pairs.	*/
185
					{
D
Dave Gamble 已提交
186
						if (ptr[1]!='\\' || ptr[2]!='u')	break;	/* missing second-half of surrogate.	*/
187
						uc2=parse_hex4(ptr+3);ptr+=6;
D
Dave Gamble 已提交
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;
D
Dave Gamble 已提交
193 194
					
					switch (len) {
195
						case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
D
Dave Gamble 已提交
196 197 198 199
						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
						case 1: *--ptr2 =(uc | firstByteMark[len]);
					}
200
					ptr2+=len;
D
Dave Gamble 已提交
201 202 203 204 205 206 207 208 209 210 211 212 213
					break;
				default:  *ptr2++=*ptr; break;
			}
			ptr++;
		}
	}
	*ptr2=0;
	if (*ptr=='\"') ptr++;
	item->valuestring=out;
	item->type=cJSON_String;
	return ptr;
}

214
/* Render the cstring provided to an escaped version that can be printed. */
D
Dave Gamble 已提交
215 216
static char *print_string_ptr(const char *str)
{
D
Dave Gamble 已提交
217
	const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
D
Dave Gamble 已提交
218
	
219
	if (!str) return cJSON_strdup("");
D
Dave Gamble 已提交
220
	ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
D
Dave Gamble 已提交
221
	
222
	out=(char*)cJSON_malloc(len+3);
223 224
	if (!out) return 0;

D
Dave Gamble 已提交
225 226 227 228
	ptr2=out;ptr=str;
	*ptr2++='\"';
	while (*ptr)
	{
229
		if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
D
Dave Gamble 已提交
230 231 232
		else
		{
			*ptr2++='\\';
D
Dave Gamble 已提交
233
			switch (token=*ptr++)
D
Dave Gamble 已提交
234 235 236 237 238 239 240 241
			{
				case '\\':	*ptr2++='\\';	break;
				case '\"':	*ptr2++='\"';	break;
				case '\b':	*ptr2++='b';	break;
				case '\f':	*ptr2++='f';	break;
				case '\n':	*ptr2++='n';	break;
				case '\r':	*ptr2++='r';	break;
				case '\t':	*ptr2++='t';	break;
D
Dave Gamble 已提交
242
				default: sprintf(ptr2,"u%04x",token);ptr2+=5;	break;	/* escape and print */
D
Dave Gamble 已提交
243 244 245 246 247 248
			}
		}
	}
	*ptr2++='\"';*ptr2++=0;
	return out;
}
249
/* Invote print_string_ptr (which is useful) on an item. */
D
Dave Gamble 已提交
250 251
static char *print_string(cJSON *item)	{return print_string_ptr(item->valuestring);}

252
/* Predeclare these prototypes. */
D
Dave Gamble 已提交
253
static const char *parse_value(cJSON *item,const char *value);
D
Dave Gamble 已提交
254
static char *print_value(cJSON *item,int depth,int fmt);
D
Dave Gamble 已提交
255
static const char *parse_array(cJSON *item,const char *value);
D
Dave Gamble 已提交
256
static char *print_array(cJSON *item,int depth,int fmt);
D
Dave Gamble 已提交
257
static const char *parse_object(cJSON *item,const char *value);
D
Dave Gamble 已提交
258
static char *print_object(cJSON *item,int depth,int fmt);
D
Dave Gamble 已提交
259

260
/* Utility to jump whitespace and cr/lf */
D
Dave Gamble 已提交
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. */
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();
D
Dave Gamble 已提交
268
	ep=0;
269 270
	if (!c) return 0;       /* memory fail */

271 272 273 274 275 276
	end=parse_value(c,skip(value));
	if (!end)	{cJSON_Delete(c);return 0;}	/* parse failure. ep is set. */

	/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
	if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
	if (return_parse_end) *return_parse_end=end;
277 278
	return c;
}
279 280
/* Default options for cJSON_Parse */
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
281

282
/* Render a cJSON item/entity/structure to text. */
D
Dave Gamble 已提交
283 284
char *cJSON_Print(cJSON *item)				{return print_value(item,0,1);}
char *cJSON_PrintUnformatted(cJSON *item)	{return print_value(item,0,0);}
D
Dave Gamble 已提交
285

286
/* Parser core - when encountering text, process appropriately. */
D
Dave Gamble 已提交
287 288
static const char *parse_value(cJSON *item,const char *value)
{
289
	if (!value)						return 0;	/* Fail on null. */
D
Dave Gamble 已提交
290 291 292 293 294 295 296 297
	if (!strncmp(value,"null",4))	{ item->type=cJSON_NULL;  return value+4; }
	if (!strncmp(value,"false",5))	{ item->type=cJSON_False; return value+5; }
	if (!strncmp(value,"true",4))	{ item->type=cJSON_True; item->valueint=1;	return value+4; }
	if (*value=='\"')				{ return parse_string(item,value); }
	if (*value=='-' || (*value>='0' && *value<='9'))	{ return parse_number(item,value); }
	if (*value=='[')				{ return parse_array(item,value); }
	if (*value=='{')				{ return parse_object(item,value); }

298
	ep=value;return 0;	/* failure. */
D
Dave Gamble 已提交
299 300
}

301
/* Render a value to text. */
D
Dave Gamble 已提交
302
static char *print_value(cJSON *item,int depth,int fmt)
D
Dave Gamble 已提交
303 304
{
	char *out=0;
D
Dave Gamble 已提交
305
	if (!item) return 0;
D
Dave Gamble 已提交
306
	switch ((item->type)&255)
D
Dave Gamble 已提交
307
	{
308 309 310
		case cJSON_NULL:	out=cJSON_strdup("null");	break;
		case cJSON_False:	out=cJSON_strdup("false");break;
		case cJSON_True:	out=cJSON_strdup("true"); break;
D
Dave Gamble 已提交
311 312
		case cJSON_Number:	out=print_number(item);break;
		case cJSON_String:	out=print_string(item);break;
D
Dave Gamble 已提交
313 314
		case cJSON_Array:	out=print_array(item,depth,fmt);break;
		case cJSON_Object:	out=print_object(item,depth,fmt);break;
D
Dave Gamble 已提交
315 316 317 318
	}
	return out;
}

319
/* Build an array from input text. */
D
Dave Gamble 已提交
320 321 322
static const char *parse_array(cJSON *item,const char *value)
{
	cJSON *child;
323
	if (*value!='[')	{ep=value;return 0;}	/* not an array! */
D
Dave Gamble 已提交
324 325 326

	item->type=cJSON_Array;
	value=skip(value+1);
327
	if (*value==']') return value+1;	/* empty array. */
D
Dave Gamble 已提交
328 329

	item->child=child=cJSON_New_Item();
330 331
	if (!item->child) return 0;		 /* memory fail */
	value=skip(parse_value(child,skip(value)));	/* skip any spacing, get the value. */
332
	if (!value) return 0;
D
Dave Gamble 已提交
333 334 335 336

	while (*value==',')
	{
		cJSON *new_item;
337
		if (!(new_item=cJSON_New_Item())) return 0; 	/* memory fail */
D
Dave Gamble 已提交
338 339
		child->next=new_item;new_item->prev=child;child=new_item;
		value=skip(parse_value(child,skip(value+1)));
340
		if (!value) return 0;	/* memory fail */
D
Dave Gamble 已提交
341 342
	}

343
	if (*value==']') return value+1;	/* end of array */
344
	ep=value;return 0;	/* malformed. */
D
Dave Gamble 已提交
345 346
}

347
/* Render an array to text */
D
Dave Gamble 已提交
348
static char *print_array(cJSON *item,int depth,int fmt)
D
Dave Gamble 已提交
349
{
350
	char **entries;
351
	char *out=0,*ptr,*ret;int len=5;
D
Dave Gamble 已提交
352
	cJSON *child=item->child;
353
	int numentries=0,i=0,fail=0;
D
Dave Gamble 已提交
354
	
355
	/* How many entries in the array? */
356
	while (child) numentries++,child=child->next;
357 358
	/* Explicitly handle numentries==0 */
	if (!numentries)
D
Dave Gamble 已提交
359
	{
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
		out=(char*)cJSON_malloc(3);
		if (out) strcpy(out,"[]");
		return out;
	}
	/* Allocate an array to hold the values for each */
	entries=(char**)cJSON_malloc(numentries*sizeof(char*));
	if (!entries) return 0;
	memset(entries,0,numentries*sizeof(char*));
	/* Retrieve all the results: */
	child=item->child;
	while (child && !fail)
	{
		ret=print_value(child,depth+1,fmt);
		entries[i++]=ret;
		if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
		child=child->next;
D
Dave Gamble 已提交
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 382
	if (!out) fail=1;

383
	/* Handle failure. */
384 385 386
	if (fail)
	{
		for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
387
		cJSON_free(entries);
388 389 390
		return 0;
	}
	
391
	/* Compose the output array. */
392 393 394 395 396
	*out='[';
	ptr=out+1;*ptr=0;
	for (i=0;i<numentries;i++)
	{
		strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
D
Dave Gamble 已提交
397
		if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
398 399
		cJSON_free(entries[i]);
	}
400
	cJSON_free(entries);
D
Dave Gamble 已提交
401 402 403 404
	*ptr++=']';*ptr++=0;
	return out;	
}

405
/* Build an object from the text. */
D
Dave Gamble 已提交
406 407 408
static const char *parse_object(cJSON *item,const char *value)
{
	cJSON *child;
409
	if (*value!='{')	{ep=value;return 0;}	/* not an object! */
D
Dave Gamble 已提交
410 411 412
	
	item->type=cJSON_Object;
	value=skip(value+1);
413
	if (*value=='}') return value+1;	/* empty array. */
D
Dave Gamble 已提交
414 415
	
	item->child=child=cJSON_New_Item();
416
	if (!item->child) return 0;
D
Dave Gamble 已提交
417
	value=skip(parse_string(child,skip(value)));
418
	if (!value) return 0;
D
Dave Gamble 已提交
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;
D
Dave Gamble 已提交
423 424 425 426
	
	while (*value==',')
	{
		cJSON *new_item;
427
		if (!(new_item=cJSON_New_Item()))	return 0; /* memory fail */
D
Dave Gamble 已提交
428 429
		child->next=new_item;new_item->prev=child;child=new_item;
		value=skip(parse_string(child,skip(value+1)));
430
		if (!value) return 0;
D
Dave Gamble 已提交
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;
D
Dave Gamble 已提交
435 436
	}
	
437
	if (*value=='}') return value+1;	/* end of array */
438
	ep=value;return 0;	/* malformed. */
D
Dave Gamble 已提交
439 440
}

441
/* Render an object to text. */
D
Dave Gamble 已提交
442
static char *print_object(cJSON *item,int depth,int fmt)
D
Dave Gamble 已提交
443
{
444 445
	char **entries=0,**names=0;
	char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
D
Dave Gamble 已提交
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 451 452
	/* Explicitly handle empty object case */
	if (!numentries)
	{
453
		out=(char*)cJSON_malloc(fmt?depth+4:3);
454 455 456 457 458 459
		if (!out)	return 0;
		ptr=out;*ptr++='{';
		if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
		*ptr++='}';*ptr++=0;
		return out;
	}
460
	/* Allocate space for the names and the objects */
461 462 463 464 465 466 467
	entries=(char**)cJSON_malloc(numentries*sizeof(char*));
	if (!entries) return 0;
	names=(char**)cJSON_malloc(numentries*sizeof(char*));
	if (!names) {cJSON_free(entries);return 0;}
	memset(entries,0,sizeof(char*)*numentries);
	memset(names,0,sizeof(char*)*numentries);

468
	/* Collect all the results into our arrays: */
D
Dave Gamble 已提交
469
	child=item->child;depth++;if (fmt) len+=depth;
D
Dave Gamble 已提交
470 471
	while (child)
	{
472
		names[i]=str=print_string_ptr(child->string);
D
Dave Gamble 已提交
473 474
		entries[i++]=ret=print_value(child,depth,fmt);
		if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
475 476 477
		child=child->next;
	}
	
478
	/* Try to allocate the output string */
479 480 481
	if (!fail) out=(char*)cJSON_malloc(len);
	if (!out) fail=1;

482
	/* Handle failure */
483 484
	if (fail)
	{
485 486
		for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
		cJSON_free(names);cJSON_free(entries);
487 488 489
		return 0;
	}
	
490
	/* Compose the output: */
D
Dave Gamble 已提交
491
	*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
492 493
	for (i=0;i<numentries;i++)
	{
D
Dave Gamble 已提交
494
		if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
495
		strcpy(ptr,names[i]);ptr+=strlen(names[i]);
D
Dave Gamble 已提交
496
		*ptr++=':';if (fmt) *ptr++='\t';
497 498
		strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
		if (i!=numentries-1) *ptr++=',';
D
Dave Gamble 已提交
499
		if (fmt) *ptr++='\n';*ptr=0;
500
		cJSON_free(names[i]);cJSON_free(entries[i]);
D
Dave Gamble 已提交
501
	}
502 503
	
	cJSON_free(names);cJSON_free(entries);
D
Dave Gamble 已提交
504
	if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
D
Dave Gamble 已提交
505 506 507 508
	*ptr++='}';*ptr++=0;
	return out;	
}

509
/* Get Array size/item / object item. */
D
Dave Gamble 已提交
510
int    cJSON_GetArraySize(cJSON *array)							{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
511
cJSON *cJSON_GetArrayItem(cJSON *array,int item)				{cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
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;}
D
Dave Gamble 已提交
513

514
/* Utility for array list handling. */
D
Dave Gamble 已提交
515
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
516
/* Utility for handling references. */
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;}
D
Dave Gamble 已提交
518

519
/* Add item to array/object. */
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);}}
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);}
D
Dave Gamble 已提交
522 523 524
void	cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)						{cJSON_AddItemToArray(array,create_reference(item));}
void	cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)	{cJSON_AddItemToObject(object,string,create_reference(item));}

D
Dave Gamble 已提交
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;}
527
void   cJSON_DeleteItemFromArray(cJSON *array,int which)			{cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
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;}
529
void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
D
Dave Gamble 已提交
530

531
/* Replace array/object items with new ones. */
D
Dave Gamble 已提交
532 533
void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)		{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
	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);}
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);}}
D
Dave Gamble 已提交
536

537
/* Create basic types: */
D
Dave Gamble 已提交
538 539 540
cJSON *cJSON_CreateNull(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
D
Dave Gamble 已提交
541
cJSON *cJSON_CreateBool(int b)					{cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
542 543
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 *cJSON_CreateString(const char *string)	{cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
D
Dave Gamble 已提交
544 545
cJSON *cJSON_CreateArray(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject(void)					{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
D
Dave Gamble 已提交
546

547
/* Create Arrays: */
548 549 550
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 *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 *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;}
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 554 555 556 557 558 559 560 561 562 563

/* Duplication */
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
{
	cJSON *newitem,*cptr,*nptr=0,*newchild;
	/* Bail on bad ptr */
	if (!item) return 0;
	/* Create new item */
	newitem=cJSON_New_Item();
	if (!newitem) return 0;
	/* Copy over all vars */
	newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
564 565
	if (item->valuestring)	{newitem->valuestring=cJSON_strdup(item->valuestring);	if (!newitem->valuestring)	{cJSON_Delete(newitem);return 0;}}
	if (item->string)		{newitem->string=cJSON_strdup(item->string);			if (!newitem->string)		{cJSON_Delete(newitem);return 0;}}
566 567 568 569 570 571 572
	/* If non-recursive, then we're done! */
	if (!recurse) return newitem;
	/* Walk the ->next chain for the child. */
	cptr=item->child;
	while (cptr)
	{
		newchild=cJSON_Duplicate(cptr,1);		/* Duplicate (with recurse) each item in the ->next chain */
573
		if (!newchild) {cJSON_Delete(newitem);return 0;}
574 575 576 577 578 579
		if (nptr)	{nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}	/* If newitem->child already set, then crosswire ->prev and ->next and move on */
		else		{newitem->child=newchild;nptr=newchild;}					/* Set newitem->child and move to it */
		cptr=cptr->next;
	}
	return newitem;
}
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596

void cJSON_Minify(char *json)
{
	char *into=json;
	while (*json)
	{
		if (*json==' ') json++;
		else if (*json=='\t') json++;	// Whitespace characters.
		else if (*json=='\r') json++;
		else if (*json=='\n') json++;
		else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;	// double-slash comments, to end of line.
		else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}	// multiline comments.
		else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
		else *into++=*json++;			// All other characters.
	}
	*into=0;	// and null-terminate.
}