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 #ifdef HAVE_STDINT_H
48 #include <stdint.h>
49 #endif
50 #include <sys/types.h>
51
52 #ifdef ENABLE_LOCALES
53 #include <locale.h>
54 #endif
55
56 #if defined(_MSC_VER)
57 #pragma warning (pop)
58 #endif
59 #ifdef __GNUC__
60 #pragma GCC visibility pop
61 #endif
62
63 #include "cjson.h"
64
65 /* define our own boolean type */
66 #ifdef true
67 #undef true
68 #endif
69 #define true ((cJSON_bool)1)
70
71 #ifdef false
72 #undef false
73 #endif
74 #define false ((cJSON_bool)0)
75
76 /* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
77 #ifndef isinf
78 #define isinf(d) (isnan((d - d)) && !isnan(d))
79 #endif
80 #ifndef isnan
81 #define isnan(d) (d != d)
82 #endif
83
84 #ifndef NAN
85 #define NAN 0.0/0.0
86 #endif
87
88 typedef struct {
89 const unsigned char *json;
90 size_t position;
91 } error;
92 static error global_error = { NULL, 0 };
93
94 #ifndef LLONG_MAX
95 #define LLONG_MAX 9223372036854775807LL
96 #endif
97 #ifndef LLONG_MIN
98 #define LLONG_MIN (-LLONG_MAX - 1LL)
99 #endif
100
cJSON_GetErrorPtr(void)101 CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
102 {
103 return (const char*) (global_error.json + global_error.position);
104 }
105
cJSON_GetStringValue(cJSON * item)106 CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item)
107 {
108 if (!cJSON_IsString(item))
109 {
110 return NULL;
111 }
112
113 return item->valuestring;
114 }
115
cJSON_GetNumberValue(cJSON * item)116 CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item)
117 {
118 if (!cJSON_IsNumber(item))
119 {
120 return NAN;
121 }
122
123 return item->valuedouble;
124 }
125
126 /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
127 #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 13)
128 #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
129 #endif
130
cJSON_Version(void)131 CJSON_PUBLIC(const char*) cJSON_Version(void)
132 {
133 static char version[15];
134 sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
135
136 return version;
137 }
138
139 /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
case_insensitive_strcmp(const unsigned char * string1,const unsigned char * string2)140 static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
141 {
142 if ((string1 == NULL) || (string2 == NULL))
143 {
144 return 1;
145 }
146
147 if (string1 == string2)
148 {
149 return 0;
150 }
151
152 for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
153 {
154 if (*string1 == '\0')
155 {
156 return 0;
157 }
158 }
159
160 return tolower(*string1) - tolower(*string2);
161 }
162
163 typedef struct internal_hooks
164 {
165 void *(CJSON_CDECL *allocate)(size_t size);
166 void (CJSON_CDECL *deallocate)(void *pointer);
167 void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
168 } internal_hooks;
169
170 #if defined(_MSC_VER)
171 /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
internal_malloc(size_t size)172 static void * CJSON_CDECL internal_malloc(size_t size)
173 {
174 return malloc(size);
175 }
internal_free(void * pointer)176 static void CJSON_CDECL internal_free(void *pointer)
177 {
178 free(pointer);
179 }
internal_realloc(void * pointer,size_t size)180 static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
181 {
182 return realloc(pointer, size);
183 }
184 #else
185 #define internal_malloc malloc
186 #define internal_free free
187 #define internal_realloc realloc
188 #endif
189
190 /* strlen of character literals resolved at compile time */
191 #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
192
193 static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
194
cJSON_strdup(const unsigned char * string,const internal_hooks * const hooks)195 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
196 {
197 size_t length = 0;
198 unsigned char *copy = NULL;
199
200 if (string == NULL)
201 {
202 return NULL;
203 }
204
205 length = strlen((const char*)string) + sizeof("");
206 copy = (unsigned char*)hooks->allocate(length);
207 if (copy == NULL)
208 {
209 return NULL;
210 }
211 memcpy(copy, string, length);
212
213 return copy;
214 }
215
cJSON_InitHooks(cJSON_Hooks * hooks)216 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
217 {
218 if (hooks == NULL)
219 {
220 /* Reset hooks */
221 global_hooks.allocate = malloc;
222 global_hooks.deallocate = free;
223 global_hooks.reallocate = realloc;
224 return;
225 }
226
227 global_hooks.allocate = malloc;
228 if (hooks->malloc_fn != NULL)
229 {
230 global_hooks.allocate = hooks->malloc_fn;
231 }
232
233 global_hooks.deallocate = free;
234 if (hooks->free_fn != NULL)
235 {
236 global_hooks.deallocate = hooks->free_fn;
237 }
238
239 /* use realloc only if both free and malloc are used */
240 global_hooks.reallocate = NULL;
241 if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
242 {
243 global_hooks.reallocate = realloc;
244 }
245 }
246
247 /* Internal constructor. */
cJSON_New_Item(const internal_hooks * const hooks)248 static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
249 {
250 cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
251 if (node)
252 {
253 memset(node, '\0', sizeof(cJSON));
254 }
255
256 return node;
257 }
258
259 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * item)260 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
261 {
262 cJSON *next = NULL;
263 while (item != NULL)
264 {
265 next = item->next;
266 if (!(item->type & cJSON_IsReference) && (item->child != NULL))
267 {
268 cJSON_Delete(item->child);
269 }
270 if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
271 {
272 global_hooks.deallocate(item->valuestring);
273 }
274 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
275 {
276 global_hooks.deallocate(item->string);
277 }
278 global_hooks.deallocate(item);
279 item = next;
280 }
281 }
282
283 /* get the decimal point character of the current locale */
get_decimal_point(void)284 static unsigned char get_decimal_point(void)
285 {
286 #ifdef ENABLE_LOCALES
287 struct lconv *lconv = localeconv();
288 return (unsigned char) lconv->decimal_point[0];
289 #else
290 return '.';
291 #endif
292 }
293
294 typedef struct
295 {
296 const unsigned char *content;
297 size_t length;
298 size_t offset;
299 size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
300 internal_hooks hooks;
301 } parse_buffer;
302
303 /* check if the given size is left to read in a given parse buffer (starting with 1) */
304 #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
305 /* check if the buffer can be accessed at the given index (starting with 0) */
306 #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
307 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
308 /* get a pointer to the buffer at the position */
309 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
310
311 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * const item,parse_buffer * const input_buffer)312 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
313 {
314 double number = 0;
315 unsigned char *after_end = NULL;
316 unsigned char number_c_string[64];
317 unsigned char decimal_point = get_decimal_point();
318 size_t i = 0;
319
320 if ((input_buffer == NULL) || (input_buffer->content == NULL))
321 {
322 return false;
323 }
324
325 /* copy the number into a temporary buffer and replace '.' with the decimal point
326 * of the current locale (for strtod)
327 * This also takes care of '\0' not necessarily being available for marking the end of the input */
328 for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
329 {
330 switch (buffer_at_offset(input_buffer)[i])
331 {
332 case '0':
333 case '1':
334 case '2':
335 case '3':
336 case '4':
337 case '5':
338 case '6':
339 case '7':
340 case '8':
341 case '9':
342 case '+':
343 case '-':
344 case 'e':
345 case 'E':
346 number_c_string[i] = buffer_at_offset(input_buffer)[i];
347 break;
348
349 case '.':
350 number_c_string[i] = decimal_point;
351 break;
352
353 default:
354 goto loop_end;
355 }
356 }
357 loop_end:
358 number_c_string[i] = '\0';
359
360 number = strtod((const char*)number_c_string, (char**)&after_end);
361 if (number_c_string == after_end)
362 {
363 return false; /* parse_error */
364 }
365
366 item->valuedouble = number;
367
368 /* use saturation in case of overflow */
369 if (number >= LLONG_MAX)
370 {
371 item->valueint = LLONG_MAX;
372 }
373 else if (number <= (double)LLONG_MIN)
374 {
375 item->valueint = LLONG_MIN;
376 }
377 else
378 {
379 item->valueint = (int64_t)number;
380 }
381
382 item->type = cJSON_Number;
383
384 input_buffer->offset += (size_t)(after_end - number_c_string);
385 return true;
386 }
387
388 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
cJSON_SetNumberHelper(cJSON * object,double number)389 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
390 {
391 if (number >= LLONG_MAX)
392 {
393 object->valueint = LLONG_MAX;
394 }
395 else if (number <= (double)LLONG_MIN)
396 {
397 object->valueint = LLONG_MIN;
398 }
399 else
400 {
401 object->valueint = (int64_t)number;
402 }
403
404 return object->valuedouble = number;
405 }
406
cJSON_SetValuestring(cJSON * object,const char * valuestring)407 CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
408 {
409 char *copy = NULL;
410 /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
411 if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
412 {
413 return NULL;
414 }
415 if (strlen(valuestring) <= strlen(object->valuestring))
416 {
417 strcpy(object->valuestring, valuestring);
418 return object->valuestring;
419 }
420 copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
421 if (copy == NULL)
422 {
423 return NULL;
424 }
425 if (object->valuestring != NULL)
426 {
427 cJSON_free(object->valuestring);
428 }
429 object->valuestring = copy;
430
431 return copy;
432 }
433
434 typedef struct
435 {
436 unsigned char *buffer;
437 size_t length;
438 size_t offset;
439 size_t depth; /* current nesting depth (for formatted printing) */
440 cJSON_bool noalloc;
441 cJSON_bool format; /* is this print a formatted print */
442 internal_hooks hooks;
443 } printbuffer;
444
445 /* realloc printbuffer if necessary to have at least "needed" bytes more */
ensure(printbuffer * const p,size_t needed)446 static unsigned char* ensure(printbuffer * const p, size_t needed)
447 {
448 unsigned char *newbuffer = NULL;
449 size_t newsize = 0;
450
451 if ((p == NULL) || (p->buffer == NULL))
452 {
453 return NULL;
454 }
455
456 if ((p->length > 0) && (p->offset >= p->length))
457 {
458 /* make sure that offset is valid */
459 return NULL;
460 }
461
462 if (needed > SIZE_MAX)
463 {
464 /* sizes bigger than SIZE_MAX are currently not supported */
465 return NULL;
466 }
467
468 needed += p->offset + 1;
469 if (needed <= p->length)
470 {
471 return p->buffer + p->offset;
472 }
473
474 if (p->noalloc) {
475 return NULL;
476 }
477
478 /* calculate new buffer size */
479 if (needed > (SIZE_MAX / 2))
480 {
481 /* overflow of int, use SIZE_MAX if possible */
482 if (needed <= SIZE_MAX)
483 {
484 newsize = SIZE_MAX;
485 }
486 else
487 {
488 return NULL;
489 }
490 }
491 else
492 {
493 newsize = needed * 2;
494 }
495
496 if (p->hooks.reallocate != NULL)
497 {
498 /* reallocate with realloc if available */
499 newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
500 if (newbuffer == NULL)
501 {
502 p->hooks.deallocate(p->buffer);
503 p->length = 0;
504 p->buffer = NULL;
505
506 return NULL;
507 }
508 }
509 else
510 {
511 /* otherwise reallocate manually */
512 newbuffer = (unsigned char*)p->hooks.allocate(newsize);
513 if (!newbuffer)
514 {
515 p->hooks.deallocate(p->buffer);
516 p->length = 0;
517 p->buffer = NULL;
518
519 return NULL;
520 }
521 if (newbuffer)
522 {
523 memcpy(newbuffer, p->buffer, p->offset + 1);
524 }
525 p->hooks.deallocate(p->buffer);
526 }
527 p->length = newsize;
528 p->buffer = newbuffer;
529
530 return newbuffer + p->offset;
531 }
532
533 /* calculate the new length of the string in a printbuffer and update the offset */
update_offset(printbuffer * const buffer)534 static void update_offset(printbuffer * const buffer)
535 {
536 const unsigned char *buffer_pointer = NULL;
537 if ((buffer == NULL) || (buffer->buffer == NULL))
538 {
539 return;
540 }
541 buffer_pointer = buffer->buffer + buffer->offset;
542
543 buffer->offset += strlen((const char*)buffer_pointer);
544 }
545
546 /* securely comparison of floating-point variables */
compare_double(double a,double b)547 static cJSON_bool compare_double(double a, double b)
548 {
549 double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
550 return (fabs(a - b) <= maxVal * DBL_EPSILON);
551 }
552
553 /* Render the number nicely from the given item into a string. */
print_number(const cJSON * const item,printbuffer * const output_buffer)554 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
555 {
556 unsigned char *output_pointer = NULL;
557 double d = item->valuedouble;
558 int length = 0;
559 size_t i = 0;
560 unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
561 unsigned char decimal_point = get_decimal_point();
562 double test = 0.0;
563
564 if (output_buffer == NULL)
565 {
566 return false;
567 }
568
569 /* This checks for NaN and Infinity */
570 if (isnan(d) || isinf(d))
571 {
572 length = sprintf((char*)number_buffer, "null");
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 item->type = cJSON_Array;
1524 item->child = head;
1525
1526 input_buffer->offset++;
1527
1528 return true;
1529
1530 fail:
1531 if (head != NULL)
1532 {
1533 cJSON_Delete(head);
1534 }
1535
1536 return false;
1537 }
1538
1539 /* Render an array to text */
print_array(const cJSON * const item,printbuffer * const output_buffer)1540 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1541 {
1542 unsigned char *output_pointer = NULL;
1543 size_t length = 0;
1544 cJSON *current_element = item->child;
1545
1546 if (output_buffer == NULL)
1547 {
1548 return false;
1549 }
1550
1551 /* Compose the output array. */
1552 /* opening square bracket */
1553 output_pointer = ensure(output_buffer, 1);
1554 if (output_pointer == NULL)
1555 {
1556 return false;
1557 }
1558
1559 *output_pointer = '[';
1560 output_buffer->offset++;
1561 output_buffer->depth++;
1562
1563 while (current_element != NULL)
1564 {
1565 if (!print_value(current_element, output_buffer))
1566 {
1567 return false;
1568 }
1569 update_offset(output_buffer);
1570 if (current_element->next)
1571 {
1572 length = (size_t) (output_buffer->format ? 2 : 1);
1573 output_pointer = ensure(output_buffer, length + 1);
1574 if (output_pointer == NULL)
1575 {
1576 return false;
1577 }
1578 *output_pointer++ = ',';
1579 if(output_buffer->format)
1580 {
1581 *output_pointer++ = ' ';
1582 }
1583 *output_pointer = '\0';
1584 output_buffer->offset += length;
1585 }
1586 current_element = current_element->next;
1587 }
1588
1589 output_pointer = ensure(output_buffer, 2);
1590 if (output_pointer == NULL)
1591 {
1592 return false;
1593 }
1594 *output_pointer++ = ']';
1595 *output_pointer = '\0';
1596 output_buffer->depth--;
1597
1598 return true;
1599 }
1600
1601 /* Build an object from the text. */
parse_object(cJSON * const item,parse_buffer * const input_buffer)1602 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1603 {
1604 cJSON *head = NULL; /* linked list head */
1605 cJSON *current_item = NULL;
1606
1607 if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1608 {
1609 return false; /* to deeply nested */
1610 }
1611 input_buffer->depth++;
1612
1613 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1614 {
1615 goto fail; /* not an object */
1616 }
1617
1618 input_buffer->offset++;
1619 buffer_skip_whitespace(input_buffer);
1620 if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1621 {
1622 goto success; /* empty object */
1623 }
1624
1625 /* check if we skipped to the end of the buffer */
1626 if (cannot_access_at_index(input_buffer, 0))
1627 {
1628 input_buffer->offset--;
1629 goto fail;
1630 }
1631
1632 /* step back to character in front of the first element */
1633 input_buffer->offset--;
1634 /* loop through the comma separated array elements */
1635 do
1636 {
1637 /* allocate next item */
1638 cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1639 if (new_item == NULL)
1640 {
1641 goto fail; /* allocation failure */
1642 }
1643
1644 /* attach next item to list */
1645 if (head == NULL)
1646 {
1647 /* start the linked list */
1648 current_item = head = new_item;
1649 }
1650 else
1651 {
1652 /* add to the end and advance */
1653 current_item->next = new_item;
1654 new_item->prev = current_item;
1655 current_item = new_item;
1656 }
1657
1658 /* parse the name of the child */
1659 input_buffer->offset++;
1660 buffer_skip_whitespace(input_buffer);
1661 if (!parse_string(current_item, input_buffer))
1662 {
1663 goto fail; /* failed to parse name */
1664 }
1665 buffer_skip_whitespace(input_buffer);
1666
1667 /* swap valuestring and string, because we parsed the name */
1668 current_item->string = current_item->valuestring;
1669 current_item->valuestring = NULL;
1670
1671 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1672 {
1673 goto fail; /* invalid object */
1674 }
1675
1676 /* parse the value */
1677 input_buffer->offset++;
1678 buffer_skip_whitespace(input_buffer);
1679 if (!parse_value(current_item, input_buffer))
1680 {
1681 goto fail; /* failed to parse value */
1682 }
1683 buffer_skip_whitespace(input_buffer);
1684 }
1685 while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1686
1687 if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1688 {
1689 goto fail; /* expected end of object */
1690 }
1691
1692 success:
1693 input_buffer->depth--;
1694
1695 item->type = cJSON_Object;
1696 item->child = head;
1697
1698 input_buffer->offset++;
1699 return true;
1700
1701 fail:
1702 if (head != NULL)
1703 {
1704 cJSON_Delete(head);
1705 }
1706
1707 return false;
1708 }
1709
1710 /* Render an object to text. */
print_object(const cJSON * const item,printbuffer * const output_buffer)1711 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1712 {
1713 unsigned char *output_pointer = NULL;
1714 size_t length = 0;
1715 cJSON *current_item = item->child;
1716
1717 if (output_buffer == NULL)
1718 {
1719 return false;
1720 }
1721
1722 /* Compose the output: */
1723 length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1724 output_pointer = ensure(output_buffer, length + 1);
1725 if (output_pointer == NULL)
1726 {
1727 return false;
1728 }
1729
1730 *output_pointer++ = '{';
1731 output_buffer->depth++;
1732 if (output_buffer->format)
1733 {
1734 *output_pointer++ = '\n';
1735 }
1736 output_buffer->offset += length;
1737
1738 while (current_item)
1739 {
1740 if (output_buffer->format)
1741 {
1742 size_t i;
1743 output_pointer = ensure(output_buffer, output_buffer->depth);
1744 if (output_pointer == NULL)
1745 {
1746 return false;
1747 }
1748 for (i = 0; i < output_buffer->depth; i++)
1749 {
1750 *output_pointer++ = '\t';
1751 }
1752 output_buffer->offset += output_buffer->depth;
1753 }
1754
1755 /* print key */
1756 if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1757 {
1758 return false;
1759 }
1760 update_offset(output_buffer);
1761
1762 length = (size_t) (output_buffer->format ? 2 : 1);
1763 output_pointer = ensure(output_buffer, length);
1764 if (output_pointer == NULL)
1765 {
1766 return false;
1767 }
1768 *output_pointer++ = ':';
1769 if (output_buffer->format)
1770 {
1771 *output_pointer++ = '\t';
1772 }
1773 output_buffer->offset += length;
1774
1775 /* print value */
1776 if (!print_value(current_item, output_buffer))
1777 {
1778 return false;
1779 }
1780 update_offset(output_buffer);
1781
1782 /* print comma if not last */
1783 length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1784 output_pointer = ensure(output_buffer, length + 1);
1785 if (output_pointer == NULL)
1786 {
1787 return false;
1788 }
1789 if (current_item->next)
1790 {
1791 *output_pointer++ = ',';
1792 }
1793
1794 if (output_buffer->format)
1795 {
1796 *output_pointer++ = '\n';
1797 }
1798 *output_pointer = '\0';
1799 output_buffer->offset += length;
1800
1801 current_item = current_item->next;
1802 }
1803
1804 output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1805 if (output_pointer == NULL)
1806 {
1807 return false;
1808 }
1809 if (output_buffer->format)
1810 {
1811 size_t i;
1812 for (i = 0; i < (output_buffer->depth - 1); i++)
1813 {
1814 *output_pointer++ = '\t';
1815 }
1816 }
1817 *output_pointer++ = '}';
1818 *output_pointer = '\0';
1819 output_buffer->depth--;
1820
1821 return true;
1822 }
1823
1824 /* Get Array size/item / object item. */
cJSON_GetArraySize(const cJSON * array)1825 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1826 {
1827 cJSON *child = NULL;
1828 size_t size = 0;
1829
1830 if (array == NULL)
1831 {
1832 return 0;
1833 }
1834
1835 child = array->child;
1836
1837 while(child != NULL)
1838 {
1839 size++;
1840 child = child->next;
1841 }
1842
1843 /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1844
1845 return (int)size;
1846 }
1847
get_array_item(const cJSON * array,size_t index)1848 static cJSON* get_array_item(const cJSON *array, size_t index)
1849 {
1850 cJSON *current_child = NULL;
1851
1852 if (array == NULL)
1853 {
1854 return NULL;
1855 }
1856
1857 current_child = array->child;
1858 while ((current_child != NULL) && (index > 0))
1859 {
1860 index--;
1861 current_child = current_child->next;
1862 }
1863
1864 return current_child;
1865 }
1866
cJSON_GetArrayItem(const cJSON * array,int index)1867 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1868 {
1869 if (index < 0)
1870 {
1871 return NULL;
1872 }
1873
1874 return get_array_item(array, (size_t)index);
1875 }
1876
get_object_item(const cJSON * const object,const char * const name,const cJSON_bool case_sensitive)1877 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1878 {
1879 cJSON *current_element = NULL;
1880
1881 if ((object == NULL) || (name == NULL))
1882 {
1883 return NULL;
1884 }
1885
1886 current_element = object->child;
1887 if (case_sensitive)
1888 {
1889 while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1890 {
1891 current_element = current_element->next;
1892 }
1893 }
1894 else
1895 {
1896 while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1897 {
1898 current_element = current_element->next;
1899 }
1900 }
1901
1902 if ((current_element == NULL) || (current_element->string == NULL)) {
1903 return NULL;
1904 }
1905
1906 return current_element;
1907 }
1908
cJSON_GetObjectItem(const cJSON * const object,const char * const string)1909 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1910 {
1911 return get_object_item(object, string, false);
1912 }
1913
cJSON_GetObjectItemCaseSensitive(const cJSON * const object,const char * const string)1914 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1915 {
1916 return get_object_item(object, string, true);
1917 }
1918
cJSON_HasObjectItem(const cJSON * object,const char * string)1919 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1920 {
1921 return cJSON_GetObjectItem(object, string) ? 1 : 0;
1922 }
1923
1924 /* Utility for array list handling. */
suffix_object(cJSON * prev,cJSON * item)1925 static void suffix_object(cJSON *prev, cJSON *item)
1926 {
1927 prev->next = item;
1928 item->prev = prev;
1929 }
1930
1931 /* Utility for handling references. */
create_reference(const cJSON * item,const internal_hooks * const hooks)1932 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1933 {
1934 cJSON *reference = NULL;
1935 if (item == NULL)
1936 {
1937 return NULL;
1938 }
1939
1940 reference = cJSON_New_Item(hooks);
1941 if (reference == NULL)
1942 {
1943 return NULL;
1944 }
1945
1946 memcpy(reference, item, sizeof(cJSON));
1947 reference->string = NULL;
1948 reference->type |= cJSON_IsReference;
1949 reference->next = reference->prev = NULL;
1950 return reference;
1951 }
1952
add_item_to_array(cJSON * array,cJSON * item)1953 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1954 {
1955 cJSON *child = NULL;
1956
1957 if ((item == NULL) || (array == NULL) || (array == item))
1958 {
1959 return false;
1960 }
1961
1962 child = array->child;
1963 /*
1964 * To find the last item in array quickly, we use prev in array
1965 */
1966 if (child == NULL)
1967 {
1968 /* list is empty, start new one */
1969 array->child = item;
1970 item->prev = item;
1971 item->next = NULL;
1972 }
1973 else
1974 {
1975 /* append to the end */
1976 if (child->prev)
1977 {
1978 suffix_object(child->prev, item);
1979 array->child->prev = item;
1980 }
1981 else
1982 {
1983 while (child->next)
1984 {
1985 child = child->next;
1986 }
1987 suffix_object(child, item);
1988 array->child->prev = item;
1989 }
1990 }
1991
1992 return true;
1993 }
1994
1995 /* Add item to array/object. */
cJSON_AddItemToArray(cJSON * array,cJSON * item)1996 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1997 {
1998 return add_item_to_array(array, item);
1999 }
2000
2001 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2002 #pragma GCC diagnostic push
2003 #endif
2004 #ifdef __GNUC__
2005 #pragma GCC diagnostic ignored "-Wcast-qual"
2006 #endif
2007 /* helper function to cast away const */
cast_away_const(const void * string)2008 static void* cast_away_const(const void* string)
2009 {
2010 return (void*)string;
2011 }
2012 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2013 #pragma GCC diagnostic pop
2014 #endif
2015
2016
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 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)
2018 {
2019 char *new_key = NULL;
2020 int new_type = cJSON_Invalid;
2021
2022 if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2023 {
2024 return false;
2025 }
2026
2027 if (constant_key)
2028 {
2029 new_key = (char*)cast_away_const(string);
2030 new_type = item->type | cJSON_StringIsConst;
2031 }
2032 else
2033 {
2034 new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2035 if (new_key == NULL)
2036 {
2037 return false;
2038 }
2039
2040 new_type = item->type & ~cJSON_StringIsConst;
2041 }
2042
2043 if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2044 {
2045 hooks->deallocate(item->string);
2046 }
2047
2048 item->string = new_key;
2049 item->type = new_type;
2050
2051 return add_item_to_array(object, item);
2052 }
2053
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)2054 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2055 {
2056 return add_item_to_object(object, string, item, &global_hooks, false);
2057 }
2058
2059 /* Add an item to an object with constant string as key */
cJSON_AddItemToObjectCS(cJSON * object,const char * string,cJSON * item)2060 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2061 {
2062 return add_item_to_object(object, string, item, &global_hooks, true);
2063 }
2064
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)2065 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2066 {
2067 if (array == NULL)
2068 {
2069 return false;
2070 }
2071
2072 return add_item_to_array(array, create_reference(item, &global_hooks));
2073 }
2074
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)2075 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2076 {
2077 if ((object == NULL) || (string == NULL))
2078 {
2079 return false;
2080 }
2081
2082 return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2083 }
2084
cJSON_AddNullToObject(cJSON * const object,const char * const name)2085 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2086 {
2087 cJSON *null = cJSON_CreateNull();
2088 if (add_item_to_object(object, name, null, &global_hooks, false))
2089 {
2090 return null;
2091 }
2092
2093 cJSON_Delete(null);
2094 return NULL;
2095 }
2096
cJSON_AddTrueToObject(cJSON * const object,const char * const name)2097 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2098 {
2099 cJSON *true_item = cJSON_CreateTrue();
2100 if (add_item_to_object(object, name, true_item, &global_hooks, false))
2101 {
2102 return true_item;
2103 }
2104
2105 cJSON_Delete(true_item);
2106 return NULL;
2107 }
2108
cJSON_AddFalseToObject(cJSON * const object,const char * const name)2109 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2110 {
2111 cJSON *false_item = cJSON_CreateFalse();
2112 if (add_item_to_object(object, name, false_item, &global_hooks, false))
2113 {
2114 return false_item;
2115 }
2116
2117 cJSON_Delete(false_item);
2118 return NULL;
2119 }
2120
cJSON_AddBoolToObject(cJSON * const object,const char * const name,const cJSON_bool boolean)2121 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2122 {
2123 cJSON *bool_item = cJSON_CreateBool(boolean);
2124 if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2125 {
2126 return bool_item;
2127 }
2128
2129 cJSON_Delete(bool_item);
2130 return NULL;
2131 }
2132
cJSON_AddNumberToObject(cJSON * const object,const char * const name,const double number)2133 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2134 {
2135 cJSON *number_item = cJSON_CreateNumber(number);
2136 if (add_item_to_object(object, name, number_item, &global_hooks, false))
2137 {
2138 return number_item;
2139 }
2140
2141 cJSON_Delete(number_item);
2142 return NULL;
2143 }
2144
cJSON_AddStringToObject(cJSON * const object,const char * const name,const char * const string)2145 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2146 {
2147 cJSON *string_item = cJSON_CreateString(string);
2148 if (add_item_to_object(object, name, string_item, &global_hooks, false))
2149 {
2150 return string_item;
2151 }
2152
2153 cJSON_Delete(string_item);
2154 return NULL;
2155 }
2156
cJSON_AddRawToObject(cJSON * const object,const char * const name,const char * const raw)2157 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2158 {
2159 cJSON *raw_item = cJSON_CreateRaw(raw);
2160 if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2161 {
2162 return raw_item;
2163 }
2164
2165 cJSON_Delete(raw_item);
2166 return NULL;
2167 }
2168
cJSON_AddObjectToObject(cJSON * const object,const char * const name)2169 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2170 {
2171 cJSON *object_item = cJSON_CreateObject();
2172 if (add_item_to_object(object, name, object_item, &global_hooks, false))
2173 {
2174 return object_item;
2175 }
2176
2177 cJSON_Delete(object_item);
2178 return NULL;
2179 }
2180
cJSON_AddArrayToObject(cJSON * const object,const char * const name)2181 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2182 {
2183 cJSON *array = cJSON_CreateArray();
2184 if (add_item_to_object(object, name, array, &global_hooks, false))
2185 {
2186 return array;
2187 }
2188
2189 cJSON_Delete(array);
2190 return NULL;
2191 }
2192
cJSON_DetachItemViaPointer(cJSON * parent,cJSON * const item)2193 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2194 {
2195 if ((parent == NULL) || (item == NULL))
2196 {
2197 return NULL;
2198 }
2199
2200 if (item != parent->child)
2201 {
2202 /* not the first element */
2203 item->prev->next = item->next;
2204 }
2205 if (item->next != NULL)
2206 {
2207 /* not the last element */
2208 item->next->prev = item->prev;
2209 }
2210
2211 if (item == parent->child)
2212 {
2213 /* first element */
2214 parent->child = item->next;
2215 }
2216 /* make sure the detached item doesn't point anywhere anymore */
2217 item->prev = NULL;
2218 item->next = NULL;
2219
2220 return item;
2221 }
2222
cJSON_DetachItemFromArray(cJSON * array,int which)2223 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2224 {
2225 if (which < 0)
2226 {
2227 return NULL;
2228 }
2229
2230 return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2231 }
2232
cJSON_DeleteItemFromArray(cJSON * array,int which)2233 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2234 {
2235 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2236 }
2237
cJSON_DetachItemFromObject(cJSON * object,const char * string)2238 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2239 {
2240 cJSON *to_detach = cJSON_GetObjectItem(object, string);
2241
2242 return cJSON_DetachItemViaPointer(object, to_detach);
2243 }
2244
cJSON_DetachItemFromObjectCaseSensitive(cJSON * object,const char * string)2245 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2246 {
2247 cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2248
2249 return cJSON_DetachItemViaPointer(object, to_detach);
2250 }
2251
cJSON_DeleteItemFromObject(cJSON * object,const char * string)2252 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2253 {
2254 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2255 }
2256
cJSON_DeleteItemFromObjectCaseSensitive(cJSON * object,const char * string)2257 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2258 {
2259 cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2260 }
2261
2262 /* Replace array/object items with new ones. */
cJSON_InsertItemInArray(cJSON * array,int which,cJSON * newitem)2263 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2264 {
2265 cJSON *after_inserted = NULL;
2266
2267 if (which < 0)
2268 {
2269 return false;
2270 }
2271
2272 after_inserted = get_array_item(array, (size_t)which);
2273 if (after_inserted == NULL)
2274 {
2275 return add_item_to_array(array, newitem);
2276 }
2277
2278 newitem->next = after_inserted;
2279 newitem->prev = after_inserted->prev;
2280 after_inserted->prev = newitem;
2281 if (after_inserted == array->child)
2282 {
2283 array->child = newitem;
2284 }
2285 else
2286 {
2287 newitem->prev->next = newitem;
2288 }
2289 return true;
2290 }
2291
cJSON_ReplaceItemViaPointer(cJSON * const parent,cJSON * const item,cJSON * replacement)2292 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2293 {
2294 if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2295 {
2296 return false;
2297 }
2298
2299 if (replacement == item)
2300 {
2301 return true;
2302 }
2303
2304 replacement->next = item->next;
2305 replacement->prev = item->prev;
2306
2307 if (replacement->next != NULL)
2308 {
2309 replacement->next->prev = replacement;
2310 }
2311 if (parent->child == item)
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 }
2325
2326 item->next = NULL;
2327 item->prev = NULL;
2328 cJSON_Delete(item);
2329
2330 return true;
2331 }
2332
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)2333 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2334 {
2335 if (which < 0)
2336 {
2337 return false;
2338 }
2339
2340 return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2341 }
2342
replace_item_in_object(cJSON * object,const char * string,cJSON * replacement,cJSON_bool case_sensitive)2343 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2344 {
2345 if ((replacement == NULL) || (string == NULL))
2346 {
2347 return false;
2348 }
2349
2350 /* replace the name in the replacement */
2351 if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2352 {
2353 cJSON_free(replacement->string);
2354 }
2355 replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2356 replacement->type &= ~cJSON_StringIsConst;
2357
2358 return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2359 }
2360
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)2361 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2362 {
2363 return replace_item_in_object(object, string, newitem, false);
2364 }
2365
cJSON_ReplaceItemInObjectCaseSensitive(cJSON * object,const char * string,cJSON * newitem)2366 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2367 {
2368 return replace_item_in_object(object, string, newitem, true);
2369 }
2370
2371 /* Create basic types: */
cJSON_CreateNull(void)2372 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2373 {
2374 cJSON *item = cJSON_New_Item(&global_hooks);
2375 if(item)
2376 {
2377 item->type = cJSON_NULL;
2378 }
2379
2380 return item;
2381 }
2382
cJSON_CreateTrue(void)2383 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2384 {
2385 cJSON *item = cJSON_New_Item(&global_hooks);
2386 if(item)
2387 {
2388 item->type = cJSON_True;
2389 }
2390
2391 return item;
2392 }
2393
cJSON_CreateFalse(void)2394 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2395 {
2396 cJSON *item = cJSON_New_Item(&global_hooks);
2397 if(item)
2398 {
2399 item->type = cJSON_False;
2400 }
2401
2402 return item;
2403 }
2404
cJSON_CreateBool(cJSON_bool boolean)2405 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2406 {
2407 cJSON *item = cJSON_New_Item(&global_hooks);
2408 if(item)
2409 {
2410 item->type = boolean ? cJSON_True : cJSON_False;
2411 }
2412
2413 return item;
2414 }
2415
cJSON_CreateNumber(double num)2416 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2417 {
2418 cJSON *item = cJSON_New_Item(&global_hooks);
2419 if(item)
2420 {
2421 item->type = cJSON_Number;
2422 item->valuedouble = num;
2423
2424 /* use saturation in case of overflow */
2425 if (num >= LLONG_MAX)
2426 {
2427 item->valueint = LLONG_MAX;
2428 }
2429 else if (num <= (double)LLONG_MIN)
2430 {
2431 item->valueint = LLONG_MIN;
2432 }
2433 else
2434 {
2435 item->valueint = (int64_t)num;
2436 }
2437 }
2438
2439 return item;
2440 }
2441
cJSON_CreateString(const char * string)2442 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2443 {
2444 cJSON *item = cJSON_New_Item(&global_hooks);
2445 if(item)
2446 {
2447 item->type = cJSON_String;
2448 item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2449 if(!item->valuestring)
2450 {
2451 cJSON_Delete(item);
2452 return NULL;
2453 }
2454 }
2455
2456 return item;
2457 }
2458
cJSON_CreateStringReference(const char * string)2459 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2460 {
2461 cJSON *item = cJSON_New_Item(&global_hooks);
2462 if (item != NULL)
2463 {
2464 item->type = cJSON_String | cJSON_IsReference;
2465 item->valuestring = (char*)cast_away_const(string);
2466 }
2467
2468 return item;
2469 }
2470
cJSON_CreateObjectReference(const cJSON * child)2471 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2472 {
2473 cJSON *item = cJSON_New_Item(&global_hooks);
2474 if (item != NULL) {
2475 item->type = cJSON_Object | cJSON_IsReference;
2476 item->child = (cJSON*)cast_away_const(child);
2477 }
2478
2479 return item;
2480 }
2481
cJSON_CreateArrayReference(const cJSON * child)2482 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2483 cJSON *item = cJSON_New_Item(&global_hooks);
2484 if (item != NULL) {
2485 item->type = cJSON_Array | cJSON_IsReference;
2486 item->child = (cJSON*)cast_away_const(child);
2487 }
2488
2489 return item;
2490 }
2491
cJSON_CreateRaw(const char * raw)2492 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2493 {
2494 cJSON *item = cJSON_New_Item(&global_hooks);
2495 if(item)
2496 {
2497 item->type = cJSON_Raw;
2498 item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2499 if(!item->valuestring)
2500 {
2501 cJSON_Delete(item);
2502 return NULL;
2503 }
2504 }
2505
2506 return item;
2507 }
2508
cJSON_CreateArray(void)2509 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2510 {
2511 cJSON *item = cJSON_New_Item(&global_hooks);
2512 if(item)
2513 {
2514 item->type=cJSON_Array;
2515 }
2516
2517 return item;
2518 }
2519
cJSON_CreateObject(void)2520 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2521 {
2522 cJSON *item = cJSON_New_Item(&global_hooks);
2523 if (item)
2524 {
2525 item->type = cJSON_Object;
2526 }
2527
2528 return item;
2529 }
2530
2531 /* Create Arrays: */
cJSON_CreateIntArray(const int * numbers,int count)2532 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2533 {
2534 size_t i = 0;
2535 cJSON *n = NULL;
2536 cJSON *p = NULL;
2537 cJSON *a = NULL;
2538
2539 if ((count < 0) || (numbers == NULL))
2540 {
2541 return NULL;
2542 }
2543
2544 a = cJSON_CreateArray();
2545 for(i = 0; a && (i < (size_t)count); i++)
2546 {
2547 n = cJSON_CreateNumber(numbers[i]);
2548 if (!n)
2549 {
2550 cJSON_Delete(a);
2551 return NULL;
2552 }
2553 if(!i)
2554 {
2555 a->child = n;
2556 }
2557 else
2558 {
2559 suffix_object(p, n);
2560 }
2561 p = n;
2562 }
2563
2564 return a;
2565 }
2566
cJSON_CreateFloatArray(const float * numbers,int count)2567 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2568 {
2569 size_t i = 0;
2570 cJSON *n = NULL;
2571 cJSON *p = NULL;
2572 cJSON *a = NULL;
2573
2574 if ((count < 0) || (numbers == NULL))
2575 {
2576 return NULL;
2577 }
2578
2579 a = cJSON_CreateArray();
2580
2581 for(i = 0; a && (i < (size_t)count); i++)
2582 {
2583 n = cJSON_CreateNumber((double)numbers[i]);
2584 if(!n)
2585 {
2586 cJSON_Delete(a);
2587 return NULL;
2588 }
2589 if(!i)
2590 {
2591 a->child = n;
2592 }
2593 else
2594 {
2595 suffix_object(p, n);
2596 }
2597 p = n;
2598 }
2599
2600 return a;
2601 }
2602
cJSON_CreateDoubleArray(const double * numbers,int count)2603 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2604 {
2605 size_t i = 0;
2606 cJSON *n = NULL;
2607 cJSON *p = NULL;
2608 cJSON *a = NULL;
2609
2610 if ((count < 0) || (numbers == NULL))
2611 {
2612 return NULL;
2613 }
2614
2615 a = cJSON_CreateArray();
2616
2617 for(i = 0;a && (i < (size_t)count); i++)
2618 {
2619 n = cJSON_CreateNumber(numbers[i]);
2620 if(!n)
2621 {
2622 cJSON_Delete(a);
2623 return NULL;
2624 }
2625 if(!i)
2626 {
2627 a->child = n;
2628 }
2629 else
2630 {
2631 suffix_object(p, n);
2632 }
2633 p = n;
2634 }
2635
2636 return a;
2637 }
2638
cJSON_CreateStringArray(const char * const * strings,int count)2639 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2640 {
2641 size_t i = 0;
2642 cJSON *n = NULL;
2643 cJSON *p = NULL;
2644 cJSON *a = NULL;
2645
2646 if ((count < 0) || (strings == NULL))
2647 {
2648 return NULL;
2649 }
2650
2651 a = cJSON_CreateArray();
2652
2653 for (i = 0; a && (i < (size_t)count); i++)
2654 {
2655 n = cJSON_CreateString(strings[i]);
2656 if(!n)
2657 {
2658 cJSON_Delete(a);
2659 return NULL;
2660 }
2661 if(!i)
2662 {
2663 a->child = n;
2664 }
2665 else
2666 {
2667 suffix_object(p,n);
2668 }
2669 p = n;
2670 }
2671
2672 return a;
2673 }
2674
2675 /* Duplication */
cJSON_Duplicate(const cJSON * item,cJSON_bool recurse)2676 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2677 {
2678 cJSON *newitem = NULL;
2679 cJSON *child = NULL;
2680 cJSON *next = NULL;
2681 cJSON *newchild = NULL;
2682
2683 /* Bail on bad ptr */
2684 if (!item)
2685 {
2686 goto fail;
2687 }
2688 /* Create new item */
2689 newitem = cJSON_New_Item(&global_hooks);
2690 if (!newitem)
2691 {
2692 goto fail;
2693 }
2694 /* Copy over all vars */
2695 newitem->type = item->type & (~cJSON_IsReference);
2696 newitem->valueint = item->valueint;
2697 newitem->valuedouble = item->valuedouble;
2698 if (item->valuestring)
2699 {
2700 newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2701 if (!newitem->valuestring)
2702 {
2703 goto fail;
2704 }
2705 }
2706 if (item->string)
2707 {
2708 newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2709 if (!newitem->string)
2710 {
2711 goto fail;
2712 }
2713 }
2714 /* If non-recursive, then we're done! */
2715 if (!recurse)
2716 {
2717 return newitem;
2718 }
2719 /* Walk the ->next chain for the child. */
2720 child = item->child;
2721 while (child != NULL)
2722 {
2723 newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2724 if (!newchild)
2725 {
2726 goto fail;
2727 }
2728 if (next != NULL)
2729 {
2730 /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2731 next->next = newchild;
2732 newchild->prev = next;
2733 next = newchild;
2734 }
2735 else
2736 {
2737 /* Set newitem->child and move to it */
2738 newitem->child = newchild;
2739 next = newchild;
2740 }
2741 child = child->next;
2742 }
2743
2744 return newitem;
2745
2746 fail:
2747 if (newitem != NULL)
2748 {
2749 cJSON_Delete(newitem);
2750 }
2751
2752 return NULL;
2753 }
2754
skip_oneline_comment(char ** input)2755 static void skip_oneline_comment(char **input)
2756 {
2757 *input += static_strlen("//");
2758
2759 for (; (*input)[0] != '\0'; ++(*input))
2760 {
2761 if ((*input)[0] == '\n') {
2762 *input += static_strlen("\n");
2763 return;
2764 }
2765 }
2766 }
2767
skip_multiline_comment(char ** input)2768 static void skip_multiline_comment(char **input)
2769 {
2770 *input += static_strlen("/*");
2771
2772 for (; (*input)[0] != '\0'; ++(*input))
2773 {
2774 if (((*input)[0] == '*') && ((*input)[1] == '/'))
2775 {
2776 *input += static_strlen("*/");
2777 return;
2778 }
2779 }
2780 }
2781
minify_string(char ** input,char ** output)2782 static void minify_string(char **input, char **output) {
2783 (*output)[0] = (*input)[0];
2784 *input += static_strlen("\"");
2785 *output += static_strlen("\"");
2786
2787
2788 for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2789 (*output)[0] = (*input)[0];
2790
2791 if ((*input)[0] == '\"') {
2792 (*output)[0] = '\"';
2793 *input += static_strlen("\"");
2794 *output += static_strlen("\"");
2795 return;
2796 } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2797 (*output)[1] = (*input)[1];
2798 *input += static_strlen("\"");
2799 *output += static_strlen("\"");
2800 }
2801 }
2802 }
2803
cJSON_Minify(char * json)2804 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2805 {
2806 char *into = json;
2807
2808 if (json == NULL)
2809 {
2810 return;
2811 }
2812
2813 while (json[0] != '\0')
2814 {
2815 switch (json[0])
2816 {
2817 case ' ':
2818 case '\t':
2819 case '\r':
2820 case '\n':
2821 json++;
2822 break;
2823
2824 case '/':
2825 if (json[1] == '/')
2826 {
2827 skip_oneline_comment(&json);
2828 }
2829 else if (json[1] == '*')
2830 {
2831 skip_multiline_comment(&json);
2832 } else {
2833 json++;
2834 }
2835 break;
2836
2837 case '\"':
2838 minify_string(&json, (char**)&into);
2839 break;
2840
2841 default:
2842 into[0] = json[0];
2843 json++;
2844 into++;
2845 }
2846 }
2847
2848 /* and null-terminate. */
2849 *into = '\0';
2850 }
2851
cJSON_IsInvalid(const cJSON * const item)2852 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2853 {
2854 if (item == NULL)
2855 {
2856 return false;
2857 }
2858
2859 return (item->type & 0xFF) == cJSON_Invalid;
2860 }
2861
cJSON_IsFalse(const cJSON * const item)2862 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2863 {
2864 if (item == NULL)
2865 {
2866 return false;
2867 }
2868
2869 return (item->type & 0xFF) == cJSON_False;
2870 }
2871
cJSON_IsTrue(const cJSON * const item)2872 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2873 {
2874 if (item == NULL)
2875 {
2876 return false;
2877 }
2878
2879 return (item->type & 0xff) == cJSON_True;
2880 }
2881
2882
cJSON_IsBool(const cJSON * const item)2883 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2884 {
2885 if (item == NULL)
2886 {
2887 return false;
2888 }
2889
2890 return (item->type & (cJSON_True | cJSON_False)) != 0;
2891 }
cJSON_IsNull(const cJSON * const item)2892 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2893 {
2894 if (item == NULL)
2895 {
2896 return false;
2897 }
2898
2899 return (item->type & 0xFF) == cJSON_NULL;
2900 }
2901
cJSON_IsNumber(const cJSON * const item)2902 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2903 {
2904 if (item == NULL)
2905 {
2906 return false;
2907 }
2908
2909 return (item->type & 0xFF) == cJSON_Number;
2910 }
2911
cJSON_IsString(const cJSON * const item)2912 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2913 {
2914 if (item == NULL)
2915 {
2916 return false;
2917 }
2918
2919 return (item->type & 0xFF) == cJSON_String;
2920 }
2921
cJSON_IsArray(const cJSON * const item)2922 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2923 {
2924 if (item == NULL)
2925 {
2926 return false;
2927 }
2928
2929 return (item->type & 0xFF) == cJSON_Array;
2930 }
2931
cJSON_IsObject(const cJSON * const item)2932 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2933 {
2934 if (item == NULL)
2935 {
2936 return false;
2937 }
2938
2939 return (item->type & 0xFF) == cJSON_Object;
2940 }
2941
cJSON_IsRaw(const cJSON * const item)2942 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2943 {
2944 if (item == NULL)
2945 {
2946 return false;
2947 }
2948
2949 return (item->type & 0xFF) == cJSON_Raw;
2950 }
2951
cJSON_Compare(const cJSON * const a,const cJSON * const b,const cJSON_bool case_sensitive)2952 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2953 {
2954 if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2955 {
2956 return false;
2957 }
2958
2959 /* check if type is valid */
2960 switch (a->type & 0xFF)
2961 {
2962 case cJSON_False:
2963 case cJSON_True:
2964 case cJSON_NULL:
2965 case cJSON_Number:
2966 case cJSON_String:
2967 case cJSON_Raw:
2968 case cJSON_Array:
2969 case cJSON_Object:
2970 break;
2971
2972 default:
2973 return false;
2974 }
2975
2976 /* identical objects are equal */
2977 if (a == b)
2978 {
2979 return true;
2980 }
2981
2982 switch (a->type & 0xFF)
2983 {
2984 /* in these cases and equal type is enough */
2985 case cJSON_False:
2986 case cJSON_True:
2987 case cJSON_NULL:
2988 return true;
2989
2990 case cJSON_Number:
2991 if (compare_double(a->valuedouble, b->valuedouble))
2992 {
2993 return true;
2994 }
2995 return false;
2996
2997 case cJSON_String:
2998 case cJSON_Raw:
2999 if ((a->valuestring == NULL) || (b->valuestring == NULL))
3000 {
3001 return false;
3002 }
3003 if (strcmp(a->valuestring, b->valuestring) == 0)
3004 {
3005 return true;
3006 }
3007
3008 return false;
3009
3010 case cJSON_Array:
3011 {
3012 cJSON *a_element = a->child;
3013 cJSON *b_element = b->child;
3014
3015 for (; (a_element != NULL) && (b_element != NULL);)
3016 {
3017 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3018 {
3019 return false;
3020 }
3021
3022 a_element = a_element->next;
3023 b_element = b_element->next;
3024 }
3025
3026 /* one of the arrays is longer than the other */
3027 if (a_element != b_element) {
3028 return false;
3029 }
3030
3031 return true;
3032 }
3033
3034 case cJSON_Object:
3035 {
3036 cJSON *a_element = NULL;
3037 cJSON *b_element = NULL;
3038 cJSON_ArrayForEach(a_element, a)
3039 {
3040 /* TODO This has O(n^2) runtime, which is horrible! */
3041 b_element = get_object_item(b, a_element->string, case_sensitive);
3042 if (b_element == NULL)
3043 {
3044 return false;
3045 }
3046
3047 if (!cJSON_Compare(a_element, b_element, case_sensitive))
3048 {
3049 return false;
3050 }
3051 }
3052
3053 /* doing this twice, once on a and b to prevent true comparison if a subset of b
3054 * TODO: Do this the proper way, this is just a fix for now */
3055 cJSON_ArrayForEach(b_element, b)
3056 {
3057 a_element = get_object_item(a, b_element->string, case_sensitive);
3058 if (a_element == NULL)
3059 {
3060 return false;
3061 }
3062
3063 if (!cJSON_Compare(b_element, a_element, case_sensitive))
3064 {
3065 return false;
3066 }
3067 }
3068
3069 return true;
3070 }
3071
3072 default:
3073 return false;
3074 }
3075 }
3076
cJSON_malloc(size_t size)3077 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3078 {
3079 return global_hooks.allocate(size);
3080 }
3081
cJSON_free(void * object)3082 CJSON_PUBLIC(void) cJSON_free(void *object)
3083 {
3084 global_hooks.deallocate(object);
3085 }
3086