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


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:48