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