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