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