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