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