xref: /iperf/src/cjson.c (revision ec2d0670)
1 /*
2   Copyright (c) 2009 Dave Gamble
3 
4   Permission is hereby granted, free of charge, to any person obtaining a copy
5   of this software and associated documentation files (the "Software"), to deal
6   in the Software without restriction, including without limitation the rights
7   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8   copies of the Software, and to permit persons to whom the Software is
9   furnished to do so, subject to the following conditions:
10 
11   The above copyright notice and this permission notice shall be included in
12   all copies or substantial portions of the Software.
13 
14   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   THE SOFTWARE.
21 */
22 
23 /* cJSON */
24 /* JSON parser in C. */
25 
26 #include <string.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <stdlib.h>
30 #include <float.h>
31 #include <limits.h>
32 #include <ctype.h>
33 #include "cjson.h"
34 
35 
36 static const char *ep;
37 
38 const char *cJSON_GetErrorPtr( void )
39 {
40 	return ep;
41 }
42 
43 
44 static int cJSON_strcasecmp( const char *s1, const char *s2 )
45 {
46 	if ( ! s1 )
47 		return ( s1 == s2 ) ? 0 : 1;
48 	if ( ! s2 )
49 		return 1;
50 	for ( ; tolower(*s1) == tolower(*s2); ++s1, ++s2)
51 		if( *s1 == 0 )
52 			return 0;
53 	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
54 }
55 
56 
57 static void *(*cJSON_malloc)( size_t ) = malloc;
58 static void (*cJSON_free)( void * ) = free;
59 
60 void cJSON_InitHooks(cJSON_Hooks* hooks)
61 {
62 	if ( ! hooks ) {
63 		/* Reset hooks. */
64 		cJSON_malloc = malloc;
65 		cJSON_free = free;
66 		return;
67 	}
68 	cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
69 	cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
70 }
71 
72 
73 static char* cJSON_strdup( const char* str )
74 {
75 	size_t len;
76 	char* copy;
77 
78 	len = strlen( str ) + 1;
79 	if ( ! ( copy = (char*) cJSON_malloc( len ) ) )
80 		return 0;
81 	memcpy( copy, str, len );
82 	return copy;
83 }
84 
85 
86 /* Internal constructor. */
87 static cJSON *cJSON_New_Item( void )
88 {
89 	cJSON* node = (cJSON*) cJSON_malloc( sizeof(cJSON) );
90 	if ( node )
91 		memset( node, 0, sizeof(cJSON) );
92 	return node;
93 }
94 
95 
96 /* Delete a cJSON structure. */
97 void cJSON_Delete( cJSON *c )
98 {
99 	cJSON *next;
100 
101 	while ( c ) {
102 		next = c->next;
103 		if ( ! ( c->type & cJSON_IsReference ) && c->child )
104 			cJSON_Delete( c->child );
105 		if ( ! ( c->type & cJSON_IsReference ) && c->valuestring )
106 			cJSON_free( c->valuestring );
107 		if ( c->string )
108 			cJSON_free( c->string );
109 		cJSON_free( c );
110 		c = next;
111 	}
112 }
113 
114 
115 static double ipow( double n, int exp )
116 {
117 	double r;
118 
119 	if ( exp < 0 )
120 		return 1.0 / ipow( n, -exp );
121 	r = 1;
122 	while ( exp > 0 ) {
123 		if ( exp & 1 )
124 			r *= n;
125 		exp >>= 1;
126 		n *= n;
127 	}
128 	return r;
129 }
130 
131 
132 /* Parse the input text to generate a number, and populate the result into item. */
133 static const char *parse_number( cJSON *item, const char *num )
134 {
135 	int64_t i = 0;
136 	double f = 0;
137 	int isint = 1;
138 	int sign = 1, scale = 0, subscale = 0, signsubscale = 1;
139 
140 	/* Could use sscanf for this? */
141 	if ( *num == '-' ) {
142 		/* Has sign. */
143 		sign = -1;
144 		++num;
145 	}
146 	if ( *num == '0' )
147 		/* Is zero. */
148 		++num;
149 	if ( *num >= '1' && *num<='9' ) {
150 		/* Number. */
151 		do {
152 			i = ( i * 10 ) + ( *num - '0' );
153 			f = ( f * 10.0 ) + ( *num - '0' );
154 			++num;
155 		} while ( *num >= '0' && *num <= '9' );
156 	}
157 	if ( *num == '.' && num[1] >= '0' && num[1] <= '9' ) {
158 		/* Fractional part. */
159 		isint = 0;
160 		++num;
161 		do {
162 			f = ( f * 10.0 ) + ( *num++ - '0' );
163 			scale--;
164 		} while ( *num >= '0' && *num <= '9' );
165 	}
166 	if ( *num == 'e' || *num == 'E' ) {
167 		/* Exponent. */
168 		isint = 0;
169 		++num;
170 		if ( *num == '+' )
171 			++num;
172 		else if ( *num == '-' ) {
173 			/* With sign. */
174 			signsubscale = -1;
175 			++num;
176 		}
177 		while ( *num >= '0' && *num <= '9' )
178 			subscale = ( subscale * 10 ) + ( *num++ - '0' );
179 	}
180 
181 	/* Put it together. */
182 	if ( isint ) {
183 	    /* Int: number = +/- number */
184 	    i = sign * i;
185 	    item->valueint = i;
186 	    item->valuefloat = i;
187 	} else {
188 	    /* Float: number = +/- number.fraction * 10^+/- exponent */
189 	    f = sign * f * ipow( 10.0, scale + subscale * signsubscale );
190 	    item->valueint = f;
191 	    item->valuefloat = f;
192 	}
193 
194 	item->type = cJSON_Number;
195 	return num;
196 }
197 
198 
199 /* Render the number nicely from the given item into a string. */
200 static char *print_number( cJSON *item )
201 {
202 	char *str;
203 	double d = item->valuefloat;
204 	if ( fabs( ( (double) item->valueint ) - d ) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN ) {
205 		str = (char*) cJSON_malloc( 21 );	/* 2^64+1 can be represented in 21 chars. */
206 		if ( str )
207 			sprintf( str, "%lld", item->valueint );
208 	} else {
209 		str = (char*) cJSON_malloc( 64 );	/* This is a nice tradeoff. */
210 		if ( str ) {
211 			if ( fabs( floor( d ) - d ) <= DBL_EPSILON )
212 				sprintf( str, "%.0f", d );
213 			else if ( fabs( d ) < 1.0e-6 || fabs( d ) > 1.0e9 )
214 				sprintf( str, "%e", d );
215 			else
216 				sprintf( str, "%f", d );
217 		}
218 	}
219 	return str;
220 }
221 
222 
223 /* Parse the input text into an unescaped cstring, and populate item. */
224 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
225 
226 static const char *parse_string( cJSON *item, const char *str )
227 {
228 	const char *ptr = str + 1;
229 	char *ptr2;
230 	char *out;
231 	int len = 0;
232 	unsigned uc, uc2;
233 
234 	if ( *str != '\"' ) {
235 		/* Not a string! */
236 		ep = str;
237 		return 0;
238 	}
239 
240 	/* Skip escaped quotes. */
241 	while ( *ptr != '\"' && *ptr && ++len )
242 		if ( *ptr++ == '\\' )
243 			ptr++;
244 
245 	if ( ! ( out = (char*) cJSON_malloc( len + 1 ) ) )
246 		return 0;
247 
248 	ptr = str + 1;
249 	ptr2 = out;
250 	while ( *ptr != '\"' && *ptr ) {
251 		if ( *ptr != '\\' )
252 			*ptr2++ = *ptr++;
253 		else {
254 			ptr++;
255 			switch ( *ptr ) {
256 				case 'b': *ptr2++ ='\b'; break;
257 				case 'f': *ptr2++ ='\f'; break;
258 				case 'n': *ptr2++ ='\n'; break;
259 				case 'r': *ptr2++ ='\r'; break;
260 				case 't': *ptr2++ ='\t'; break;
261 				case 'u':
262 					/* Transcode utf16 to utf8. */
263 					/* Get the unicode char. */
264 					sscanf( ptr + 1,"%4x", &uc );
265 					ptr += 4;
266 					/* Check for invalid. */
267 					if ( ( uc >= 0xDC00 && uc <= 0xDFFF ) || uc == 0 )
268 						break;
269 
270 					/* UTF16 surrogate pairs. */
271 					if ( uc >= 0xD800 && uc <= 0xDBFF ) {
272 						if ( ptr[1] != '\\' || ptr[2] != 'u' )
273 							/* Missing second-half of surrogate. */
274 							break;
275 						sscanf( ptr + 3, "%4x", &uc2 );
276 						ptr += 6;
277 						if ( uc2 < 0xDC00 || uc2 > 0xDFFF )
278 							/* Invalid second-half of surrogate. */
279 							break;
280 						uc = 0x10000 | ( ( uc & 0x3FF ) << 10 ) | ( uc2 & 0x3FF );
281 					}
282 
283 					len = 4;
284 					if ( uc < 0x80 )
285 						len = 1;
286 					else if ( uc < 0x800 )
287 						len = 2;
288 					else if ( uc < 0x10000 )
289 						len = 3;
290 					ptr2 += len;
291 
292 					switch ( len ) {
293 						case 4: *--ptr2 = ( ( uc | 0x80) & 0xBF ); uc >>= 6;
294 						case 3: *--ptr2 = ( ( uc | 0x80) & 0xBF ); uc >>= 6;
295 						case 2: *--ptr2 = ( ( uc | 0x80) & 0xBF ); uc >>= 6;
296 						case 1: *--ptr2 = ( uc | firstByteMark[len] );
297 					}
298 					ptr2 += len;
299 					break;
300 				default:  *ptr2++ = *ptr; break;
301 			}
302 			++ptr;
303 		}
304 	}
305 	*ptr2 = 0;
306 	if ( *ptr == '\"' )
307 		++ptr;
308 	item->valuestring = out;
309 	item->type = cJSON_String;
310 	return ptr;
311 }
312 
313 
314 /* Render the cstring provided to an escaped version that can be printed. */
315 static char *print_string_ptr( const char *str )
316 {
317 	const char *ptr;
318 	char *ptr2, *out;
319 	int len = 0;
320 	unsigned char token;
321 
322 	if ( ! str )
323 		return cJSON_strdup( "" );
324 	ptr = str;
325 	while ( ( token = *ptr ) && ++len ) {
326 		if ( strchr( "\"\\\b\f\n\r\t", token ) )
327 			++len;
328 		else if ( token < 32 )
329 			len += 5;
330 		++ptr;
331 	}
332 
333 	if ( ! ( out = (char*) cJSON_malloc( len + 3 ) ) )
334 		return 0;
335 
336 	ptr2 = out;
337 	ptr = str;
338 	*ptr2++ = '\"';
339 	while ( *ptr ) {
340 		if ( (unsigned char) *ptr > 31 && *ptr != '\"' && *ptr != '\\' )
341 			*ptr2++ = *ptr++;
342 		else {
343 			*ptr2++ = '\\';
344 			switch ( token = *ptr++ ) {
345 				case '\\': *ptr2++ = '\\'; break;
346 				case '\"': *ptr2++ = '\"'; break;
347 				case '\b': *ptr2++ = 'b'; break;
348 				case '\f': *ptr2++ = 'f'; break;
349 				case '\n': *ptr2++ = 'n'; break;
350 				case '\r': *ptr2++ = 'r'; break;
351 				case '\t': *ptr2++ = 't'; break;
352 				default:
353 				/* Escape and print. */
354 				sprintf( ptr2, "u%04x", token );
355 				ptr2 += 5;
356 				break;
357 			}
358 		}
359 	}
360 	*ptr2++ = '\"';
361 	*ptr2++ = 0;
362 	return out;
363 }
364 
365 
366 /* Invote print_string_ptr (which is useful) on an item. */
367 static char *print_string( cJSON *item )
368 {
369 	return print_string_ptr( item->valuestring );
370 }
371 
372 
373 /* Predeclare these prototypes. */
374 static const char *parse_value( cJSON *item, const char *value );
375 static char *print_value( cJSON *item, int depth, int fmt );
376 static const char *parse_array( cJSON *item, const char *value );
377 static char *print_array( cJSON *item, int depth, int fmt );
378 static const char *parse_object( cJSON *item, const char *value );
379 static char *print_object( cJSON *item, int depth, int fmt );
380 
381 /* Utility to jump whitespace and cr/lf. */
382 static const char *skip( const char *in )
383 {
384 	while ( in && *in && (unsigned char) *in <= 32 )
385 		in++;
386 	return in;
387 }
388 
389 
390 /* Parse an object - create a new root, and populate. */
391 cJSON *cJSON_Parse( const char *value )
392 {
393 	cJSON *c;
394 	ep = 0;
395 	if ( ! ( c = cJSON_New_Item() ) )
396 		return 0;       /* memory fail */
397 
398 	if ( ! parse_value( c, skip( value ) ) ) {
399 		cJSON_Delete( c );
400 		return 0;
401 	}
402 	return c;
403 }
404 
405 
406 /* Render a cJSON item/entity/structure to text. */
407 char *cJSON_Print( cJSON *item )
408 {
409 	return print_value( item, 0, 1 );
410 }
411 char *cJSON_PrintUnformatted( cJSON *item )
412 {
413 	return print_value( item, 0, 0 );
414 }
415 
416 
417 /* Parser core - when encountering text, process appropriately. */
418 static const char *parse_value( cJSON *item, const char *value )
419 {
420 	if ( ! value )
421 		return 0;	/* Fail on null. */
422 	if ( ! strncmp( value, "null", 4 ) ) {
423 		item->type = cJSON_NULL;
424 		return value + 4;
425 	}
426 	if ( ! strncmp( value, "false", 5 ) ) {
427 		item->type = cJSON_False;
428 		return value + 5;
429 	}
430 	if ( ! strncmp( value, "true", 4 ) ) {
431 		item->type = cJSON_True;
432 		item->valueint = 1;
433 		return value + 4;
434 	}
435 	if ( *value == '\"' )
436 		return parse_string( item, value );
437 	if ( *value == '-' || ( *value >= '0' && *value <= '9' ) )
438 		return parse_number( item, value );
439 	if ( *value == '[' )
440 		return parse_array( item, value );
441 	if ( *value == '{' )
442 		return parse_object( item, value );
443 
444 	/* Fail. */
445 	ep = value;
446 	return 0;
447 }
448 
449 
450 /* Render a value to text. */
451 static char *print_value( cJSON *item, int depth, int fmt )
452 {
453 	char *out = 0;
454 
455 	if ( ! item )
456 		return 0;
457 	switch ( ( item->type ) & 255 ) {
458 		case cJSON_NULL:   out = cJSON_strdup( "null" ); break;
459 		case cJSON_False:  out = cJSON_strdup( "false" ); break;
460 		case cJSON_True:   out = cJSON_strdup( "true" ); break;
461 		case cJSON_Number: out = print_number( item ); break;
462 		case cJSON_String: out = print_string( item ); break;
463 		case cJSON_Array:  out = print_array( item, depth, fmt ); break;
464 		case cJSON_Object: out = print_object( item, depth, fmt ); break;
465 	}
466 	return out;
467 }
468 
469 
470 /* Build an array from input text. */
471 static const char *parse_array( cJSON *item, const char *value )
472 {
473 	cJSON *child;
474 
475 	if ( *value != '[' ) {
476 		/* Not an array! */
477 		ep = value;
478 		return 0;
479 	}
480 
481 	item->type = cJSON_Array;
482 	value = skip( value + 1 );
483 	if ( *value == ']' )
484 		return value + 1;	/* empty array. */
485 
486 	if ( ! ( item->child = child = cJSON_New_Item() ) )
487 		return 0;		 /* memory fail */
488 	if ( ! ( value = skip( parse_value( child, skip( value ) ) ) ) )
489 		return 0;
490 
491 	while ( *value == ',' ) {
492 		cJSON *new_item;
493 		if ( ! ( new_item = cJSON_New_Item() ) )
494 			return 0;	/* memory fail */
495 		child->next = new_item;
496 		new_item->prev = child;
497 		child = new_item;
498 		if ( ! ( value = skip( parse_value( child, skip( value+1 ) ) ) ) )
499 			return 0;	/* memory fail */
500 	}
501 
502 	if ( *value == ']' )
503 		return value + 1;	/* end of array */
504 	/* Malformed. */
505 	ep = value;
506 	return 0;
507 }
508 
509 
510 /* Render an array to text */
511 static char *print_array( cJSON *item, int depth, int fmt )
512 {
513 	char **entries;
514 	char *out = 0, *ptr, *ret;
515 	int len = 5;
516 	cJSON *child = item->child;
517 	int numentries = 0, i = 0, fail = 0;
518 
519 	/* How many entries in the array? */
520 	while ( child ) {
521 		++numentries;
522 		child = child->next;
523 	}
524 	/* Allocate an array to hold the values for each. */
525 	if ( ! ( entries = (char**) cJSON_malloc( numentries * sizeof(char*) ) ) )
526 		return 0;
527 	memset( entries, 0, numentries * sizeof(char*) );
528 	/* Retrieve all the results. */
529 	child = item->child;
530 	while ( child && ! fail ) {
531 		ret = print_value( child, depth + 1, fmt );
532 		entries[i++] = ret;
533 		if ( ret )
534 			len += strlen( ret ) + 2 + ( fmt ? 1 : 0 );
535 		else
536 			fail = 1;
537 		child = child -> next;
538 	}
539 
540 	/* If we didn't fail, try to malloc the output string. */
541 	if ( ! fail ) {
542 		out = (char*) cJSON_malloc( len );
543 		if ( ! out )
544 			fail = 1;
545 	}
546 
547 	/* Handle failure. */
548 	if ( fail ) {
549 		for ( i = 0; i < numentries; ++i )
550 			if ( entries[i] )
551 				cJSON_free( entries[i] );
552 		cJSON_free( entries );
553 		return 0;
554 	}
555 
556 	/* Compose the output array. */
557 	*out = '[';
558 	ptr = out + 1;
559 	*ptr = 0;
560 	for ( i = 0; i < numentries; ++i ) {
561 		strcpy( ptr, entries[i] );
562 		ptr += strlen( entries[i] );
563 		if ( i != numentries - 1 ) {
564 			*ptr++ = ',';
565 			if ( fmt )
566 				*ptr++ = ' ';
567 			*ptr = 0;
568 		}
569 		cJSON_free( entries[i] );
570 	}
571 	cJSON_free( entries );
572 	*ptr++ = ']';
573 	*ptr++ = 0;
574 	return out;
575 }
576 
577 
578 /* Build an object from the text. */
579 static const char *parse_object( cJSON *item, const char *value )
580 {
581 	cJSON *child;
582 
583 	if ( *value != '{' ) {
584 		/* Not an object! */
585 		ep = value;
586 		return 0;
587 	}
588 
589 	item->type = cJSON_Object;
590 	value =skip( value + 1 );
591 	if ( *value == '}' )
592 		return value + 1;	/* empty array. */
593 
594 	if ( ! ( item->child = child = cJSON_New_Item() ) )
595 		return 0;
596 	if ( ! ( value = skip( parse_string( child, skip( value ) ) ) ) )
597 		return 0;
598 	child->string = child->valuestring;
599 	child->valuestring = 0;
600 	if ( *value != ':' ) {
601 		/* Fail! */
602 		ep = value;
603 		return 0;
604 	}
605 	if ( ! ( value = skip( parse_value( child, skip( value + 1 ) ) ) ) )
606 		return 0;
607 
608 	while ( *value == ',' ) {
609 		cJSON *new_item;
610 		if ( ! ( new_item = cJSON_New_Item() ) )
611 			return 0;	/* memory fail */
612 		child->next = new_item;
613 		new_item->prev = child;
614 		child = new_item;
615 		if ( ! ( value = skip( parse_string( child, skip( value + 1 ) ) ) ) )
616 			return 0;
617 		child->string = child->valuestring;
618 		child->valuestring = 0;
619 		if ( *value != ':' ) {
620 			/* Fail! */
621 			ep = value;
622 			return 0;
623 		}
624 		if ( ! ( value = skip( parse_value( child, skip( value + 1 ) ) ) ) )
625 			return 0;
626 	}
627 
628 	if ( *value == '}' )
629 		return value + 1;	/* end of array */
630 	/* Malformed. */
631 	ep = value;
632 	return 0;
633 }
634 
635 
636 /* Render an object to text. */
637 static char *print_object( cJSON *item, int depth, int fmt )
638 {
639 	char **entries = 0, **names = 0;
640 	char *out = 0, *ptr, *ret, *str;
641 	int len = 7, i = 0, j;
642 	cJSON *child = item->child;
643 	int numentries = 0, fail = 0;
644 
645 	/* Count the number of entries. */
646 	while ( child ) {
647 		++numentries;
648 		child = child->next;
649 	}
650 	/* Allocate space for the names and the objects. */
651 	if ( ! ( entries = (char**) cJSON_malloc( numentries * sizeof(char*) ) ) )
652 		return 0;
653 	if ( ! ( names = (char**) cJSON_malloc( numentries * sizeof(char*) ) ) ) {
654 		cJSON_free( entries );
655 		return 0;
656 	}
657 	memset( entries, 0, sizeof(char*) * numentries );
658 	memset( names, 0, sizeof(char*) * numentries );
659 
660 	/* Collect all the results into our arrays. */
661 	child = item->child;
662 	++depth;
663 	if ( fmt )
664 		len += depth;
665 	while ( child ) {
666 		names[i] = str = print_string_ptr( child->string );
667 		entries[i++] = ret = print_value( child, depth, fmt );
668 		if ( str && ret )
669 			len += strlen( ret ) + strlen( str ) + 2 + ( fmt ? 2 + depth : 0 );
670 		else
671 			fail = 1;
672 		child = child->next;
673 	}
674 
675 	/* Try to allocate the output string. */
676 	if ( ! fail ) {
677 		out = (char*) cJSON_malloc( len );
678 		if ( ! out )
679 			fail = 1;
680 	}
681 
682 	/* Handle failure. */
683 	if ( fail ) {
684 		for ( i = 0; i < numentries; ++i ) {
685 			if ( names[i] )
686 				cJSON_free( names[i] );
687 			if ( entries[i] )
688 				cJSON_free( entries[i] );
689 		}
690 		cJSON_free( names );
691 		cJSON_free( entries );
692 		return 0;
693 	}
694 
695 	/* Compose the output. */
696 	*out = '{';
697 	ptr = out + 1;
698 	if ( fmt )
699 		*ptr++ = '\n';
700 	*ptr = 0;
701 	for ( i = 0; i < numentries; ++i ) {
702 		if ( fmt )
703 			for ( j = 0; j < depth; ++j )
704 				*ptr++ = '\t';
705 		strcpy( ptr, names[i] );
706 		ptr += strlen( names[i] );
707 		*ptr++ = ':';
708 		if ( fmt )
709 			*ptr++ = '\t';
710 		strcpy( ptr, entries[i] );
711 		ptr += strlen( entries[i] );
712 		if ( i != numentries - 1 )
713 			*ptr++ = ',';
714 		if ( fmt )
715 			*ptr++ = '\n';
716 		*ptr = 0;
717 		cJSON_free( names[i] );
718 		cJSON_free( entries[i] );
719 	}
720 
721 	cJSON_free( names );
722 	cJSON_free( entries );
723 	if ( fmt )
724 		for ( i = 0; i < depth - 1; ++i )
725 			*ptr++ = '\t';
726 	*ptr++ = '}';
727 	*ptr++ = 0;
728 	return out;
729 }
730 
731 
732 int cJSON_GetArraySize( cJSON *array )
733 {
734 	cJSON *c = array->child;
735 	int i = 0;
736 	while ( c ) {
737 		++i;
738 		c = c->next;
739 	}
740 	return i;
741 }
742 
743 
744 cJSON *cJSON_GetArrayItem( cJSON *array, int item )
745 {
746 	cJSON *c = array->child;
747 	while ( c && item > 0 ) {
748 		--item;
749 		c = c->next;
750 	}
751 	return c;
752 }
753 
754 
755 cJSON *cJSON_GetObjectItem( cJSON *object, const char *string )
756 {
757 	cJSON *c = object->child;
758 	while ( c && cJSON_strcasecmp( c->string, string ) )
759 		c = c->next;
760 	return c;
761 }
762 
763 
764 /* Utility for array list handling. */
765 static void suffix_object( cJSON *prev, cJSON *item )
766 {
767 	prev->next = item;
768 	item->prev = prev;
769 }
770 
771 
772 /* Utility for handling references. */
773 static cJSON *create_reference( cJSON *item )
774 {
775 	cJSON *ref;
776 	if ( ! ( ref = cJSON_New_Item() ) )
777 		return 0;
778 	memcpy( ref, item, sizeof(cJSON) );
779 	ref->string = 0;
780 	ref->type |= cJSON_IsReference;
781 	ref->next = ref->prev = 0;
782 	return ref;
783 }
784 
785 
786 /* Add item to array/object. */
787 void cJSON_AddItemToArray( cJSON *array, cJSON *item )
788 {
789 	cJSON *c = array->child;
790 	if ( ! item )
791 		return;
792 	if ( ! c ) {
793 		array->child = item;
794 	} else {
795 		while ( c && c->next )
796 			c = c->next;
797 		suffix_object( c, item );
798 	}
799 }
800 
801 void cJSON_AddItemToObject( cJSON *object, const char *string, cJSON *item )
802 {
803 	if ( ! item )
804 		return;
805 	if ( item->string )
806 		cJSON_free( item->string );
807 	item->string = cJSON_strdup( string );
808 	cJSON_AddItemToArray( object, item );
809 }
810 
811 void cJSON_AddItemReferenceToArray( cJSON *array, cJSON *item )
812 {
813 	cJSON_AddItemToArray( array, create_reference( item ) );
814 }
815 
816 void cJSON_AddItemReferenceToObject( cJSON *object, const char *string, cJSON *item )
817 {
818 	cJSON_AddItemToObject( object, string, create_reference( item ) );
819 }
820 
821 cJSON *cJSON_DetachItemFromArray( cJSON *array, int which )
822 {
823 	cJSON *c = array->child;
824 	while ( c && which > 0 ) {
825 		c = c->next;
826 		--which;
827 	}
828 	if ( ! c )
829 		return 0;
830 	if ( c->prev )
831 		c->prev->next = c->next;
832 	if ( c->next ) c->next->prev = c->prev;
833 	if ( c == array->child )
834 		array->child = c->next;
835 	c->prev = c->next = 0;
836 	return c;
837 }
838 
839 void cJSON_DeleteItemFromArray( cJSON *array, int which )
840 {
841 	cJSON_Delete( cJSON_DetachItemFromArray( array, which ) );
842 }
843 
844 cJSON *cJSON_DetachItemFromObject( cJSON *object, const char *string )
845 {
846 	int i = 0;
847 	cJSON *c = object->child;
848 	while ( c && cJSON_strcasecmp( c->string, string ) ) {
849 		++i;
850 		c = c->next;
851 	}
852 	if ( c )
853 		return cJSON_DetachItemFromArray( object, i );
854 	return 0;
855 }
856 
857 void cJSON_DeleteItemFromObject( cJSON *object, const char *string )
858 {
859 	cJSON_Delete( cJSON_DetachItemFromObject( object, string ) );
860 }
861 
862 /* Replace array/object items with new ones. */
863 void cJSON_ReplaceItemInArray( cJSON *array, int which, cJSON *newitem )
864 {
865 	cJSON *c = array->child;
866 	while ( c && which > 0 ) {
867 		c = c->next;
868 		--which;
869 	}
870 	if ( ! c )
871 		return;
872 	newitem->next = c->next;
873 	newitem->prev = c->prev;
874 	if ( newitem->next )
875 		newitem->next->prev = newitem;
876 	if ( c == array->child )
877 		array->child = newitem;
878 	else
879 		newitem->prev->next = newitem;
880 	c->next = c->prev = 0;
881 	cJSON_Delete( c );
882 }
883 
884 void cJSON_ReplaceItemInObject( cJSON *object, const char *string, cJSON *newitem )
885 {
886 	int i = 0;
887 	cJSON *c = object->child;
888 	while ( c && cJSON_strcasecmp( c->string, string ) ) {
889 		++i;
890 		c = c->next;
891 	}
892 	if ( c ) {
893 		newitem->string = cJSON_strdup( string );
894 		cJSON_ReplaceItemInArray( object, i, newitem );
895 	}
896 }
897 
898 
899 /* Create basic types: */
900 
901 cJSON *cJSON_CreateNull( void )
902 {
903 	cJSON *item = cJSON_New_Item();
904 	if ( item )
905 		item->type = cJSON_NULL;
906 	return item;
907 }
908 
909 cJSON *cJSON_CreateTrue( void )
910 {
911 	cJSON *item = cJSON_New_Item();
912 	if ( item )
913 		item->type = cJSON_True;
914 	return item;
915 }
916 
917 cJSON *cJSON_CreateFalse( void )
918 {
919 	cJSON *item = cJSON_New_Item();
920 	if ( item )
921 		item->type = cJSON_False;
922 	return item;
923 }
924 
925 cJSON *cJSON_CreateBool( int b )
926 {
927 	cJSON *item = cJSON_New_Item();
928 	if ( item )
929 		item->type = b ? cJSON_True : cJSON_False;
930 	return item;
931 }
932 
933 cJSON *cJSON_CreateInt( int64_t num )
934 {
935 	cJSON *item = cJSON_New_Item();
936 	if ( item ) {
937 		item->type = cJSON_Number;
938 		item->valuefloat = num;
939 		item->valueint = num;
940 	}
941 	return item;
942 }
943 
944 cJSON *cJSON_CreateFloat( double num )
945 {
946 	cJSON *item = cJSON_New_Item();
947 	if ( item ) {
948 		item->type = cJSON_Number;
949 		item->valuefloat = num;
950 		item->valueint = num;
951 	}
952 	return item;
953 }
954 
955 cJSON *cJSON_CreateString( const char *string )
956 {
957 	cJSON *item = cJSON_New_Item();
958 	if ( item ) {
959 		item->type = cJSON_String;
960 		item->valuestring = cJSON_strdup( string );
961 	}
962 	return item;
963 }
964 
965 cJSON *cJSON_CreateArray( void )
966 {
967 	cJSON *item = cJSON_New_Item();
968 	if ( item )
969 		item->type = cJSON_Array;
970 	return item;
971 }
972 
973 cJSON *cJSON_CreateObject( void )
974 {
975 	cJSON *item = cJSON_New_Item();
976 	if ( item )
977 		item->type = cJSON_Object;
978 	return item;
979 }
980 
981 
982 /* Create Arrays. */
983 
984 cJSON *cJSON_CreateIntArray( int64_t *numbers, int count )
985 {
986 	int i;
987 	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
988 	for ( i = 0; a && i < count; ++i ) {
989 		n = cJSON_CreateInt( numbers[i] );
990 		if ( ! i )
991 			a->child = n;
992 		else
993 			suffix_object( p, n );
994 		p = n;
995 	}
996 	return a;
997 }
998 
999 cJSON *cJSON_CreateFloatArray( double *numbers, int count )
1000 {
1001 	int i;
1002 	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1003 	for ( i = 0; a && i < count; ++i ) {
1004 		n = cJSON_CreateFloat( numbers[i] );
1005 		if ( ! i )
1006 			a->child = n;
1007 		else
1008 			suffix_object( p, n );
1009 		p = n;
1010 	}
1011 	return a;
1012 }
1013 
1014 cJSON *cJSON_CreateStringArray( const char **strings, int count )
1015 {
1016 	int i;
1017 	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1018 	for ( i = 0; a && i < count; ++i ) {
1019 		n = cJSON_CreateString( strings[i] );
1020 		if ( ! i )
1021 			a->child = n;
1022 		else
1023 			suffix_object( p, n );
1024 		p = n;
1025 	}
1026 	return a;
1027 }
1028