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