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