blob: f28eadb7e3c6f7673d2d5e0733481ea818e17518 [file] [log] [blame]
Jon Ashburn2077e382015-06-29 11:25:34 -06001/*
2 Copyright (c) 2009 Dave Gamble
Jon Ashburn23d36b12016-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 Ashburn2077e382015-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 Ashburn23d36b12016-02-02 17:47:28 -070040const char *cJSON_GetErrorPtr(void) { return ep; }
Jon Ashburn2077e382015-06-29 11:25:34 -060041
Jon Ashburn2077e382015-06-29 11:25:34 -060042static void *(*cJSON_malloc)(size_t sz) = malloc;
43static void (*cJSON_free)(void *ptr) = free;
44
Jon Ashburn23d36b12016-02-02 17:47:28 -070045static char *cJSON_strdup(const char *str) {
46 size_t len;
47 char *copy;
Jon Ashburn2077e382015-06-29 11:25:34 -060048
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -060054}
55
Jon Ashburn23d36b12016-02-02 17:47:28 -070056void cJSON_InitHooks(cJSON_Hooks *hooks) {
Jon Ashburn2077e382015-06-29 11:25:34 -060057 if (!hooks) { /* Reset hooks */
58 cJSON_malloc = malloc;
59 cJSON_free = free;
60 return;
61 }
62
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -060065}
66
67/* Internal constructor. */
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -060073}
74
75/* Delete a cJSON structure. */
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -060089}
90
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -060096
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600121
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600131}
132
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600141}
142
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600179}
180
181/* Render the number nicely from the given item into a string. */
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600216}
217
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600259}
260
261/* Parse the input text into an unescaped cstring, and populate item. */
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600274
Jon Ashburn23d36b12016-02-02 17:47:28 -0700275 while (*ptr != '\"' && *ptr && ++len)
276 if (*ptr++ == '\\')
277 ptr++; /* Skip escaped quotes. */
Jon Ashburn2077e382015-06-29 11:25:34 -0600278
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600283
Jon Ashburn23d36b12016-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:
Karl Schultz2558bd32016-02-24 14:39:39 -0700346 *--ptr2 = ((unsigned char)uc | firstByteMark[len]);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700347 }
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 Ashburn2077e382015-06-29 11:25:34 -0600363}
364
365/* Render the cstring provided to an escaped version that can be printed. */
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600372
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600459}
460/* Invote print_string_ptr (which is useful) on an item. */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700461static char *print_string(cJSON *item, printbuffer *p) {
462 return print_string_ptr(item->valuestring, p);
463}
Jon Ashburn2077e382015-06-29 11:25:34 -0600464
465/* Predeclare these prototypes. */
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600472
473/* Utility to jump whitespace and cr/lf */
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600479
480/* Parse an object - create a new root, and populate. */
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600488
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600494
Jon Ashburn23d36b12016-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 Ashburn2077e382015-06-29 11:25:34 -0600508}
509/* Default options for cJSON_Parse */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700510cJSON *cJSON_Parse(const char *value) {
511 return cJSON_ParseWithOpts(value, 0, 0);
Jon Ashburn2077e382015-06-29 11:25:34 -0600512}
513
Jon Ashburn23d36b12016-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);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700524}
Jon Ashburn2077e382015-06-29 11:25:34 -0600525
526/* Parser core - when encountering text, process appropriately. */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700527static const char *parse_value(cJSON *item, const char *value) {
528 if (!value)
529 return 0; /* Fail on null. */
530 if (!strncmp(value, "null", 4)) {
531 item->type = cJSON_NULL;
532 return value + 4;
533 }
534 if (!strncmp(value, "false", 5)) {
535 item->type = cJSON_False;
536 return value + 5;
537 }
538 if (!strncmp(value, "true", 4)) {
539 item->type = cJSON_True;
540 item->valueint = 1;
541 return value + 4;
542 }
543 if (*value == '\"') {
544 return parse_string(item, value);
545 }
546 if (*value == '-' || (*value >= '0' && *value <= '9')) {
547 return parse_number(item, value);
548 }
549 if (*value == '[') {
550 return parse_array(item, value);
551 }
552 if (*value == '{') {
553 return parse_object(item, value);
554 }
Jon Ashburn2077e382015-06-29 11:25:34 -0600555
Jon Ashburn23d36b12016-02-02 17:47:28 -0700556 ep = value;
557 return 0; /* failure. */
Jon Ashburn2077e382015-06-29 11:25:34 -0600558}
559
560/* Render a value to text. */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700561static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p) {
562 char *out = 0;
563 if (!item)
564 return 0;
565 if (p) {
566 switch ((item->type) & 255) {
567 case cJSON_NULL: {
568 out = ensure(p, 5);
569 if (out)
570 strcpy(out, "null");
571 break;
572 }
573 case cJSON_False: {
574 out = ensure(p, 6);
575 if (out)
576 strcpy(out, "false");
577 break;
578 }
579 case cJSON_True: {
580 out = ensure(p, 5);
581 if (out)
582 strcpy(out, "true");
583 break;
584 }
585 case cJSON_Number:
586 out = print_number(item, p);
587 break;
588 case cJSON_String:
589 out = print_string(item, p);
590 break;
591 case cJSON_Array:
592 out = print_array(item, depth, fmt, p);
593 break;
594 case cJSON_Object:
595 out = print_object(item, depth, fmt, p);
596 break;
597 }
598 } else {
599 switch ((item->type) & 255) {
600 case cJSON_NULL:
601 out = cJSON_strdup("null");
602 break;
603 case cJSON_False:
604 out = cJSON_strdup("false");
605 break;
606 case cJSON_True:
607 out = cJSON_strdup("true");
608 break;
609 case cJSON_Number:
610 out = print_number(item, 0);
611 break;
612 case cJSON_String:
613 out = print_string(item, 0);
614 break;
615 case cJSON_Array:
616 out = print_array(item, depth, fmt, 0);
617 break;
618 case cJSON_Object:
619 out = print_object(item, depth, fmt, 0);
620 break;
621 }
622 }
623 return out;
Jon Ashburn2077e382015-06-29 11:25:34 -0600624}
625
626/* Build an array from input text. */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700627static const char *parse_array(cJSON *item, const char *value) {
628 cJSON *child;
629 if (*value != '[') {
630 ep = value;
631 return 0;
632 } /* not an array! */
Jon Ashburn2077e382015-06-29 11:25:34 -0600633
Jon Ashburn23d36b12016-02-02 17:47:28 -0700634 item->type = cJSON_Array;
635 value = skip(value + 1);
636 if (*value == ']')
637 return value + 1; /* empty array. */
Jon Ashburn2077e382015-06-29 11:25:34 -0600638
Jon Ashburn23d36b12016-02-02 17:47:28 -0700639 item->child = child = cJSON_New_Item();
640 if (!item->child)
641 return 0; /* memory fail */
642 value = skip(
643 parse_value(child, skip(value))); /* skip any spacing, get the value. */
644 if (!value)
645 return 0;
Jon Ashburn2077e382015-06-29 11:25:34 -0600646
Jon Ashburn23d36b12016-02-02 17:47:28 -0700647 while (*value == ',') {
648 cJSON *new_item;
649 if (!(new_item = cJSON_New_Item()))
650 return 0; /* memory fail */
651 child->next = new_item;
652 new_item->prev = child;
653 child = new_item;
654 value = skip(parse_value(child, skip(value + 1)));
655 if (!value)
656 return 0; /* memory fail */
657 }
Jon Ashburn2077e382015-06-29 11:25:34 -0600658
Jon Ashburn23d36b12016-02-02 17:47:28 -0700659 if (*value == ']')
660 return value + 1; /* end of array */
661 ep = value;
662 return 0; /* malformed. */
Jon Ashburn2077e382015-06-29 11:25:34 -0600663}
664
665/* Render an array to text */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700666static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p) {
667 char **entries;
668 char *out = 0, *ptr, *ret;
669 size_t len = 5;
670 cJSON *child = item->child;
671 int numentries = 0, fail = 0, j = 0;
672 size_t tmplen = 0, i = 0;
Jon Ashburn2077e382015-06-29 11:25:34 -0600673
Jon Ashburn23d36b12016-02-02 17:47:28 -0700674 /* How many entries in the array? */
675 while (child)
676 numentries++, child = child->next;
677 /* Explicitly handle numentries==0 */
678 if (!numentries) {
679 if (p)
680 out = ensure(p, 3);
681 else
682 out = (char *)cJSON_malloc(3);
683 if (out)
684 strcpy(out, "[]");
685 return out;
686 }
Jon Ashburn2077e382015-06-29 11:25:34 -0600687
Jon Ashburn23d36b12016-02-02 17:47:28 -0700688 if (p) {
689 /* Compose the output array. */
690 i = p->offset;
691 ptr = ensure(p, 1);
692 if (!ptr)
693 return 0;
694 *ptr = '[';
695 p->offset++;
696 child = item->child;
697 while (child && !fail) {
698 print_value(child, depth + 1, fmt, p);
699 p->offset = update(p);
700 if (child->next) {
701 len = fmt ? 2 : 1;
702 ptr = ensure(p, len + 1);
703 if (!ptr)
704 return 0;
705 *ptr++ = ',';
706 if (fmt)
707 *ptr++ = ' ';
708 *ptr = 0;
709 p->offset += len;
710 }
711 child = child->next;
712 }
713 ptr = ensure(p, 2);
714 if (!ptr)
715 return 0;
716 *ptr++ = ']';
717 *ptr = 0;
718 out = (p->buffer) + i;
719 } else {
720 /* Allocate an array to hold the values for each */
721 entries = (char **)cJSON_malloc(numentries * sizeof(char *));
722 if (!entries)
723 return 0;
724 memset(entries, 0, numentries * sizeof(char *));
725 /* Retrieve all the results: */
726 child = item->child;
727 while (child && !fail) {
728 ret = print_value(child, depth + 1, fmt, 0);
729 entries[i++] = ret;
730 if (ret)
731 len += strlen(ret) + 2 + (fmt ? 1 : 0);
732 else
733 fail = 1;
734 child = child->next;
735 }
736
737 /* If we didn't fail, try to malloc the output string */
738 if (!fail)
739 out = (char *)cJSON_malloc(len);
740 /* If that fails, we fail. */
741 if (!out)
742 fail = 1;
743
744 /* Handle failure. */
745 if (fail) {
746 for (j = 0; j < numentries; j++)
747 if (entries[j])
748 cJSON_free(entries[j]);
749 cJSON_free(entries);
750 return 0;
751 }
752
753 /* Compose the output array. */
754 *out = '[';
755 ptr = out + 1;
756 *ptr = 0;
757 for (j = 0; j < numentries; j++) {
758 tmplen = strlen(entries[j]);
759 memcpy(ptr, entries[j], tmplen);
760 ptr += tmplen;
761 if (j != numentries - 1) {
762 *ptr++ = ',';
763 if (fmt)
764 *ptr++ = ' ';
765 *ptr = 0;
766 }
767 cJSON_free(entries[j]);
768 }
769 cJSON_free(entries);
770 *ptr++ = ']';
771 *ptr++ = 0;
772 }
773 return out;
Jon Ashburn2077e382015-06-29 11:25:34 -0600774}
775
776/* Build an object from the text. */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700777static const char *parse_object(cJSON *item, const char *value) {
778 cJSON *child;
779 if (*value != '{') {
780 ep = value;
781 return 0;
782 } /* not an object! */
783
784 item->type = cJSON_Object;
785 value = skip(value + 1);
786 if (*value == '}')
787 return value + 1; /* empty array. */
788
789 item->child = child = cJSON_New_Item();
790 if (!item->child)
791 return 0;
792 value = skip(parse_string(child, skip(value)));
793 if (!value)
794 return 0;
795 child->string = child->valuestring;
796 child->valuestring = 0;
797 if (*value != ':') {
798 ep = value;
799 return 0;
800 } /* fail! */
801 value = skip(parse_value(
802 child, skip(value + 1))); /* skip any spacing, get the value. */
803 if (!value)
804 return 0;
805
806 while (*value == ',') {
807 cJSON *new_item;
808 if (!(new_item = cJSON_New_Item()))
809 return 0; /* memory fail */
810 child->next = new_item;
811 new_item->prev = child;
812 child = new_item;
813 value = skip(parse_string(child, skip(value + 1)));
814 if (!value)
815 return 0;
816 child->string = child->valuestring;
817 child->valuestring = 0;
818 if (*value != ':') {
819 ep = value;
820 return 0;
821 } /* fail! */
822 value = skip(parse_value(
823 child, skip(value + 1))); /* skip any spacing, get the value. */
824 if (!value)
825 return 0;
826 }
827
828 if (*value == '}')
829 return value + 1; /* end of array */
830 ep = value;
831 return 0; /* malformed. */
Jon Ashburn2077e382015-06-29 11:25:34 -0600832}
833
834/* Render an object to text. */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700835static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p) {
836 char **entries = 0, **names = 0;
837 char *out = 0, *ptr, *ret, *str;
838 int j;
839 cJSON *child = item->child;
840 int numentries = 0, fail = 0, k;
841 size_t tmplen = 0, i = 0, len = 7;
842 /* Count the number of entries. */
843 while (child)
844 numentries++, child = child->next;
845 /* Explicitly handle empty object case */
846 if (!numentries) {
847 if (p)
848 out = ensure(p, fmt ? depth + 4 : 3);
849 else
850 out = (char *)cJSON_malloc(fmt ? depth + 4 : 3);
851 if (!out)
852 return 0;
853 ptr = out;
854 *ptr++ = '{';
855 if (fmt) {
856 *ptr++ = '\n';
857 for (j = 0; j < depth - 1; j++)
858 *ptr++ = '\t';
859 }
860 *ptr++ = '}';
861 *ptr++ = 0;
862 return out;
863 }
864 if (p) {
865 /* Compose the output: */
866 i = p->offset;
867 len = fmt ? 2 : 1;
868 ptr = ensure(p, len + 1);
869 if (!ptr)
870 return 0;
871 *ptr++ = '{';
872 if (fmt)
873 *ptr++ = '\n';
874 *ptr = 0;
875 p->offset += len;
876 child = item->child;
877 depth++;
878 while (child) {
879 if (fmt) {
880 ptr = ensure(p, depth);
881 if (!ptr)
882 return 0;
883 for (j = 0; j < depth; j++)
884 *ptr++ = '\t';
885 p->offset += depth;
886 }
887 print_string_ptr(child->string, p);
888 p->offset = update(p);
Jon Ashburn2077e382015-06-29 11:25:34 -0600889
Jon Ashburn23d36b12016-02-02 17:47:28 -0700890 len = fmt ? 2 : 1;
891 ptr = ensure(p, len);
892 if (!ptr)
893 return 0;
894 *ptr++ = ':';
895 if (fmt)
896 *ptr++ = '\t';
897 p->offset += len;
Jon Ashburn2077e382015-06-29 11:25:34 -0600898
Jon Ashburn23d36b12016-02-02 17:47:28 -0700899 print_value(child, depth, fmt, p);
900 p->offset = update(p);
Jon Ashburn2077e382015-06-29 11:25:34 -0600901
Jon Ashburn23d36b12016-02-02 17:47:28 -0700902 len = (fmt ? 1 : 0) + (child->next ? 1 : 0);
903 ptr = ensure(p, len + 1);
904 if (!ptr)
905 return 0;
906 if (child->next)
907 *ptr++ = ',';
908 if (fmt)
909 *ptr++ = '\n';
910 *ptr = 0;
911 p->offset += len;
912 child = child->next;
913 }
914 ptr = ensure(p, fmt ? (depth + 1) : 2);
915 if (!ptr)
916 return 0;
917 if (fmt)
918 for (j = 0; j < depth - 1; j++)
919 *ptr++ = '\t';
920 *ptr++ = '}';
921 *ptr = 0;
922 out = (p->buffer) + i;
923 } else {
924 /* Allocate space for the names and the objects */
925 entries = (char **)cJSON_malloc(numentries * sizeof(char *));
926 if (!entries)
927 return 0;
928 names = (char **)cJSON_malloc(numentries * sizeof(char *));
929 if (!names) {
930 cJSON_free(entries);
931 return 0;
932 }
933 memset(entries, 0, sizeof(char *) * numentries);
934 memset(names, 0, sizeof(char *) * numentries);
935
936 /* Collect all the results into our arrays: */
937 child = item->child;
938 depth++;
939 if (fmt)
940 len += depth;
941 while (child) {
942 names[i] = str = print_string_ptr(child->string, 0);
943 entries[i++] = ret = print_value(child, depth, fmt, 0);
944 if (str && ret)
945 len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
946 else
947 fail = 1;
948 child = child->next;
949 }
950
951 /* Try to allocate the output string */
952 if (!fail)
953 out = (char *)cJSON_malloc(len);
954 if (!out)
955 fail = 1;
956
957 /* Handle failure */
958 if (fail) {
959 for (j = 0; j < numentries; j++) {
960 if (names[i])
961 cJSON_free(names[j]);
962 if (entries[j])
963 cJSON_free(entries[j]);
964 }
965 cJSON_free(names);
966 cJSON_free(entries);
967 return 0;
968 }
969
970 /* Compose the output: */
971 *out = '{';
972 ptr = out + 1;
973 if (fmt)
974 *ptr++ = '\n';
975 *ptr = 0;
976 for (j = 0; j < numentries; j++) {
977 if (fmt)
978 for (k = 0; k < depth; k++)
979 *ptr++ = '\t';
980 tmplen = strlen(names[j]);
981 memcpy(ptr, names[j], tmplen);
982 ptr += tmplen;
983 *ptr++ = ':';
984 if (fmt)
985 *ptr++ = '\t';
986 strcpy(ptr, entries[j]);
987 ptr += strlen(entries[j]);
988 if (j != numentries - 1)
989 *ptr++ = ',';
990 if (fmt)
991 *ptr++ = '\n';
992 *ptr = 0;
993 cJSON_free(names[j]);
994 cJSON_free(entries[j]);
995 }
996
997 cJSON_free(names);
998 cJSON_free(entries);
999 if (fmt)
1000 for (j = 0; j < depth - 1; j++)
1001 *ptr++ = '\t';
1002 *ptr++ = '}';
1003 *ptr++ = 0;
1004 }
1005 return out;
Jon Ashburn2077e382015-06-29 11:25:34 -06001006}
1007
1008/* Get Array size/item / object item. */
Jon Ashburn23d36b12016-02-02 17:47:28 -07001009int cJSON_GetArraySize(cJSON *array) {
1010 cJSON *c = array->child;
1011 int i = 0;
1012 while (c)
1013 i++, c = c->next;
1014 return i;
1015}
1016cJSON *cJSON_GetArrayItem(cJSON *array, int item) {
1017 cJSON *c = array->child;
1018 while (c && item > 0)
1019 item--, c = c->next;
1020 return c;
1021}
1022cJSON *cJSON_GetObjectItem(cJSON *object, const char *string) {
1023 cJSON *c = object->child;
1024 while (c && strcmp(c->string, string))
1025 c = c->next;
1026 return c;
Jon Ashburn2077e382015-06-29 11:25:34 -06001027}
1028
Jon Ashburn23d36b12016-02-02 17:47:28 -07001029/* Utility for array list handling. */
1030static void suffix_object(cJSON *prev, cJSON *item) {
1031 prev->next = item;
1032 item->prev = prev;
1033}
1034/* Utility for handling references. */
1035static cJSON *create_reference(cJSON *item) {
1036 cJSON *ref = cJSON_New_Item();
1037 if (!ref)
1038 return 0;
1039 memcpy(ref, item, sizeof(cJSON));
1040 ref->string = 0;
1041 ref->type |= cJSON_IsReference;
1042 ref->next = ref->prev = 0;
1043 return ref;
1044}
1045
1046/* Add item to array/object. */
1047void cJSON_AddItemToArray(cJSON *array, cJSON *item) {
1048 cJSON *c = array->child;
1049 if (!item)
1050 return;
1051 if (!c) {
1052 array->child = item;
1053 } else {
1054 while (c && c->next)
1055 c = c->next;
1056 suffix_object(c, item);
1057 }
1058}
1059void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) {
1060 if (!item)
1061 return;
1062 if (item->string)
1063 cJSON_free(item->string);
1064 item->string = cJSON_strdup(string);
1065 cJSON_AddItemToArray(object, item);
1066}
1067void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) {
1068 if (!item)
1069 return;
1070 if (!(item->type & cJSON_StringIsConst) && item->string)
1071 cJSON_free(item->string);
1072 item->string = (char *)string;
1073 item->type |= cJSON_StringIsConst;
1074 cJSON_AddItemToArray(object, item);
1075}
1076void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {
1077 cJSON_AddItemToArray(array, create_reference(item));
1078}
1079void cJSON_AddItemReferenceToObject(cJSON *object, const char *string,
1080 cJSON *item) {
1081 cJSON_AddItemToObject(object, string, create_reference(item));
1082}
1083
1084cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) {
1085 cJSON *c = array->child;
1086 while (c && which > 0)
1087 c = c->next, which--;
1088 if (!c)
1089 return 0;
1090 if (c->prev)
1091 c->prev->next = c->next;
1092 if (c->next)
1093 c->next->prev = c->prev;
1094 if (c == array->child)
1095 array->child = c->next;
1096 c->prev = c->next = 0;
1097 return c;
1098}
1099void cJSON_DeleteItemFromArray(cJSON *array, int which) {
1100 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
1101}
1102cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string) {
1103 int i = 0;
1104 cJSON *c = object->child;
1105 while (c && strcmp(c->string, string))
1106 i++, c = c->next;
1107 if (c)
1108 return cJSON_DetachItemFromArray(object, i);
1109 return 0;
1110}
1111void cJSON_DeleteItemFromObject(cJSON *object, const char *string) {
1112 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
1113}
1114
1115/* Replace array/object items with new ones. */
1116void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) {
1117 cJSON *c = array->child;
1118 while (c && which > 0)
1119 c = c->next, which--;
1120 if (!c) {
1121 cJSON_AddItemToArray(array, newitem);
1122 return;
1123 }
1124 newitem->next = c;
1125 newitem->prev = c->prev;
1126 c->prev = newitem;
1127 if (c == array->child)
1128 array->child = newitem;
1129 else
1130 newitem->prev->next = newitem;
1131}
1132void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) {
1133 cJSON *c = array->child;
1134 while (c && which > 0)
1135 c = c->next, which--;
1136 if (!c)
1137 return;
1138 newitem->next = c->next;
1139 newitem->prev = c->prev;
1140 if (newitem->next)
1141 newitem->next->prev = newitem;
1142 if (c == array->child)
1143 array->child = newitem;
1144 else
1145 newitem->prev->next = newitem;
1146 c->next = c->prev = 0;
1147 cJSON_Delete(c);
1148}
1149void cJSON_ReplaceItemInObject(cJSON *object, const char *string,
1150 cJSON *newitem) {
1151 int i = 0;
1152 cJSON *c = object->child;
1153 while (c && strcmp(c->string, string))
1154 i++, c = c->next;
1155 if (c) {
1156 newitem->string = cJSON_strdup(string);
1157 cJSON_ReplaceItemInArray(object, i, newitem);
1158 }
1159}
1160
1161/* Create basic types: */
1162cJSON *cJSON_CreateNull(void) {
1163 cJSON *item = cJSON_New_Item();
1164 if (item)
1165 item->type = cJSON_NULL;
1166 return item;
1167}
1168cJSON *cJSON_CreateTrue(void) {
1169 cJSON *item = cJSON_New_Item();
1170 if (item)
1171 item->type = cJSON_True;
1172 return item;
1173}
1174cJSON *cJSON_CreateFalse(void) {
1175 cJSON *item = cJSON_New_Item();
1176 if (item)
1177 item->type = cJSON_False;
1178 return item;
1179}
1180cJSON *cJSON_CreateBool(int b) {
1181 cJSON *item = cJSON_New_Item();
1182 if (item)
1183 item->type = b ? cJSON_True : cJSON_False;
1184 return item;
1185}
1186cJSON *cJSON_CreateNumber(double num) {
1187 cJSON *item = cJSON_New_Item();
1188 if (item) {
1189 item->type = cJSON_Number;
1190 item->valuedouble = num;
1191 item->valueint = (int)num;
1192 }
1193 return item;
1194}
1195cJSON *cJSON_CreateString(const char *string) {
1196 cJSON *item = cJSON_New_Item();
1197 if (item) {
1198 item->type = cJSON_String;
1199 item->valuestring = cJSON_strdup(string);
1200 }
1201 return item;
1202}
1203cJSON *cJSON_CreateArray(void) {
1204 cJSON *item = cJSON_New_Item();
1205 if (item)
1206 item->type = cJSON_Array;
1207 return item;
1208}
1209cJSON *cJSON_CreateObject(void) {
1210 cJSON *item = cJSON_New_Item();
1211 if (item)
1212 item->type = cJSON_Object;
1213 return item;
1214}
1215
1216/* Create Arrays: */
1217cJSON *cJSON_CreateIntArray(const int *numbers, int count) {
1218 int i;
1219 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1220 for (i = 0; a && i < count; i++) {
1221 n = cJSON_CreateNumber(numbers[i]);
1222 if (!i)
1223 a->child = n;
1224 else
1225 suffix_object(p, n);
1226 p = n;
1227 }
1228 return a;
1229}
1230cJSON *cJSON_CreateFloatArray(const float *numbers, int count) {
1231 int i;
1232 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1233 for (i = 0; a && i < count; i++) {
1234 n = cJSON_CreateNumber(numbers[i]);
1235 if (!i)
1236 a->child = n;
1237 else
1238 suffix_object(p, n);
1239 p = n;
1240 }
1241 return a;
1242}
1243cJSON *cJSON_CreateDoubleArray(const double *numbers, int count) {
1244 int i;
1245 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1246 for (i = 0; a && i < count; i++) {
1247 n = cJSON_CreateNumber(numbers[i]);
1248 if (!i)
1249 a->child = n;
1250 else
1251 suffix_object(p, n);
1252 p = n;
1253 }
1254 return a;
1255}
1256cJSON *cJSON_CreateStringArray(const char **strings, int count) {
1257 int i;
1258 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1259 for (i = 0; a && i < count; i++) {
1260 n = cJSON_CreateString(strings[i]);
1261 if (!i)
1262 a->child = n;
1263 else
1264 suffix_object(p, n);
1265 p = n;
1266 }
1267 return a;
1268}
1269
1270/* Duplication */
1271cJSON *cJSON_Duplicate(cJSON *item, int recurse) {
1272 cJSON *newitem, *cptr, *nptr = 0, *newchild;
1273 /* Bail on bad ptr */
1274 if (!item)
1275 return 0;
1276 /* Create new item */
1277 newitem = cJSON_New_Item();
1278 if (!newitem)
1279 return 0;
1280 /* Copy over all vars */
1281 newitem->type = item->type & (~cJSON_IsReference),
1282 newitem->valueint = item->valueint,
1283 newitem->valuedouble = item->valuedouble;
1284 if (item->valuestring) {
1285 newitem->valuestring = cJSON_strdup(item->valuestring);
1286 if (!newitem->valuestring) {
1287 cJSON_Delete(newitem);
1288 return 0;
1289 }
1290 }
1291 if (item->string) {
1292 newitem->string = cJSON_strdup(item->string);
1293 if (!newitem->string) {
1294 cJSON_Delete(newitem);
1295 return 0;
1296 }
1297 }
1298 /* If non-recursive, then we're done! */
1299 if (!recurse)
1300 return newitem;
1301 /* Walk the ->next chain for the child. */
1302 cptr = item->child;
1303 while (cptr) {
1304 newchild = cJSON_Duplicate(
1305 cptr,
1306 1); /* Duplicate (with recurse) each item in the ->next chain */
1307 if (!newchild) {
1308 cJSON_Delete(newitem);
1309 return 0;
1310 }
1311 if (nptr) {
1312 nptr->next = newchild, newchild->prev = nptr;
1313 nptr = newchild;
1314 } /* If newitem->child already set, then crosswire ->prev and ->next and
1315 move on */
1316 else {
1317 newitem->child = newchild;
1318 nptr = newchild;
1319 } /* Set newitem->child and move to it */
1320 cptr = cptr->next;
1321 }
1322 return newitem;
1323}
1324
1325void cJSON_Minify(char *json) {
1326 char *into = json;
1327 while (*json) {
1328 if (*json == ' ')
1329 json++;
1330 else if (*json == '\t')
1331 json++; /* Whitespace characters. */
1332 else if (*json == '\r')
1333 json++;
1334 else if (*json == '\n')
1335 json++;
1336 else if (*json == '/' && json[1] == '/')
1337 while (*json && *json != '\n')
1338 json++; /* double-slash comments, to end of line. */
1339 else if (*json == '/' && json[1] == '*') {
1340 while (*json && !(*json == '*' && json[1] == '/'))
1341 json++;
1342 json += 2;
1343 } /* multiline comments. */
1344 else if (*json == '\"') {
1345 *into++ = *json++;
1346 while (*json && *json != '\"') {
1347 if (*json == '\\')
1348 *into++ = *json++;
1349 *into++ = *json++;
1350 }
1351 *into++ = *json++;
1352 } /* string literals, which are \" sensitive. */
1353 else
1354 *into++ = *json++; /* All other characters. */
1355 }
1356 *into = 0; /* and null-terminate. */
Jon Ashburn2077e382015-06-29 11:25:34 -06001357}