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