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