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