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 != '\\') { 662 *output_pointer++ = *input_pointer++; 663 } 664 /* escape sequence */ 665 else { 666 unsigned char sequence_length = 2; 667 if ((input_end - input_pointer) < 1) { goto fail; } 668 669 switch (input_pointer[1]) { 670 case 'b': 671 *output_pointer++ = '\b'; 672 break; 673 case 'f': 674 *output_pointer++ = '\f'; 675 break; 676 case 'n': 677 *output_pointer++ = '\n'; 678 break; 679 case 'r': 680 *output_pointer++ = '\r'; 681 break; 682 case 't': 683 *output_pointer++ = '\t'; 684 break; 685 case '\"': 686 case '\\': 687 case '/': 688 *output_pointer++ = input_pointer[1]; 689 break; 690 691 /* UTF-16 literal */ 692 case 'u': 693 sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); 694 if (sequence_length == 0) { 695 /* failed to convert UTF16-literal to UTF-8 */ 696 goto fail; 697 } 698 break; 699 700 default: 701 goto fail; 702 } 703 input_pointer += sequence_length; 704 } 705 } 706 707 /* zero terminate the output */ 708 *output_pointer = '\0'; 709 710 item->type = cJSON_String; 711 item->valuestring = (char *)output; 712 713 input_buffer->offset = (size_t)(input_end - input_buffer->content); 714 input_buffer->offset++; 715 716 return true; 717 718 fail: 719 if (output != NULL) { input_buffer->hooks.deallocate(output); } 720 721 if (input_pointer != NULL) { input_buffer->offset = (size_t)(input_pointer - input_buffer->content); } 722 723 return false; 724 } 725 726 /* Render the cstring provided to an escaped version that can be printed. */ 727 static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) 728 { 729 const unsigned char *input_pointer = NULL; 730 unsigned char *output = NULL; 731 unsigned char *output_pointer = NULL; 732 size_t output_length = 0; 733 /* numbers of additional characters needed for escaping */ 734 size_t escape_characters = 0; 735 736 if (output_buffer == NULL) { return false; } 737 738 /* empty string */ 739 if (input == NULL) { 740 output = ensure(output_buffer, sizeof("\"\"")); 741 if (output == NULL) { return false; } 742 strcpy((char *)output, "\"\""); 743 744 return true; 745 } 746 747 /* set "flag" to 1 if something needs to be escaped */ 748 for (input_pointer = input; *input_pointer; input_pointer++) { 749 switch (*input_pointer) { 750 case '\"': 751 case '\\': 752 case '\b': 753 case '\f': 754 case '\n': 755 case '\r': 756 case '\t': 757 /* one character escape sequence */ 758 escape_characters++; 759 break; 760 default: 761 if (*input_pointer < 32) { 762 /* UTF-16 escape sequence uXXXX */ 763 escape_characters += 5; 764 } 765 break; 766 } 767 } 768 output_length = (size_t)(input_pointer - input) + escape_characters; 769 770 output = ensure(output_buffer, output_length + sizeof("\"\"")); 771 if (output == NULL) { return false; } 772 773 /* no characters have to be escaped */ 774 if (escape_characters == 0) { 775 output[0] = '\"'; 776 memcpy(output + 1, input, output_length); 777 output[output_length + 1] = '\"'; 778 output[output_length + 2] = '\0'; 779 780 return true; 781 } 782 783 output[0] = '\"'; 784 output_pointer = output + 1; 785 /* copy the string */ 786 for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) { 787 if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) { 788 /* normal character, copy */ 789 *output_pointer = *input_pointer; 790 } else { 791 /* character needs to be escaped */ 792 *output_pointer++ = '\\'; 793 switch (*input_pointer) { 794 case '\\': 795 *output_pointer = '\\'; 796 break; 797 case '\"': 798 *output_pointer = '\"'; 799 break; 800 case '\b': 801 *output_pointer = 'b'; 802 break; 803 case '\f': 804 *output_pointer = 'f'; 805 break; 806 case '\n': 807 *output_pointer = 'n'; 808 break; 809 case '\r': 810 *output_pointer = 'r'; 811 break; 812 case '\t': 813 *output_pointer = 't'; 814 break; 815 default: 816 /* escape and print as unicode codepoint */ 817 snprintf((char *)output_pointer, 6, "u%04x", *input_pointer); 818 output_pointer += 5; 819 break; 820 } 821 } 822 } 823 output[output_length + 1] = '\"'; 824 output[output_length + 2] = '\0'; 825 826 return true; 827 } 828 829 /* Invoke print_string_ptr (which is useful) on an item. */ 830 static cJSON_bool print_string(const cJSON *const item, printbuffer *const p) 831 { 832 return print_string_ptr((unsigned char *)item->valuestring, p); 833 } 834 835 /* Predeclare these prototypes. */ 836 static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer); 837 static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer); 838 static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer); 839 static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer); 840 static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer); 841 static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer); 842 843 /* Utility to jump whitespace and cr/lf */ 844 static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) 845 { 846 if ((buffer == NULL) || (buffer->content == NULL)) { return NULL; } 847 848 if (cannot_access_at_index(buffer, 0)) { return buffer; } 849 850 while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { buffer->offset++; } 851 852 if (buffer->offset == buffer->length) { buffer->offset--; } 853 854 return buffer; 855 } 856 857 /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ 858 static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) 859 { 860 if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) { return NULL; } 861 862 if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) { buffer->offset += 3; } 863 864 return buffer; 865 } 866 867 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) 868 { 869 size_t buffer_length; 870 871 if (NULL == value) { return NULL; } 872 873 /* Adding null character size due to require_null_terminated. */ 874 buffer_length = strlen(value) + sizeof(""); 875 876 return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); 877 } 878 879 /* Parse an object - create a new root, and populate. */ 880 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) 881 { 882 parse_buffer buffer = { 883 0, 0, 0, 0, {0, 0, 0} 884 }; 885 cJSON *item = NULL; 886 887 /* reset error position */ 888 global_error.json = NULL; 889 global_error.position = 0; 890 891 if (value == NULL || 0 == buffer_length) { goto fail; } 892 893 buffer.content = (const unsigned char *)value; 894 buffer.length = buffer_length; 895 buffer.offset = 0; 896 buffer.hooks = global_hooks; 897 898 item = cJSON_New_Item(&global_hooks); 899 if (item == NULL) /* memory fail */ 900 { 901 goto fail; 902 } 903 904 if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) { 905 /* parse failure. ep is set. */ 906 goto fail; 907 } 908 909 /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 910 if (require_null_terminated) { 911 buffer_skip_whitespace(&buffer); 912 if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') { goto fail; } 913 } 914 if (return_parse_end) { *return_parse_end = (const char *)buffer_at_offset(&buffer); } 915 916 return item; 917 918 fail: 919 if (item != NULL) { cJSON_Delete(item); } 920 921 if (value != NULL) { 922 error local_error; 923 local_error.json = (const unsigned char *)value; 924 local_error.position = 0; 925 926 if (buffer.offset < buffer.length) { 927 local_error.position = buffer.offset; 928 } else if (buffer.length > 0) { 929 local_error.position = buffer.length - 1; 930 } 931 932 if (return_parse_end != NULL) { *return_parse_end = (const char *)local_error.json + local_error.position; } 933 934 global_error = local_error; 935 } 936 937 return NULL; 938 } 939 940 /* Default options for cJSON_Parse */ 941 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) 942 { 943 return cJSON_ParseWithOpts(value, 0, 0); 944 } 945 946 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) 947 { 948 return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); 949 } 950 951 #define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) 952 953 static unsigned char *print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks) 954 { 955 static const size_t default_buffer_size = 256; 956 printbuffer buffer[1]; 957 unsigned char *printed = NULL; 958 959 memset(buffer, 0, sizeof(buffer)); 960 961 /* create buffer */ 962 buffer->buffer = (unsigned char *)hooks->allocate(default_buffer_size); 963 buffer->length = default_buffer_size; 964 buffer->format = format; 965 buffer->hooks = *hooks; 966 if (buffer->buffer == NULL) { goto fail; } 967 968 /* print the value */ 969 if (!print_value(item, buffer)) { goto fail; } 970 update_offset(buffer); 971 972 /* check if reallocate is available */ 973 if (hooks->reallocate != NULL) { 974 printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->offset + 1); 975 if (printed == NULL) { goto fail; } 976 buffer->buffer = NULL; 977 } else /* otherwise copy the JSON over to a new buffer */ 978 { 979 printed = (unsigned char *)hooks->allocate(buffer->offset + 1); 980 if (printed == NULL) { goto fail; } 981 memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); 982 printed[buffer->offset] = '\0'; /* just to be sure */ 983 984 /* free the buffer */ 985 hooks->deallocate(buffer->buffer); 986 } 987 988 return printed; 989 990 fail: 991 if (buffer->buffer != NULL) { hooks->deallocate(buffer->buffer); } 992 993 if (printed != NULL) { hooks->deallocate(printed); } 994 995 return NULL; 996 } 997 998 /* Render a cJSON item/entity/structure to text. */ 999 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) 1000 { 1001 return (char *)print(item, true, &global_hooks); 1002 } 1003 1004 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) 1005 { 1006 return (char *)print(item, false, &global_hooks); 1007 } 1008 1009 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) 1010 { 1011 printbuffer p = { 1012 0, 0, 0, 0, 0, 0, {0, 0, 0} 1013 }; 1014 1015 if (prebuffer < 0) { return NULL; } 1016 1017 p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer); 1018 if (!p.buffer) { return NULL; } 1019 1020 p.length = (size_t)prebuffer; 1021 p.offset = 0; 1022 p.noalloc = false; 1023 p.format = fmt; 1024 p.hooks = global_hooks; 1025 1026 if (!print_value(item, &p)) { 1027 global_hooks.deallocate(p.buffer); 1028 return NULL; 1029 } 1030 1031 return (char *)p.buffer; 1032 } 1033 1034 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) 1035 { 1036 printbuffer p = { 1037 0, 0, 0, 0, 0, 0, {0, 0, 0} 1038 }; 1039 1040 if ((length < 0) || (buffer == NULL)) { return false; } 1041 1042 p.buffer = (unsigned char *)buffer; 1043 p.length = (size_t)length; 1044 p.offset = 0; 1045 p.noalloc = true; 1046 p.format = format; 1047 p.hooks = global_hooks; 1048 1049 return print_value(item, &p); 1050 } 1051 1052 /* Parser core - when encountering text, process appropriately. */ 1053 static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer) 1054 { 1055 if ((input_buffer == NULL) || (input_buffer->content == NULL)) { return false; /* no input */ } 1056 1057 /* parse the different types of values */ 1058 /* null */ 1059 if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) { 1060 item->type = cJSON_NULL; 1061 input_buffer->offset += 4; 1062 return true; 1063 } 1064 /* false */ 1065 if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) { 1066 item->type = cJSON_False; 1067 input_buffer->offset += 5; 1068 return true; 1069 } 1070 /* true */ 1071 if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) { 1072 item->type = cJSON_True; 1073 item->valueint = 1; 1074 input_buffer->offset += 4; 1075 return true; 1076 } 1077 /* string */ 1078 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { return parse_string(item, input_buffer); } 1079 /* number */ 1080 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); } 1081 /* array */ 1082 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) { return parse_array(item, input_buffer); } 1083 /* object */ 1084 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { return parse_object(item, input_buffer); } 1085 1086 return false; 1087 } 1088 1089 /* Render a value to text. */ 1090 static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer) 1091 { 1092 unsigned char *output = NULL; 1093 1094 if ((item == NULL) || (output_buffer == NULL)) { return false; } 1095 1096 switch ((item->type) & 0xFF) { 1097 case cJSON_NULL: 1098 output = ensure(output_buffer, 5); 1099 if (output == NULL) { return false; } 1100 strcpy((char *)output, "null"); 1101 return true; 1102 1103 case cJSON_False: 1104 output = ensure(output_buffer, 6); 1105 if (output == NULL) { return false; } 1106 strcpy((char *)output, "false"); 1107 return true; 1108 1109 case cJSON_True: 1110 output = ensure(output_buffer, 5); 1111 if (output == NULL) { return false; } 1112 strcpy((char *)output, "true"); 1113 return true; 1114 1115 case cJSON_Number: 1116 return print_number(item, output_buffer); 1117 1118 case cJSON_Raw: { 1119 size_t raw_length = 0; 1120 if (item->valuestring == NULL) { return false; } 1121 1122 raw_length = strlen(item->valuestring) + sizeof(""); 1123 output = ensure(output_buffer, raw_length); 1124 if (output == NULL) { return false; } 1125 memcpy(output, item->valuestring, raw_length); 1126 return true; 1127 } 1128 1129 case cJSON_String: 1130 return print_string(item, output_buffer); 1131 1132 case cJSON_Array: 1133 return print_array(item, output_buffer); 1134 1135 case cJSON_Object: 1136 return print_object(item, output_buffer); 1137 1138 default: 1139 return false; 1140 } 1141 } 1142 1143 /* Build an array from input text. */ 1144 static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer) 1145 { 1146 cJSON *head = NULL; /* head of the linked list */ 1147 cJSON *current_item = NULL; 1148 1149 if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ } 1150 input_buffer->depth++; 1151 1152 if (buffer_at_offset(input_buffer)[0] != '[') { 1153 /* not an array */ 1154 goto fail; 1155 } 1156 1157 input_buffer->offset++; 1158 buffer_skip_whitespace(input_buffer); 1159 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) { 1160 /* empty array */ 1161 goto success; 1162 } 1163 1164 /* check if we skipped to the end of the buffer */ 1165 if (cannot_access_at_index(input_buffer, 0)) { 1166 input_buffer->offset--; 1167 goto fail; 1168 } 1169 1170 /* step back to character in front of the first element */ 1171 input_buffer->offset--; 1172 /* loop through the comma separated array elements */ 1173 do { 1174 /* allocate next item */ 1175 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); 1176 if (new_item == NULL) { goto fail; /* allocation failure */ } 1177 1178 /* attach next item to list */ 1179 if (head == NULL) { 1180 /* start the linked list */ 1181 current_item = head = new_item; 1182 } else { 1183 /* add to the end and advance */ 1184 current_item->next = new_item; 1185 new_item->prev = current_item; 1186 current_item = new_item; 1187 } 1188 1189 /* parse next value */ 1190 input_buffer->offset++; 1191 buffer_skip_whitespace(input_buffer); 1192 if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ } 1193 buffer_skip_whitespace(input_buffer); 1194 } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); 1195 1196 if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { goto fail; /* expected end of array */ } 1197 1198 success: 1199 input_buffer->depth--; 1200 1201 if (head != NULL) { head->prev = current_item; } 1202 1203 item->type = cJSON_Array; 1204 item->child = head; 1205 1206 input_buffer->offset++; 1207 1208 return true; 1209 1210 fail: 1211 if (head != NULL) { cJSON_Delete(head); } 1212 1213 return false; 1214 } 1215 1216 /* Render an array to text */ 1217 static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer) 1218 { 1219 unsigned char *output_pointer = NULL; 1220 size_t length = 0; 1221 cJSON *current_element = item->child; 1222 1223 if (output_buffer == NULL) { return false; } 1224 1225 /* Compose the output array. */ 1226 /* opening square bracket */ 1227 output_pointer = ensure(output_buffer, 1); 1228 if (output_pointer == NULL) { return false; } 1229 1230 *output_pointer = '['; 1231 output_buffer->offset++; 1232 output_buffer->depth++; 1233 1234 while (current_element != NULL) { 1235 if (!print_value(current_element, output_buffer)) { return false; } 1236 update_offset(output_buffer); 1237 if (current_element->next) { 1238 length = (size_t)(output_buffer->format ? 2 : 1); 1239 output_pointer = ensure(output_buffer, length + 1); 1240 if (output_pointer == NULL) { return false; } 1241 *output_pointer++ = ','; 1242 if (output_buffer->format) { *output_pointer++ = ' '; } 1243 *output_pointer = '\0'; 1244 output_buffer->offset += length; 1245 } 1246 current_element = current_element->next; 1247 } 1248 1249 output_pointer = ensure(output_buffer, 2); 1250 if (output_pointer == NULL) { return false; } 1251 *output_pointer++ = ']'; 1252 *output_pointer = '\0'; 1253 output_buffer->depth--; 1254 1255 return true; 1256 } 1257 1258 /* Build an object from the text. */ 1259 static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer) 1260 { 1261 cJSON *head = NULL; /* linked list head */ 1262 cJSON *current_item = NULL; 1263 1264 if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ } 1265 input_buffer->depth++; 1266 1267 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { goto fail; /* not an object */ } 1268 1269 input_buffer->offset++; 1270 buffer_skip_whitespace(input_buffer); 1271 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { goto success; /* empty object */ } 1272 1273 /* check if we skipped to the end of the buffer */ 1274 if (cannot_access_at_index(input_buffer, 0)) { 1275 input_buffer->offset--; 1276 goto fail; 1277 } 1278 1279 /* step back to character in front of the first element */ 1280 input_buffer->offset--; 1281 /* loop through the comma separated array elements */ 1282 do { 1283 /* allocate next item */ 1284 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); 1285 if (new_item == NULL) { goto fail; /* allocation failure */ } 1286 1287 /* attach next item to list */ 1288 if (head == NULL) { 1289 /* start the linked list */ 1290 current_item = head = new_item; 1291 } else { 1292 /* add to the end and advance */ 1293 current_item->next = new_item; 1294 new_item->prev = current_item; 1295 current_item = new_item; 1296 } 1297 1298 /* parse the name of the child */ 1299 input_buffer->offset++; 1300 buffer_skip_whitespace(input_buffer); 1301 if (!parse_string(current_item, input_buffer)) { goto fail; /* failed to parse name */ } 1302 buffer_skip_whitespace(input_buffer); 1303 1304 /* swap valuestring and string, because we parsed the name */ 1305 current_item->string = current_item->valuestring; 1306 current_item->valuestring = NULL; 1307 1308 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { goto fail; /* invalid object */ } 1309 1310 /* parse the value */ 1311 input_buffer->offset++; 1312 buffer_skip_whitespace(input_buffer); 1313 if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ } 1314 buffer_skip_whitespace(input_buffer); 1315 } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); 1316 1317 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { goto fail; /* expected end of object */ } 1318 1319 success: 1320 input_buffer->depth--; 1321 1322 if (head != NULL) { head->prev = current_item; } 1323 1324 item->type = cJSON_Object; 1325 item->child = head; 1326 1327 input_buffer->offset++; 1328 return true; 1329 1330 fail: 1331 if (head != NULL) { cJSON_Delete(head); } 1332 1333 return false; 1334 } 1335 1336 /* Render an object to text. */ 1337 static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer) 1338 { 1339 unsigned char *output_pointer = NULL; 1340 size_t length = 0; 1341 cJSON *current_item = item->child; 1342 1343 if (output_buffer == NULL) { return false; } 1344 1345 /* Compose the output: */ 1346 length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ 1347 output_pointer = ensure(output_buffer, length + 1); 1348 if (output_pointer == NULL) { return false; } 1349 1350 *output_pointer++ = '{'; 1351 output_buffer->depth++; 1352 if (output_buffer->format) { *output_pointer++ = '\n'; } 1353 output_buffer->offset += length; 1354 1355 while (current_item) { 1356 if (output_buffer->format) { 1357 size_t i; 1358 output_pointer = ensure(output_buffer, output_buffer->depth); 1359 if (output_pointer == NULL) { return false; } 1360 for (i = 0; i < output_buffer->depth; i++) { *output_pointer++ = '\t'; } 1361 output_buffer->offset += output_buffer->depth; 1362 } 1363 1364 /* print key */ 1365 if (!print_string_ptr((unsigned char *)current_item->string, output_buffer)) { return false; } 1366 update_offset(output_buffer); 1367 1368 length = (size_t)(output_buffer->format ? 2 : 1); 1369 output_pointer = ensure(output_buffer, length); 1370 if (output_pointer == NULL) { return false; } 1371 *output_pointer++ = ':'; 1372 if (output_buffer->format) { *output_pointer++ = '\t'; } 1373 output_buffer->offset += length; 1374 1375 /* print value */ 1376 if (!print_value(current_item, output_buffer)) { return false; } 1377 update_offset(output_buffer); 1378 1379 /* print comma if not last */ 1380 length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); 1381 output_pointer = ensure(output_buffer, length + 1); 1382 if (output_pointer == NULL) { return false; } 1383 if (current_item->next) { *output_pointer++ = ','; } 1384 1385 if (output_buffer->format) { *output_pointer++ = '\n'; } 1386 *output_pointer = '\0'; 1387 output_buffer->offset += length; 1388 1389 current_item = current_item->next; 1390 } 1391 1392 output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); 1393 if (output_pointer == NULL) { return false; } 1394 if (output_buffer->format) { 1395 size_t i; 1396 for (i = 0; i < (output_buffer->depth - 1); i++) { *output_pointer++ = '\t'; } 1397 } 1398 *output_pointer++ = '}'; 1399 *output_pointer = '\0'; 1400 output_buffer->depth--; 1401 1402 return true; 1403 } 1404 1405 /* Get Array size/item / object item. */ 1406 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) 1407 { 1408 cJSON *child = NULL; 1409 size_t size = 0; 1410 1411 if (array == NULL) { return 0; } 1412 1413 child = array->child; 1414 1415 while (child != NULL) { 1416 size++; 1417 child = child->next; 1418 } 1419 1420 /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ 1421 1422 return (int)size; 1423 } 1424 1425 static cJSON *get_array_item(const cJSON *array, size_t index) 1426 { 1427 cJSON *current_child = NULL; 1428 1429 if (array == NULL) { return NULL; } 1430 1431 current_child = array->child; 1432 while ((current_child != NULL) && (index > 0)) { 1433 index--; 1434 current_child = current_child->next; 1435 } 1436 1437 return current_child; 1438 } 1439 1440 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) 1441 { 1442 if (index < 0) { return NULL; } 1443 1444 return get_array_item(array, (size_t)index); 1445 } 1446 1447 static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) 1448 { 1449 cJSON *current_element = NULL; 1450 1451 if ((object == NULL) || (name == NULL)) { return NULL; } 1452 1453 current_element = object->child; 1454 if (case_sensitive) { 1455 while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) { current_element = current_element->next; } 1456 } else { 1457 while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) { current_element = current_element->next; } 1458 } 1459 1460 if ((current_element == NULL) || (current_element->string == NULL)) { return NULL; } 1461 1462 return current_element; 1463 } 1464 1465 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string) 1466 { 1467 return get_object_item(object, string, false); 1468 } 1469 1470 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string) 1471 { 1472 return get_object_item(object, string, true); 1473 } 1474 1475 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) 1476 { 1477 return cJSON_GetObjectItem(object, string) ? 1 : 0; 1478 } 1479 1480 /* Utility for array list handling. */ 1481 static void suffix_object(cJSON *prev, cJSON *item) 1482 { 1483 prev->next = item; 1484 item->prev = prev; 1485 } 1486 1487 /* Utility for handling references. */ 1488 static cJSON *create_reference(const cJSON *item, const internal_hooks *const hooks) 1489 { 1490 cJSON *reference = NULL; 1491 if (item == NULL) { return NULL; } 1492 1493 reference = cJSON_New_Item(hooks); 1494 if (reference == NULL) { return NULL; } 1495 1496 memcpy(reference, item, sizeof(cJSON)); 1497 reference->string = NULL; 1498 reference->type |= cJSON_IsReference; 1499 reference->next = reference->prev = NULL; 1500 return reference; 1501 } 1502 1503 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) 1504 { 1505 cJSON *child = NULL; 1506 1507 if ((item == NULL) || (array == NULL) || (array == item)) { return false; } 1508 1509 child = array->child; 1510 /* 1511 * To find the last item in array quickly, we use prev in array 1512 */ 1513 if (child == NULL) { 1514 /* list is empty, start new one */ 1515 array->child = item; 1516 item->prev = item; 1517 item->next = NULL; 1518 } else { 1519 /* append to the end */ 1520 if (child->prev) { 1521 suffix_object(child->prev, item); 1522 array->child->prev = item; 1523 } 1524 } 1525 1526 return true; 1527 } 1528 1529 /* Add item to array/object. */ 1530 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) 1531 { 1532 return add_item_to_array(array, item); 1533 } 1534 1535 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) 1536 #pragma GCC diagnostic push 1537 #endif 1538 #ifdef __GNUC__ 1539 #pragma GCC diagnostic ignored "-Wcast-qual" 1540 #endif 1541 /* helper function to cast away const */ 1542 static void *cast_away_const(const void *string) 1543 { 1544 return (void *)string; 1545 } 1546 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) 1547 #pragma GCC diagnostic pop 1548 #endif 1549 1550 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) 1551 { 1552 char *new_key = NULL; 1553 int new_type = cJSON_Invalid; 1554 1555 if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) { return false; } 1556 1557 if (constant_key) { 1558 new_key = (char *)cast_away_const(string); 1559 new_type = item->type | cJSON_StringIsConst; 1560 } else { 1561 new_key = (char *)cJSON_strdup((const unsigned char *)string, hooks); 1562 if (new_key == NULL) { return false; } 1563 1564 new_type = item->type & ~cJSON_StringIsConst; 1565 } 1566 1567 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { hooks->deallocate(item->string); } 1568 1569 item->string = new_key; 1570 item->type = new_type; 1571 1572 return add_item_to_array(object, item); 1573 } 1574 1575 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) 1576 { 1577 return add_item_to_object(object, string, item, &global_hooks, false); 1578 } 1579 1580 /* Add an item to an object with constant string as key */ 1581 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) 1582 { 1583 return add_item_to_object(object, string, item, &global_hooks, true); 1584 } 1585 1586 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) 1587 { 1588 if (array == NULL) { return false; } 1589 1590 return add_item_to_array(array, create_reference(item, &global_hooks)); 1591 } 1592 1593 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) 1594 { 1595 if ((object == NULL) || (string == NULL)) { return false; } 1596 1597 return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); 1598 } 1599 1600 CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name) 1601 { 1602 cJSON *null = cJSON_CreateNull(); 1603 if (add_item_to_object(object, name, null, &global_hooks, false)) { return null; } 1604 1605 cJSON_Delete(null); 1606 return NULL; 1607 } 1608 1609 CJSON_PUBLIC(cJSON *) cJSON_AddTrueToObject(cJSON *const object, const char *const name) 1610 { 1611 cJSON *true_item = cJSON_CreateTrue(); 1612 if (add_item_to_object(object, name, true_item, &global_hooks, false)) { return true_item; } 1613 1614 cJSON_Delete(true_item); 1615 return NULL; 1616 } 1617 1618 CJSON_PUBLIC(cJSON *) cJSON_AddFalseToObject(cJSON *const object, const char *const name) 1619 { 1620 cJSON *false_item = cJSON_CreateFalse(); 1621 if (add_item_to_object(object, name, false_item, &global_hooks, false)) { return false_item; } 1622 1623 cJSON_Delete(false_item); 1624 return NULL; 1625 } 1626 1627 CJSON_PUBLIC(cJSON *) cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean) 1628 { 1629 cJSON *bool_item = cJSON_CreateBool(boolean); 1630 if (add_item_to_object(object, name, bool_item, &global_hooks, false)) { return bool_item; } 1631 1632 cJSON_Delete(bool_item); 1633 return NULL; 1634 } 1635 1636 CJSON_PUBLIC(cJSON *) cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number) 1637 { 1638 cJSON *number_item = cJSON_CreateNumber(number); 1639 if (add_item_to_object(object, name, number_item, &global_hooks, false)) { return number_item; } 1640 1641 cJSON_Delete(number_item); 1642 return NULL; 1643 } 1644 1645 CJSON_PUBLIC(cJSON *) cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string) 1646 { 1647 cJSON *string_item = cJSON_CreateString(string); 1648 if (add_item_to_object(object, name, string_item, &global_hooks, false)) { return string_item; } 1649 1650 cJSON_Delete(string_item); 1651 return NULL; 1652 } 1653 1654 CJSON_PUBLIC(cJSON *) cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw) 1655 { 1656 cJSON *raw_item = cJSON_CreateRaw(raw); 1657 if (add_item_to_object(object, name, raw_item, &global_hooks, false)) { return raw_item; } 1658 1659 cJSON_Delete(raw_item); 1660 return NULL; 1661 } 1662 1663 CJSON_PUBLIC(cJSON *) cJSON_AddObjectToObject(cJSON *const object, const char *const name) 1664 { 1665 cJSON *object_item = cJSON_CreateObject(); 1666 if (add_item_to_object(object, name, object_item, &global_hooks, false)) { return object_item; } 1667 1668 cJSON_Delete(object_item); 1669 return NULL; 1670 } 1671 1672 CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name) 1673 { 1674 cJSON *array = cJSON_CreateArray(); 1675 if (add_item_to_object(object, name, array, &global_hooks, false)) { return array; } 1676 1677 cJSON_Delete(array); 1678 return NULL; 1679 } 1680 1681 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) 1682 { 1683 if ((parent == NULL) || (item == NULL)) { return NULL; } 1684 1685 if (item != parent->child) { 1686 /* not the first element */ 1687 item->prev->next = item->next; 1688 } 1689 if (item->next != NULL) { 1690 /* not the last element */ 1691 item->next->prev = item->prev; 1692 } 1693 1694 if (item == parent->child) { 1695 /* first element */ 1696 parent->child = item->next; 1697 } else if (item->next == NULL) { 1698 /* last element */ 1699 parent->child->prev = item->prev; 1700 } 1701 1702 /* make sure the detached item doesn't point anywhere anymore */ 1703 item->prev = NULL; 1704 item->next = NULL; 1705 1706 return item; 1707 } 1708 1709 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) 1710 { 1711 if (which < 0) { return NULL; } 1712 1713 return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); 1714 } 1715 1716 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) 1717 { 1718 cJSON_Delete(cJSON_DetachItemFromArray(array, which)); 1719 } 1720 1721 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) 1722 { 1723 cJSON *to_detach = cJSON_GetObjectItem(object, string); 1724 1725 return cJSON_DetachItemViaPointer(object, to_detach); 1726 } 1727 1728 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) 1729 { 1730 cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); 1731 1732 return cJSON_DetachItemViaPointer(object, to_detach); 1733 } 1734 1735 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) 1736 { 1737 cJSON_Delete(cJSON_DetachItemFromObject(object, string)); 1738 } 1739 1740 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) 1741 { 1742 cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); 1743 } 1744 1745 /* Replace array/object items with new ones. */ 1746 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) 1747 { 1748 cJSON *after_inserted = NULL; 1749 1750 if (which < 0) { return false; } 1751 1752 after_inserted = get_array_item(array, (size_t)which); 1753 if (after_inserted == NULL) { return add_item_to_array(array, newitem); } 1754 1755 newitem->next = after_inserted; 1756 newitem->prev = after_inserted->prev; 1757 after_inserted->prev = newitem; 1758 if (after_inserted == array->child) { 1759 array->child = newitem; 1760 } else { 1761 newitem->prev->next = newitem; 1762 } 1763 return true; 1764 } 1765 1766 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement) 1767 { 1768 if ((parent == NULL) || (replacement == NULL) || (item == NULL)) { return false; } 1769 1770 if (replacement == item) { return true; } 1771 1772 replacement->next = item->next; 1773 replacement->prev = item->prev; 1774 1775 if (replacement->next != NULL) { replacement->next->prev = replacement; } 1776 if (parent->child == item) { 1777 if (parent->child->prev == parent->child) { replacement->prev = replacement; } 1778 parent->child = replacement; 1779 } else { /* 1780 * To find the last item in array quickly, we use prev in array. 1781 * We can't modify the last item's next pointer where this item was the parent's child 1782 */ 1783 if (replacement->prev != NULL) { replacement->prev->next = replacement; } 1784 if (replacement->next == NULL) { parent->child->prev = replacement; } 1785 } 1786 1787 item->next = NULL; 1788 item->prev = NULL; 1789 cJSON_Delete(item); 1790 1791 return true; 1792 } 1793 1794 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) 1795 { 1796 if (which < 0) { return false; } 1797 1798 return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); 1799 } 1800 1801 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) 1802 { 1803 if ((replacement == NULL) || (string == NULL)) { return false; } 1804 1805 /* replace the name in the replacement */ 1806 if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { cJSON_free(replacement->string); } 1807 replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); 1808 if (replacement->string == NULL) { return false; } 1809 1810 replacement->type &= ~cJSON_StringIsConst; 1811 1812 return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); 1813 } 1814 1815 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) 1816 { 1817 return replace_item_in_object(object, string, newitem, false); 1818 } 1819 1820 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) 1821 { 1822 return replace_item_in_object(object, string, newitem, true); 1823 } 1824 1825 /* Create basic types: */ 1826 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) 1827 { 1828 cJSON *item = cJSON_New_Item(&global_hooks); 1829 if (item) { item->type = cJSON_NULL; } 1830 1831 return item; 1832 } 1833 1834 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) 1835 { 1836 cJSON *item = cJSON_New_Item(&global_hooks); 1837 if (item) { item->type = cJSON_True; } 1838 1839 return item; 1840 } 1841 1842 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) 1843 { 1844 cJSON *item = cJSON_New_Item(&global_hooks); 1845 if (item) { item->type = cJSON_False; } 1846 1847 return item; 1848 } 1849 1850 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) 1851 { 1852 cJSON *item = cJSON_New_Item(&global_hooks); 1853 if (item) { item->type = boolean ? cJSON_True : cJSON_False; } 1854 1855 return item; 1856 } 1857 1858 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) 1859 { 1860 cJSON *item = cJSON_New_Item(&global_hooks); 1861 if (item) { 1862 item->type = cJSON_Number; 1863 item->valuedouble = num; 1864 1865 /* use saturation in case of overflow */ 1866 if (num >= INT_MAX) { 1867 item->valueint = INT_MAX; 1868 } else if (num <= (double)INT_MIN) { 1869 item->valueint = INT_MIN; 1870 } else { 1871 item->valueint = (int)num; 1872 } 1873 } 1874 1875 return item; 1876 } 1877 1878 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) 1879 { 1880 cJSON *item = cJSON_New_Item(&global_hooks); 1881 if (item) { 1882 item->type = cJSON_String; 1883 item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); 1884 if (!item->valuestring) { 1885 cJSON_Delete(item); 1886 return NULL; 1887 } 1888 } 1889 1890 return item; 1891 } 1892 1893 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) 1894 { 1895 cJSON *item = cJSON_New_Item(&global_hooks); 1896 if (item != NULL) { 1897 item->type = cJSON_String | cJSON_IsReference; 1898 item->valuestring = (char *)cast_away_const(string); 1899 } 1900 1901 return item; 1902 } 1903 1904 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) 1905 { 1906 cJSON *item = cJSON_New_Item(&global_hooks); 1907 if (item != NULL) { 1908 item->type = cJSON_Object | cJSON_IsReference; 1909 item->child = (cJSON *)cast_away_const(child); 1910 } 1911 1912 return item; 1913 } 1914 1915 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) 1916 { 1917 cJSON *item = cJSON_New_Item(&global_hooks); 1918 if (item != NULL) { 1919 item->type = cJSON_Array | cJSON_IsReference; 1920 item->child = (cJSON *)cast_away_const(child); 1921 } 1922 1923 return item; 1924 } 1925 1926 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) 1927 { 1928 cJSON *item = cJSON_New_Item(&global_hooks); 1929 if (item) { 1930 item->type = cJSON_Raw; 1931 item->valuestring = (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks); 1932 if (!item->valuestring) { 1933 cJSON_Delete(item); 1934 return NULL; 1935 } 1936 } 1937 1938 return item; 1939 } 1940 1941 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) 1942 { 1943 cJSON *item = cJSON_New_Item(&global_hooks); 1944 if (item) { item->type = cJSON_Array; } 1945 1946 return item; 1947 } 1948 1949 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) 1950 { 1951 cJSON *item = cJSON_New_Item(&global_hooks); 1952 if (item) { item->type = cJSON_Object; } 1953 1954 return item; 1955 } 1956 1957 /* Create Arrays: */ 1958 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) 1959 { 1960 size_t i = 0; 1961 cJSON *n = NULL; 1962 cJSON *p = NULL; 1963 cJSON *a = NULL; 1964 1965 if ((count < 0) || (numbers == NULL)) { return NULL; } 1966 1967 a = cJSON_CreateArray(); 1968 1969 for (i = 0; a && (i < (size_t)count); i++) { 1970 n = cJSON_CreateNumber(numbers[i]); 1971 if (!n) { 1972 cJSON_Delete(a); 1973 return NULL; 1974 } 1975 if (!i) { 1976 a->child = n; 1977 } else { 1978 suffix_object(p, n); 1979 } 1980 p = n; 1981 } 1982 1983 if (a && a->child) { a->child->prev = n; } 1984 1985 return a; 1986 } 1987 1988 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) 1989 { 1990 size_t i = 0; 1991 cJSON *n = NULL; 1992 cJSON *p = NULL; 1993 cJSON *a = NULL; 1994 1995 if ((count < 0) || (numbers == NULL)) { return NULL; } 1996 1997 a = cJSON_CreateArray(); 1998 1999 for (i = 0; a && (i < (size_t)count); i++) { 2000 n = cJSON_CreateNumber((double)numbers[i]); 2001 if (!n) { 2002 cJSON_Delete(a); 2003 return NULL; 2004 } 2005 if (!i) { 2006 a->child = n; 2007 } else { 2008 suffix_object(p, n); 2009 } 2010 p = n; 2011 } 2012 2013 if (a && a->child) { a->child->prev = n; } 2014 2015 return a; 2016 } 2017 2018 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) 2019 { 2020 size_t i = 0; 2021 cJSON *n = NULL; 2022 cJSON *p = NULL; 2023 cJSON *a = NULL; 2024 2025 if ((count < 0) || (numbers == NULL)) { return NULL; } 2026 2027 a = cJSON_CreateArray(); 2028 2029 for (i = 0; a && (i < (size_t)count); i++) { 2030 n = cJSON_CreateNumber(numbers[i]); 2031 if (!n) { 2032 cJSON_Delete(a); 2033 return NULL; 2034 } 2035 if (!i) { 2036 a->child = n; 2037 } else { 2038 suffix_object(p, n); 2039 } 2040 p = n; 2041 } 2042 2043 if (a && a->child) { a->child->prev = n; } 2044 2045 return a; 2046 } 2047 2048 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) 2049 { 2050 size_t i = 0; 2051 cJSON *n = NULL; 2052 cJSON *p = NULL; 2053 cJSON *a = NULL; 2054 2055 if ((count < 0) || (strings == NULL)) { return NULL; } 2056 2057 a = cJSON_CreateArray(); 2058 2059 for (i = 0; a && (i < (size_t)count); i++) { 2060 n = cJSON_CreateString(strings[i]); 2061 if (!n) { 2062 cJSON_Delete(a); 2063 return NULL; 2064 } 2065 if (!i) { 2066 a->child = n; 2067 } else { 2068 suffix_object(p, n); 2069 } 2070 p = n; 2071 } 2072 2073 if (a && a->child) { a->child->prev = n; } 2074 2075 return a; 2076 } 2077 2078 /* Duplication */ 2079 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) 2080 { 2081 cJSON *newitem = NULL; 2082 cJSON *child = NULL; 2083 cJSON *next = NULL; 2084 cJSON *newchild = NULL; 2085 2086 /* Bail on bad ptr */ 2087 if (!item) { goto fail; } 2088 /* Create new item */ 2089 newitem = cJSON_New_Item(&global_hooks); 2090 if (!newitem) { goto fail; } 2091 /* Copy over all vars */ 2092 newitem->type = item->type & (~cJSON_IsReference); 2093 newitem->valueint = item->valueint; 2094 newitem->valuedouble = item->valuedouble; 2095 if (item->valuestring) { 2096 newitem->valuestring = (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks); 2097 if (!newitem->valuestring) { goto fail; } 2098 } 2099 if (item->string) { 2100 newitem->string = (item->type & cJSON_StringIsConst) ? item->string : (char *)cJSON_strdup((unsigned char *)item->string, &global_hooks); 2101 if (!newitem->string) { goto fail; } 2102 } 2103 /* If non-recursive, then we're done! */ 2104 if (!recurse) { return newitem; } 2105 /* Walk the ->next chain for the child. */ 2106 child = item->child; 2107 while (child != NULL) { 2108 newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ 2109 if (!newchild) { goto fail; } 2110 if (next != NULL) { 2111 /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 2112 next->next = newchild; 2113 newchild->prev = next; 2114 next = newchild; 2115 } else { 2116 /* Set newitem->child and move to it */ 2117 newitem->child = newchild; 2118 next = newchild; 2119 } 2120 child = child->next; 2121 } 2122 if (newitem && newitem->child) { newitem->child->prev = newchild; } 2123 2124 return newitem; 2125 2126 fail: 2127 if (newitem != NULL) { cJSON_Delete(newitem); } 2128 2129 return NULL; 2130 } 2131 2132 static void skip_oneline_comment(char **input) 2133 { 2134 *input += static_strlen("//"); 2135 2136 for (; (*input)[0] != '\0'; ++(*input)) { 2137 if ((*input)[0] == '\n') { 2138 *input += static_strlen("\n"); 2139 return; 2140 } 2141 } 2142 } 2143 2144 static void skip_multiline_comment(char **input) 2145 { 2146 *input += static_strlen("/*"); 2147 2148 for (; (*input)[0] != '\0'; ++(*input)) { 2149 if (((*input)[0] == '*') && ((*input)[1] == '/')) { 2150 *input += static_strlen("*/"); 2151 return; 2152 } 2153 } 2154 } 2155 2156 static void minify_string(char **input, char **output) 2157 { 2158 (*output)[0] = (*input)[0]; 2159 *input += static_strlen("\""); 2160 *output += static_strlen("\""); 2161 2162 for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { 2163 (*output)[0] = (*input)[0]; 2164 2165 if ((*input)[0] == '\"') { 2166 (*output)[0] = '\"'; 2167 *input += static_strlen("\""); 2168 *output += static_strlen("\""); 2169 return; 2170 } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { 2171 (*output)[1] = (*input)[1]; 2172 *input += static_strlen("\""); 2173 *output += static_strlen("\""); 2174 } 2175 } 2176 } 2177 2178 CJSON_PUBLIC(void) cJSON_Minify(char *json) 2179 { 2180 char *into = json; 2181 2182 if (json == NULL) { return; } 2183 2184 while (json[0] != '\0') { 2185 switch (json[0]) { 2186 case ' ': 2187 case '\t': 2188 case '\r': 2189 case '\n': 2190 json++; 2191 break; 2192 2193 case '/': 2194 if (json[1] == '/') { 2195 skip_oneline_comment(&json); 2196 } else if (json[1] == '*') { 2197 skip_multiline_comment(&json); 2198 } else { 2199 json++; 2200 } 2201 break; 2202 2203 case '\"': 2204 minify_string(&json, (char **)&into); 2205 break; 2206 2207 default: 2208 into[0] = json[0]; 2209 json++; 2210 into++; 2211 } 2212 } 2213 2214 /* and null-terminate. */ 2215 *into = '\0'; 2216 } 2217 2218 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item) 2219 { 2220 if (item == NULL) { return false; } 2221 2222 return (item->type & 0xFF) == cJSON_Invalid; 2223 } 2224 2225 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item) 2226 { 2227 if (item == NULL) { return false; } 2228 2229 return (item->type & 0xFF) == cJSON_False; 2230 } 2231 2232 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item) 2233 { 2234 if (item == NULL) { return false; } 2235 2236 return (item->type & 0xff) == cJSON_True; 2237 } 2238 2239 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item) 2240 { 2241 if (item == NULL) { return false; } 2242 2243 return (item->type & (cJSON_True | cJSON_False)) != 0; 2244 } 2245 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item) 2246 { 2247 if (item == NULL) { return false; } 2248 2249 return (item->type & 0xFF) == cJSON_NULL; 2250 } 2251 2252 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item) 2253 { 2254 if (item == NULL) { return false; } 2255 2256 return (item->type & 0xFF) == cJSON_Number; 2257 } 2258 2259 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item) 2260 { 2261 if (item == NULL) { return false; } 2262 2263 return (item->type & 0xFF) == cJSON_String; 2264 } 2265 2266 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item) 2267 { 2268 if (item == NULL) { return false; } 2269 2270 return (item->type & 0xFF) == cJSON_Array; 2271 } 2272 2273 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) 2274 { 2275 if (item == NULL) { return false; } 2276 2277 return (item->type & 0xFF) == cJSON_Object; 2278 } 2279 2280 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item) 2281 { 2282 if (item == NULL) { return false; } 2283 2284 return (item->type & 0xFF) == cJSON_Raw; 2285 } 2286 2287 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) 2288 { 2289 if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { return false; } 2290 2291 /* check if type is valid */ 2292 switch (a->type & 0xFF) { 2293 case cJSON_False: 2294 case cJSON_True: 2295 case cJSON_NULL: 2296 case cJSON_Number: 2297 case cJSON_String: 2298 case cJSON_Raw: 2299 case cJSON_Array: 2300 case cJSON_Object: 2301 break; 2302 2303 default: 2304 return false; 2305 } 2306 2307 /* identical objects are equal */ 2308 if (a == b) { return true; } 2309 2310 switch (a->type & 0xFF) { 2311 /* in these cases and equal type is enough */ 2312 case cJSON_False: 2313 case cJSON_True: 2314 case cJSON_NULL: 2315 return true; 2316 2317 case cJSON_Number: 2318 if (compare_double(a->valuedouble, b->valuedouble)) { return true; } 2319 return false; 2320 2321 case cJSON_String: 2322 case cJSON_Raw: 2323 if ((a->valuestring == NULL) || (b->valuestring == NULL)) { return false; } 2324 if (strcmp(a->valuestring, b->valuestring) == 0) { return true; } 2325 2326 return false; 2327 2328 case cJSON_Array: { 2329 cJSON *a_element = a->child; 2330 cJSON *b_element = b->child; 2331 2332 for (; (a_element != NULL) && (b_element != NULL);) { 2333 if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; } 2334 2335 a_element = a_element->next; 2336 b_element = b_element->next; 2337 } 2338 2339 /* one of the arrays is longer than the other */ 2340 if (a_element != b_element) { return false; } 2341 2342 return true; 2343 } 2344 2345 case cJSON_Object: { 2346 cJSON *a_element = NULL; 2347 cJSON *b_element = NULL; 2348 cJSON_ArrayForEach(a_element, a) 2349 { 2350 /* TODO This has O(n^2) runtime, which is horrible! */ 2351 b_element = get_object_item(b, a_element->string, case_sensitive); 2352 if (b_element == NULL) { return false; } 2353 2354 if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; } 2355 } 2356 2357 /* doing this twice, once on a and b to prevent true comparison if a subset of b 2358 * TODO: Do this the proper way, this is just a fix for now */ 2359 cJSON_ArrayForEach(b_element, b) 2360 { 2361 a_element = get_object_item(a, b_element->string, case_sensitive); 2362 if (a_element == NULL) { return false; } 2363 2364 if (!cJSON_Compare(b_element, a_element, case_sensitive)) { return false; } 2365 } 2366 2367 return true; 2368 } 2369 2370 default: 2371 return false; 2372 } 2373 } 2374 2375 CJSON_PUBLIC(void *) cJSON_malloc(size_t size) 2376 { 2377 return global_hooks.allocate(size); 2378 } 2379 2380 CJSON_PUBLIC(void) cJSON_free(void *object) 2381 { 2382 global_hooks.deallocate(object); 2383 } 2384