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