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