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