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