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