- Main
- Tutorials
- Library
- Samples

- File List
- Globals

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