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 != 3)
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     if ((object == NULL) || (string == NULL) || (item == NULL))
1899     {
1900         return false;
1901     }
1902 
1903     if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
1904     {
1905         hooks->deallocate(item->string);
1906     }
1907 
1908     if (constant_key)
1909     {
1910         item->string = (char*)cast_away_const(string);
1911         item->type |= cJSON_StringIsConst;
1912     }
1913     else
1914     {
1915         char *key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
1916         if (key == NULL)
1917         {
1918             return false;
1919         }
1920 
1921         item->string = key;
1922         item->type &= ~cJSON_StringIsConst;
1923     }
1924 
1925     return add_item_to_array(object, item);
1926 }
1927 
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)1928 CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
1929 {
1930     add_item_to_object(object, string, item, &global_hooks, false);
1931 }
1932 
1933 /* Add an item to an object with constant string as key */
cJSON_AddItemToObjectCS(cJSON * object,const char * string,cJSON * item)1934 CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1935 {
1936     add_item_to_object(object, string, item, &global_hooks, true);
1937 }
1938 
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)1939 CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1940 {
1941     if (array == NULL)
1942     {
1943         return;
1944     }
1945 
1946     add_item_to_array(array, create_reference(item, &global_hooks));
1947 }
1948 
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)1949 CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1950 {
1951     if ((object == NULL) || (string == NULL))
1952     {
1953         return;
1954     }
1955 
1956     add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
1957 }
1958 
cJSON_AddNullToObject(cJSON * const object,const char * const name)1959 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
1960 {
1961     cJSON *null = cJSON_CreateNull();
1962     if (add_item_to_object(object, name, null, &global_hooks, false))
1963     {
1964         return null;
1965     }
1966 
1967     cJSON_Delete(null);
1968     return NULL;
1969 }
1970 
cJSON_AddTrueToObject(cJSON * const object,const char * const name)1971 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
1972 {
1973     cJSON *true_item = cJSON_CreateTrue();
1974     if (add_item_to_object(object, name, true_item, &global_hooks, false))
1975     {
1976         return true_item;
1977     }
1978 
1979     cJSON_Delete(true_item);
1980     return NULL;
1981 }
1982 
cJSON_AddFalseToObject(cJSON * const object,const char * const name)1983 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
1984 {
1985     cJSON *false_item = cJSON_CreateFalse();
1986     if (add_item_to_object(object, name, false_item, &global_hooks, false))
1987     {
1988         return false_item;
1989     }
1990 
1991     cJSON_Delete(false_item);
1992     return NULL;
1993 }
1994 
cJSON_AddBoolToObject(cJSON * const object,const char * const name,const cJSON_bool boolean)1995 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
1996 {
1997     cJSON *bool_item = cJSON_CreateBool(boolean);
1998     if (add_item_to_object(object, name, bool_item, &global_hooks, false))
1999     {
2000         return bool_item;
2001     }
2002 
2003     cJSON_Delete(bool_item);
2004     return NULL;
2005 }
2006 
cJSON_AddNumberToObject(cJSON * const object,const char * const name,const double number)2007 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2008 {
2009     cJSON *number_item = cJSON_CreateNumber(number);
2010     if (add_item_to_object(object, name, number_item, &global_hooks, false))
2011     {
2012         return number_item;
2013     }
2014 
2015     cJSON_Delete(number_item);
2016     return NULL;
2017 }
2018 
cJSON_AddStringToObject(cJSON * const object,const char * const name,const char * const string)2019 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2020 {
2021     cJSON *string_item = cJSON_CreateString(string);
2022     if (add_item_to_object(object, name, string_item, &global_hooks, false))
2023     {
2024         return string_item;
2025     }
2026 
2027     cJSON_Delete(string_item);
2028     return NULL;
2029 }
2030 
cJSON_AddRawToObject(cJSON * const object,const char * const name,const char * const raw)2031 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2032 {
2033     cJSON *raw_item = cJSON_CreateRaw(raw);
2034     if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2035     {
2036         return raw_item;
2037     }
2038 
2039     cJSON_Delete(raw_item);
2040     return NULL;
2041 }
2042 
cJSON_AddObjectToObject(cJSON * const object,const char * const name)2043 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2044 {
2045     cJSON *object_item = cJSON_CreateObject();
2046     if (add_item_to_object(object, name, object_item, &global_hooks, false))
2047     {
2048         return object_item;
2049     }
2050 
2051     cJSON_Delete(object_item);
2052     return NULL;
2053 }
2054 
cJSON_AddArrayToObject(cJSON * const object,const char * const name)2055 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2056 {
2057     cJSON *array = cJSON_CreateArray();
2058     if (add_item_to_object(object, name, array, &global_hooks, false))
2059     {
2060         return array;
2061     }
2062 
2063     cJSON_Delete(array);
2064     return NULL;
2065 }
2066 
cJSON_DetachItemViaPointer(cJSON * parent,cJSON * const item)2067 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2068 {
2069     if ((parent == NULL) || (item == NULL))
2070     {
2071         return NULL;
2072     }
2073 
2074     if (item->prev != NULL)
2075     {
2076         /* not the first element */
2077         item->prev->next = item->next;
2078     }
2079     if (item->next != NULL)
2080     {
2081         /* not the last element */
2082         item->next->prev = item->prev;
2083     }
2084 
2085     if (item == parent->child)
2086     {
2087         /* first element */
2088         parent->child = item->next;
2089     }
2090     /* make sure the detached item doesn't point anywhere anymore */
2091     item->prev = NULL;
2092     item->next = NULL;
2093 
2094     return item;
2095 }
2096 
cJSON_DetachItemFromArray(cJSON * array,int which)2097 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2098 {
2099     if (which < 0)
2100     {
2101         return NULL;
2102     }
2103 
2104     return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2105 }
2106 
cJSON_DeleteItemFromArray(cJSON * array,int which)2107 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2108 {
2109     cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2110 }
2111 
cJSON_DetachItemFromObject(cJSON * object,const char * string)2112 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2113 {
2114     cJSON *to_detach = cJSON_GetObjectItem(object, string);
2115 
2116     return cJSON_DetachItemViaPointer(object, to_detach);
2117 }
2118 
cJSON_DetachItemFromObjectCaseSensitive(cJSON * object,const char * string)2119 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2120 {
2121     cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2122 
2123     return cJSON_DetachItemViaPointer(object, to_detach);
2124 }
2125 
cJSON_DeleteItemFromObject(cJSON * object,const char * string)2126 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2127 {
2128     cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2129 }
2130 
cJSON_DeleteItemFromObjectCaseSensitive(cJSON * object,const char * string)2131 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2132 {
2133     cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2134 }
2135 
2136 /* Replace array/object items with new ones. */
cJSON_InsertItemInArray(cJSON * array,int which,cJSON * newitem)2137 CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2138 {
2139     cJSON *after_inserted = NULL;
2140 
2141     if (which < 0)
2142     {
2143         return;
2144     }
2145 
2146     after_inserted = get_array_item(array, (size_t)which);
2147     if (after_inserted == NULL)
2148     {
2149         add_item_to_array(array, newitem);
2150         return;
2151     }
2152 
2153     newitem->next = after_inserted;
2154     newitem->prev = after_inserted->prev;
2155     after_inserted->prev = newitem;
2156     if (after_inserted == array->child)
2157     {
2158         array->child = newitem;
2159     }
2160     else
2161     {
2162         newitem->prev->next = newitem;
2163     }
2164 }
2165 
cJSON_ReplaceItemViaPointer(cJSON * const parent,cJSON * const item,cJSON * replacement)2166 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2167 {
2168     if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2169     {
2170         return false;
2171     }
2172 
2173     if (replacement == item)
2174     {
2175         return true;
2176     }
2177 
2178     replacement->next = item->next;
2179     replacement->prev = item->prev;
2180 
2181     if (replacement->next != NULL)
2182     {
2183         replacement->next->prev = replacement;
2184     }
2185     if (replacement->prev != NULL)
2186     {
2187         replacement->prev->next = replacement;
2188     }
2189     if (parent->child == item)
2190     {
2191         parent->child = replacement;
2192     }
2193 
2194     item->next = NULL;
2195     item->prev = NULL;
2196     cJSON_Delete(item);
2197 
2198     return true;
2199 }
2200 
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)2201 CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2202 {
2203     if (which < 0)
2204     {
2205         return;
2206     }
2207 
2208     cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2209 }
2210 
replace_item_in_object(cJSON * object,const char * string,cJSON * replacement,cJSON_bool case_sensitive)2211 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2212 {
2213     if ((replacement == NULL) || (string == NULL))
2214     {
2215         return false;
2216     }
2217 
2218     /* replace the name in the replacement */
2219     if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2220     {
2221         cJSON_free(replacement->string);
2222     }
2223     replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2224     replacement->type &= ~cJSON_StringIsConst;
2225 
2226     cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2227 
2228     return true;
2229 }
2230 
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)2231 CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2232 {
2233     replace_item_in_object(object, string, newitem, false);
2234 }
2235 
cJSON_ReplaceItemInObjectCaseSensitive(cJSON * object,const char * string,cJSON * newitem)2236 CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2237 {
2238     replace_item_in_object(object, string, newitem, true);
2239 }
2240 
2241 /* Create basic types: */
cJSON_CreateNull(void)2242 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2243 {
2244     cJSON *item = cJSON_New_Item(&global_hooks);
2245     if(item)
2246     {
2247         item->type = cJSON_NULL;
2248     }
2249 
2250     return item;
2251 }
2252 
cJSON_CreateTrue(void)2253 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2254 {
2255     cJSON *item = cJSON_New_Item(&global_hooks);
2256     if(item)
2257     {
2258         item->type = cJSON_True;
2259     }
2260 
2261     return item;
2262 }
2263 
cJSON_CreateFalse(void)2264 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2265 {
2266     cJSON *item = cJSON_New_Item(&global_hooks);
2267     if(item)
2268     {
2269         item->type = cJSON_False;
2270     }
2271 
2272     return item;
2273 }
2274 
cJSON_CreateBool(cJSON_bool b)2275 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
2276 {
2277     cJSON *item = cJSON_New_Item(&global_hooks);
2278     if(item)
2279     {
2280         item->type = b ? cJSON_True : cJSON_False;
2281     }
2282 
2283     return item;
2284 }
2285 
cJSON_CreateNumber(double num)2286 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2287 {
2288     cJSON *item = cJSON_New_Item(&global_hooks);
2289     if(item)
2290     {
2291         item->type = cJSON_Number;
2292         item->valuedouble = num;
2293 
2294         /* use saturation in case of overflow */
2295         if (num >= INT_MAX)
2296         {
2297             item->valueint = INT_MAX;
2298         }
2299         else if (num <= INT_MIN)
2300         {
2301             item->valueint = INT_MIN;
2302         }
2303         else
2304         {
2305             item->valueint = (int)num;
2306         }
2307     }
2308 
2309     return item;
2310 }
2311 
cJSON_CreateString(const char * string)2312 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2313 {
2314     cJSON *item = cJSON_New_Item(&global_hooks);
2315     if(item)
2316     {
2317         item->type = cJSON_String;
2318         item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2319         if(!item->valuestring)
2320         {
2321             cJSON_Delete(item);
2322             return NULL;
2323         }
2324     }
2325 
2326     return item;
2327 }
2328 
cJSON_CreateStringReference(const char * string)2329 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2330 {
2331     cJSON *item = cJSON_New_Item(&global_hooks);
2332     if (item != NULL)
2333     {
2334         item->type = cJSON_String | cJSON_IsReference;
2335         item->valuestring = (char*)cast_away_const(string);
2336     }
2337 
2338     return item;
2339 }
2340 
cJSON_CreateObjectReference(const cJSON * child)2341 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2342 {
2343     cJSON *item = cJSON_New_Item(&global_hooks);
2344     if (item != NULL) {
2345         item->type = cJSON_Object | cJSON_IsReference;
2346         item->child = (cJSON*)cast_away_const(child);
2347     }
2348 
2349     return item;
2350 }
2351 
cJSON_CreateArrayReference(const cJSON * child)2352 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2353     cJSON *item = cJSON_New_Item(&global_hooks);
2354     if (item != NULL) {
2355         item->type = cJSON_Array | cJSON_IsReference;
2356         item->child = (cJSON*)cast_away_const(child);
2357     }
2358 
2359     return item;
2360 }
2361 
cJSON_CreateRaw(const char * raw)2362 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2363 {
2364     cJSON *item = cJSON_New_Item(&global_hooks);
2365     if(item)
2366     {
2367         item->type = cJSON_Raw;
2368         item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2369         if(!item->valuestring)
2370         {
2371             cJSON_Delete(item);
2372             return NULL;
2373         }
2374     }
2375 
2376     return item;
2377 }
2378 
cJSON_CreateArray(void)2379 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2380 {
2381     cJSON *item = cJSON_New_Item(&global_hooks);
2382     if(item)
2383     {
2384         item->type=cJSON_Array;
2385     }
2386 
2387     return item;
2388 }
2389 
cJSON_CreateObject(void)2390 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2391 {
2392     cJSON *item = cJSON_New_Item(&global_hooks);
2393     if (item)
2394     {
2395         item->type = cJSON_Object;
2396     }
2397 
2398     return item;
2399 }
2400 
2401 /* Create Arrays: */
cJSON_CreateIntArray(const int * numbers,int count)2402 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2403 {
2404     size_t i = 0;
2405     cJSON *n = NULL;
2406     cJSON *p = NULL;
2407     cJSON *a = NULL;
2408 
2409     if ((count < 0) || (numbers == NULL))
2410     {
2411         return NULL;
2412     }
2413 
2414     a = cJSON_CreateArray();
2415     for(i = 0; a && (i < (size_t)count); i++)
2416     {
2417         n = cJSON_CreateNumber(numbers[i]);
2418         if (!n)
2419         {
2420             cJSON_Delete(a);
2421             return NULL;
2422         }
2423         if(!i)
2424         {
2425             a->child = n;
2426         }
2427         else
2428         {
2429             suffix_object(p, n);
2430         }
2431         p = n;
2432     }
2433 
2434     return a;
2435 }
2436 
cJSON_CreateFloatArray(const float * numbers,int count)2437 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2438 {
2439     size_t i = 0;
2440     cJSON *n = NULL;
2441     cJSON *p = NULL;
2442     cJSON *a = NULL;
2443 
2444     if ((count < 0) || (numbers == NULL))
2445     {
2446         return NULL;
2447     }
2448 
2449     a = cJSON_CreateArray();
2450 
2451     for(i = 0; a && (i < (size_t)count); i++)
2452     {
2453         n = cJSON_CreateNumber((double)numbers[i]);
2454         if(!n)
2455         {
2456             cJSON_Delete(a);
2457             return NULL;
2458         }
2459         if(!i)
2460         {
2461             a->child = n;
2462         }
2463         else
2464         {
2465             suffix_object(p, n);
2466         }
2467         p = n;
2468     }
2469 
2470     return a;
2471 }
2472 
cJSON_CreateDoubleArray(const double * numbers,int count)2473 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2474 {
2475     size_t i = 0;
2476     cJSON *n = NULL;
2477     cJSON *p = NULL;
2478     cJSON *a = NULL;
2479 
2480     if ((count < 0) || (numbers == NULL))
2481     {
2482         return NULL;
2483     }
2484 
2485     a = cJSON_CreateArray();
2486 
2487     for(i = 0;a && (i < (size_t)count); i++)
2488     {
2489         n = cJSON_CreateNumber(numbers[i]);
2490         if(!n)
2491         {
2492             cJSON_Delete(a);
2493             return NULL;
2494         }
2495         if(!i)
2496         {
2497             a->child = n;
2498         }
2499         else
2500         {
2501             suffix_object(p, n);
2502         }
2503         p = n;
2504     }
2505 
2506     return a;
2507 }
2508 
cJSON_CreateStringArray(const char ** strings,int count)2509 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2510 {
2511     size_t i = 0;
2512     cJSON *n = NULL;
2513     cJSON *p = NULL;
2514     cJSON *a = NULL;
2515 
2516     if ((count < 0) || (strings == NULL))
2517     {
2518         return NULL;
2519     }
2520 
2521     a = cJSON_CreateArray();
2522 
2523     for (i = 0; a && (i < (size_t)count); i++)
2524     {
2525         n = cJSON_CreateString(strings[i]);
2526         if(!n)
2527         {
2528             cJSON_Delete(a);
2529             return NULL;
2530         }
2531         if(!i)
2532         {
2533             a->child = n;
2534         }
2535         else
2536         {
2537             suffix_object(p,n);
2538         }
2539         p = n;
2540     }
2541 
2542     return a;
2543 }
2544 
2545 /* Duplication */
cJSON_Duplicate(const cJSON * item,cJSON_bool recurse)2546 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2547 {
2548     cJSON *newitem = NULL;
2549     cJSON *child = NULL;
2550     cJSON *next = NULL;
2551     cJSON *newchild = NULL;
2552 
2553     /* Bail on bad ptr */
2554     if (!item)
2555     {
2556         goto fail;
2557     }
2558     /* Create new item */
2559     newitem = cJSON_New_Item(&global_hooks);
2560     if (!newitem)
2561     {
2562         goto fail;
2563     }
2564     /* Copy over all vars */
2565     newitem->type = item->type & (~cJSON_IsReference);
2566     newitem->valueint = item->valueint;
2567     newitem->valuedouble = item->valuedouble;
2568     if (item->valuestring)
2569     {
2570         newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2571         if (!newitem->valuestring)
2572         {
2573             goto fail;
2574         }
2575     }
2576     if (item->string)
2577     {
2578         newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2579         if (!newitem->string)
2580         {
2581             goto fail;
2582         }
2583     }
2584     /* If non-recursive, then we're done! */
2585     if (!recurse)
2586     {
2587         return newitem;
2588     }
2589     /* Walk the ->next chain for the child. */
2590     child = item->child;
2591     while (child != NULL)
2592     {
2593         newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2594         if (!newchild)
2595         {
2596             goto fail;
2597         }
2598         if (next != NULL)
2599         {
2600             /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2601             next->next = newchild;
2602             newchild->prev = next;
2603             next = newchild;
2604         }
2605         else
2606         {
2607             /* Set newitem->child and move to it */
2608             newitem->child = newchild;
2609             next = newchild;
2610         }
2611         child = child->next;
2612     }
2613 
2614     return newitem;
2615 
2616 fail:
2617     if (newitem != NULL)
2618     {
2619         cJSON_Delete(newitem);
2620     }
2621 
2622     return NULL;
2623 }
2624 
cJSON_Minify(char * json)2625 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2626 {
2627     unsigned char *into = (unsigned char*)json;
2628 
2629     if (json == NULL)
2630     {
2631         return;
2632     }
2633 
2634     while (*json)
2635     {
2636         if (*json == ' ')
2637         {
2638             json++;
2639         }
2640         else if (*json == '\t')
2641         {
2642             /* Whitespace characters. */
2643             json++;
2644         }
2645         else if (*json == '\r')
2646         {
2647             json++;
2648         }
2649         else if (*json=='\n')
2650         {
2651             json++;
2652         }
2653         else if ((*json == '/') && (json[1] == '/'))
2654         {
2655             /* double-slash comments, to end of line. */
2656             while (*json && (*json != '\n'))
2657             {
2658                 json++;
2659             }
2660         }
2661         else if ((*json == '/') && (json[1] == '*'))
2662         {
2663             /* multiline comments. */
2664             while (*json && !((*json == '*') && (json[1] == '/')))
2665             {
2666                 json++;
2667             }
2668             json += 2;
2669         }
2670         else if (*json == '\"')
2671         {
2672             /* string literals, which are \" sensitive. */
2673             *into++ = (unsigned char)*json++;
2674             while (*json && (*json != '\"'))
2675             {
2676                 if (*json == '\\')
2677                 {
2678                     *into++ = (unsigned char)*json++;
2679                 }
2680                 *into++ = (unsigned char)*json++;
2681             }
2682             *into++ = (unsigned char)*json++;
2683         }
2684         else
2685         {
2686             /* All other characters. */
2687             *into++ = (unsigned char)*json++;
2688         }
2689     }
2690 
2691     /* and null-terminate. */
2692     *into = '\0';
2693 }
2694 
cJSON_IsInvalid(const cJSON * const item)2695 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2696 {
2697     if (item == NULL)
2698     {
2699         return false;
2700     }
2701 
2702     return (item->type & 0xFF) == cJSON_Invalid;
2703 }
2704 
cJSON_IsFalse(const cJSON * const item)2705 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2706 {
2707     if (item == NULL)
2708     {
2709         return false;
2710     }
2711 
2712     return (item->type & 0xFF) == cJSON_False;
2713 }
2714 
cJSON_IsTrue(const cJSON * const item)2715 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2716 {
2717     if (item == NULL)
2718     {
2719         return false;
2720     }
2721 
2722     return (item->type & 0xff) == cJSON_True;
2723 }
2724 
2725 
cJSON_IsBool(const cJSON * const item)2726 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2727 {
2728     if (item == NULL)
2729     {
2730         return false;
2731     }
2732 
2733     return (item->type & (cJSON_True | cJSON_False)) != 0;
2734 }
cJSON_IsNull(const cJSON * const item)2735 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2736 {
2737     if (item == NULL)
2738     {
2739         return false;
2740     }
2741 
2742     return (item->type & 0xFF) == cJSON_NULL;
2743 }
2744 
cJSON_IsNumber(const cJSON * const item)2745 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2746 {
2747     if (item == NULL)
2748     {
2749         return false;
2750     }
2751 
2752     return (item->type & 0xFF) == cJSON_Number;
2753 }
2754 
cJSON_IsString(const cJSON * const item)2755 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2756 {
2757     if (item == NULL)
2758     {
2759         return false;
2760     }
2761 
2762     return (item->type & 0xFF) == cJSON_String;
2763 }
2764 
cJSON_IsArray(const cJSON * const item)2765 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2766 {
2767     if (item == NULL)
2768     {
2769         return false;
2770     }
2771 
2772     return (item->type & 0xFF) == cJSON_Array;
2773 }
2774 
cJSON_IsObject(const cJSON * const item)2775 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2776 {
2777     if (item == NULL)
2778     {
2779         return false;
2780     }
2781 
2782     return (item->type & 0xFF) == cJSON_Object;
2783 }
2784 
cJSON_IsRaw(const cJSON * const item)2785 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2786 {
2787     if (item == NULL)
2788     {
2789         return false;
2790     }
2791 
2792     return (item->type & 0xFF) == cJSON_Raw;
2793 }
2794 
cJSON_Compare(const cJSON * const a,const cJSON * const b,const cJSON_bool case_sensitive)2795 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2796 {
2797     if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2798     {
2799         return false;
2800     }
2801 
2802     /* check if type is valid */
2803     switch (a->type & 0xFF)
2804     {
2805         case cJSON_False:
2806         case cJSON_True:
2807         case cJSON_NULL:
2808         case cJSON_Number:
2809         case cJSON_String:
2810         case cJSON_Raw:
2811         case cJSON_Array:
2812         case cJSON_Object:
2813             break;
2814 
2815         default:
2816             return false;
2817     }
2818 
2819     /* identical objects are equal */
2820     if (a == b)
2821     {
2822         return true;
2823     }
2824 
2825     switch (a->type & 0xFF)
2826     {
2827         /* in these cases and equal type is enough */
2828         case cJSON_False:
2829         case cJSON_True:
2830         case cJSON_NULL:
2831             return true;
2832 
2833         case cJSON_Number:
2834             if (a->valuedouble == b->valuedouble)
2835             {
2836                 return true;
2837             }
2838             return false;
2839 
2840         case cJSON_String:
2841         case cJSON_Raw:
2842             if ((a->valuestring == NULL) || (b->valuestring == NULL))
2843             {
2844                 return false;
2845             }
2846             if (strcmp(a->valuestring, b->valuestring) == 0)
2847             {
2848                 return true;
2849             }
2850 
2851             return false;
2852 
2853         case cJSON_Array:
2854         {
2855             cJSON *a_element = a->child;
2856             cJSON *b_element = b->child;
2857 
2858             for (; (a_element != NULL) && (b_element != NULL);)
2859             {
2860                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
2861                 {
2862                     return false;
2863                 }
2864 
2865                 a_element = a_element->next;
2866                 b_element = b_element->next;
2867             }
2868 
2869             /* one of the arrays is longer than the other */
2870             if (a_element != b_element) {
2871                 return false;
2872             }
2873 
2874             return true;
2875         }
2876 
2877         case cJSON_Object:
2878         {
2879             cJSON *a_element = NULL;
2880             cJSON *b_element = NULL;
2881             cJSON_ArrayForEach(a_element, a)
2882             {
2883                 /* TODO This has O(n^2) runtime, which is horrible! */
2884                 b_element = get_object_item(b, a_element->string, case_sensitive);
2885                 if (b_element == NULL)
2886                 {
2887                     return false;
2888                 }
2889 
2890                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
2891                 {
2892                     return false;
2893                 }
2894             }
2895 
2896             /* doing this twice, once on a and b to prevent true comparison if a subset of b
2897              * TODO: Do this the proper way, this is just a fix for now */
2898             cJSON_ArrayForEach(b_element, b)
2899             {
2900                 a_element = get_object_item(a, b_element->string, case_sensitive);
2901                 if (a_element == NULL)
2902                 {
2903                     return false;
2904                 }
2905 
2906                 if (!cJSON_Compare(b_element, a_element, case_sensitive))
2907                 {
2908                     return false;
2909                 }
2910             }
2911 
2912             return true;
2913         }
2914 
2915         default:
2916             return false;
2917     }
2918 }
2919 
cJSON_malloc(size_t size)2920 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
2921 {
2922     return global_hooks.allocate(size);
2923 }
2924 
cJSON_free(void * object)2925 CJSON_PUBLIC(void) cJSON_free(void *object)
2926 {
2927     global_hooks.deallocate(object);
2928 }
2929