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