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