TapestryEngine

A 2D Platformer Game Engine
Log | Files | Refs

123872eedae5d93aaa9c95199507f963a9de142d.svn-base (30457B)


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