blob: 0978660324bba7e77e46b2739a944e9b488a4b6c [file] [log] [blame]
Jon Ashburn752e06e2015-06-29 11:25:34 -06001/*
2 Copyright (c) 2009 Dave Gamble
Jon Ashburn1c75aec2016-02-02 17:47:28 -07003 Copyright (c) 2015-2016 The Khronos Group Inc.
4 Copyright (c) 2015-2016 Valve Corporation
5 Copyright (c) 2015-2016 LunarG, Inc.
Jon Ashburn752e06e2015-06-29 11:25:34 -06006
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 THE SOFTWARE.
24*/
25
26/* cJSON */
27/* JSON parser in C. */
28
29#include <string.h>
30#include <stdio.h>
31#include <math.h>
32#include <stdlib.h>
33#include <float.h>
34#include <limits.h>
35#include <ctype.h>
36#include "cJSON.h"
37
38static const char *ep;
39
Jon Ashburn1c75aec2016-02-02 17:47:28 -070040const char *cJSON_GetErrorPtr(void) { return ep; }
Jon Ashburn752e06e2015-06-29 11:25:34 -060041
Jon Ashburn752e06e2015-06-29 11:25:34 -060042static void *(*cJSON_malloc)(size_t sz) = malloc;
43static void (*cJSON_free)(void *ptr) = free;
44
Jon Ashburn1c75aec2016-02-02 17:47:28 -070045static char *cJSON_strdup(const char *str) {
46 size_t len;
47 char *copy;
Jon Ashburn752e06e2015-06-29 11:25:34 -060048
Jon Ashburn1c75aec2016-02-02 17:47:28 -070049 len = strlen(str) + 1;
50 if (!(copy = (char *)cJSON_malloc(len)))
51 return 0;
52 memcpy(copy, str, len);
53 return copy;
Jon Ashburn752e06e2015-06-29 11:25:34 -060054}
55
Jon Ashburn1c75aec2016-02-02 17:47:28 -070056void cJSON_InitHooks(cJSON_Hooks *hooks) {
Jon Ashburn752e06e2015-06-29 11:25:34 -060057 if (!hooks) { /* Reset hooks */
58 cJSON_malloc = malloc;
59 cJSON_free = free;
60 return;
61 }
62
Jon Ashburn1c75aec2016-02-02 17:47:28 -070063 cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
64 cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
Jon Ashburn752e06e2015-06-29 11:25:34 -060065}
66
67/* Internal constructor. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -070068static cJSON *cJSON_New_Item(void) {
69 cJSON *node = (cJSON *)cJSON_malloc(sizeof(cJSON));
70 if (node)
71 memset(node, 0, sizeof(cJSON));
72 return node;
Jon Ashburn752e06e2015-06-29 11:25:34 -060073}
74
75/* Delete a cJSON structure. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -070076void cJSON_Delete(cJSON *c) {
77 cJSON *next;
78 while (c) {
79 next = c->next;
80 if (!(c->type & cJSON_IsReference) && c->child)
81 cJSON_Delete(c->child);
82 if (!(c->type & cJSON_IsReference) && c->valuestring)
83 cJSON_free(c->valuestring);
84 if (!(c->type & cJSON_StringIsConst) && c->string)
85 cJSON_free(c->string);
86 cJSON_free(c);
87 c = next;
88 }
Jon Ashburn752e06e2015-06-29 11:25:34 -060089}
90
Jon Ashburn1c75aec2016-02-02 17:47:28 -070091/* Parse the input text to generate a number, and populate the result into item.
92 */
93static const char *parse_number(cJSON *item, const char *num) {
94 double n = 0, sign = 1, scale = 0;
95 int subscale = 0, signsubscale = 1;
Jon Ashburn752e06e2015-06-29 11:25:34 -060096
Jon Ashburn1c75aec2016-02-02 17:47:28 -070097 if (*num == '-')
98 sign = -1, num++; /* Has sign? */
99 if (*num == '0')
100 num++; /* is zero */
101 if (*num >= '1' && *num <= '9')
102 do
103 n = (n * 10.0) + (*num++ - '0');
104 while (*num >= '0' && *num <= '9'); /* Number? */
105 if (*num == '.' && num[1] >= '0' && num[1] <= '9') {
106 num++;
107 do
108 n = (n * 10.0) + (*num++ - '0'), scale--;
109 while (*num >= '0' && *num <= '9');
110 } /* Fractional part? */
111 if (*num == 'e' || *num == 'E') /* Exponent? */
112 {
113 num++;
114 if (*num == '+')
115 num++;
116 else if (*num == '-')
117 signsubscale = -1, num++; /* With sign? */
118 while (*num >= '0' && *num <= '9')
119 subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
120 }
Jon Ashburn752e06e2015-06-29 11:25:34 -0600121
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700122 n = sign * n *
123 pow(10.0, (scale + subscale * signsubscale)); /* number = +/-
124 number.fraction *
125 10^+/- exponent */
126
127 item->valuedouble = n;
128 item->valueint = (int)n;
129 item->type = cJSON_Number;
130 return num;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600131}
132
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700133static size_t pow2gt(size_t x) {
134 --x;
135 x |= x >> 1;
136 x |= x >> 2;
137 x |= x >> 4;
138 x |= x >> 8;
139 x |= x >> 16;
140 return x + 1;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600141}
142
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700143typedef struct {
144 char *buffer;
145 size_t length;
146 size_t offset;
147} printbuffer;
148
149static char *ensure(printbuffer *p, size_t needed) {
150 char *newbuffer;
151 size_t newsize;
152 if (!p || !p->buffer)
153 return 0;
154 needed += p->offset;
155 if (needed <= p->length)
156 return p->buffer + p->offset;
157
158 newsize = pow2gt(needed);
159 newbuffer = (char *)cJSON_malloc(newsize);
160 if (!newbuffer) {
161 cJSON_free(p->buffer);
162 p->length = 0, p->buffer = 0;
163 return 0;
164 }
165 if (newbuffer)
166 memcpy(newbuffer, p->buffer, p->length);
167 cJSON_free(p->buffer);
168 p->length = newsize;
169 p->buffer = newbuffer;
170 return newbuffer + p->offset;
171}
172
173static size_t update(printbuffer *p) {
174 char *str;
175 if (!p || !p->buffer)
176 return 0;
177 str = p->buffer + p->offset;
178 return p->offset + strlen(str);
Jon Ashburn752e06e2015-06-29 11:25:34 -0600179}
180
181/* Render the number nicely from the given item into a string. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700182static char *print_number(cJSON *item, printbuffer *p) {
183 char *str = 0;
184 double d = item->valuedouble;
185 if (d == 0) {
186 if (p)
187 str = ensure(p, 2);
188 else
189 str = (char *)cJSON_malloc(2); /* special case for 0. */
190 if (str)
191 strcpy(str, "0");
192 } else if (fabs(((double)item->valueint) - d) <= DBL_EPSILON &&
193 d <= INT_MAX && d >= INT_MIN) {
194 if (p)
195 str = ensure(p, 21);
196 else
197 str = (char *)cJSON_malloc(
198 21); /* 2^64+1 can be represented in 21 chars. */
199 if (str)
200 sprintf(str, "%d", item->valueint);
201 } else {
202 if (p)
203 str = ensure(p, 64);
204 else
205 str = (char *)cJSON_malloc(64); /* This is a nice tradeoff. */
206 if (str) {
207 if (fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60)
208 sprintf(str, "%.0f", d);
209 else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)
210 sprintf(str, "%e", d);
211 else
212 sprintf(str, "%f", d);
213 }
214 }
215 return str;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600216}
217
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700218static unsigned parse_hex4(const char *str) {
219 unsigned h = 0;
220 if (*str >= '0' && *str <= '9')
221 h += (*str) - '0';
222 else if (*str >= 'A' && *str <= 'F')
223 h += 10 + (*str) - 'A';
224 else if (*str >= 'a' && *str <= 'f')
225 h += 10 + (*str) - 'a';
226 else
227 return 0;
228 h = h << 4;
229 str++;
230 if (*str >= '0' && *str <= '9')
231 h += (*str) - '0';
232 else if (*str >= 'A' && *str <= 'F')
233 h += 10 + (*str) - 'A';
234 else if (*str >= 'a' && *str <= 'f')
235 h += 10 + (*str) - 'a';
236 else
237 return 0;
238 h = h << 4;
239 str++;
240 if (*str >= '0' && *str <= '9')
241 h += (*str) - '0';
242 else if (*str >= 'A' && *str <= 'F')
243 h += 10 + (*str) - 'A';
244 else if (*str >= 'a' && *str <= 'f')
245 h += 10 + (*str) - 'a';
246 else
247 return 0;
248 h = h << 4;
249 str++;
250 if (*str >= '0' && *str <= '9')
251 h += (*str) - '0';
252 else if (*str >= 'A' && *str <= 'F')
253 h += 10 + (*str) - 'A';
254 else if (*str >= 'a' && *str <= 'f')
255 h += 10 + (*str) - 'a';
256 else
257 return 0;
258 return h;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600259}
260
261/* Parse the input text into an unescaped cstring, and populate item. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700262static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0,
263 0xF0, 0xF8, 0xFC};
264static const char *parse_string(cJSON *item, const char *str) {
265 const char *ptr = str + 1;
266 char *ptr2;
267 char *out;
268 int len = 0;
269 unsigned uc, uc2;
270 if (*str != '\"') {
271 ep = str;
272 return 0;
273 } /* not a string! */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600274
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700275 while (*ptr != '\"' && *ptr && ++len)
276 if (*ptr++ == '\\')
277 ptr++; /* Skip escaped quotes. */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600278
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700279 out = (char *)cJSON_malloc(
280 len + 1); /* This is how long we need for the string, roughly. */
281 if (!out)
282 return 0;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600283
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700284 ptr = str + 1;
285 ptr2 = out;
286 while (*ptr != '\"' && *ptr) {
287 if (*ptr != '\\')
288 *ptr2++ = *ptr++;
289 else {
290 ptr++;
291 switch (*ptr) {
292 case 'b':
293 *ptr2++ = '\b';
294 break;
295 case 'f':
296 *ptr2++ = '\f';
297 break;
298 case 'n':
299 *ptr2++ = '\n';
300 break;
301 case 'r':
302 *ptr2++ = '\r';
303 break;
304 case 't':
305 *ptr2++ = '\t';
306 break;
307 case 'u': /* transcode utf16 to utf8. */
308 uc = parse_hex4(ptr + 1);
309 ptr += 4; /* get the unicode char. */
310
311 if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0)
312 break; /* check for invalid. */
313
314 if (uc >= 0xD800 &&
315 uc <= 0xDBFF) /* UTF16 surrogate pairs. */
316 {
317 if (ptr[1] != '\\' || ptr[2] != 'u')
318 break; /* missing second-half of surrogate. */
319 uc2 = parse_hex4(ptr + 3);
320 ptr += 6;
321 if (uc2 < 0xDC00 || uc2 > 0xDFFF)
322 break; /* invalid second-half of surrogate. */
323 uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
324 }
325
326 len = 4;
327 if (uc < 0x80)
328 len = 1;
329 else if (uc < 0x800)
330 len = 2;
331 else if (uc < 0x10000)
332 len = 3;
333 ptr2 += len;
334
335 switch (len) {
336 case 4:
337 *--ptr2 = ((uc | 0x80) & 0xBF);
338 uc >>= 6;
339 case 3:
340 *--ptr2 = ((uc | 0x80) & 0xBF);
341 uc >>= 6;
342 case 2:
343 *--ptr2 = ((uc | 0x80) & 0xBF);
344 uc >>= 6;
345 case 1:
346 *--ptr2 = (uc | firstByteMark[len]);
347 }
348 ptr2 += len;
349 break;
350 default:
351 *ptr2++ = *ptr;
352 break;
353 }
354 ptr++;
355 }
356 }
357 *ptr2 = 0;
358 if (*ptr == '\"')
359 ptr++;
360 item->valuestring = out;
361 item->type = cJSON_String;
362 return ptr;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600363}
364
365/* Render the cstring provided to an escaped version that can be printed. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700366static char *print_string_ptr(const char *str, printbuffer *p) {
367 const char *ptr;
368 char *ptr2;
369 char *out;
370 size_t len = 0, flag = 0;
371 unsigned char token;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600372
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700373 for (ptr = str; *ptr; ptr++)
374 flag |= ((*ptr > 0 && *ptr < 32) || (*ptr == '\"') || (*ptr == '\\'))
375 ? 1
376 : 0;
377 if (!flag) {
378 len = ptr - str;
379 if (p)
380 out = ensure(p, len + 3);
381 else
382 out = (char *)cJSON_malloc(len + 3);
383 if (!out)
384 return 0;
385 ptr2 = out;
386 *ptr2++ = '\"';
387 strcpy(ptr2, str);
388 ptr2[len] = '\"';
389 ptr2[len + 1] = 0;
390 return out;
391 }
392
393 if (!str) {
394 if (p)
395 out = ensure(p, 3);
396 else
397 out = (char *)cJSON_malloc(3);
398 if (!out)
399 return 0;
400 strcpy(out, "\"\"");
401 return out;
402 }
403 ptr = str;
404 while ((token = *ptr) && ++len) {
405 if (strchr("\"\\\b\f\n\r\t", token))
406 len++;
407 else if (token < 32)
408 len += 5;
409 ptr++;
410 }
411
412 if (p)
413 out = ensure(p, len + 3);
414 else
415 out = (char *)cJSON_malloc(len + 3);
416 if (!out)
417 return 0;
418
419 ptr2 = out;
420 ptr = str;
421 *ptr2++ = '\"';
422 while (*ptr) {
423 if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
424 *ptr2++ = *ptr++;
425 else {
426 *ptr2++ = '\\';
427 switch (token = *ptr++) {
428 case '\\':
429 *ptr2++ = '\\';
430 break;
431 case '\"':
432 *ptr2++ = '\"';
433 break;
434 case '\b':
435 *ptr2++ = 'b';
436 break;
437 case '\f':
438 *ptr2++ = 'f';
439 break;
440 case '\n':
441 *ptr2++ = 'n';
442 break;
443 case '\r':
444 *ptr2++ = 'r';
445 break;
446 case '\t':
447 *ptr2++ = 't';
448 break;
449 default:
450 sprintf(ptr2, "u%04x", token);
451 ptr2 += 5;
452 break; /* escape and print */
453 }
454 }
455 }
456 *ptr2++ = '\"';
457 *ptr2++ = 0;
458 return out;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600459}
460/* Invote print_string_ptr (which is useful) on an item. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700461static char *print_string(cJSON *item, printbuffer *p) {
462 return print_string_ptr(item->valuestring, p);
463}
Jon Ashburn752e06e2015-06-29 11:25:34 -0600464
465/* Predeclare these prototypes. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700466static const char *parse_value(cJSON *item, const char *value);
467static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p);
468static const char *parse_array(cJSON *item, const char *value);
469static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p);
470static const char *parse_object(cJSON *item, const char *value);
471static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p);
Jon Ashburn752e06e2015-06-29 11:25:34 -0600472
473/* Utility to jump whitespace and cr/lf */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700474static const char *skip(const char *in) {
475 while (in && *in && (unsigned char)*in <= 32)
476 in++;
477 return in;
478}
Jon Ashburn752e06e2015-06-29 11:25:34 -0600479
480/* Parse an object - create a new root, and populate. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700481cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
482 int require_null_terminated) {
483 const char *end = 0;
484 cJSON *c = cJSON_New_Item();
485 ep = 0;
486 if (!c)
487 return 0; /* memory fail */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600488
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700489 end = parse_value(c, skip(value));
490 if (!end) {
491 cJSON_Delete(c);
492 return 0;
493 } /* parse failure. ep is set. */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600494
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700495 /* if we require null-terminated JSON without appended garbage, skip and
496 * then check for a null terminator */
497 if (require_null_terminated) {
498 end = skip(end);
499 if (*end) {
500 cJSON_Delete(c);
501 ep = end;
502 return 0;
503 }
504 }
505 if (return_parse_end)
506 *return_parse_end = end;
507 return c;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600508}
509/* Default options for cJSON_Parse */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700510cJSON *cJSON_Parse(const char *value) {
511 return cJSON_ParseWithOpts(value, 0, 0);
Jon Ashburn752e06e2015-06-29 11:25:34 -0600512}
513
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700514/* Render a cJSON item/entity/structure to text. */
515char *cJSON_Print(cJSON *item) { return print_value(item, 0, 1, 0); }
516char *cJSON_PrintUnformatted(cJSON *item) { return print_value(item, 0, 0, 0); }
517
518char *cJSON_PrintBuffered(cJSON *item, int prebuffer, int fmt) {
519 printbuffer p;
520 p.buffer = (char *)cJSON_malloc(prebuffer);
521 p.length = prebuffer;
522 p.offset = 0;
523 return print_value(item, 0, fmt, &p);
524 return p.buffer;
525}
Jon Ashburn752e06e2015-06-29 11:25:34 -0600526
527/* Parser core - when encountering text, process appropriately. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700528static const char *parse_value(cJSON *item, const char *value) {
529 if (!value)
530 return 0; /* Fail on null. */
531 if (!strncmp(value, "null", 4)) {
532 item->type = cJSON_NULL;
533 return value + 4;
534 }
535 if (!strncmp(value, "false", 5)) {
536 item->type = cJSON_False;
537 return value + 5;
538 }
539 if (!strncmp(value, "true", 4)) {
540 item->type = cJSON_True;
541 item->valueint = 1;
542 return value + 4;
543 }
544 if (*value == '\"') {
545 return parse_string(item, value);
546 }
547 if (*value == '-' || (*value >= '0' && *value <= '9')) {
548 return parse_number(item, value);
549 }
550 if (*value == '[') {
551 return parse_array(item, value);
552 }
553 if (*value == '{') {
554 return parse_object(item, value);
555 }
Jon Ashburn752e06e2015-06-29 11:25:34 -0600556
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700557 ep = value;
558 return 0; /* failure. */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600559}
560
561/* Render a value to text. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700562static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p) {
563 char *out = 0;
564 if (!item)
565 return 0;
566 if (p) {
567 switch ((item->type) & 255) {
568 case cJSON_NULL: {
569 out = ensure(p, 5);
570 if (out)
571 strcpy(out, "null");
572 break;
573 }
574 case cJSON_False: {
575 out = ensure(p, 6);
576 if (out)
577 strcpy(out, "false");
578 break;
579 }
580 case cJSON_True: {
581 out = ensure(p, 5);
582 if (out)
583 strcpy(out, "true");
584 break;
585 }
586 case cJSON_Number:
587 out = print_number(item, p);
588 break;
589 case cJSON_String:
590 out = print_string(item, p);
591 break;
592 case cJSON_Array:
593 out = print_array(item, depth, fmt, p);
594 break;
595 case cJSON_Object:
596 out = print_object(item, depth, fmt, p);
597 break;
598 }
599 } else {
600 switch ((item->type) & 255) {
601 case cJSON_NULL:
602 out = cJSON_strdup("null");
603 break;
604 case cJSON_False:
605 out = cJSON_strdup("false");
606 break;
607 case cJSON_True:
608 out = cJSON_strdup("true");
609 break;
610 case cJSON_Number:
611 out = print_number(item, 0);
612 break;
613 case cJSON_String:
614 out = print_string(item, 0);
615 break;
616 case cJSON_Array:
617 out = print_array(item, depth, fmt, 0);
618 break;
619 case cJSON_Object:
620 out = print_object(item, depth, fmt, 0);
621 break;
622 }
623 }
624 return out;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600625}
626
627/* Build an array from input text. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700628static const char *parse_array(cJSON *item, const char *value) {
629 cJSON *child;
630 if (*value != '[') {
631 ep = value;
632 return 0;
633 } /* not an array! */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600634
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700635 item->type = cJSON_Array;
636 value = skip(value + 1);
637 if (*value == ']')
638 return value + 1; /* empty array. */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600639
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700640 item->child = child = cJSON_New_Item();
641 if (!item->child)
642 return 0; /* memory fail */
643 value = skip(
644 parse_value(child, skip(value))); /* skip any spacing, get the value. */
645 if (!value)
646 return 0;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600647
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700648 while (*value == ',') {
649 cJSON *new_item;
650 if (!(new_item = cJSON_New_Item()))
651 return 0; /* memory fail */
652 child->next = new_item;
653 new_item->prev = child;
654 child = new_item;
655 value = skip(parse_value(child, skip(value + 1)));
656 if (!value)
657 return 0; /* memory fail */
658 }
Jon Ashburn752e06e2015-06-29 11:25:34 -0600659
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700660 if (*value == ']')
661 return value + 1; /* end of array */
662 ep = value;
663 return 0; /* malformed. */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600664}
665
666/* Render an array to text */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700667static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p) {
668 char **entries;
669 char *out = 0, *ptr, *ret;
670 size_t len = 5;
671 cJSON *child = item->child;
672 int numentries = 0, fail = 0, j = 0;
673 size_t tmplen = 0, i = 0;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600674
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700675 /* How many entries in the array? */
676 while (child)
677 numentries++, child = child->next;
678 /* Explicitly handle numentries==0 */
679 if (!numentries) {
680 if (p)
681 out = ensure(p, 3);
682 else
683 out = (char *)cJSON_malloc(3);
684 if (out)
685 strcpy(out, "[]");
686 return out;
687 }
Jon Ashburn752e06e2015-06-29 11:25:34 -0600688
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700689 if (p) {
690 /* Compose the output array. */
691 i = p->offset;
692 ptr = ensure(p, 1);
693 if (!ptr)
694 return 0;
695 *ptr = '[';
696 p->offset++;
697 child = item->child;
698 while (child && !fail) {
699 print_value(child, depth + 1, fmt, p);
700 p->offset = update(p);
701 if (child->next) {
702 len = fmt ? 2 : 1;
703 ptr = ensure(p, len + 1);
704 if (!ptr)
705 return 0;
706 *ptr++ = ',';
707 if (fmt)
708 *ptr++ = ' ';
709 *ptr = 0;
710 p->offset += len;
711 }
712 child = child->next;
713 }
714 ptr = ensure(p, 2);
715 if (!ptr)
716 return 0;
717 *ptr++ = ']';
718 *ptr = 0;
719 out = (p->buffer) + i;
720 } else {
721 /* Allocate an array to hold the values for each */
722 entries = (char **)cJSON_malloc(numentries * sizeof(char *));
723 if (!entries)
724 return 0;
725 memset(entries, 0, numentries * sizeof(char *));
726 /* Retrieve all the results: */
727 child = item->child;
728 while (child && !fail) {
729 ret = print_value(child, depth + 1, fmt, 0);
730 entries[i++] = ret;
731 if (ret)
732 len += strlen(ret) + 2 + (fmt ? 1 : 0);
733 else
734 fail = 1;
735 child = child->next;
736 }
737
738 /* If we didn't fail, try to malloc the output string */
739 if (!fail)
740 out = (char *)cJSON_malloc(len);
741 /* If that fails, we fail. */
742 if (!out)
743 fail = 1;
744
745 /* Handle failure. */
746 if (fail) {
747 for (j = 0; j < numentries; j++)
748 if (entries[j])
749 cJSON_free(entries[j]);
750 cJSON_free(entries);
751 return 0;
752 }
753
754 /* Compose the output array. */
755 *out = '[';
756 ptr = out + 1;
757 *ptr = 0;
758 for (j = 0; j < numentries; j++) {
759 tmplen = strlen(entries[j]);
760 memcpy(ptr, entries[j], tmplen);
761 ptr += tmplen;
762 if (j != numentries - 1) {
763 *ptr++ = ',';
764 if (fmt)
765 *ptr++ = ' ';
766 *ptr = 0;
767 }
768 cJSON_free(entries[j]);
769 }
770 cJSON_free(entries);
771 *ptr++ = ']';
772 *ptr++ = 0;
773 }
774 return out;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600775}
776
777/* Build an object from the text. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700778static const char *parse_object(cJSON *item, const char *value) {
779 cJSON *child;
780 if (*value != '{') {
781 ep = value;
782 return 0;
783 } /* not an object! */
784
785 item->type = cJSON_Object;
786 value = skip(value + 1);
787 if (*value == '}')
788 return value + 1; /* empty array. */
789
790 item->child = child = cJSON_New_Item();
791 if (!item->child)
792 return 0;
793 value = skip(parse_string(child, skip(value)));
794 if (!value)
795 return 0;
796 child->string = child->valuestring;
797 child->valuestring = 0;
798 if (*value != ':') {
799 ep = value;
800 return 0;
801 } /* fail! */
802 value = skip(parse_value(
803 child, skip(value + 1))); /* skip any spacing, get the value. */
804 if (!value)
805 return 0;
806
807 while (*value == ',') {
808 cJSON *new_item;
809 if (!(new_item = cJSON_New_Item()))
810 return 0; /* memory fail */
811 child->next = new_item;
812 new_item->prev = child;
813 child = new_item;
814 value = skip(parse_string(child, skip(value + 1)));
815 if (!value)
816 return 0;
817 child->string = child->valuestring;
818 child->valuestring = 0;
819 if (*value != ':') {
820 ep = value;
821 return 0;
822 } /* fail! */
823 value = skip(parse_value(
824 child, skip(value + 1))); /* skip any spacing, get the value. */
825 if (!value)
826 return 0;
827 }
828
829 if (*value == '}')
830 return value + 1; /* end of array */
831 ep = value;
832 return 0; /* malformed. */
Jon Ashburn752e06e2015-06-29 11:25:34 -0600833}
834
835/* Render an object to text. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700836static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p) {
837 char **entries = 0, **names = 0;
838 char *out = 0, *ptr, *ret, *str;
839 int j;
840 cJSON *child = item->child;
841 int numentries = 0, fail = 0, k;
842 size_t tmplen = 0, i = 0, len = 7;
843 /* Count the number of entries. */
844 while (child)
845 numentries++, child = child->next;
846 /* Explicitly handle empty object case */
847 if (!numentries) {
848 if (p)
849 out = ensure(p, fmt ? depth + 4 : 3);
850 else
851 out = (char *)cJSON_malloc(fmt ? depth + 4 : 3);
852 if (!out)
853 return 0;
854 ptr = out;
855 *ptr++ = '{';
856 if (fmt) {
857 *ptr++ = '\n';
858 for (j = 0; j < depth - 1; j++)
859 *ptr++ = '\t';
860 }
861 *ptr++ = '}';
862 *ptr++ = 0;
863 return out;
864 }
865 if (p) {
866 /* Compose the output: */
867 i = p->offset;
868 len = fmt ? 2 : 1;
869 ptr = ensure(p, len + 1);
870 if (!ptr)
871 return 0;
872 *ptr++ = '{';
873 if (fmt)
874 *ptr++ = '\n';
875 *ptr = 0;
876 p->offset += len;
877 child = item->child;
878 depth++;
879 while (child) {
880 if (fmt) {
881 ptr = ensure(p, depth);
882 if (!ptr)
883 return 0;
884 for (j = 0; j < depth; j++)
885 *ptr++ = '\t';
886 p->offset += depth;
887 }
888 print_string_ptr(child->string, p);
889 p->offset = update(p);
Jon Ashburn752e06e2015-06-29 11:25:34 -0600890
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700891 len = fmt ? 2 : 1;
892 ptr = ensure(p, len);
893 if (!ptr)
894 return 0;
895 *ptr++ = ':';
896 if (fmt)
897 *ptr++ = '\t';
898 p->offset += len;
Jon Ashburn752e06e2015-06-29 11:25:34 -0600899
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700900 print_value(child, depth, fmt, p);
901 p->offset = update(p);
Jon Ashburn752e06e2015-06-29 11:25:34 -0600902
Jon Ashburn1c75aec2016-02-02 17:47:28 -0700903 len = (fmt ? 1 : 0) + (child->next ? 1 : 0);
904 ptr = ensure(p, len + 1);
905 if (!ptr)
906 return 0;
907 if (child->next)
908 *ptr++ = ',';
909 if (fmt)
910 *ptr++ = '\n';
911 *ptr = 0;
912 p->offset += len;
913 child = child->next;
914 }
915 ptr = ensure(p, fmt ? (depth + 1) : 2);
916 if (!ptr)
917 return 0;
918 if (fmt)
919 for (j = 0; j < depth - 1; j++)
920 *ptr++ = '\t';
921 *ptr++ = '}';
922 *ptr = 0;
923 out = (p->buffer) + i;
924 } else {
925 /* Allocate space for the names and the objects */
926 entries = (char **)cJSON_malloc(numentries * sizeof(char *));
927 if (!entries)
928 return 0;
929 names = (char **)cJSON_malloc(numentries * sizeof(char *));
930 if (!names) {
931 cJSON_free(entries);
932 return 0;
933 }
934 memset(entries, 0, sizeof(char *) * numentries);
935 memset(names, 0, sizeof(char *) * numentries);
936
937 /* Collect all the results into our arrays: */
938 child = item->child;
939 depth++;
940 if (fmt)
941 len += depth;
942 while (child) {
943 names[i] = str = print_string_ptr(child->string, 0);
944 entries[i++] = ret = print_value(child, depth, fmt, 0);
945 if (str && ret)
946 len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
947 else
948 fail = 1;
949 child = child->next;
950 }
951
952 /* Try to allocate the output string */
953 if (!fail)
954 out = (char *)cJSON_malloc(len);
955 if (!out)
956 fail = 1;
957
958 /* Handle failure */
959 if (fail) {
960 for (j = 0; j < numentries; j++) {
961 if (names[i])
962 cJSON_free(names[j]);
963 if (entries[j])
964 cJSON_free(entries[j]);
965 }
966 cJSON_free(names);
967 cJSON_free(entries);
968 return 0;
969 }
970
971 /* Compose the output: */
972 *out = '{';
973 ptr = out + 1;
974 if (fmt)
975 *ptr++ = '\n';
976 *ptr = 0;
977 for (j = 0; j < numentries; j++) {
978 if (fmt)
979 for (k = 0; k < depth; k++)
980 *ptr++ = '\t';
981 tmplen = strlen(names[j]);
982 memcpy(ptr, names[j], tmplen);
983 ptr += tmplen;
984 *ptr++ = ':';
985 if (fmt)
986 *ptr++ = '\t';
987 strcpy(ptr, entries[j]);
988 ptr += strlen(entries[j]);
989 if (j != numentries - 1)
990 *ptr++ = ',';
991 if (fmt)
992 *ptr++ = '\n';
993 *ptr = 0;
994 cJSON_free(names[j]);
995 cJSON_free(entries[j]);
996 }
997
998 cJSON_free(names);
999 cJSON_free(entries);
1000 if (fmt)
1001 for (j = 0; j < depth - 1; j++)
1002 *ptr++ = '\t';
1003 *ptr++ = '}';
1004 *ptr++ = 0;
1005 }
1006 return out;
Jon Ashburn752e06e2015-06-29 11:25:34 -06001007}
1008
1009/* Get Array size/item / object item. */
Jon Ashburn1c75aec2016-02-02 17:47:28 -07001010int cJSON_GetArraySize(cJSON *array) {
1011 cJSON *c = array->child;
1012 int i = 0;
1013 while (c)
1014 i++, c = c->next;
1015 return i;
1016}
1017cJSON *cJSON_GetArrayItem(cJSON *array, int item) {
1018 cJSON *c = array->child;
1019 while (c && item > 0)
1020 item--, c = c->next;
1021 return c;
1022}
1023cJSON *cJSON_GetObjectItem(cJSON *object, const char *string) {
1024 cJSON *c = object->child;
1025 while (c && strcmp(c->string, string))
1026 c = c->next;
1027 return c;
Jon Ashburn752e06e2015-06-29 11:25:34 -06001028}
1029
Jon Ashburn1c75aec2016-02-02 17:47:28 -07001030/* Utility for array list handling. */
1031static void suffix_object(cJSON *prev, cJSON *item) {
1032 prev->next = item;
1033 item->prev = prev;
1034}
1035/* Utility for handling references. */
1036static cJSON *create_reference(cJSON *item) {
1037 cJSON *ref = cJSON_New_Item();
1038 if (!ref)
1039 return 0;
1040 memcpy(ref, item, sizeof(cJSON));
1041 ref->string = 0;
1042 ref->type |= cJSON_IsReference;
1043 ref->next = ref->prev = 0;
1044 return ref;
1045}
1046
1047/* Add item to array/object. */
1048void cJSON_AddItemToArray(cJSON *array, cJSON *item) {
1049 cJSON *c = array->child;
1050 if (!item)
1051 return;
1052 if (!c) {
1053 array->child = item;
1054 } else {
1055 while (c && c->next)
1056 c = c->next;
1057 suffix_object(c, item);
1058 }
1059}
1060void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) {
1061 if (!item)
1062 return;
1063 if (item->string)
1064 cJSON_free(item->string);
1065 item->string = cJSON_strdup(string);
1066 cJSON_AddItemToArray(object, item);
1067}
1068void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) {
1069 if (!item)
1070 return;
1071 if (!(item->type & cJSON_StringIsConst) && item->string)
1072 cJSON_free(item->string);
1073 item->string = (char *)string;
1074 item->type |= cJSON_StringIsConst;
1075 cJSON_AddItemToArray(object, item);
1076}
1077void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {
1078 cJSON_AddItemToArray(array, create_reference(item));
1079}
1080void cJSON_AddItemReferenceToObject(cJSON *object, const char *string,
1081 cJSON *item) {
1082 cJSON_AddItemToObject(object, string, create_reference(item));
1083}
1084
1085cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) {
1086 cJSON *c = array->child;
1087 while (c && which > 0)
1088 c = c->next, which--;
1089 if (!c)
1090 return 0;
1091 if (c->prev)
1092 c->prev->next = c->next;
1093 if (c->next)
1094 c->next->prev = c->prev;
1095 if (c == array->child)
1096 array->child = c->next;
1097 c->prev = c->next = 0;
1098 return c;
1099}
1100void cJSON_DeleteItemFromArray(cJSON *array, int which) {
1101 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
1102}
1103cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string) {
1104 int i = 0;
1105 cJSON *c = object->child;
1106 while (c && strcmp(c->string, string))
1107 i++, c = c->next;
1108 if (c)
1109 return cJSON_DetachItemFromArray(object, i);
1110 return 0;
1111}
1112void cJSON_DeleteItemFromObject(cJSON *object, const char *string) {
1113 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
1114}
1115
1116/* Replace array/object items with new ones. */
1117void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) {
1118 cJSON *c = array->child;
1119 while (c && which > 0)
1120 c = c->next, which--;
1121 if (!c) {
1122 cJSON_AddItemToArray(array, newitem);
1123 return;
1124 }
1125 newitem->next = c;
1126 newitem->prev = c->prev;
1127 c->prev = newitem;
1128 if (c == array->child)
1129 array->child = newitem;
1130 else
1131 newitem->prev->next = newitem;
1132}
1133void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) {
1134 cJSON *c = array->child;
1135 while (c && which > 0)
1136 c = c->next, which--;
1137 if (!c)
1138 return;
1139 newitem->next = c->next;
1140 newitem->prev = c->prev;
1141 if (newitem->next)
1142 newitem->next->prev = newitem;
1143 if (c == array->child)
1144 array->child = newitem;
1145 else
1146 newitem->prev->next = newitem;
1147 c->next = c->prev = 0;
1148 cJSON_Delete(c);
1149}
1150void cJSON_ReplaceItemInObject(cJSON *object, const char *string,
1151 cJSON *newitem) {
1152 int i = 0;
1153 cJSON *c = object->child;
1154 while (c && strcmp(c->string, string))
1155 i++, c = c->next;
1156 if (c) {
1157 newitem->string = cJSON_strdup(string);
1158 cJSON_ReplaceItemInArray(object, i, newitem);
1159 }
1160}
1161
1162/* Create basic types: */
1163cJSON *cJSON_CreateNull(void) {
1164 cJSON *item = cJSON_New_Item();
1165 if (item)
1166 item->type = cJSON_NULL;
1167 return item;
1168}
1169cJSON *cJSON_CreateTrue(void) {
1170 cJSON *item = cJSON_New_Item();
1171 if (item)
1172 item->type = cJSON_True;
1173 return item;
1174}
1175cJSON *cJSON_CreateFalse(void) {
1176 cJSON *item = cJSON_New_Item();
1177 if (item)
1178 item->type = cJSON_False;
1179 return item;
1180}
1181cJSON *cJSON_CreateBool(int b) {
1182 cJSON *item = cJSON_New_Item();
1183 if (item)
1184 item->type = b ? cJSON_True : cJSON_False;
1185 return item;
1186}
1187cJSON *cJSON_CreateNumber(double num) {
1188 cJSON *item = cJSON_New_Item();
1189 if (item) {
1190 item->type = cJSON_Number;
1191 item->valuedouble = num;
1192 item->valueint = (int)num;
1193 }
1194 return item;
1195}
1196cJSON *cJSON_CreateString(const char *string) {
1197 cJSON *item = cJSON_New_Item();
1198 if (item) {
1199 item->type = cJSON_String;
1200 item->valuestring = cJSON_strdup(string);
1201 }
1202 return item;
1203}
1204cJSON *cJSON_CreateArray(void) {
1205 cJSON *item = cJSON_New_Item();
1206 if (item)
1207 item->type = cJSON_Array;
1208 return item;
1209}
1210cJSON *cJSON_CreateObject(void) {
1211 cJSON *item = cJSON_New_Item();
1212 if (item)
1213 item->type = cJSON_Object;
1214 return item;
1215}
1216
1217/* Create Arrays: */
1218cJSON *cJSON_CreateIntArray(const int *numbers, int count) {
1219 int i;
1220 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1221 for (i = 0; a && i < count; i++) {
1222 n = cJSON_CreateNumber(numbers[i]);
1223 if (!i)
1224 a->child = n;
1225 else
1226 suffix_object(p, n);
1227 p = n;
1228 }
1229 return a;
1230}
1231cJSON *cJSON_CreateFloatArray(const float *numbers, int count) {
1232 int i;
1233 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1234 for (i = 0; a && i < count; i++) {
1235 n = cJSON_CreateNumber(numbers[i]);
1236 if (!i)
1237 a->child = n;
1238 else
1239 suffix_object(p, n);
1240 p = n;
1241 }
1242 return a;
1243}
1244cJSON *cJSON_CreateDoubleArray(const double *numbers, int count) {
1245 int i;
1246 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1247 for (i = 0; a && i < count; i++) {
1248 n = cJSON_CreateNumber(numbers[i]);
1249 if (!i)
1250 a->child = n;
1251 else
1252 suffix_object(p, n);
1253 p = n;
1254 }
1255 return a;
1256}
1257cJSON *cJSON_CreateStringArray(const char **strings, int count) {
1258 int i;
1259 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1260 for (i = 0; a && i < count; i++) {
1261 n = cJSON_CreateString(strings[i]);
1262 if (!i)
1263 a->child = n;
1264 else
1265 suffix_object(p, n);
1266 p = n;
1267 }
1268 return a;
1269}
1270
1271/* Duplication */
1272cJSON *cJSON_Duplicate(cJSON *item, int recurse) {
1273 cJSON *newitem, *cptr, *nptr = 0, *newchild;
1274 /* Bail on bad ptr */
1275 if (!item)
1276 return 0;
1277 /* Create new item */
1278 newitem = cJSON_New_Item();
1279 if (!newitem)
1280 return 0;
1281 /* Copy over all vars */
1282 newitem->type = item->type & (~cJSON_IsReference),
1283 newitem->valueint = item->valueint,
1284 newitem->valuedouble = item->valuedouble;
1285 if (item->valuestring) {
1286 newitem->valuestring = cJSON_strdup(item->valuestring);
1287 if (!newitem->valuestring) {
1288 cJSON_Delete(newitem);
1289 return 0;
1290 }
1291 }
1292 if (item->string) {
1293 newitem->string = cJSON_strdup(item->string);
1294 if (!newitem->string) {
1295 cJSON_Delete(newitem);
1296 return 0;
1297 }
1298 }
1299 /* If non-recursive, then we're done! */
1300 if (!recurse)
1301 return newitem;
1302 /* Walk the ->next chain for the child. */
1303 cptr = item->child;
1304 while (cptr) {
1305 newchild = cJSON_Duplicate(
1306 cptr,
1307 1); /* Duplicate (with recurse) each item in the ->next chain */
1308 if (!newchild) {
1309 cJSON_Delete(newitem);
1310 return 0;
1311 }
1312 if (nptr) {
1313 nptr->next = newchild, newchild->prev = nptr;
1314 nptr = newchild;
1315 } /* If newitem->child already set, then crosswire ->prev and ->next and
1316 move on */
1317 else {
1318 newitem->child = newchild;
1319 nptr = newchild;
1320 } /* Set newitem->child and move to it */
1321 cptr = cptr->next;
1322 }
1323 return newitem;
1324}
1325
1326void cJSON_Minify(char *json) {
1327 char *into = json;
1328 while (*json) {
1329 if (*json == ' ')
1330 json++;
1331 else if (*json == '\t')
1332 json++; /* Whitespace characters. */
1333 else if (*json == '\r')
1334 json++;
1335 else if (*json == '\n')
1336 json++;
1337 else if (*json == '/' && json[1] == '/')
1338 while (*json && *json != '\n')
1339 json++; /* double-slash comments, to end of line. */
1340 else if (*json == '/' && json[1] == '*') {
1341 while (*json && !(*json == '*' && json[1] == '/'))
1342 json++;
1343 json += 2;
1344 } /* multiline comments. */
1345 else if (*json == '\"') {
1346 *into++ = *json++;
1347 while (*json && *json != '\"') {
1348 if (*json == '\\')
1349 *into++ = *json++;
1350 *into++ = *json++;
1351 }
1352 *into++ = *json++;
1353 } /* string literals, which are \" sensitive. */
1354 else
1355 *into++ = *json++; /* All other characters. */
1356 }
1357 *into = 0; /* and null-terminate. */
Jon Ashburn752e06e2015-06-29 11:25:34 -06001358}