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