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