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