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