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