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