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