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