xref: /petsc/src/mat/tests/cJSON.c (revision 66af8762ec03dbef0e079729eb2a1734a35ed7ff)
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 != '\\') {
662       *output_pointer++ = *input_pointer++;
663     }
664     /* escape sequence */
665     else {
666       unsigned char sequence_length = 2;
667       if ((input_end - input_pointer) < 1) { goto fail; }
668 
669       switch (input_pointer[1]) {
670       case 'b':
671         *output_pointer++ = '\b';
672         break;
673       case 'f':
674         *output_pointer++ = '\f';
675         break;
676       case 'n':
677         *output_pointer++ = '\n';
678         break;
679       case 'r':
680         *output_pointer++ = '\r';
681         break;
682       case 't':
683         *output_pointer++ = '\t';
684         break;
685       case '\"':
686       case '\\':
687       case '/':
688         *output_pointer++ = input_pointer[1];
689         break;
690 
691       /* UTF-16 literal */
692       case 'u':
693         sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
694         if (sequence_length == 0) {
695           /* failed to convert UTF16-literal to UTF-8 */
696           goto fail;
697         }
698         break;
699 
700       default:
701         goto fail;
702       }
703       input_pointer += sequence_length;
704     }
705   }
706 
707   /* zero terminate the output */
708   *output_pointer = '\0';
709 
710   item->type        = cJSON_String;
711   item->valuestring = (char *)output;
712 
713   input_buffer->offset = (size_t)(input_end - input_buffer->content);
714   input_buffer->offset++;
715 
716   return true;
717 
718 fail:
719   if (output != NULL) { input_buffer->hooks.deallocate(output); }
720 
721   if (input_pointer != NULL) { input_buffer->offset = (size_t)(input_pointer - input_buffer->content); }
722 
723   return false;
724 }
725 
726 /* Render the cstring provided to an escaped version that can be printed. */
727 static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer)
728 {
729   const unsigned char *input_pointer  = NULL;
730   unsigned char       *output         = NULL;
731   unsigned char       *output_pointer = NULL;
732   size_t               output_length  = 0;
733   /* numbers of additional characters needed for escaping */
734   size_t escape_characters = 0;
735 
736   if (output_buffer == NULL) { return false; }
737 
738   /* empty string */
739   if (input == NULL) {
740     output = ensure(output_buffer, sizeof("\"\""));
741     if (output == NULL) { return false; }
742     strcpy((char *)output, "\"\"");
743 
744     return true;
745   }
746 
747   /* set "flag" to 1 if something needs to be escaped */
748   for (input_pointer = input; *input_pointer; input_pointer++) {
749     switch (*input_pointer) {
750     case '\"':
751     case '\\':
752     case '\b':
753     case '\f':
754     case '\n':
755     case '\r':
756     case '\t':
757       /* one character escape sequence */
758       escape_characters++;
759       break;
760     default:
761       if (*input_pointer < 32) {
762         /* UTF-16 escape sequence uXXXX */
763         escape_characters += 5;
764       }
765       break;
766     }
767   }
768   output_length = (size_t)(input_pointer - input) + escape_characters;
769 
770   output = ensure(output_buffer, output_length + sizeof("\"\""));
771   if (output == NULL) { return false; }
772 
773   /* no characters have to be escaped */
774   if (escape_characters == 0) {
775     output[0] = '\"';
776     memcpy(output + 1, input, output_length);
777     output[output_length + 1] = '\"';
778     output[output_length + 2] = '\0';
779 
780     return true;
781   }
782 
783   output[0]      = '\"';
784   output_pointer = output + 1;
785   /* copy the string */
786   for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
787     if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
788       /* normal character, copy */
789       *output_pointer = *input_pointer;
790     } else {
791       /* character needs to be escaped */
792       *output_pointer++ = '\\';
793       switch (*input_pointer) {
794       case '\\':
795         *output_pointer = '\\';
796         break;
797       case '\"':
798         *output_pointer = '\"';
799         break;
800       case '\b':
801         *output_pointer = 'b';
802         break;
803       case '\f':
804         *output_pointer = 'f';
805         break;
806       case '\n':
807         *output_pointer = 'n';
808         break;
809       case '\r':
810         *output_pointer = 'r';
811         break;
812       case '\t':
813         *output_pointer = 't';
814         break;
815       default:
816         /* escape and print as unicode codepoint */
817         snprintf((char *)output_pointer, 6, "u%04x", *input_pointer);
818         output_pointer += 5;
819         break;
820       }
821     }
822   }
823   output[output_length + 1] = '\"';
824   output[output_length + 2] = '\0';
825 
826   return true;
827 }
828 
829 /* Invoke print_string_ptr (which is useful) on an item. */
830 static cJSON_bool print_string(const cJSON *const item, printbuffer *const p)
831 {
832   return print_string_ptr((unsigned char *)item->valuestring, p);
833 }
834 
835 /* Predeclare these prototypes. */
836 static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer);
837 static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer);
838 static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer);
839 static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer);
840 static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer);
841 static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer);
842 
843 /* Utility to jump whitespace and cr/lf */
844 static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer)
845 {
846   if ((buffer == NULL) || (buffer->content == NULL)) { return NULL; }
847 
848   if (cannot_access_at_index(buffer, 0)) { return buffer; }
849 
850   while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { buffer->offset++; }
851 
852   if (buffer->offset == buffer->length) { buffer->offset--; }
853 
854   return buffer;
855 }
856 
857 /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
858 static parse_buffer *skip_utf8_bom(parse_buffer *const buffer)
859 {
860   if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) { return NULL; }
861 
862   if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) { buffer->offset += 3; }
863 
864   return buffer;
865 }
866 
867 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
868 {
869   size_t buffer_length;
870 
871   if (NULL == value) { return NULL; }
872 
873   /* Adding null character size due to require_null_terminated. */
874   buffer_length = strlen(value) + sizeof("");
875 
876   return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
877 }
878 
879 /* Parse an object - create a new root, and populate. */
880 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
881 {
882   parse_buffer buffer = {
883     0, 0, 0, 0, {0, 0, 0}
884   };
885   cJSON *item = NULL;
886 
887   /* reset error position */
888   global_error.json     = NULL;
889   global_error.position = 0;
890 
891   if (value == NULL || 0 == buffer_length) { goto fail; }
892 
893   buffer.content = (const unsigned char *)value;
894   buffer.length  = buffer_length;
895   buffer.offset  = 0;
896   buffer.hooks   = global_hooks;
897 
898   item = cJSON_New_Item(&global_hooks);
899   if (item == NULL) /* memory fail */
900   {
901     goto fail;
902   }
903 
904   if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) {
905     /* parse failure. ep is set. */
906     goto fail;
907   }
908 
909   /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
910   if (require_null_terminated) {
911     buffer_skip_whitespace(&buffer);
912     if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') { goto fail; }
913   }
914   if (return_parse_end) { *return_parse_end = (const char *)buffer_at_offset(&buffer); }
915 
916   return item;
917 
918 fail:
919   if (item != NULL) { cJSON_Delete(item); }
920 
921   if (value != NULL) {
922     error local_error;
923     local_error.json     = (const unsigned char *)value;
924     local_error.position = 0;
925 
926     if (buffer.offset < buffer.length) {
927       local_error.position = buffer.offset;
928     } else if (buffer.length > 0) {
929       local_error.position = buffer.length - 1;
930     }
931 
932     if (return_parse_end != NULL) { *return_parse_end = (const char *)local_error.json + local_error.position; }
933 
934     global_error = local_error;
935   }
936 
937   return NULL;
938 }
939 
940 /* Default options for cJSON_Parse */
941 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
942 {
943   return cJSON_ParseWithOpts(value, 0, 0);
944 }
945 
946 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
947 {
948   return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
949 }
950 
951 #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
952 
953 static unsigned char *print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks)
954 {
955   static const size_t default_buffer_size = 256;
956   printbuffer         buffer[1];
957   unsigned char      *printed = NULL;
958 
959   memset(buffer, 0, sizeof(buffer));
960 
961   /* create buffer */
962   buffer->buffer = (unsigned char *)hooks->allocate(default_buffer_size);
963   buffer->length = default_buffer_size;
964   buffer->format = format;
965   buffer->hooks  = *hooks;
966   if (buffer->buffer == NULL) { goto fail; }
967 
968   /* print the value */
969   if (!print_value(item, buffer)) { goto fail; }
970   update_offset(buffer);
971 
972   /* check if reallocate is available */
973   if (hooks->reallocate != NULL) {
974     printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->offset + 1);
975     if (printed == NULL) { goto fail; }
976     buffer->buffer = NULL;
977   } else /* otherwise copy the JSON over to a new buffer */
978   {
979     printed = (unsigned char *)hooks->allocate(buffer->offset + 1);
980     if (printed == NULL) { goto fail; }
981     memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
982     printed[buffer->offset] = '\0'; /* just to be sure */
983 
984     /* free the buffer */
985     hooks->deallocate(buffer->buffer);
986   }
987 
988   return printed;
989 
990 fail:
991   if (buffer->buffer != NULL) { hooks->deallocate(buffer->buffer); }
992 
993   if (printed != NULL) { hooks->deallocate(printed); }
994 
995   return NULL;
996 }
997 
998 /* Render a cJSON item/entity/structure to text. */
999 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1000 {
1001   return (char *)print(item, true, &global_hooks);
1002 }
1003 
1004 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1005 {
1006   return (char *)print(item, false, &global_hooks);
1007 }
1008 
1009 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1010 {
1011   printbuffer p = {
1012     0, 0, 0, 0, 0, 0, {0, 0, 0}
1013   };
1014 
1015   if (prebuffer < 0) { return NULL; }
1016 
1017   p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer);
1018   if (!p.buffer) { return NULL; }
1019 
1020   p.length  = (size_t)prebuffer;
1021   p.offset  = 0;
1022   p.noalloc = false;
1023   p.format  = fmt;
1024   p.hooks   = global_hooks;
1025 
1026   if (!print_value(item, &p)) {
1027     global_hooks.deallocate(p.buffer);
1028     return NULL;
1029   }
1030 
1031   return (char *)p.buffer;
1032 }
1033 
1034 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1035 {
1036   printbuffer p = {
1037     0, 0, 0, 0, 0, 0, {0, 0, 0}
1038   };
1039 
1040   if ((length < 0) || (buffer == NULL)) { return false; }
1041 
1042   p.buffer  = (unsigned char *)buffer;
1043   p.length  = (size_t)length;
1044   p.offset  = 0;
1045   p.noalloc = true;
1046   p.format  = format;
1047   p.hooks   = global_hooks;
1048 
1049   return print_value(item, &p);
1050 }
1051 
1052 /* Parser core - when encountering text, process appropriately. */
1053 static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer)
1054 {
1055   if ((input_buffer == NULL) || (input_buffer->content == NULL)) { return false; /* no input */ }
1056 
1057   /* parse the different types of values */
1058   /* null */
1059   if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
1060     item->type = cJSON_NULL;
1061     input_buffer->offset += 4;
1062     return true;
1063   }
1064   /* false */
1065   if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
1066     item->type = cJSON_False;
1067     input_buffer->offset += 5;
1068     return true;
1069   }
1070   /* true */
1071   if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
1072     item->type     = cJSON_True;
1073     item->valueint = 1;
1074     input_buffer->offset += 4;
1075     return true;
1076   }
1077   /* string */
1078   if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { return parse_string(item, input_buffer); }
1079   /* number */
1080   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); }
1081   /* array */
1082   if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) { return parse_array(item, input_buffer); }
1083   /* object */
1084   if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { return parse_object(item, input_buffer); }
1085 
1086   return false;
1087 }
1088 
1089 /* Render a value to text. */
1090 static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer)
1091 {
1092   unsigned char *output = NULL;
1093 
1094   if ((item == NULL) || (output_buffer == NULL)) { return false; }
1095 
1096   switch ((item->type) & 0xFF) {
1097   case cJSON_NULL:
1098     output = ensure(output_buffer, 5);
1099     if (output == NULL) { return false; }
1100     strcpy((char *)output, "null");
1101     return true;
1102 
1103   case cJSON_False:
1104     output = ensure(output_buffer, 6);
1105     if (output == NULL) { return false; }
1106     strcpy((char *)output, "false");
1107     return true;
1108 
1109   case cJSON_True:
1110     output = ensure(output_buffer, 5);
1111     if (output == NULL) { return false; }
1112     strcpy((char *)output, "true");
1113     return true;
1114 
1115   case cJSON_Number:
1116     return print_number(item, output_buffer);
1117 
1118   case cJSON_Raw: {
1119     size_t raw_length = 0;
1120     if (item->valuestring == NULL) { return false; }
1121 
1122     raw_length = strlen(item->valuestring) + sizeof("");
1123     output     = ensure(output_buffer, raw_length);
1124     if (output == NULL) { return false; }
1125     memcpy(output, item->valuestring, raw_length);
1126     return true;
1127   }
1128 
1129   case cJSON_String:
1130     return print_string(item, output_buffer);
1131 
1132   case cJSON_Array:
1133     return print_array(item, output_buffer);
1134 
1135   case cJSON_Object:
1136     return print_object(item, output_buffer);
1137 
1138   default:
1139     return false;
1140   }
1141 }
1142 
1143 /* Build an array from input text. */
1144 static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer)
1145 {
1146   cJSON *head         = NULL; /* head of the linked list */
1147   cJSON *current_item = NULL;
1148 
1149   if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ }
1150   input_buffer->depth++;
1151 
1152   if (buffer_at_offset(input_buffer)[0] != '[') {
1153     /* not an array */
1154     goto fail;
1155   }
1156 
1157   input_buffer->offset++;
1158   buffer_skip_whitespace(input_buffer);
1159   if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
1160     /* empty array */
1161     goto success;
1162   }
1163 
1164   /* check if we skipped to the end of the buffer */
1165   if (cannot_access_at_index(input_buffer, 0)) {
1166     input_buffer->offset--;
1167     goto fail;
1168   }
1169 
1170   /* step back to character in front of the first element */
1171   input_buffer->offset--;
1172   /* loop through the comma separated array elements */
1173   do {
1174     /* allocate next item */
1175     cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1176     if (new_item == NULL) { goto fail; /* allocation failure */ }
1177 
1178     /* attach next item to list */
1179     if (head == NULL) {
1180       /* start the linked list */
1181       current_item = head = new_item;
1182     } else {
1183       /* add to the end and advance */
1184       current_item->next = new_item;
1185       new_item->prev     = current_item;
1186       current_item       = new_item;
1187     }
1188 
1189     /* parse next value */
1190     input_buffer->offset++;
1191     buffer_skip_whitespace(input_buffer);
1192     if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ }
1193     buffer_skip_whitespace(input_buffer);
1194   } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1195 
1196   if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { goto fail; /* expected end of array */ }
1197 
1198 success:
1199   input_buffer->depth--;
1200 
1201   if (head != NULL) { head->prev = current_item; }
1202 
1203   item->type  = cJSON_Array;
1204   item->child = head;
1205 
1206   input_buffer->offset++;
1207 
1208   return true;
1209 
1210 fail:
1211   if (head != NULL) { cJSON_Delete(head); }
1212 
1213   return false;
1214 }
1215 
1216 /* Render an array to text */
1217 static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer)
1218 {
1219   unsigned char *output_pointer  = NULL;
1220   size_t         length          = 0;
1221   cJSON         *current_element = item->child;
1222 
1223   if (output_buffer == NULL) { return false; }
1224 
1225   /* Compose the output array. */
1226   /* opening square bracket */
1227   output_pointer = ensure(output_buffer, 1);
1228   if (output_pointer == NULL) { return false; }
1229 
1230   *output_pointer = '[';
1231   output_buffer->offset++;
1232   output_buffer->depth++;
1233 
1234   while (current_element != NULL) {
1235     if (!print_value(current_element, output_buffer)) { return false; }
1236     update_offset(output_buffer);
1237     if (current_element->next) {
1238       length         = (size_t)(output_buffer->format ? 2 : 1);
1239       output_pointer = ensure(output_buffer, length + 1);
1240       if (output_pointer == NULL) { return false; }
1241       *output_pointer++ = ',';
1242       if (output_buffer->format) { *output_pointer++ = ' '; }
1243       *output_pointer = '\0';
1244       output_buffer->offset += length;
1245     }
1246     current_element = current_element->next;
1247   }
1248 
1249   output_pointer = ensure(output_buffer, 2);
1250   if (output_pointer == NULL) { return false; }
1251   *output_pointer++ = ']';
1252   *output_pointer   = '\0';
1253   output_buffer->depth--;
1254 
1255   return true;
1256 }
1257 
1258 /* Build an object from the text. */
1259 static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer)
1260 {
1261   cJSON *head         = NULL; /* linked list head */
1262   cJSON *current_item = NULL;
1263 
1264   if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ }
1265   input_buffer->depth++;
1266 
1267   if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { goto fail; /* not an object */ }
1268 
1269   input_buffer->offset++;
1270   buffer_skip_whitespace(input_buffer);
1271   if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { goto success; /* empty object */ }
1272 
1273   /* check if we skipped to the end of the buffer */
1274   if (cannot_access_at_index(input_buffer, 0)) {
1275     input_buffer->offset--;
1276     goto fail;
1277   }
1278 
1279   /* step back to character in front of the first element */
1280   input_buffer->offset--;
1281   /* loop through the comma separated array elements */
1282   do {
1283     /* allocate next item */
1284     cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1285     if (new_item == NULL) { goto fail; /* allocation failure */ }
1286 
1287     /* attach next item to list */
1288     if (head == NULL) {
1289       /* start the linked list */
1290       current_item = head = new_item;
1291     } else {
1292       /* add to the end and advance */
1293       current_item->next = new_item;
1294       new_item->prev     = current_item;
1295       current_item       = new_item;
1296     }
1297 
1298     /* parse the name of the child */
1299     input_buffer->offset++;
1300     buffer_skip_whitespace(input_buffer);
1301     if (!parse_string(current_item, input_buffer)) { goto fail; /* failed to parse name */ }
1302     buffer_skip_whitespace(input_buffer);
1303 
1304     /* swap valuestring and string, because we parsed the name */
1305     current_item->string      = current_item->valuestring;
1306     current_item->valuestring = NULL;
1307 
1308     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { goto fail; /* invalid object */ }
1309 
1310     /* parse the value */
1311     input_buffer->offset++;
1312     buffer_skip_whitespace(input_buffer);
1313     if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ }
1314     buffer_skip_whitespace(input_buffer);
1315   } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1316 
1317   if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { goto fail; /* expected end of object */ }
1318 
1319 success:
1320   input_buffer->depth--;
1321 
1322   if (head != NULL) { head->prev = current_item; }
1323 
1324   item->type  = cJSON_Object;
1325   item->child = head;
1326 
1327   input_buffer->offset++;
1328   return true;
1329 
1330 fail:
1331   if (head != NULL) { cJSON_Delete(head); }
1332 
1333   return false;
1334 }
1335 
1336 /* Render an object to text. */
1337 static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer)
1338 {
1339   unsigned char *output_pointer = NULL;
1340   size_t         length         = 0;
1341   cJSON         *current_item   = item->child;
1342 
1343   if (output_buffer == NULL) { return false; }
1344 
1345   /* Compose the output: */
1346   length         = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
1347   output_pointer = ensure(output_buffer, length + 1);
1348   if (output_pointer == NULL) { return false; }
1349 
1350   *output_pointer++ = '{';
1351   output_buffer->depth++;
1352   if (output_buffer->format) { *output_pointer++ = '\n'; }
1353   output_buffer->offset += length;
1354 
1355   while (current_item) {
1356     if (output_buffer->format) {
1357       size_t i;
1358       output_pointer = ensure(output_buffer, output_buffer->depth);
1359       if (output_pointer == NULL) { return false; }
1360       for (i = 0; i < output_buffer->depth; i++) { *output_pointer++ = '\t'; }
1361       output_buffer->offset += output_buffer->depth;
1362     }
1363 
1364     /* print key */
1365     if (!print_string_ptr((unsigned char *)current_item->string, output_buffer)) { return false; }
1366     update_offset(output_buffer);
1367 
1368     length         = (size_t)(output_buffer->format ? 2 : 1);
1369     output_pointer = ensure(output_buffer, length);
1370     if (output_pointer == NULL) { return false; }
1371     *output_pointer++ = ':';
1372     if (output_buffer->format) { *output_pointer++ = '\t'; }
1373     output_buffer->offset += length;
1374 
1375     /* print value */
1376     if (!print_value(current_item, output_buffer)) { return false; }
1377     update_offset(output_buffer);
1378 
1379     /* print comma if not last */
1380     length         = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1381     output_pointer = ensure(output_buffer, length + 1);
1382     if (output_pointer == NULL) { return false; }
1383     if (current_item->next) { *output_pointer++ = ','; }
1384 
1385     if (output_buffer->format) { *output_pointer++ = '\n'; }
1386     *output_pointer = '\0';
1387     output_buffer->offset += length;
1388 
1389     current_item = current_item->next;
1390   }
1391 
1392   output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1393   if (output_pointer == NULL) { return false; }
1394   if (output_buffer->format) {
1395     size_t i;
1396     for (i = 0; i < (output_buffer->depth - 1); i++) { *output_pointer++ = '\t'; }
1397   }
1398   *output_pointer++ = '}';
1399   *output_pointer   = '\0';
1400   output_buffer->depth--;
1401 
1402   return true;
1403 }
1404 
1405 /* Get Array size/item / object item. */
1406 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1407 {
1408   cJSON *child = NULL;
1409   size_t size  = 0;
1410 
1411   if (array == NULL) { return 0; }
1412 
1413   child = array->child;
1414 
1415   while (child != NULL) {
1416     size++;
1417     child = child->next;
1418   }
1419 
1420   /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1421 
1422   return (int)size;
1423 }
1424 
1425 static cJSON *get_array_item(const cJSON *array, size_t index)
1426 {
1427   cJSON *current_child = NULL;
1428 
1429   if (array == NULL) { return NULL; }
1430 
1431   current_child = array->child;
1432   while ((current_child != NULL) && (index > 0)) {
1433     index--;
1434     current_child = current_child->next;
1435   }
1436 
1437   return current_child;
1438 }
1439 
1440 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1441 {
1442   if (index < 0) { return NULL; }
1443 
1444   return get_array_item(array, (size_t)index);
1445 }
1446 
1447 static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive)
1448 {
1449   cJSON *current_element = NULL;
1450 
1451   if ((object == NULL) || (name == NULL)) { return NULL; }
1452 
1453   current_element = object->child;
1454   if (case_sensitive) {
1455     while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) { current_element = current_element->next; }
1456   } else {
1457     while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) { current_element = current_element->next; }
1458   }
1459 
1460   if ((current_element == NULL) || (current_element->string == NULL)) { return NULL; }
1461 
1462   return current_element;
1463 }
1464 
1465 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string)
1466 {
1467   return get_object_item(object, string, false);
1468 }
1469 
1470 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string)
1471 {
1472   return get_object_item(object, string, true);
1473 }
1474 
1475 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1476 {
1477   return cJSON_GetObjectItem(object, string) ? 1 : 0;
1478 }
1479 
1480 /* Utility for array list handling. */
1481 static void suffix_object(cJSON *prev, cJSON *item)
1482 {
1483   prev->next = item;
1484   item->prev = prev;
1485 }
1486 
1487 /* Utility for handling references. */
1488 static cJSON *create_reference(const cJSON *item, const internal_hooks *const hooks)
1489 {
1490   cJSON *reference = NULL;
1491   if (item == NULL) { return NULL; }
1492 
1493   reference = cJSON_New_Item(hooks);
1494   if (reference == NULL) { return NULL; }
1495 
1496   memcpy(reference, item, sizeof(cJSON));
1497   reference->string = NULL;
1498   reference->type |= cJSON_IsReference;
1499   reference->next = reference->prev = NULL;
1500   return reference;
1501 }
1502 
1503 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1504 {
1505   cJSON *child = NULL;
1506 
1507   if ((item == NULL) || (array == NULL) || (array == item)) { return false; }
1508 
1509   child = array->child;
1510   /*
1511      * To find the last item in array quickly, we use prev in array
1512      */
1513   if (child == NULL) {
1514     /* list is empty, start new one */
1515     array->child = item;
1516     item->prev   = item;
1517     item->next   = NULL;
1518   } else {
1519     /* append to the end */
1520     if (child->prev) {
1521       suffix_object(child->prev, item);
1522       array->child->prev = item;
1523     }
1524   }
1525 
1526   return true;
1527 }
1528 
1529 /* Add item to array/object. */
1530 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1531 {
1532   return add_item_to_array(array, item);
1533 }
1534 
1535 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1536   #pragma GCC diagnostic push
1537 #endif
1538 #ifdef __GNUC__
1539   #pragma GCC diagnostic ignored "-Wcast-qual"
1540 #endif
1541 /* helper function to cast away const */
1542 static void *cast_away_const(const void *string)
1543 {
1544   return (void *)string;
1545 }
1546 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1547   #pragma GCC diagnostic pop
1548 #endif
1549 
1550 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)
1551 {
1552   char *new_key  = NULL;
1553   int   new_type = cJSON_Invalid;
1554 
1555   if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) { return false; }
1556 
1557   if (constant_key) {
1558     new_key  = (char *)cast_away_const(string);
1559     new_type = item->type | cJSON_StringIsConst;
1560   } else {
1561     new_key = (char *)cJSON_strdup((const unsigned char *)string, hooks);
1562     if (new_key == NULL) { return false; }
1563 
1564     new_type = item->type & ~cJSON_StringIsConst;
1565   }
1566 
1567   if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { hooks->deallocate(item->string); }
1568 
1569   item->string = new_key;
1570   item->type   = new_type;
1571 
1572   return add_item_to_array(object, item);
1573 }
1574 
1575 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
1576 {
1577   return add_item_to_object(object, string, item, &global_hooks, false);
1578 }
1579 
1580 /* Add an item to an object with constant string as key */
1581 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1582 {
1583   return add_item_to_object(object, string, item, &global_hooks, true);
1584 }
1585 
1586 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1587 {
1588   if (array == NULL) { return false; }
1589 
1590   return add_item_to_array(array, create_reference(item, &global_hooks));
1591 }
1592 
1593 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1594 {
1595   if ((object == NULL) || (string == NULL)) { return false; }
1596 
1597   return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
1598 }
1599 
1600 CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name)
1601 {
1602   cJSON *null = cJSON_CreateNull();
1603   if (add_item_to_object(object, name, null, &global_hooks, false)) { return null; }
1604 
1605   cJSON_Delete(null);
1606   return NULL;
1607 }
1608 
1609 CJSON_PUBLIC(cJSON *) cJSON_AddTrueToObject(cJSON *const object, const char *const name)
1610 {
1611   cJSON *true_item = cJSON_CreateTrue();
1612   if (add_item_to_object(object, name, true_item, &global_hooks, false)) { return true_item; }
1613 
1614   cJSON_Delete(true_item);
1615   return NULL;
1616 }
1617 
1618 CJSON_PUBLIC(cJSON *) cJSON_AddFalseToObject(cJSON *const object, const char *const name)
1619 {
1620   cJSON *false_item = cJSON_CreateFalse();
1621   if (add_item_to_object(object, name, false_item, &global_hooks, false)) { return false_item; }
1622 
1623   cJSON_Delete(false_item);
1624   return NULL;
1625 }
1626 
1627 CJSON_PUBLIC(cJSON *) cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean)
1628 {
1629   cJSON *bool_item = cJSON_CreateBool(boolean);
1630   if (add_item_to_object(object, name, bool_item, &global_hooks, false)) { return bool_item; }
1631 
1632   cJSON_Delete(bool_item);
1633   return NULL;
1634 }
1635 
1636 CJSON_PUBLIC(cJSON *) cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number)
1637 {
1638   cJSON *number_item = cJSON_CreateNumber(number);
1639   if (add_item_to_object(object, name, number_item, &global_hooks, false)) { return number_item; }
1640 
1641   cJSON_Delete(number_item);
1642   return NULL;
1643 }
1644 
1645 CJSON_PUBLIC(cJSON *) cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string)
1646 {
1647   cJSON *string_item = cJSON_CreateString(string);
1648   if (add_item_to_object(object, name, string_item, &global_hooks, false)) { return string_item; }
1649 
1650   cJSON_Delete(string_item);
1651   return NULL;
1652 }
1653 
1654 CJSON_PUBLIC(cJSON *) cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw)
1655 {
1656   cJSON *raw_item = cJSON_CreateRaw(raw);
1657   if (add_item_to_object(object, name, raw_item, &global_hooks, false)) { return raw_item; }
1658 
1659   cJSON_Delete(raw_item);
1660   return NULL;
1661 }
1662 
1663 CJSON_PUBLIC(cJSON *) cJSON_AddObjectToObject(cJSON *const object, const char *const name)
1664 {
1665   cJSON *object_item = cJSON_CreateObject();
1666   if (add_item_to_object(object, name, object_item, &global_hooks, false)) { return object_item; }
1667 
1668   cJSON_Delete(object_item);
1669   return NULL;
1670 }
1671 
1672 CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name)
1673 {
1674   cJSON *array = cJSON_CreateArray();
1675   if (add_item_to_object(object, name, array, &global_hooks, false)) { return array; }
1676 
1677   cJSON_Delete(array);
1678   return NULL;
1679 }
1680 
1681 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item)
1682 {
1683   if ((parent == NULL) || (item == NULL)) { return NULL; }
1684 
1685   if (item != parent->child) {
1686     /* not the first element */
1687     item->prev->next = item->next;
1688   }
1689   if (item->next != NULL) {
1690     /* not the last element */
1691     item->next->prev = item->prev;
1692   }
1693 
1694   if (item == parent->child) {
1695     /* first element */
1696     parent->child = item->next;
1697   } else if (item->next == NULL) {
1698     /* last element */
1699     parent->child->prev = item->prev;
1700   }
1701 
1702   /* make sure the detached item doesn't point anywhere anymore */
1703   item->prev = NULL;
1704   item->next = NULL;
1705 
1706   return item;
1707 }
1708 
1709 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
1710 {
1711   if (which < 0) { return NULL; }
1712 
1713   return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
1714 }
1715 
1716 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
1717 {
1718   cJSON_Delete(cJSON_DetachItemFromArray(array, which));
1719 }
1720 
1721 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
1722 {
1723   cJSON *to_detach = cJSON_GetObjectItem(object, string);
1724 
1725   return cJSON_DetachItemViaPointer(object, to_detach);
1726 }
1727 
1728 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
1729 {
1730   cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
1731 
1732   return cJSON_DetachItemViaPointer(object, to_detach);
1733 }
1734 
1735 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
1736 {
1737   cJSON_Delete(cJSON_DetachItemFromObject(object, string));
1738 }
1739 
1740 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
1741 {
1742   cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
1743 }
1744 
1745 /* Replace array/object items with new ones. */
1746 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
1747 {
1748   cJSON *after_inserted = NULL;
1749 
1750   if (which < 0) { return false; }
1751 
1752   after_inserted = get_array_item(array, (size_t)which);
1753   if (after_inserted == NULL) { return add_item_to_array(array, newitem); }
1754 
1755   newitem->next        = after_inserted;
1756   newitem->prev        = after_inserted->prev;
1757   after_inserted->prev = newitem;
1758   if (after_inserted == array->child) {
1759     array->child = newitem;
1760   } else {
1761     newitem->prev->next = newitem;
1762   }
1763   return true;
1764 }
1765 
1766 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement)
1767 {
1768   if ((parent == NULL) || (replacement == NULL) || (item == NULL)) { return false; }
1769 
1770   if (replacement == item) { return true; }
1771 
1772   replacement->next = item->next;
1773   replacement->prev = item->prev;
1774 
1775   if (replacement->next != NULL) { replacement->next->prev = replacement; }
1776   if (parent->child == item) {
1777     if (parent->child->prev == parent->child) { replacement->prev = replacement; }
1778     parent->child = replacement;
1779   } else { /*
1780          * To find the last item in array quickly, we use prev in array.
1781          * We can't modify the last item's next pointer where this item was the parent's child
1782          */
1783     if (replacement->prev != NULL) { replacement->prev->next = replacement; }
1784     if (replacement->next == NULL) { parent->child->prev = replacement; }
1785   }
1786 
1787   item->next = NULL;
1788   item->prev = NULL;
1789   cJSON_Delete(item);
1790 
1791   return true;
1792 }
1793 
1794 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
1795 {
1796   if (which < 0) { return false; }
1797 
1798   return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
1799 }
1800 
1801 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
1802 {
1803   if ((replacement == NULL) || (string == NULL)) { return false; }
1804 
1805   /* replace the name in the replacement */
1806   if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { cJSON_free(replacement->string); }
1807   replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks);
1808   if (replacement->string == NULL) { return false; }
1809 
1810   replacement->type &= ~cJSON_StringIsConst;
1811 
1812   return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
1813 }
1814 
1815 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
1816 {
1817   return replace_item_in_object(object, string, newitem, false);
1818 }
1819 
1820 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
1821 {
1822   return replace_item_in_object(object, string, newitem, true);
1823 }
1824 
1825 /* Create basic types: */
1826 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
1827 {
1828   cJSON *item = cJSON_New_Item(&global_hooks);
1829   if (item) { item->type = cJSON_NULL; }
1830 
1831   return item;
1832 }
1833 
1834 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
1835 {
1836   cJSON *item = cJSON_New_Item(&global_hooks);
1837   if (item) { item->type = cJSON_True; }
1838 
1839   return item;
1840 }
1841 
1842 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
1843 {
1844   cJSON *item = cJSON_New_Item(&global_hooks);
1845   if (item) { item->type = cJSON_False; }
1846 
1847   return item;
1848 }
1849 
1850 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
1851 {
1852   cJSON *item = cJSON_New_Item(&global_hooks);
1853   if (item) { item->type = boolean ? cJSON_True : cJSON_False; }
1854 
1855   return item;
1856 }
1857 
1858 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
1859 {
1860   cJSON *item = cJSON_New_Item(&global_hooks);
1861   if (item) {
1862     item->type        = cJSON_Number;
1863     item->valuedouble = num;
1864 
1865     /* use saturation in case of overflow */
1866     if (num >= INT_MAX) {
1867       item->valueint = INT_MAX;
1868     } else if (num <= (double)INT_MIN) {
1869       item->valueint = INT_MIN;
1870     } else {
1871       item->valueint = (int)num;
1872     }
1873   }
1874 
1875   return item;
1876 }
1877 
1878 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
1879 {
1880   cJSON *item = cJSON_New_Item(&global_hooks);
1881   if (item) {
1882     item->type        = cJSON_String;
1883     item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks);
1884     if (!item->valuestring) {
1885       cJSON_Delete(item);
1886       return NULL;
1887     }
1888   }
1889 
1890   return item;
1891 }
1892 
1893 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
1894 {
1895   cJSON *item = cJSON_New_Item(&global_hooks);
1896   if (item != NULL) {
1897     item->type        = cJSON_String | cJSON_IsReference;
1898     item->valuestring = (char *)cast_away_const(string);
1899   }
1900 
1901   return item;
1902 }
1903 
1904 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
1905 {
1906   cJSON *item = cJSON_New_Item(&global_hooks);
1907   if (item != NULL) {
1908     item->type  = cJSON_Object | cJSON_IsReference;
1909     item->child = (cJSON *)cast_away_const(child);
1910   }
1911 
1912   return item;
1913 }
1914 
1915 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child)
1916 {
1917   cJSON *item = cJSON_New_Item(&global_hooks);
1918   if (item != NULL) {
1919     item->type  = cJSON_Array | cJSON_IsReference;
1920     item->child = (cJSON *)cast_away_const(child);
1921   }
1922 
1923   return item;
1924 }
1925 
1926 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
1927 {
1928   cJSON *item = cJSON_New_Item(&global_hooks);
1929   if (item) {
1930     item->type        = cJSON_Raw;
1931     item->valuestring = (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks);
1932     if (!item->valuestring) {
1933       cJSON_Delete(item);
1934       return NULL;
1935     }
1936   }
1937 
1938   return item;
1939 }
1940 
1941 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
1942 {
1943   cJSON *item = cJSON_New_Item(&global_hooks);
1944   if (item) { item->type = cJSON_Array; }
1945 
1946   return item;
1947 }
1948 
1949 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
1950 {
1951   cJSON *item = cJSON_New_Item(&global_hooks);
1952   if (item) { item->type = cJSON_Object; }
1953 
1954   return item;
1955 }
1956 
1957 /* Create Arrays: */
1958 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
1959 {
1960   size_t i = 0;
1961   cJSON *n = NULL;
1962   cJSON *p = NULL;
1963   cJSON *a = NULL;
1964 
1965   if ((count < 0) || (numbers == NULL)) { return NULL; }
1966 
1967   a = cJSON_CreateArray();
1968 
1969   for (i = 0; a && (i < (size_t)count); i++) {
1970     n = cJSON_CreateNumber(numbers[i]);
1971     if (!n) {
1972       cJSON_Delete(a);
1973       return NULL;
1974     }
1975     if (!i) {
1976       a->child = n;
1977     } else {
1978       suffix_object(p, n);
1979     }
1980     p = n;
1981   }
1982 
1983   if (a && a->child) { a->child->prev = n; }
1984 
1985   return a;
1986 }
1987 
1988 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
1989 {
1990   size_t i = 0;
1991   cJSON *n = NULL;
1992   cJSON *p = NULL;
1993   cJSON *a = NULL;
1994 
1995   if ((count < 0) || (numbers == NULL)) { return NULL; }
1996 
1997   a = cJSON_CreateArray();
1998 
1999   for (i = 0; a && (i < (size_t)count); i++) {
2000     n = cJSON_CreateNumber((double)numbers[i]);
2001     if (!n) {
2002       cJSON_Delete(a);
2003       return NULL;
2004     }
2005     if (!i) {
2006       a->child = n;
2007     } else {
2008       suffix_object(p, n);
2009     }
2010     p = n;
2011   }
2012 
2013   if (a && a->child) { a->child->prev = n; }
2014 
2015   return a;
2016 }
2017 
2018 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2019 {
2020   size_t i = 0;
2021   cJSON *n = NULL;
2022   cJSON *p = NULL;
2023   cJSON *a = NULL;
2024 
2025   if ((count < 0) || (numbers == NULL)) { return NULL; }
2026 
2027   a = cJSON_CreateArray();
2028 
2029   for (i = 0; a && (i < (size_t)count); i++) {
2030     n = cJSON_CreateNumber(numbers[i]);
2031     if (!n) {
2032       cJSON_Delete(a);
2033       return NULL;
2034     }
2035     if (!i) {
2036       a->child = n;
2037     } else {
2038       suffix_object(p, n);
2039     }
2040     p = n;
2041   }
2042 
2043   if (a && a->child) { a->child->prev = n; }
2044 
2045   return a;
2046 }
2047 
2048 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2049 {
2050   size_t i = 0;
2051   cJSON *n = NULL;
2052   cJSON *p = NULL;
2053   cJSON *a = NULL;
2054 
2055   if ((count < 0) || (strings == NULL)) { return NULL; }
2056 
2057   a = cJSON_CreateArray();
2058 
2059   for (i = 0; a && (i < (size_t)count); i++) {
2060     n = cJSON_CreateString(strings[i]);
2061     if (!n) {
2062       cJSON_Delete(a);
2063       return NULL;
2064     }
2065     if (!i) {
2066       a->child = n;
2067     } else {
2068       suffix_object(p, n);
2069     }
2070     p = n;
2071   }
2072 
2073   if (a && a->child) { a->child->prev = n; }
2074 
2075   return a;
2076 }
2077 
2078 /* Duplication */
2079 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2080 {
2081   cJSON *newitem  = NULL;
2082   cJSON *child    = NULL;
2083   cJSON *next     = NULL;
2084   cJSON *newchild = NULL;
2085 
2086   /* Bail on bad ptr */
2087   if (!item) { goto fail; }
2088   /* Create new item */
2089   newitem = cJSON_New_Item(&global_hooks);
2090   if (!newitem) { goto fail; }
2091   /* Copy over all vars */
2092   newitem->type        = item->type & (~cJSON_IsReference);
2093   newitem->valueint    = item->valueint;
2094   newitem->valuedouble = item->valuedouble;
2095   if (item->valuestring) {
2096     newitem->valuestring = (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks);
2097     if (!newitem->valuestring) { goto fail; }
2098   }
2099   if (item->string) {
2100     newitem->string = (item->type & cJSON_StringIsConst) ? item->string : (char *)cJSON_strdup((unsigned char *)item->string, &global_hooks);
2101     if (!newitem->string) { goto fail; }
2102   }
2103   /* If non-recursive, then we're done! */
2104   if (!recurse) { return newitem; }
2105   /* Walk the ->next chain for the child. */
2106   child = item->child;
2107   while (child != NULL) {
2108     newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2109     if (!newchild) { goto fail; }
2110     if (next != NULL) {
2111       /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2112       next->next     = newchild;
2113       newchild->prev = next;
2114       next           = newchild;
2115     } else {
2116       /* Set newitem->child and move to it */
2117       newitem->child = newchild;
2118       next           = newchild;
2119     }
2120     child = child->next;
2121   }
2122   if (newitem && newitem->child) { newitem->child->prev = newchild; }
2123 
2124   return newitem;
2125 
2126 fail:
2127   if (newitem != NULL) { cJSON_Delete(newitem); }
2128 
2129   return NULL;
2130 }
2131 
2132 static void skip_oneline_comment(char **input)
2133 {
2134   *input += static_strlen("//");
2135 
2136   for (; (*input)[0] != '\0'; ++(*input)) {
2137     if ((*input)[0] == '\n') {
2138       *input += static_strlen("\n");
2139       return;
2140     }
2141   }
2142 }
2143 
2144 static void skip_multiline_comment(char **input)
2145 {
2146   *input += static_strlen("/*");
2147 
2148   for (; (*input)[0] != '\0'; ++(*input)) {
2149     if (((*input)[0] == '*') && ((*input)[1] == '/')) {
2150       *input += static_strlen("*/");
2151       return;
2152     }
2153   }
2154 }
2155 
2156 static void minify_string(char **input, char **output)
2157 {
2158   (*output)[0] = (*input)[0];
2159   *input += static_strlen("\"");
2160   *output += static_strlen("\"");
2161 
2162   for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2163     (*output)[0] = (*input)[0];
2164 
2165     if ((*input)[0] == '\"') {
2166       (*output)[0] = '\"';
2167       *input += static_strlen("\"");
2168       *output += static_strlen("\"");
2169       return;
2170     } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2171       (*output)[1] = (*input)[1];
2172       *input += static_strlen("\"");
2173       *output += static_strlen("\"");
2174     }
2175   }
2176 }
2177 
2178 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2179 {
2180   char *into = json;
2181 
2182   if (json == NULL) { return; }
2183 
2184   while (json[0] != '\0') {
2185     switch (json[0]) {
2186     case ' ':
2187     case '\t':
2188     case '\r':
2189     case '\n':
2190       json++;
2191       break;
2192 
2193     case '/':
2194       if (json[1] == '/') {
2195         skip_oneline_comment(&json);
2196       } else if (json[1] == '*') {
2197         skip_multiline_comment(&json);
2198       } else {
2199         json++;
2200       }
2201       break;
2202 
2203     case '\"':
2204       minify_string(&json, (char **)&into);
2205       break;
2206 
2207     default:
2208       into[0] = json[0];
2209       json++;
2210       into++;
2211     }
2212   }
2213 
2214   /* and null-terminate. */
2215   *into = '\0';
2216 }
2217 
2218 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item)
2219 {
2220   if (item == NULL) { return false; }
2221 
2222   return (item->type & 0xFF) == cJSON_Invalid;
2223 }
2224 
2225 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item)
2226 {
2227   if (item == NULL) { return false; }
2228 
2229   return (item->type & 0xFF) == cJSON_False;
2230 }
2231 
2232 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item)
2233 {
2234   if (item == NULL) { return false; }
2235 
2236   return (item->type & 0xff) == cJSON_True;
2237 }
2238 
2239 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item)
2240 {
2241   if (item == NULL) { return false; }
2242 
2243   return (item->type & (cJSON_True | cJSON_False)) != 0;
2244 }
2245 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item)
2246 {
2247   if (item == NULL) { return false; }
2248 
2249   return (item->type & 0xFF) == cJSON_NULL;
2250 }
2251 
2252 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item)
2253 {
2254   if (item == NULL) { return false; }
2255 
2256   return (item->type & 0xFF) == cJSON_Number;
2257 }
2258 
2259 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item)
2260 {
2261   if (item == NULL) { return false; }
2262 
2263   return (item->type & 0xFF) == cJSON_String;
2264 }
2265 
2266 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item)
2267 {
2268   if (item == NULL) { return false; }
2269 
2270   return (item->type & 0xFF) == cJSON_Array;
2271 }
2272 
2273 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item)
2274 {
2275   if (item == NULL) { return false; }
2276 
2277   return (item->type & 0xFF) == cJSON_Object;
2278 }
2279 
2280 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item)
2281 {
2282   if (item == NULL) { return false; }
2283 
2284   return (item->type & 0xFF) == cJSON_Raw;
2285 }
2286 
2287 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive)
2288 {
2289   if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { return false; }
2290 
2291   /* check if type is valid */
2292   switch (a->type & 0xFF) {
2293   case cJSON_False:
2294   case cJSON_True:
2295   case cJSON_NULL:
2296   case cJSON_Number:
2297   case cJSON_String:
2298   case cJSON_Raw:
2299   case cJSON_Array:
2300   case cJSON_Object:
2301     break;
2302 
2303   default:
2304     return false;
2305   }
2306 
2307   /* identical objects are equal */
2308   if (a == b) { return true; }
2309 
2310   switch (a->type & 0xFF) {
2311   /* in these cases and equal type is enough */
2312   case cJSON_False:
2313   case cJSON_True:
2314   case cJSON_NULL:
2315     return true;
2316 
2317   case cJSON_Number:
2318     if (compare_double(a->valuedouble, b->valuedouble)) { return true; }
2319     return false;
2320 
2321   case cJSON_String:
2322   case cJSON_Raw:
2323     if ((a->valuestring == NULL) || (b->valuestring == NULL)) { return false; }
2324     if (strcmp(a->valuestring, b->valuestring) == 0) { return true; }
2325 
2326     return false;
2327 
2328   case cJSON_Array: {
2329     cJSON *a_element = a->child;
2330     cJSON *b_element = b->child;
2331 
2332     for (; (a_element != NULL) && (b_element != NULL);) {
2333       if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; }
2334 
2335       a_element = a_element->next;
2336       b_element = b_element->next;
2337     }
2338 
2339     /* one of the arrays is longer than the other */
2340     if (a_element != b_element) { return false; }
2341 
2342     return true;
2343   }
2344 
2345   case cJSON_Object: {
2346     cJSON *a_element = NULL;
2347     cJSON *b_element = NULL;
2348     cJSON_ArrayForEach(a_element, a)
2349     {
2350       /* TODO This has O(n^2) runtime, which is horrible! */
2351       b_element = get_object_item(b, a_element->string, case_sensitive);
2352       if (b_element == NULL) { return false; }
2353 
2354       if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; }
2355     }
2356 
2357     /* doing this twice, once on a and b to prevent true comparison if a subset of b
2358              * TODO: Do this the proper way, this is just a fix for now */
2359     cJSON_ArrayForEach(b_element, b)
2360     {
2361       a_element = get_object_item(a, b_element->string, case_sensitive);
2362       if (a_element == NULL) { return false; }
2363 
2364       if (!cJSON_Compare(b_element, a_element, case_sensitive)) { return false; }
2365     }
2366 
2367     return true;
2368   }
2369 
2370   default:
2371     return false;
2372   }
2373 }
2374 
2375 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
2376 {
2377   return global_hooks.allocate(size);
2378 }
2379 
2380 CJSON_PUBLIC(void) cJSON_free(void *object)
2381 {
2382   global_hooks.deallocate(object);
2383 }
2384