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