1 /* 2 Copyright (c) 2009-2017 Dave Gamble and cJSON contributors 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 #ifdef __GNUC__ 27 #pragma GCC visibility push(default) 28 #endif 29 30 #include <string.h> 31 #include <stdio.h> 32 #include <math.h> 33 #include <stdlib.h> 34 #include <float.h> 35 #include <limits.h> 36 #include <ctype.h> 37 #ifdef HAVE_STDINT_H 38 #include <stdint.h> 39 #endif 40 #include <sys/types.h> 41 #include <locale.h> 42 43 #ifdef __GNUC__ 44 #pragma GCC visibility pop 45 #endif 46 47 #include "cjson.h" 48 49 /* define our own boolean type */ 50 #ifdef true 51 #undef true 52 #endif 53 #define true ((cJSON_bool)1) 54 55 #ifdef false 56 #undef false 57 #endif 58 #define false ((cJSON_bool)0) 59 60 typedef struct { 61 const unsigned char *json; 62 size_t position; 63 } error; 64 static error global_error = { NULL, 0 }; 65 66 #ifndef LLONG_MAX 67 #define LLONG_MAX 9223372036854775807LL 68 #endif 69 #ifndef LLONG_MIN 70 #define LLONG_MIN (-LLONG_MAX - 1LL) 71 #endif 72 73 CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) 74 { 75 return (const char*) (global_error.json + global_error.position); 76 } 77 78 /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ 79 #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 2) 80 #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. 81 #endif 82 83 CJSON_PUBLIC(const char*) cJSON_Version(void) 84 { 85 static char version[15]; 86 sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); 87 88 return version; 89 } 90 91 /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ 92 static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) 93 { 94 if ((string1 == NULL) || (string2 == NULL)) 95 { 96 return 1; 97 } 98 99 if (string1 == string2) 100 { 101 return 0; 102 } 103 104 for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) 105 { 106 if (*string1 == '\0') 107 { 108 return 0; 109 } 110 } 111 112 return tolower(*string1) - tolower(*string2); 113 } 114 115 typedef struct internal_hooks 116 { 117 void *(*allocate)(size_t size); 118 void (*deallocate)(void *pointer); 119 void *(*reallocate)(void *pointer, size_t size); 120 } internal_hooks; 121 122 static internal_hooks global_hooks = { malloc, free, realloc }; 123 124 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) 125 { 126 size_t length = 0; 127 unsigned char *copy = NULL; 128 129 if (string == NULL) 130 { 131 return NULL; 132 } 133 134 length = strlen((const char*)string) + sizeof(""); 135 if (!(copy = (unsigned char*)hooks->allocate(length))) 136 { 137 return NULL; 138 } 139 memcpy(copy, string, length); 140 141 return copy; 142 } 143 144 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) 145 { 146 if (hooks == NULL) 147 { 148 /* Reset hooks */ 149 global_hooks.allocate = malloc; 150 global_hooks.deallocate = free; 151 global_hooks.reallocate = realloc; 152 return; 153 } 154 155 global_hooks.allocate = malloc; 156 if (hooks->malloc_fn != NULL) 157 { 158 global_hooks.allocate = hooks->malloc_fn; 159 } 160 161 global_hooks.deallocate = free; 162 if (hooks->free_fn != NULL) 163 { 164 global_hooks.deallocate = hooks->free_fn; 165 } 166 167 /* use realloc only if both free and malloc are used */ 168 global_hooks.reallocate = NULL; 169 if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) 170 { 171 global_hooks.reallocate = realloc; 172 } 173 } 174 175 /* Internal constructor. */ 176 static cJSON *cJSON_New_Item(const internal_hooks * const hooks) 177 { 178 cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); 179 if (node) 180 { 181 memset(node, '\0', sizeof(cJSON)); 182 } 183 184 return node; 185 } 186 187 /* Delete a cJSON structure. */ 188 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) 189 { 190 cJSON *next = NULL; 191 while (item != NULL) 192 { 193 next = item->next; 194 if (!(item->type & cJSON_IsReference) && (item->child != NULL)) 195 { 196 cJSON_Delete(item->child); 197 } 198 if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) 199 { 200 global_hooks.deallocate(item->valuestring); 201 } 202 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) 203 { 204 global_hooks.deallocate(item->string); 205 } 206 global_hooks.deallocate(item); 207 item = next; 208 } 209 } 210 211 /* get the decimal point character of the current locale */ 212 static unsigned char get_decimal_point(void) 213 { 214 struct lconv *lconv = localeconv(); 215 return (unsigned char) lconv->decimal_point[0]; 216 } 217 218 typedef struct 219 { 220 const unsigned char *content; 221 size_t length; 222 size_t offset; 223 size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ 224 internal_hooks hooks; 225 } parse_buffer; 226 227 /* check if the given size is left to read in a given parse buffer (starting with 1) */ 228 #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) 229 #define cannot_read(buffer, size) (!can_read(buffer, size)) 230 /* check if the buffer can be accessed at the given index (starting with 0) */ 231 #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) 232 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) 233 /* get a pointer to the buffer at the position */ 234 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) 235 236 /* Parse the input text to generate a number, and populate the result into item. */ 237 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) 238 { 239 double number = 0; 240 unsigned char *after_end = NULL; 241 unsigned char number_c_string[64]; 242 unsigned char decimal_point = get_decimal_point(); 243 size_t i = 0; 244 245 if ((input_buffer == NULL) || (input_buffer->content == NULL)) 246 { 247 return false; 248 } 249 250 /* copy the number into a temporary buffer and replace '.' with the decimal point 251 * of the current locale (for strtod) 252 * This also takes care of '\0' not necessarily being available for marking the end of the input */ 253 for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) 254 { 255 switch (buffer_at_offset(input_buffer)[i]) 256 { 257 case '0': 258 case '1': 259 case '2': 260 case '3': 261 case '4': 262 case '5': 263 case '6': 264 case '7': 265 case '8': 266 case '9': 267 case '+': 268 case '-': 269 case 'e': 270 case 'E': 271 number_c_string[i] = buffer_at_offset(input_buffer)[i]; 272 break; 273 274 case '.': 275 number_c_string[i] = decimal_point; 276 break; 277 278 default: 279 goto loop_end; 280 } 281 } 282 loop_end: 283 number_c_string[i] = '\0'; 284 285 number = strtod((const char*)number_c_string, (char**)&after_end); 286 if (number_c_string == after_end) 287 { 288 return false; /* parse_error */ 289 } 290 291 item->valuedouble = number; 292 293 /* use saturation in case of overflow */ 294 if (number >= LLONG_MAX) 295 { 296 item->valueint = LLONG_MAX; 297 } 298 else if (number <= LLONG_MIN) 299 { 300 item->valueint = LLONG_MIN; 301 } 302 else 303 { 304 item->valueint = (int64_t)number; 305 } 306 307 item->type = cJSON_Number; 308 309 input_buffer->offset += (size_t)(after_end - number_c_string); 310 return true; 311 } 312 313 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ 314 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) 315 { 316 if (number >= LLONG_MAX) 317 { 318 object->valueint = LLONG_MAX; 319 } 320 else if (number <= LLONG_MIN) 321 { 322 object->valueint = LLONG_MIN; 323 } 324 else 325 { 326 object->valueint = (int64_t)number; 327 } 328 329 return object->valuedouble = number; 330 } 331 332 typedef struct 333 { 334 unsigned char *buffer; 335 size_t length; 336 size_t offset; 337 size_t depth; /* current nesting depth (for formatted printing) */ 338 cJSON_bool noalloc; 339 cJSON_bool format; /* is this print a formatted print */ 340 internal_hooks hooks; 341 } printbuffer; 342 343 /* realloc printbuffer if necessary to have at least "needed" bytes more */ 344 static unsigned char* ensure(printbuffer * const p, size_t needed) 345 { 346 unsigned char *newbuffer = NULL; 347 size_t newsize = 0; 348 349 if ((p == NULL) || (p->buffer == NULL)) 350 { 351 return NULL; 352 } 353 354 if ((p->length > 0) && (p->offset >= p->length)) 355 { 356 /* make sure that offset is valid */ 357 return NULL; 358 } 359 360 if (needed > LLONG_MAX) 361 { 362 /* sizes bigger than LLONG_MAX are currently not supported */ 363 return NULL; 364 } 365 366 needed += p->offset + 1; 367 if (needed <= p->length) 368 { 369 return p->buffer + p->offset; 370 } 371 372 if (p->noalloc) { 373 return NULL; 374 } 375 376 /* calculate new buffer size */ 377 if (needed > (LLONG_MAX / 2)) 378 { 379 /* overflow of int, use LLONG_MAX if possible */ 380 if (needed <= LLONG_MAX) 381 { 382 newsize = LLONG_MAX; 383 } 384 else 385 { 386 return NULL; 387 } 388 } 389 else 390 { 391 newsize = needed * 2; 392 } 393 394 if (p->hooks.reallocate != NULL) 395 { 396 /* reallocate with realloc if available */ 397 newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); 398 } 399 else 400 { 401 /* otherwise reallocate manually */ 402 newbuffer = (unsigned char*)p->hooks.allocate(newsize); 403 if (!newbuffer) 404 { 405 p->hooks.deallocate(p->buffer); 406 p->length = 0; 407 p->buffer = NULL; 408 409 return NULL; 410 } 411 if (newbuffer) 412 { 413 memcpy(newbuffer, p->buffer, p->offset + 1); 414 } 415 p->hooks.deallocate(p->buffer); 416 } 417 p->length = newsize; 418 p->buffer = newbuffer; 419 420 return newbuffer + p->offset; 421 } 422 423 /* calculate the new length of the string in a printbuffer and update the offset */ 424 static void update_offset(printbuffer * const buffer) 425 { 426 const unsigned char *buffer_pointer = NULL; 427 if ((buffer == NULL) || (buffer->buffer == NULL)) 428 { 429 return; 430 } 431 buffer_pointer = buffer->buffer + buffer->offset; 432 433 buffer->offset += strlen((const char*)buffer_pointer); 434 } 435 436 /* Render the number nicely from the given item into a string. */ 437 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) 438 { 439 unsigned char *output_pointer = NULL; 440 double d = item->valuedouble; 441 int length = 0; 442 size_t i = 0; 443 unsigned char number_buffer[26]; /* temporary buffer to print the number into */ 444 unsigned char decimal_point = get_decimal_point(); 445 double test; 446 447 if (output_buffer == NULL) 448 { 449 return false; 450 } 451 452 /* This checks for NaN and Infinity */ 453 if ((d * 0) != 0) 454 { 455 length = sprintf((char*)number_buffer, "null"); 456 } 457 else 458 { 459 /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ 460 length = sprintf((char*)number_buffer, "%1.15g", d); 461 462 /* Check whether the original double can be recovered */ 463 if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d)) 464 { 465 /* If not, print with 17 decimal places of precision */ 466 length = sprintf((char*)number_buffer, "%1.17g", d); 467 } 468 } 469 470 /* sprintf failed or buffer overrun occured */ 471 if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) 472 { 473 return false; 474 } 475 476 /* reserve appropriate space in the output */ 477 output_pointer = ensure(output_buffer, (size_t)length); 478 if (output_pointer == NULL) 479 { 480 return false; 481 } 482 483 /* copy the printed number to the output and replace locale 484 * dependent decimal point with '.' */ 485 for (i = 0; i < ((size_t)length); i++) 486 { 487 if (number_buffer[i] == decimal_point) 488 { 489 output_pointer[i] = '.'; 490 continue; 491 } 492 493 output_pointer[i] = number_buffer[i]; 494 } 495 output_pointer[i] = '\0'; 496 497 output_buffer->offset += (size_t)length; 498 499 return true; 500 } 501 502 /* parse 4 digit hexadecimal number */ 503 static unsigned parse_hex4(const unsigned char * const input) 504 { 505 unsigned int h = 0; 506 size_t i = 0; 507 508 for (i = 0; i < 4; i++) 509 { 510 /* parse digit */ 511 if ((input[i] >= '0') && (input[i] <= '9')) 512 { 513 h += (unsigned int) input[i] - '0'; 514 } 515 else if ((input[i] >= 'A') && (input[i] <= 'F')) 516 { 517 h += (unsigned int) 10 + input[i] - 'A'; 518 } 519 else if ((input[i] >= 'a') && (input[i] <= 'f')) 520 { 521 h += (unsigned int) 10 + input[i] - 'a'; 522 } 523 else /* invalid */ 524 { 525 return 0; 526 } 527 528 if (i < 3) 529 { 530 /* shift left to make place for the next nibble */ 531 h = h << 4; 532 } 533 } 534 535 return h; 536 } 537 538 /* converts a UTF-16 literal to UTF-8 539 * A literal can be one or two sequences of the form \uXXXX */ 540 static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) 541 { 542 long unsigned int codepoint = 0; 543 unsigned int first_code = 0; 544 const unsigned char *first_sequence = input_pointer; 545 unsigned char utf8_length = 0; 546 unsigned char utf8_position = 0; 547 unsigned char sequence_length = 0; 548 unsigned char first_byte_mark = 0; 549 550 if ((input_end - first_sequence) < 6) 551 { 552 /* input ends unexpectedly */ 553 goto fail; 554 } 555 556 /* get the first utf16 sequence */ 557 first_code = parse_hex4(first_sequence + 2); 558 559 /* check that the code is valid */ 560 if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) 561 { 562 goto fail; 563 } 564 565 /* UTF16 surrogate pair */ 566 if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) 567 { 568 const unsigned char *second_sequence = first_sequence + 6; 569 unsigned int second_code = 0; 570 sequence_length = 12; /* \uXXXX\uXXXX */ 571 572 if ((input_end - second_sequence) < 6) 573 { 574 /* input ends unexpectedly */ 575 goto fail; 576 } 577 578 if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) 579 { 580 /* missing second half of the surrogate pair */ 581 goto fail; 582 } 583 584 /* get the second utf16 sequence */ 585 second_code = parse_hex4(second_sequence + 2); 586 /* check that the code is valid */ 587 if ((second_code < 0xDC00) || (second_code > 0xDFFF)) 588 { 589 /* invalid second half of the surrogate pair */ 590 goto fail; 591 } 592 593 594 /* calculate the unicode codepoint from the surrogate pair */ 595 codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); 596 } 597 else 598 { 599 sequence_length = 6; /* \uXXXX */ 600 codepoint = first_code; 601 } 602 603 /* encode as UTF-8 604 * takes at maximum 4 bytes to encode: 605 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ 606 if (codepoint < 0x80) 607 { 608 /* normal ascii, encoding 0xxxxxxx */ 609 utf8_length = 1; 610 } 611 else if (codepoint < 0x800) 612 { 613 /* two bytes, encoding 110xxxxx 10xxxxxx */ 614 utf8_length = 2; 615 first_byte_mark = 0xC0; /* 11000000 */ 616 } 617 else if (codepoint < 0x10000) 618 { 619 /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ 620 utf8_length = 3; 621 first_byte_mark = 0xE0; /* 11100000 */ 622 } 623 else if (codepoint <= 0x10FFFF) 624 { 625 /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ 626 utf8_length = 4; 627 first_byte_mark = 0xF0; /* 11110000 */ 628 } 629 else 630 { 631 /* invalid unicode codepoint */ 632 goto fail; 633 } 634 635 /* encode as utf8 */ 636 for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) 637 { 638 /* 10xxxxxx */ 639 (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); 640 codepoint >>= 6; 641 } 642 /* encode first byte */ 643 if (utf8_length > 1) 644 { 645 (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); 646 } 647 else 648 { 649 (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); 650 } 651 652 *output_pointer += utf8_length; 653 654 return sequence_length; 655 656 fail: 657 return 0; 658 } 659 660 /* Parse the input text into an unescaped cinput, and populate item. */ 661 static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) 662 { 663 const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; 664 const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; 665 unsigned char *output_pointer = NULL; 666 unsigned char *output = NULL; 667 668 /* not a string */ 669 if (buffer_at_offset(input_buffer)[0] != '\"') 670 { 671 goto fail; 672 } 673 674 { 675 /* calculate approximate size of the output (overestimate) */ 676 size_t allocation_length = 0; 677 size_t skipped_bytes = 0; 678 while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) 679 { 680 /* is escape sequence */ 681 if (input_end[0] == '\\') 682 { 683 if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) 684 { 685 /* prevent buffer overflow when last input character is a backslash */ 686 goto fail; 687 } 688 skipped_bytes++; 689 input_end++; 690 } 691 input_end++; 692 } 693 if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) 694 { 695 goto fail; /* string ended unexpectedly */ 696 } 697 698 /* This is at most how much we need for the output */ 699 allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; 700 output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); 701 if (output == NULL) 702 { 703 goto fail; /* allocation failure */ 704 } 705 } 706 707 output_pointer = output; 708 /* loop through the string literal */ 709 while (input_pointer < input_end) 710 { 711 if (*input_pointer != '\\') 712 { 713 *output_pointer++ = *input_pointer++; 714 } 715 /* escape sequence */ 716 else 717 { 718 unsigned char sequence_length = 2; 719 if ((input_end - input_pointer) < 1) 720 { 721 goto fail; 722 } 723 724 switch (input_pointer[1]) 725 { 726 case 'b': 727 *output_pointer++ = '\b'; 728 break; 729 case 'f': 730 *output_pointer++ = '\f'; 731 break; 732 case 'n': 733 *output_pointer++ = '\n'; 734 break; 735 case 'r': 736 *output_pointer++ = '\r'; 737 break; 738 case 't': 739 *output_pointer++ = '\t'; 740 break; 741 case '\"': 742 case '\\': 743 case '/': 744 *output_pointer++ = input_pointer[1]; 745 break; 746 747 /* UTF-16 literal */ 748 case 'u': 749 sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); 750 if (sequence_length == 0) 751 { 752 /* failed to convert UTF16-literal to UTF-8 */ 753 goto fail; 754 } 755 break; 756 757 default: 758 goto fail; 759 } 760 input_pointer += sequence_length; 761 } 762 } 763 764 /* zero terminate the output */ 765 *output_pointer = '\0'; 766 767 item->type = cJSON_String; 768 item->valuestring = (char*)output; 769 770 input_buffer->offset = (size_t) (input_end - input_buffer->content); 771 input_buffer->offset++; 772 773 return true; 774 775 fail: 776 if (output != NULL) 777 { 778 input_buffer->hooks.deallocate(output); 779 } 780 781 if (input_pointer != NULL) 782 { 783 input_buffer->offset = (size_t)(input_pointer - input_buffer->content); 784 } 785 786 return false; 787 } 788 789 /* Render the cstring provided to an escaped version that can be printed. */ 790 static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) 791 { 792 const unsigned char *input_pointer = NULL; 793 unsigned char *output = NULL; 794 unsigned char *output_pointer = NULL; 795 size_t output_length = 0; 796 /* numbers of additional characters needed for escaping */ 797 size_t escape_characters = 0; 798 799 if (output_buffer == NULL) 800 { 801 return false; 802 } 803 804 /* empty string */ 805 if (input == NULL) 806 { 807 output = ensure(output_buffer, sizeof("\"\"")); 808 if (output == NULL) 809 { 810 return false; 811 } 812 strcpy((char*)output, "\"\""); 813 814 return true; 815 } 816 817 /* set "flag" to 1 if something needs to be escaped */ 818 for (input_pointer = input; *input_pointer; input_pointer++) 819 { 820 switch (*input_pointer) 821 { 822 case '\"': 823 case '\\': 824 case '\b': 825 case '\f': 826 case '\n': 827 case '\r': 828 case '\t': 829 /* one character escape sequence */ 830 escape_characters++; 831 break; 832 default: 833 if (*input_pointer < 32) 834 { 835 /* UTF-16 escape sequence uXXXX */ 836 escape_characters += 5; 837 } 838 break; 839 } 840 } 841 output_length = (size_t)(input_pointer - input) + escape_characters; 842 843 output = ensure(output_buffer, output_length + sizeof("\"\"")); 844 if (output == NULL) 845 { 846 return false; 847 } 848 849 /* no characters have to be escaped */ 850 if (escape_characters == 0) 851 { 852 output[0] = '\"'; 853 memcpy(output + 1, input, output_length); 854 output[output_length + 1] = '\"'; 855 output[output_length + 2] = '\0'; 856 857 return true; 858 } 859 860 output[0] = '\"'; 861 output_pointer = output + 1; 862 /* copy the string */ 863 for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) 864 { 865 if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) 866 { 867 /* normal character, copy */ 868 *output_pointer = *input_pointer; 869 } 870 else 871 { 872 /* character needs to be escaped */ 873 *output_pointer++ = '\\'; 874 switch (*input_pointer) 875 { 876 case '\\': 877 *output_pointer = '\\'; 878 break; 879 case '\"': 880 *output_pointer = '\"'; 881 break; 882 case '\b': 883 *output_pointer = 'b'; 884 break; 885 case '\f': 886 *output_pointer = 'f'; 887 break; 888 case '\n': 889 *output_pointer = 'n'; 890 break; 891 case '\r': 892 *output_pointer = 'r'; 893 break; 894 case '\t': 895 *output_pointer = 't'; 896 break; 897 default: 898 /* escape and print as unicode codepoint */ 899 sprintf((char*)output_pointer, "u%04x", *input_pointer); 900 output_pointer += 4; 901 break; 902 } 903 } 904 } 905 output[output_length + 1] = '\"'; 906 output[output_length + 2] = '\0'; 907 908 return true; 909 } 910 911 /* Invoke print_string_ptr (which is useful) on an item. */ 912 static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) 913 { 914 return print_string_ptr((unsigned char*)item->valuestring, p); 915 } 916 917 /* Predeclare these prototypes. */ 918 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); 919 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); 920 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); 921 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); 922 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); 923 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); 924 925 /* Utility to jump whitespace and cr/lf */ 926 static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) 927 { 928 if ((buffer == NULL) || (buffer->content == NULL)) 929 { 930 return NULL; 931 } 932 933 while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) 934 { 935 buffer->offset++; 936 } 937 938 if (buffer->offset == buffer->length) 939 { 940 buffer->offset--; 941 } 942 943 return buffer; 944 } 945 946 /* Parse an object - create a new root, and populate. */ 947 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) 948 { 949 parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; 950 cJSON *item = NULL; 951 952 /* reset error position */ 953 global_error.json = NULL; 954 global_error.position = 0; 955 956 if (value == NULL) 957 { 958 goto fail; 959 } 960 961 buffer.content = (const unsigned char*)value; 962 buffer.length = strlen((const char*)value) + sizeof(""); 963 buffer.offset = 0; 964 buffer.hooks = global_hooks; 965 966 item = cJSON_New_Item(&global_hooks); 967 if (item == NULL) /* memory fail */ 968 { 969 goto fail; 970 } 971 972 if (!parse_value(item, buffer_skip_whitespace(&buffer))) 973 { 974 /* parse failure. ep is set. */ 975 goto fail; 976 } 977 978 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 979 if (require_null_terminated) 980 { 981 buffer_skip_whitespace(&buffer); 982 if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') 983 { 984 goto fail; 985 } 986 } 987 if (return_parse_end) 988 { 989 *return_parse_end = (const char*)buffer_at_offset(&buffer); 990 } 991 992 return item; 993 994 fail: 995 if (item != NULL) 996 { 997 cJSON_Delete(item); 998 } 999 1000 if (value != NULL) 1001 { 1002 error local_error; 1003 local_error.json = (const unsigned char*)value; 1004 local_error.position = 0; 1005 1006 if (buffer.offset < buffer.length) 1007 { 1008 local_error.position = buffer.offset; 1009 } 1010 else if (buffer.length > 0) 1011 { 1012 local_error.position = buffer.length - 1; 1013 } 1014 1015 if (return_parse_end != NULL) 1016 { 1017 *return_parse_end = (const char*)local_error.json + local_error.position; 1018 } 1019 else 1020 { 1021 global_error = local_error; 1022 } 1023 } 1024 1025 return NULL; 1026 } 1027 1028 /* Default options for cJSON_Parse */ 1029 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) 1030 { 1031 return cJSON_ParseWithOpts(value, 0, 0); 1032 } 1033 1034 #define cjson_min(a, b) ((a < b) ? a : b) 1035 1036 static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) 1037 { 1038 printbuffer buffer[1]; 1039 unsigned char *printed = NULL; 1040 1041 memset(buffer, 0, sizeof(buffer)); 1042 1043 /* create buffer */ 1044 buffer->buffer = (unsigned char*) hooks->allocate(256); 1045 buffer->format = format; 1046 buffer->hooks = *hooks; 1047 if (buffer->buffer == NULL) 1048 { 1049 goto fail; 1050 } 1051 1052 /* print the value */ 1053 if (!print_value(item, buffer)) 1054 { 1055 goto fail; 1056 } 1057 update_offset(buffer); 1058 1059 /* check if reallocate is available */ 1060 if (hooks->reallocate != NULL) 1061 { 1062 printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->length); 1063 buffer->buffer = NULL; 1064 if (printed == NULL) { 1065 goto fail; 1066 } 1067 } 1068 else /* otherwise copy the JSON over to a new buffer */ 1069 { 1070 printed = (unsigned char*) hooks->allocate(buffer->offset + 1); 1071 if (printed == NULL) 1072 { 1073 goto fail; 1074 } 1075 memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); 1076 printed[buffer->offset] = '\0'; /* just to be sure */ 1077 1078 /* free the buffer */ 1079 hooks->deallocate(buffer->buffer); 1080 } 1081 1082 return printed; 1083 1084 fail: 1085 if (buffer->buffer != NULL) 1086 { 1087 hooks->deallocate(buffer->buffer); 1088 } 1089 1090 if (printed != NULL) 1091 { 1092 hooks->deallocate(printed); 1093 } 1094 1095 return NULL; 1096 } 1097 1098 /* Render a cJSON item/entity/structure to text. */ 1099 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) 1100 { 1101 return (char*)print(item, true, &global_hooks); 1102 } 1103 1104 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) 1105 { 1106 return (char*)print(item, false, &global_hooks); 1107 } 1108 1109 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) 1110 { 1111 printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; 1112 1113 if (prebuffer < 0) 1114 { 1115 return NULL; 1116 } 1117 1118 p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); 1119 if (!p.buffer) 1120 { 1121 return NULL; 1122 } 1123 1124 p.length = (size_t)prebuffer; 1125 p.offset = 0; 1126 p.noalloc = false; 1127 p.format = fmt; 1128 p.hooks = global_hooks; 1129 1130 if (!print_value(item, &p)) 1131 { 1132 return NULL; 1133 } 1134 1135 return (char*)p.buffer; 1136 } 1137 1138 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) 1139 { 1140 printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; 1141 1142 if (len < 0) 1143 { 1144 return false; 1145 } 1146 1147 p.buffer = (unsigned char*)buf; 1148 p.length = (size_t)len; 1149 p.offset = 0; 1150 p.noalloc = true; 1151 p.format = fmt; 1152 p.hooks = global_hooks; 1153 1154 return print_value(item, &p); 1155 } 1156 1157 /* Parser core - when encountering text, process appropriately. */ 1158 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) 1159 { 1160 if ((input_buffer == NULL) || (input_buffer->content == NULL)) 1161 { 1162 return false; /* no input */ 1163 } 1164 1165 /* parse the different types of values */ 1166 /* null */ 1167 if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) 1168 { 1169 item->type = cJSON_NULL; 1170 input_buffer->offset += 4; 1171 return true; 1172 } 1173 /* false */ 1174 if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) 1175 { 1176 item->type = cJSON_False; 1177 input_buffer->offset += 5; 1178 return true; 1179 } 1180 /* true */ 1181 if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) 1182 { 1183 item->type = cJSON_True; 1184 item->valueint = 1; 1185 input_buffer->offset += 4; 1186 return true; 1187 } 1188 /* string */ 1189 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) 1190 { 1191 return parse_string(item, input_buffer); 1192 } 1193 /* number */ 1194 if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) 1195 { 1196 return parse_number(item, input_buffer); 1197 } 1198 /* array */ 1199 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) 1200 { 1201 return parse_array(item, input_buffer); 1202 } 1203 /* object */ 1204 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) 1205 { 1206 return parse_object(item, input_buffer); 1207 } 1208 1209 1210 return false; 1211 } 1212 1213 /* Render a value to text. */ 1214 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) 1215 { 1216 unsigned char *output = NULL; 1217 1218 if ((item == NULL) || (output_buffer == NULL)) 1219 { 1220 return false; 1221 } 1222 1223 switch ((item->type) & 0xFF) 1224 { 1225 case cJSON_NULL: 1226 output = ensure(output_buffer, 5); 1227 if (output == NULL) 1228 { 1229 return false; 1230 } 1231 strcpy((char*)output, "null"); 1232 return true; 1233 1234 case cJSON_False: 1235 output = ensure(output_buffer, 6); 1236 if (output == NULL) 1237 { 1238 return false; 1239 } 1240 strcpy((char*)output, "false"); 1241 return true; 1242 1243 case cJSON_True: 1244 output = ensure(output_buffer, 5); 1245 if (output == NULL) 1246 { 1247 return false; 1248 } 1249 strcpy((char*)output, "true"); 1250 return true; 1251 1252 case cJSON_Number: 1253 return print_number(item, output_buffer); 1254 1255 case cJSON_Raw: 1256 { 1257 size_t raw_length = 0; 1258 if (item->valuestring == NULL) 1259 { 1260 if (!output_buffer->noalloc) 1261 { 1262 output_buffer->hooks.deallocate(output_buffer->buffer); 1263 } 1264 return false; 1265 } 1266 1267 raw_length = strlen(item->valuestring) + sizeof(""); 1268 output = ensure(output_buffer, raw_length); 1269 if (output == NULL) 1270 { 1271 return false; 1272 } 1273 memcpy(output, item->valuestring, raw_length); 1274 return true; 1275 } 1276 1277 case cJSON_String: 1278 return print_string(item, output_buffer); 1279 1280 case cJSON_Array: 1281 return print_array(item, output_buffer); 1282 1283 case cJSON_Object: 1284 return print_object(item, output_buffer); 1285 1286 default: 1287 return false; 1288 } 1289 } 1290 1291 /* Build an array from input text. */ 1292 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) 1293 { 1294 cJSON *head = NULL; /* head of the linked list */ 1295 cJSON *current_item = NULL; 1296 1297 if (input_buffer->depth >= CJSON_NESTING_LIMIT) 1298 { 1299 return false; /* to deeply nested */ 1300 } 1301 input_buffer->depth++; 1302 1303 if (buffer_at_offset(input_buffer)[0] != '[') 1304 { 1305 /* not an array */ 1306 goto fail; 1307 } 1308 1309 input_buffer->offset++; 1310 buffer_skip_whitespace(input_buffer); 1311 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) 1312 { 1313 /* empty array */ 1314 goto success; 1315 } 1316 1317 /* check if we skipped to the end of the buffer */ 1318 if (cannot_access_at_index(input_buffer, 0)) 1319 { 1320 input_buffer->offset--; 1321 goto fail; 1322 } 1323 1324 /* step back to character in front of the first element */ 1325 input_buffer->offset--; 1326 /* loop through the comma separated array elements */ 1327 do 1328 { 1329 /* allocate next item */ 1330 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); 1331 if (new_item == NULL) 1332 { 1333 goto fail; /* allocation failure */ 1334 } 1335 1336 /* attach next item to list */ 1337 if (head == NULL) 1338 { 1339 /* start the linked list */ 1340 current_item = head = new_item; 1341 } 1342 else 1343 { 1344 /* add to the end and advance */ 1345 current_item->next = new_item; 1346 new_item->prev = current_item; 1347 current_item = new_item; 1348 } 1349 1350 /* parse next value */ 1351 input_buffer->offset++; 1352 buffer_skip_whitespace(input_buffer); 1353 if (!parse_value(current_item, input_buffer)) 1354 { 1355 goto fail; /* failed to parse value */ 1356 } 1357 buffer_skip_whitespace(input_buffer); 1358 } 1359 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); 1360 1361 if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') 1362 { 1363 goto fail; /* expected end of array */ 1364 } 1365 1366 success: 1367 input_buffer->depth--; 1368 1369 item->type = cJSON_Array; 1370 item->child = head; 1371 1372 input_buffer->offset++; 1373 1374 return true; 1375 1376 fail: 1377 if (head != NULL) 1378 { 1379 cJSON_Delete(head); 1380 } 1381 1382 return false; 1383 } 1384 1385 /* Render an array to text */ 1386 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) 1387 { 1388 unsigned char *output_pointer = NULL; 1389 size_t length = 0; 1390 cJSON *current_element = item->child; 1391 1392 if (output_buffer == NULL) 1393 { 1394 return false; 1395 } 1396 1397 /* Compose the output array. */ 1398 /* opening square bracket */ 1399 output_pointer = ensure(output_buffer, 1); 1400 if (output_pointer == NULL) 1401 { 1402 return false; 1403 } 1404 1405 *output_pointer = '['; 1406 output_buffer->offset++; 1407 output_buffer->depth++; 1408 1409 while (current_element != NULL) 1410 { 1411 if (!print_value(current_element, output_buffer)) 1412 { 1413 return false; 1414 } 1415 update_offset(output_buffer); 1416 if (current_element->next) 1417 { 1418 length = (size_t) (output_buffer->format ? 2 : 1); 1419 output_pointer = ensure(output_buffer, length + 1); 1420 if (output_pointer == NULL) 1421 { 1422 return false; 1423 } 1424 *output_pointer++ = ','; 1425 if(output_buffer->format) 1426 { 1427 *output_pointer++ = ' '; 1428 } 1429 *output_pointer = '\0'; 1430 output_buffer->offset += length; 1431 } 1432 current_element = current_element->next; 1433 } 1434 1435 output_pointer = ensure(output_buffer, 2); 1436 if (output_pointer == NULL) 1437 { 1438 return false; 1439 } 1440 *output_pointer++ = ']'; 1441 *output_pointer = '\0'; 1442 output_buffer->depth--; 1443 1444 return true; 1445 } 1446 1447 /* Build an object from the text. */ 1448 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) 1449 { 1450 cJSON *head = NULL; /* linked list head */ 1451 cJSON *current_item = NULL; 1452 1453 if (input_buffer->depth >= CJSON_NESTING_LIMIT) 1454 { 1455 return false; /* to deeply nested */ 1456 } 1457 input_buffer->depth++; 1458 1459 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) 1460 { 1461 goto fail; /* not an object */ 1462 } 1463 1464 input_buffer->offset++; 1465 buffer_skip_whitespace(input_buffer); 1466 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) 1467 { 1468 goto success; /* empty object */ 1469 } 1470 1471 /* check if we skipped to the end of the buffer */ 1472 if (cannot_access_at_index(input_buffer, 0)) 1473 { 1474 input_buffer->offset--; 1475 goto fail; 1476 } 1477 1478 /* step back to character in front of the first element */ 1479 input_buffer->offset--; 1480 /* loop through the comma separated array elements */ 1481 do 1482 { 1483 /* allocate next item */ 1484 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); 1485 if (new_item == NULL) 1486 { 1487 goto fail; /* allocation failure */ 1488 } 1489 1490 /* attach next item to list */ 1491 if (head == NULL) 1492 { 1493 /* start the linked list */ 1494 current_item = head = new_item; 1495 } 1496 else 1497 { 1498 /* add to the end and advance */ 1499 current_item->next = new_item; 1500 new_item->prev = current_item; 1501 current_item = new_item; 1502 } 1503 1504 /* parse the name of the child */ 1505 input_buffer->offset++; 1506 buffer_skip_whitespace(input_buffer); 1507 if (!parse_string(current_item, input_buffer)) 1508 { 1509 goto fail; /* faile to parse name */ 1510 } 1511 buffer_skip_whitespace(input_buffer); 1512 1513 /* swap valuestring and string, because we parsed the name */ 1514 current_item->string = current_item->valuestring; 1515 current_item->valuestring = NULL; 1516 1517 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) 1518 { 1519 goto fail; /* invalid object */ 1520 } 1521 1522 /* parse the value */ 1523 input_buffer->offset++; 1524 buffer_skip_whitespace(input_buffer); 1525 if (!parse_value(current_item, input_buffer)) 1526 { 1527 goto fail; /* failed to parse value */ 1528 } 1529 buffer_skip_whitespace(input_buffer); 1530 } 1531 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); 1532 1533 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) 1534 { 1535 goto fail; /* expected end of object */ 1536 } 1537 1538 success: 1539 input_buffer->depth--; 1540 1541 item->type = cJSON_Object; 1542 item->child = head; 1543 1544 input_buffer->offset++; 1545 return true; 1546 1547 fail: 1548 if (head != NULL) 1549 { 1550 cJSON_Delete(head); 1551 } 1552 1553 return false; 1554 } 1555 1556 /* Render an object to text. */ 1557 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) 1558 { 1559 unsigned char *output_pointer = NULL; 1560 size_t length = 0; 1561 cJSON *current_item = item->child; 1562 1563 if (output_buffer == NULL) 1564 { 1565 return false; 1566 } 1567 1568 /* Compose the output: */ 1569 length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ 1570 output_pointer = ensure(output_buffer, length + 1); 1571 if (output_pointer == NULL) 1572 { 1573 return false; 1574 } 1575 1576 *output_pointer++ = '{'; 1577 output_buffer->depth++; 1578 if (output_buffer->format) 1579 { 1580 *output_pointer++ = '\n'; 1581 } 1582 output_buffer->offset += length; 1583 1584 while (current_item) 1585 { 1586 if (output_buffer->format) 1587 { 1588 size_t i; 1589 output_pointer = ensure(output_buffer, output_buffer->depth); 1590 if (output_pointer == NULL) 1591 { 1592 return false; 1593 } 1594 for (i = 0; i < output_buffer->depth; i++) 1595 { 1596 *output_pointer++ = '\t'; 1597 } 1598 output_buffer->offset += output_buffer->depth; 1599 } 1600 1601 /* print key */ 1602 if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) 1603 { 1604 return false; 1605 } 1606 update_offset(output_buffer); 1607 1608 length = (size_t) (output_buffer->format ? 2 : 1); 1609 output_pointer = ensure(output_buffer, length); 1610 if (output_pointer == NULL) 1611 { 1612 return false; 1613 } 1614 *output_pointer++ = ':'; 1615 if (output_buffer->format) 1616 { 1617 *output_pointer++ = '\t'; 1618 } 1619 output_buffer->offset += length; 1620 1621 /* print value */ 1622 if (!print_value(current_item, output_buffer)) 1623 { 1624 return false; 1625 } 1626 update_offset(output_buffer); 1627 1628 /* print comma if not last */ 1629 length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); 1630 output_pointer = ensure(output_buffer, length + 1); 1631 if (output_pointer == NULL) 1632 { 1633 return false; 1634 } 1635 if (current_item->next) 1636 { 1637 *output_pointer++ = ','; 1638 } 1639 1640 if (output_buffer->format) 1641 { 1642 *output_pointer++ = '\n'; 1643 } 1644 *output_pointer = '\0'; 1645 output_buffer->offset += length; 1646 1647 current_item = current_item->next; 1648 } 1649 1650 output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); 1651 if (output_pointer == NULL) 1652 { 1653 return false; 1654 } 1655 if (output_buffer->format) 1656 { 1657 size_t i; 1658 for (i = 0; i < (output_buffer->depth - 1); i++) 1659 { 1660 *output_pointer++ = '\t'; 1661 } 1662 } 1663 *output_pointer++ = '}'; 1664 *output_pointer = '\0'; 1665 output_buffer->depth--; 1666 1667 return true; 1668 } 1669 1670 /* Get Array size/item / object item. */ 1671 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) 1672 { 1673 cJSON *c = array->child; 1674 size_t i = 0; 1675 while(c) 1676 { 1677 i++; 1678 c = c->next; 1679 } 1680 1681 /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ 1682 1683 return (int)i; 1684 } 1685 1686 static cJSON* get_array_item(const cJSON *array, size_t index) 1687 { 1688 cJSON *current_child = NULL; 1689 1690 if (array == NULL) 1691 { 1692 return NULL; 1693 } 1694 1695 current_child = array->child; 1696 while ((current_child != NULL) && (index > 0)) 1697 { 1698 index--; 1699 current_child = current_child->next; 1700 } 1701 1702 return current_child; 1703 } 1704 1705 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) 1706 { 1707 if (index < 0) 1708 { 1709 return NULL; 1710 } 1711 1712 return get_array_item(array, (size_t)index); 1713 } 1714 1715 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) 1716 { 1717 cJSON *current_element = NULL; 1718 1719 if ((object == NULL) || (name == NULL)) 1720 { 1721 return NULL; 1722 } 1723 1724 current_element = object->child; 1725 if (case_sensitive) 1726 { 1727 while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) 1728 { 1729 current_element = current_element->next; 1730 } 1731 } 1732 else 1733 { 1734 while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) 1735 { 1736 current_element = current_element->next; 1737 } 1738 } 1739 1740 return current_element; 1741 } 1742 1743 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) 1744 { 1745 return get_object_item(object, string, false); 1746 } 1747 1748 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) 1749 { 1750 return get_object_item(object, string, true); 1751 } 1752 1753 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) 1754 { 1755 return cJSON_GetObjectItem(object, string) ? 1 : 0; 1756 } 1757 1758 /* Utility for array list handling. */ 1759 static void suffix_object(cJSON *prev, cJSON *item) 1760 { 1761 prev->next = item; 1762 item->prev = prev; 1763 } 1764 1765 /* Utility for handling references. */ 1766 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) 1767 { 1768 cJSON *ref = cJSON_New_Item(hooks); 1769 if (!ref) 1770 { 1771 return NULL; 1772 } 1773 memcpy(ref, item, sizeof(cJSON)); 1774 ref->string = NULL; 1775 ref->type |= cJSON_IsReference; 1776 ref->next = ref->prev = NULL; 1777 return ref; 1778 } 1779 1780 /* Add item to array/object. */ 1781 CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) 1782 { 1783 cJSON *child = NULL; 1784 1785 if ((item == NULL) || (array == NULL)) 1786 { 1787 return; 1788 } 1789 1790 child = array->child; 1791 1792 if (child == NULL) 1793 { 1794 /* list is empty, start new one */ 1795 array->child = item; 1796 } 1797 else 1798 { 1799 /* append to the end */ 1800 while (child->next) 1801 { 1802 child = child->next; 1803 } 1804 suffix_object(child, item); 1805 } 1806 } 1807 1808 CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) 1809 { 1810 /* call cJSON_AddItemToObjectCS for code reuse */ 1811 cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item); 1812 /* remove cJSON_StringIsConst flag */ 1813 item->type &= ~cJSON_StringIsConst; 1814 } 1815 1816 #if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) 1817 #pragma GCC diagnostic push 1818 #endif 1819 #ifdef __GNUC__ 1820 #pragma GCC diagnostic ignored "-Wcast-qual" 1821 #endif 1822 1823 /* Add an item to an object with constant string as key */ 1824 CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) 1825 { 1826 if (!item) 1827 { 1828 return; 1829 } 1830 if (!(item->type & cJSON_StringIsConst) && item->string) 1831 { 1832 global_hooks.deallocate(item->string); 1833 } 1834 item->string = (char*)string; 1835 item->type |= cJSON_StringIsConst; 1836 cJSON_AddItemToArray(object, item); 1837 } 1838 #if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) 1839 #pragma GCC diagnostic pop 1840 #endif 1841 1842 CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) 1843 { 1844 cJSON_AddItemToArray(array, create_reference(item, &global_hooks)); 1845 } 1846 1847 CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) 1848 { 1849 cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks)); 1850 } 1851 1852 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) 1853 { 1854 if ((parent == NULL) || (item == NULL)) 1855 { 1856 return NULL; 1857 } 1858 1859 if (item->prev != NULL) 1860 { 1861 /* not the first element */ 1862 item->prev->next = item->next; 1863 } 1864 if (item->next != NULL) 1865 { 1866 /* not the last element */ 1867 item->next->prev = item->prev; 1868 } 1869 1870 if (item == parent->child) 1871 { 1872 /* first element */ 1873 parent->child = item->next; 1874 } 1875 /* make sure the detached item doesn't point anywhere anymore */ 1876 item->prev = NULL; 1877 item->next = NULL; 1878 1879 return item; 1880 } 1881 1882 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) 1883 { 1884 if (which < 0) 1885 { 1886 return NULL; 1887 } 1888 1889 return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); 1890 } 1891 1892 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) 1893 { 1894 cJSON_Delete(cJSON_DetachItemFromArray(array, which)); 1895 } 1896 1897 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) 1898 { 1899 cJSON *to_detach = cJSON_GetObjectItem(object, string); 1900 1901 return cJSON_DetachItemViaPointer(object, to_detach); 1902 } 1903 1904 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) 1905 { 1906 cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); 1907 1908 return cJSON_DetachItemViaPointer(object, to_detach); 1909 } 1910 1911 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) 1912 { 1913 cJSON_Delete(cJSON_DetachItemFromObject(object, string)); 1914 } 1915 1916 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) 1917 { 1918 cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); 1919 } 1920 1921 /* Replace array/object items with new ones. */ 1922 CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) 1923 { 1924 cJSON *after_inserted = NULL; 1925 1926 if (which < 0) 1927 { 1928 return; 1929 } 1930 1931 after_inserted = get_array_item(array, (size_t)which); 1932 if (after_inserted == NULL) 1933 { 1934 cJSON_AddItemToArray(array, newitem); 1935 return; 1936 } 1937 1938 newitem->next = after_inserted; 1939 newitem->prev = after_inserted->prev; 1940 after_inserted->prev = newitem; 1941 if (after_inserted == array->child) 1942 { 1943 array->child = newitem; 1944 } 1945 else 1946 { 1947 newitem->prev->next = newitem; 1948 } 1949 } 1950 1951 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) 1952 { 1953 if ((parent == NULL) || (replacement == NULL)) 1954 { 1955 return false; 1956 } 1957 1958 if (replacement == item) 1959 { 1960 return true; 1961 } 1962 1963 replacement->next = item->next; 1964 replacement->prev = item->prev; 1965 1966 if (replacement->next != NULL) 1967 { 1968 replacement->next->prev = replacement; 1969 } 1970 if (replacement->prev != NULL) 1971 { 1972 replacement->prev->next = replacement; 1973 } 1974 if (parent->child == item) 1975 { 1976 parent->child = replacement; 1977 } 1978 1979 item->next = NULL; 1980 item->prev = NULL; 1981 cJSON_Delete(item); 1982 1983 return true; 1984 } 1985 1986 CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) 1987 { 1988 if (which < 0) 1989 { 1990 return; 1991 } 1992 1993 cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); 1994 } 1995 1996 CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) 1997 { 1998 cJSON_ReplaceItemViaPointer(object, cJSON_GetObjectItem(object, string), newitem); 1999 } 2000 2001 CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) 2002 { 2003 cJSON_ReplaceItemViaPointer(object, cJSON_GetObjectItemCaseSensitive(object, string), newitem); 2004 } 2005 2006 /* Create basic types: */ 2007 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) 2008 { 2009 cJSON *item = cJSON_New_Item(&global_hooks); 2010 if(item) 2011 { 2012 item->type = cJSON_NULL; 2013 } 2014 2015 return item; 2016 } 2017 2018 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) 2019 { 2020 cJSON *item = cJSON_New_Item(&global_hooks); 2021 if(item) 2022 { 2023 item->type = cJSON_True; 2024 } 2025 2026 return item; 2027 } 2028 2029 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) 2030 { 2031 cJSON *item = cJSON_New_Item(&global_hooks); 2032 if(item) 2033 { 2034 item->type = cJSON_False; 2035 } 2036 2037 return item; 2038 } 2039 2040 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) 2041 { 2042 cJSON *item = cJSON_New_Item(&global_hooks); 2043 if(item) 2044 { 2045 item->type = b ? cJSON_True : cJSON_False; 2046 } 2047 2048 return item; 2049 } 2050 2051 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) 2052 { 2053 cJSON *item = cJSON_New_Item(&global_hooks); 2054 if(item) 2055 { 2056 item->type = cJSON_Number; 2057 item->valuedouble = num; 2058 2059 /* use saturation in case of overflow */ 2060 if (num >= LLONG_MAX) 2061 { 2062 item->valueint = LLONG_MAX; 2063 } 2064 else if (num <= LLONG_MIN) 2065 { 2066 item->valueint = LLONG_MIN; 2067 } 2068 else 2069 { 2070 item->valueint = (int64_t)num; 2071 } 2072 } 2073 2074 return item; 2075 } 2076 2077 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) 2078 { 2079 cJSON *item = cJSON_New_Item(&global_hooks); 2080 if(item) 2081 { 2082 item->type = cJSON_String; 2083 item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); 2084 if(!item->valuestring) 2085 { 2086 cJSON_Delete(item); 2087 return NULL; 2088 } 2089 } 2090 2091 return item; 2092 } 2093 2094 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) 2095 { 2096 cJSON *item = cJSON_New_Item(&global_hooks); 2097 if(item) 2098 { 2099 item->type = cJSON_Raw; 2100 item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); 2101 if(!item->valuestring) 2102 { 2103 cJSON_Delete(item); 2104 return NULL; 2105 } 2106 } 2107 2108 return item; 2109 } 2110 2111 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) 2112 { 2113 cJSON *item = cJSON_New_Item(&global_hooks); 2114 if(item) 2115 { 2116 item->type=cJSON_Array; 2117 } 2118 2119 return item; 2120 } 2121 2122 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) 2123 { 2124 cJSON *item = cJSON_New_Item(&global_hooks); 2125 if (item) 2126 { 2127 item->type = cJSON_Object; 2128 } 2129 2130 return item; 2131 } 2132 2133 /* Create Arrays: */ 2134 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) 2135 { 2136 size_t i = 0; 2137 cJSON *n = NULL; 2138 cJSON *p = NULL; 2139 cJSON *a = NULL; 2140 2141 if (count < 0) 2142 { 2143 return NULL; 2144 } 2145 2146 a = cJSON_CreateArray(); 2147 for(i = 0; a && (i < (size_t)count); i++) 2148 { 2149 n = cJSON_CreateNumber(numbers[i]); 2150 if (!n) 2151 { 2152 cJSON_Delete(a); 2153 return NULL; 2154 } 2155 if(!i) 2156 { 2157 a->child = n; 2158 } 2159 else 2160 { 2161 suffix_object(p, n); 2162 } 2163 p = n; 2164 } 2165 2166 return a; 2167 } 2168 2169 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) 2170 { 2171 size_t i = 0; 2172 cJSON *n = NULL; 2173 cJSON *p = NULL; 2174 cJSON *a = NULL; 2175 2176 if (count < 0) 2177 { 2178 return NULL; 2179 } 2180 2181 a = cJSON_CreateArray(); 2182 2183 for(i = 0; a && (i < (size_t)count); i++) 2184 { 2185 n = cJSON_CreateNumber((double)numbers[i]); 2186 if(!n) 2187 { 2188 cJSON_Delete(a); 2189 return NULL; 2190 } 2191 if(!i) 2192 { 2193 a->child = n; 2194 } 2195 else 2196 { 2197 suffix_object(p, n); 2198 } 2199 p = n; 2200 } 2201 2202 return a; 2203 } 2204 2205 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) 2206 { 2207 size_t i = 0; 2208 cJSON *n = NULL; 2209 cJSON *p = NULL; 2210 cJSON *a = NULL; 2211 2212 if (count < 0) 2213 { 2214 return NULL; 2215 } 2216 2217 a = cJSON_CreateArray(); 2218 2219 for(i = 0;a && (i < (size_t)count); i++) 2220 { 2221 n = cJSON_CreateNumber(numbers[i]); 2222 if(!n) 2223 { 2224 cJSON_Delete(a); 2225 return NULL; 2226 } 2227 if(!i) 2228 { 2229 a->child = n; 2230 } 2231 else 2232 { 2233 suffix_object(p, n); 2234 } 2235 p = n; 2236 } 2237 2238 return a; 2239 } 2240 2241 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) 2242 { 2243 size_t i = 0; 2244 cJSON *n = NULL; 2245 cJSON *p = NULL; 2246 cJSON *a = NULL; 2247 2248 if (count < 0) 2249 { 2250 return NULL; 2251 } 2252 2253 a = cJSON_CreateArray(); 2254 2255 for (i = 0; a && (i < (size_t)count); i++) 2256 { 2257 n = cJSON_CreateString(strings[i]); 2258 if(!n) 2259 { 2260 cJSON_Delete(a); 2261 return NULL; 2262 } 2263 if(!i) 2264 { 2265 a->child = n; 2266 } 2267 else 2268 { 2269 suffix_object(p,n); 2270 } 2271 p = n; 2272 } 2273 2274 return a; 2275 } 2276 2277 /* Duplication */ 2278 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) 2279 { 2280 cJSON *newitem = NULL; 2281 cJSON *child = NULL; 2282 cJSON *next = NULL; 2283 cJSON *newchild = NULL; 2284 2285 /* Bail on bad ptr */ 2286 if (!item) 2287 { 2288 goto fail; 2289 } 2290 /* Create new item */ 2291 newitem = cJSON_New_Item(&global_hooks); 2292 if (!newitem) 2293 { 2294 goto fail; 2295 } 2296 /* Copy over all vars */ 2297 newitem->type = item->type & (~cJSON_IsReference); 2298 newitem->valueint = item->valueint; 2299 newitem->valuedouble = item->valuedouble; 2300 if (item->valuestring) 2301 { 2302 newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); 2303 if (!newitem->valuestring) 2304 { 2305 goto fail; 2306 } 2307 } 2308 if (item->string) 2309 { 2310 newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); 2311 if (!newitem->string) 2312 { 2313 goto fail; 2314 } 2315 } 2316 /* If non-recursive, then we're done! */ 2317 if (!recurse) 2318 { 2319 return newitem; 2320 } 2321 /* Walk the ->next chain for the child. */ 2322 child = item->child; 2323 while (child != NULL) 2324 { 2325 newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ 2326 if (!newchild) 2327 { 2328 goto fail; 2329 } 2330 if (next != NULL) 2331 { 2332 /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 2333 next->next = newchild; 2334 newchild->prev = next; 2335 next = newchild; 2336 } 2337 else 2338 { 2339 /* Set newitem->child and move to it */ 2340 newitem->child = newchild; 2341 next = newchild; 2342 } 2343 child = child->next; 2344 } 2345 2346 return newitem; 2347 2348 fail: 2349 if (newitem != NULL) 2350 { 2351 cJSON_Delete(newitem); 2352 } 2353 2354 return NULL; 2355 } 2356 2357 CJSON_PUBLIC(void) cJSON_Minify(char *json) 2358 { 2359 unsigned char *into = (unsigned char*)json; 2360 while (*json) 2361 { 2362 if (*json == ' ') 2363 { 2364 json++; 2365 } 2366 else if (*json == '\t') 2367 { 2368 /* Whitespace characters. */ 2369 json++; 2370 } 2371 else if (*json == '\r') 2372 { 2373 json++; 2374 } 2375 else if (*json=='\n') 2376 { 2377 json++; 2378 } 2379 else if ((*json == '/') && (json[1] == '/')) 2380 { 2381 /* double-slash comments, to end of line. */ 2382 while (*json && (*json != '\n')) 2383 { 2384 json++; 2385 } 2386 } 2387 else if ((*json == '/') && (json[1] == '*')) 2388 { 2389 /* multiline comments. */ 2390 while (*json && !((*json == '*') && (json[1] == '/'))) 2391 { 2392 json++; 2393 } 2394 json += 2; 2395 } 2396 else if (*json == '\"') 2397 { 2398 /* string literals, which are \" sensitive. */ 2399 *into++ = (unsigned char)*json++; 2400 while (*json && (*json != '\"')) 2401 { 2402 if (*json == '\\') 2403 { 2404 *into++ = (unsigned char)*json++; 2405 } 2406 *into++ = (unsigned char)*json++; 2407 } 2408 *into++ = (unsigned char)*json++; 2409 } 2410 else 2411 { 2412 /* All other characters. */ 2413 *into++ = (unsigned char)*json++; 2414 } 2415 } 2416 2417 /* and null-terminate. */ 2418 *into = '\0'; 2419 } 2420 2421 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) 2422 { 2423 if (item == NULL) 2424 { 2425 return false; 2426 } 2427 2428 return (item->type & 0xFF) == cJSON_Invalid; 2429 } 2430 2431 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) 2432 { 2433 if (item == NULL) 2434 { 2435 return false; 2436 } 2437 2438 return (item->type & 0xFF) == cJSON_False; 2439 } 2440 2441 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) 2442 { 2443 if (item == NULL) 2444 { 2445 return false; 2446 } 2447 2448 return (item->type & 0xff) == cJSON_True; 2449 } 2450 2451 2452 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) 2453 { 2454 if (item == NULL) 2455 { 2456 return false; 2457 } 2458 2459 return (item->type & (cJSON_True | cJSON_False)) != 0; 2460 } 2461 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) 2462 { 2463 if (item == NULL) 2464 { 2465 return false; 2466 } 2467 2468 return (item->type & 0xFF) == cJSON_NULL; 2469 } 2470 2471 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) 2472 { 2473 if (item == NULL) 2474 { 2475 return false; 2476 } 2477 2478 return (item->type & 0xFF) == cJSON_Number; 2479 } 2480 2481 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) 2482 { 2483 if (item == NULL) 2484 { 2485 return false; 2486 } 2487 2488 return (item->type & 0xFF) == cJSON_String; 2489 } 2490 2491 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) 2492 { 2493 if (item == NULL) 2494 { 2495 return false; 2496 } 2497 2498 return (item->type & 0xFF) == cJSON_Array; 2499 } 2500 2501 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) 2502 { 2503 if (item == NULL) 2504 { 2505 return false; 2506 } 2507 2508 return (item->type & 0xFF) == cJSON_Object; 2509 } 2510 2511 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) 2512 { 2513 if (item == NULL) 2514 { 2515 return false; 2516 } 2517 2518 return (item->type & 0xFF) == cJSON_Raw; 2519 } 2520 2521 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) 2522 { 2523 if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) 2524 { 2525 return false; 2526 } 2527 2528 /* check if type is valid */ 2529 switch (a->type & 0xFF) 2530 { 2531 case cJSON_False: 2532 case cJSON_True: 2533 case cJSON_NULL: 2534 case cJSON_Number: 2535 case cJSON_String: 2536 case cJSON_Raw: 2537 case cJSON_Array: 2538 case cJSON_Object: 2539 break; 2540 2541 default: 2542 return false; 2543 } 2544 2545 /* identical objects are equal */ 2546 if (a == b) 2547 { 2548 return true; 2549 } 2550 2551 switch (a->type & 0xFF) 2552 { 2553 /* in these cases and equal type is enough */ 2554 case cJSON_False: 2555 case cJSON_True: 2556 case cJSON_NULL: 2557 return true; 2558 2559 case cJSON_Number: 2560 if (a->valuedouble == b->valuedouble) 2561 { 2562 return true; 2563 } 2564 return false; 2565 2566 case cJSON_String: 2567 case cJSON_Raw: 2568 if ((a->valuestring == NULL) || (b->valuestring == NULL)) 2569 { 2570 return false; 2571 } 2572 if (strcmp(a->valuestring, b->valuestring) == 0) 2573 { 2574 return true; 2575 } 2576 2577 return false; 2578 2579 case cJSON_Array: 2580 { 2581 cJSON *a_element = a->child; 2582 cJSON *b_element = b->child; 2583 2584 for (; (a_element != NULL) && (b_element != NULL);) 2585 { 2586 if (!cJSON_Compare(a_element, b_element, case_sensitive)) 2587 { 2588 return false; 2589 } 2590 2591 a_element = a_element->next; 2592 b_element = b_element->next; 2593 } 2594 2595 return true; 2596 } 2597 2598 case cJSON_Object: 2599 { 2600 cJSON *a_element = NULL; 2601 cJSON_ArrayForEach(a_element, a) 2602 { 2603 /* TODO This has O(n^2) runtime, which is horrible! */ 2604 cJSON *b_element = get_object_item(b, a_element->string, case_sensitive); 2605 if (b_element == NULL) 2606 { 2607 return false; 2608 } 2609 2610 if (!cJSON_Compare(a_element, b_element, case_sensitive)) 2611 { 2612 return false; 2613 } 2614 } 2615 2616 return true; 2617 } 2618 2619 default: 2620 return false; 2621 } 2622 } 2623 2624 CJSON_PUBLIC(void *) cJSON_malloc(size_t size) 2625 { 2626 return global_hooks.allocate(size); 2627 } 2628 2629 CJSON_PUBLIC(void) cJSON_free(void *object) 2630 { 2631 global_hooks.deallocate(object); 2632 } 2633