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