1 /*
2 Copyright (c) 2009 Dave Gamble
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 #include <string.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <stdlib.h>
30 #include <float.h>
31 #include <limits.h>
32 #include <ctype.h>
33 #include <assert.h>
34 #include "cJSON.h"
35
cJSON_strcasecmp(const char * s1,const char * s2)36 static int cJSON_strcasecmp(const char *s1, const char *s2)
37 {
38 if (!s1)
39 return (s1 == s2) ? 0 : 1;
40 if (!s2)
41 return 1;
42 for (; tolower(*s1) == tolower(*s2); ++s1, ++s2)
43 if (*s1 == 0)
44 return 0;
45 return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
46 }
47
48 static void *(*cJSON_malloc)(size_t sz) = malloc;
49 static void (*cJSON_free)(void *ptr) = free;
50
cJSON_strdup(const char * str)51 static char *cJSON_strdup(const char *str)
52 {
53 size_t len;
54 char *copy;
55
56 len = strlen(str) + 1;
57 if (!(copy = (char *)cJSON_malloc(len)))
58 return 0;
59 memcpy(copy, str, len);
60 return copy;
61 }
62
cJSON_InitHooks(cJSON_Hooks * hooks)63 void cJSON_InitHooks(cJSON_Hooks *hooks)
64 {
65 if (!hooks) { /* Reset hooks */
66 cJSON_malloc = malloc;
67 cJSON_free = free;
68 return;
69 }
70
71 cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
72 cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
73 }
74
75 /* The size of pool allocation groups. Note that the allocation
76 pools are only used during parsing, and not generation.
77 Additionally, this default value is based on empirical
78 evidence of best performance with Couchbase configuration
79 data */
80 #ifndef CJSON_POOL_ALLOC_SIZE
81 #define CJSON_POOL_ALLOC_SIZE 1024
82 #endif
83
84 /* Creates a new allocation pool. */
cJSON_New_PoolBlock(cJSON_Pool * pool)85 static cJSON_PoolBlock *cJSON_New_PoolBlock(cJSON_Pool *pool)
86 {
87 int i;
88 cJSON *item, *new_alloc;
89 cJSON_PoolBlock *new_block;
90
91 if (CJSON_POOL_ALLOC_SIZE <= 0) {
92 return 0;
93 }
94
95 new_block = (cJSON_PoolBlock *)cJSON_malloc(sizeof(cJSON_PoolBlock) + sizeof(cJSON) * CJSON_POOL_ALLOC_SIZE);
96 if (!new_block) {
97 return 0;
98 }
99
100 new_alloc = (cJSON *)(new_block + 1);
101
102 memset(new_block, 0, sizeof(cJSON_PoolBlock) + sizeof(cJSON) * CJSON_POOL_ALLOC_SIZE);
103
104 new_block->next = pool->blocks;
105 pool->blocks = new_block;
106
107 for (i = 0, item = new_alloc; i < CJSON_POOL_ALLOC_SIZE; ++i, ++item) {
108 item->next = pool->free_items;
109 pool->free_items = item;
110 }
111
112 return new_block;
113 }
114
115 /* This will create an allocation pool */
cJSON_New_Pool(void)116 static cJSON_Pool *cJSON_New_Pool(void)
117 {
118 if (CJSON_POOL_ALLOC_SIZE <= 0) {
119 return 0;
120 } else {
121 cJSON_Pool *pool = (cJSON_Pool *)cJSON_malloc(sizeof(cJSON_Pool));
122 if (!pool) {
123 return 0;
124 }
125
126 memset(pool, 0, sizeof(cJSON_Pool));
127 pool->free_items = 0;
128 pool->blocks = 0;
129 pool->refcount = 0;
130
131 return pool;
132 }
133 }
134
135 /* This will destroy an allocation pool */
cJSON_Destroy_Pool(cJSON_Pool * pool)136 static void cJSON_Destroy_Pool(cJSON_Pool *pool)
137 {
138 cJSON_PoolBlock *cur = pool->blocks, *next;
139 while (cur) {
140 next = cur->next;
141 /* this frees all the allocations as well */
142 cJSON_free(cur);
143 cur = next;
144 }
145 cJSON_free(pool);
146 }
147
148 /* allocate new item from a pool */
cJSON_Pool_New_Item(cJSON_Pool * pool)149 static cJSON *cJSON_Pool_New_Item(cJSON_Pool *pool)
150 {
151 if (!pool->free_items) {
152 cJSON_New_PoolBlock(pool);
153 }
154 if (pool->free_items) {
155 cJSON *node = pool->free_items;
156 pool->free_items = node->next;
157 pool->refcount++;
158 node->next = 0;
159 node->alloc_pool = pool;
160 /* all items in the pool are already zeroed */
161 return node;
162 }
163 return 0;
164 }
cJSON_Pool_Free_Item(cJSON_Pool * pool,cJSON * node)165 static void cJSON_Pool_Free_Item(cJSON_Pool *pool, cJSON *node)
166 {
167 /* Note that this code intentially does not return the item
168 to the pool if we are destroying the pool anyways. */
169 assert(pool->refcount);
170 if (--pool->refcount == 0) {
171 cJSON_Destroy_Pool(pool);
172 } else {
173 memset(node, 0, sizeof(cJSON));
174 node->next = pool->free_items;
175 pool->free_items = node;
176 }
177 }
178
179 /* Internal constructor. */
cJSON_New_Item(cJSON * parent)180 static cJSON *cJSON_New_Item(cJSON *parent)
181 {
182 cJSON *node = 0;
183 if (parent && parent->alloc_pool) {
184 node = cJSON_Pool_New_Item(parent->alloc_pool);
185 }
186 if (!node) {
187 node = (cJSON *)cJSON_malloc(sizeof(cJSON));
188 if (node) {
189 memset(node, 0, sizeof(cJSON));
190 }
191 }
192 return node;
193 }
194
cJSON_Free_Item(cJSON * node)195 static void cJSON_Free_Item(cJSON *node)
196 {
197 cJSON_Pool *pool = node->alloc_pool;
198 if (pool) {
199 cJSON_Pool_Free_Item(pool, node);
200 } else {
201 cJSON_free(node);
202 }
203 }
204
205 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * c)206 void cJSON_Delete(cJSON *c)
207 {
208 cJSON *next;
209 while (c) {
210 next = c->next;
211 if (!(c->type & cJSON_IsReference) && c->child)
212 cJSON_Delete(c->child);
213 if (!(c->type & cJSON_IsReference) && c->valuestring)
214 cJSON_free(c->valuestring);
215 if (c->string)
216 cJSON_free(c->string);
217 cJSON_Free_Item(c);
218 c = next;
219 }
220 }
221
222 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * item,const char * num)223 static const char *parse_number(cJSON *item, const char *num)
224 {
225 double n = 0, sign = 1, scale = 0;
226 int subscale = 0, signsubscale = 1;
227
228 /* Could use sscanf for this? */
229 if (*num == '-')
230 sign = -1, num++; /* Has sign? */
231 if (*num == '0')
232 num++; /* is zero */
233 if (*num >= '1' && *num <= '9')
234 do
235 n = (n * 10.0) + (*num++ - '0');
236 while (*num >= '0' && *num <= '9'); /* Number? */
237 if (*num == '.') {
238 num++;
239 do
240 n = (n * 10.0) + (*num++ - '0'), scale--;
241 while (*num >= '0' && *num <= '9');
242 } /* Fractional part? */
243 if (*num == 'e' || *num == 'E') /* Exponent? */
244 {
245 num++;
246 if (*num == '+')
247 num++;
248 else if (*num == '-')
249 signsubscale = -1, num++; /* With sign? */
250 while (*num >= '0' && *num <= '9')
251 subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
252 }
253
254 n = sign * n * pow(10.0, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
255
256 item->valuedouble = n;
257 item->valueint = (int)n;
258 item->type = cJSON_Number;
259 return num;
260 }
261
262 /* Render the number nicely from the given item into a string. */
print_number(cJSON * item)263 static char *print_number(cJSON *item)
264 {
265 char *str;
266 double d = item->valuedouble;
267 if (fabs(((double)item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) {
268 str = (char *)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
269 sprintf(str, "%d", item->valueint);
270 } else {
271 str = (char *)cJSON_malloc(64); /* This is a nice tradeoff. */
272 if (fabs(floor(d) - d) <= DBL_EPSILON)
273 sprintf(str, "%.0f", d);
274 else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)
275 sprintf(str, "%e", d);
276 else
277 sprintf(str, "%f", d);
278 }
279 return str;
280 }
281
282 /* Parse the input text into an unescaped cstring, and populate item. */
283 static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
parse_string(cJSON * item,const char * str)284 static const char *parse_string(cJSON *item, const char *str)
285 {
286 const char *ptr = str + 1;
287 char *ptr2;
288 char *out;
289 int len = 0;
290 unsigned uc;
291 if (*str != '\"')
292 return 0; /* not a string! */
293
294 while (*ptr != '\"' && (unsigned char)*ptr > 31 && ++len)
295 if (*ptr++ == '\\')
296 ptr++; /* Skip escaped quotes. */
297
298 out = (char *)cJSON_malloc(len + 1); /* This is how long we need for the string, roughly. */
299 if (!out)
300 return 0;
301
302 ptr = str + 1;
303 ptr2 = out;
304 while (*ptr != '\"' && (unsigned char)*ptr > 31) {
305 if (*ptr != '\\')
306 *ptr2++ = *ptr++;
307 else {
308 ptr++;
309 switch (*ptr) {
310 case 'b':
311 *ptr2++ = '\b';
312 break;
313 case 'f':
314 *ptr2++ = '\f';
315 break;
316 case 'n':
317 *ptr2++ = '\n';
318 break;
319 case 'r':
320 *ptr2++ = '\r';
321 break;
322 case 't':
323 *ptr2++ = '\t';
324 break;
325 case 'u': /* transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY. */
326 sscanf(ptr + 1, "%4x", &uc); /* get the unicode char. */
327 len = 3;
328 if (uc < 0x80)
329 len = 1;
330 else if (uc < 0x800)
331 len = 2;
332 ptr2 += len;
333
334 switch (len) {
335 case 3:
336 *--ptr2 = ((uc | 0x80) & 0xBF);
337 uc >>= 6; /* fall through */
338 case 2:
339 *--ptr2 = ((uc | 0x80) & 0xBF);
340 uc >>= 6; /* fall through */
341 case 1:
342 *--ptr2 = (uc | firstByteMark[len]); /* fall through */
343 }
344 ptr2 += len;
345 ptr += 4;
346 break;
347 default:
348 *ptr2++ = *ptr;
349 break;
350 }
351 ptr++;
352 }
353 }
354 *ptr2 = 0;
355 if (*ptr == '\"')
356 ptr++;
357 item->valuestring = out;
358 item->type = cJSON_String;
359 return ptr;
360 }
361
362 /* Render the cstring provided to an escaped version that can be printed. */
print_string_ptr(const char * str)363 static char *print_string_ptr(const char *str)
364 {
365 const char *ptr;
366 char *ptr2, *out;
367 int len = 0;
368
369 if (!str)
370 return cJSON_strdup("");
371 ptr = str;
372 while (*ptr && ++len) {
373 if ((unsigned char)*ptr < 32 || *ptr == '\"' || *ptr == '\\')
374 len++;
375 ptr++;
376 }
377
378 out = (char *)cJSON_malloc(len + 3);
379 ptr2 = out;
380 ptr = str;
381 *ptr2++ = '\"';
382 while (*ptr) {
383 if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
384 *ptr2++ = *ptr++;
385 else {
386 *ptr2++ = '\\';
387 switch (*ptr++) {
388 case '\\':
389 *ptr2++ = '\\';
390 break;
391 case '\"':
392 *ptr2++ = '\"';
393 break;
394 case '\b':
395 *ptr2++ = 'b';
396 break;
397 case '\f':
398 *ptr2++ = 'f';
399 break;
400 case '\n':
401 *ptr2++ = 'n';
402 break;
403 case '\r':
404 *ptr2++ = 'r';
405 break;
406 case '\t':
407 *ptr2++ = 't';
408 break;
409 default:
410 ptr2--;
411 break; /* eviscerate with prejudice. */
412 }
413 }
414 }
415 *ptr2++ = '\"';
416 *ptr2++ = 0;
417 return out;
418 }
419 /* Invote print_string_ptr (which is useful) on an item. */
print_string(cJSON * item)420 static char *print_string(cJSON *item)
421 {
422 return print_string_ptr(item->valuestring);
423 }
424
425 /* Predeclare these prototypes. */
426 static const char *parse_value(cJSON *item, const char *value);
427 static char *print_value(cJSON *item, int depth, int fmt);
428 static const char *parse_array(cJSON *item, const char *value);
429 static char *print_array(cJSON *item, int depth, int fmt);
430 static const char *parse_object(cJSON *item, const char *value);
431 static char *print_object(cJSON *item, int depth, int fmt);
432
433 /* Utility to jump whitespace and cr/lf */
skip(const char * in)434 static const char *skip(const char *in)
435 {
436 while (in && *in && (unsigned char)*in <= 32)
437 in++;
438 return in;
439 }
440
441 /* Parse an object - create a new root, and populate. */
cJSON_Parse(const char * value)442 cJSON *cJSON_Parse(const char *value)
443 {
444 cJSON_Pool *pool = cJSON_New_Pool();
445 cJSON *c = 0;
446 if (pool) {
447 c = cJSON_Pool_New_Item(pool);
448 }
449 if (!c) {
450 c = cJSON_New_Item(0);
451 }
452 if (!c)
453 return 0; /* memory fail */
454
455 c->alloc_pool = pool;
456
457 if (!parse_value(c, skip(value))) {
458 cJSON_Delete(c);
459 return 0;
460 }
461 return c;
462 }
463
464 /* Render a cJSON item/entity/structure to text. */
cJSON_Print(cJSON * item)465 char *cJSON_Print(cJSON *item)
466 {
467 return print_value(item, 0, 1);
468 }
cJSON_PrintUnformatted(cJSON * item)469 char *cJSON_PrintUnformatted(cJSON *item)
470 {
471 return print_value(item, 0, 0);
472 }
473
474 /* Parser core - when encountering text, process appropriately. */
parse_value(cJSON * item,const char * value)475 static const char *parse_value(cJSON *item, const char *value)
476 {
477 if (!value)
478 return 0; /* Fail on null. */
479 if (!strncmp(value, "null", 4)) {
480 item->type = cJSON_NULL;
481 return value + 4;
482 }
483 if (!strncmp(value, "false", 5)) {
484 item->type = cJSON_False;
485 return value + 5;
486 }
487 if (!strncmp(value, "true", 4)) {
488 item->type = cJSON_True;
489 item->valueint = 1;
490 return value + 4;
491 }
492 if (*value == '\"') {
493 return parse_string(item, value);
494 }
495 if (*value == '-' || (*value >= '0' && *value <= '9')) {
496 return parse_number(item, value);
497 }
498 if (*value == '[') {
499 return parse_array(item, value);
500 }
501 if (*value == '{') {
502 return parse_object(item, value);
503 }
504
505 return 0; /* failure. */
506 }
507
508 /* Render a value to text. */
print_value(cJSON * item,int depth,int fmt)509 static char *print_value(cJSON *item, int depth, int fmt)
510 {
511 char *out = 0;
512 if (!item)
513 return 0;
514 switch ((item->type) & 255) {
515 case cJSON_NULL:
516 out = cJSON_strdup("null");
517 break;
518 case cJSON_False:
519 out = cJSON_strdup("false");
520 break;
521 case cJSON_True:
522 out = cJSON_strdup("true");
523 break;
524 case cJSON_Number:
525 out = print_number(item);
526 break;
527 case cJSON_String:
528 out = print_string(item);
529 break;
530 case cJSON_Array:
531 out = print_array(item, depth, fmt);
532 break;
533 case cJSON_Object:
534 out = print_object(item, depth, fmt);
535 break;
536 }
537 return out;
538 }
539
540 /* Build an array from input text. */
parse_array(cJSON * item,const char * value)541 static const char *parse_array(cJSON *item, const char *value)
542 {
543 cJSON *child;
544 if (*value != '[')
545 return 0; /* not an array! */
546
547 item->type = cJSON_Array;
548 value = skip(value + 1);
549 if (*value == ']')
550 return value + 1; /* empty array. */
551
552 item->child = child = cJSON_New_Item(item);
553 if (!item->child)
554 return 0; /* memory fail */
555 value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */
556 if (!value)
557 return 0;
558
559 while (*value == ',') {
560 cJSON *new_item;
561 if (!(new_item = cJSON_New_Item(item)))
562 return 0; /* memory fail */
563 child->next = new_item;
564 new_item->prev = child;
565 child = new_item;
566 value = skip(parse_value(child, skip(value + 1)));
567 if (!value)
568 return 0; /* memory fail */
569 }
570
571 if (*value == ']')
572 return value + 1; /* end of array */
573 return 0; /* malformed. */
574 }
575
576 /* Render an array to text */
print_array(cJSON * item,int depth,int fmt)577 static char *print_array(cJSON *item, int depth, int fmt)
578 {
579 char **entries;
580 char *out = 0, *ptr, *ret;
581 size_t len = 5;
582 cJSON *child = item->child;
583 int numentries = 0, i = 0, fail = 0;
584
585 /* How many entries in the array? */
586 while (child)
587 numentries++, child = child->next;
588 /* Allocate an array to hold the values for each */
589 entries = (char **)cJSON_malloc(numentries * sizeof(char *));
590 if (!entries)
591 return 0;
592 memset(entries, 0, numentries * sizeof(char *));
593 /* Retrieve all the results: */
594 child = item->child;
595 while (child && !fail) {
596 ret = print_value(child, depth + 1, fmt);
597 entries[i++] = ret;
598 if (ret)
599 len += strlen(ret) + 2 + (fmt ? 1 : 0);
600 else
601 fail = 1;
602 child = child->next;
603 }
604
605 /* If we didn't fail, try to malloc the output string */
606 if (!fail)
607 out = cJSON_malloc(len);
608 /* If that fails, we fail. */
609 if (!out)
610 fail = 1;
611
612 /* Handle failure. */
613 if (fail) {
614 for (i = 0; i < numentries; i++)
615 if (entries[i])
616 cJSON_free(entries[i]);
617 cJSON_free(entries);
618 return 0;
619 }
620
621 /* Compose the output array. */
622 *out = '[';
623 ptr = out + 1;
624 *ptr = 0;
625 for (i = 0; i < numentries; i++) {
626 strcpy(ptr, entries[i]);
627 ptr += strlen(entries[i]);
628 if (i != numentries - 1) {
629 *ptr++ = ',';
630 if (fmt)
631 *ptr++ = ' ';
632 *ptr = 0;
633 }
634 cJSON_free(entries[i]);
635 }
636 cJSON_free(entries);
637 *ptr++ = ']';
638 *ptr++ = 0;
639 return out;
640 }
641
642 /* Build an object from the text. */
parse_object(cJSON * item,const char * value)643 static const char *parse_object(cJSON *item, const char *value)
644 {
645 cJSON *child;
646 if (*value != '{')
647 return 0; /* not an object! */
648
649 item->type = cJSON_Object;
650 value = skip(value + 1);
651 if (*value == '}')
652 return value + 1; /* empty array. */
653
654 item->child = child = cJSON_New_Item(item);
655 value = skip(parse_string(child, skip(value)));
656 if (!value)
657 return 0;
658 child->string = child->valuestring;
659 child->valuestring = 0;
660 if (*value != ':')
661 return 0; /* fail! */
662 value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
663 if (!value)
664 return 0;
665
666 while (*value == ',') {
667 cJSON *new_item;
668 if (!(new_item = cJSON_New_Item(item)))
669 return 0; /* memory fail */
670 child->next = new_item;
671 new_item->prev = child;
672 child = new_item;
673 value = skip(parse_string(child, skip(value + 1)));
674 if (!value)
675 return 0;
676 child->string = child->valuestring;
677 child->valuestring = 0;
678 if (*value != ':')
679 return 0; /* fail! */
680 value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
681 if (!value)
682 return 0;
683 }
684
685 if (*value == '}')
686 return value + 1; /* end of array */
687 return 0; /* malformed. */
688 }
689
690 /* Render an object to text. */
print_object(cJSON * item,int depth,int fmt)691 static char *print_object(cJSON *item, int depth, int fmt)
692 {
693 char **entries = 0, **names = 0;
694 char *out = 0, *ptr, *ret, *str;
695 size_t len = 7;
696 int i = 0, j;
697 cJSON *child = item->child;
698 int numentries = 0, fail = 0;
699 /* Count the number of entries. */
700 while (child)
701 numentries++, child = child->next;
702 /* Allocate space for the names and the objects */
703 entries = (char **)cJSON_malloc(numentries * sizeof(char *));
704 if (!entries)
705 return 0;
706 names = (char **)cJSON_malloc(numentries * sizeof(char *));
707 if (!names) {
708 cJSON_free(entries);
709 return 0;
710 }
711 memset(entries, 0, sizeof(char *) * numentries);
712 memset(names, 0, sizeof(char *) * numentries);
713
714 /* Collect all the results into our arrays: */
715 child = item->child;
716 depth++;
717 if (fmt)
718 len += depth;
719 while (child) {
720 names[i] = str = print_string_ptr(child->string);
721 entries[i++] = ret = print_value(child, depth, fmt);
722 if (str && ret)
723 len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
724 else
725 fail = 1;
726 child = child->next;
727 }
728
729 /* Try to allocate the output string */
730 if (!fail)
731 out = (char *)cJSON_malloc(len);
732 if (!out)
733 fail = 1;
734
735 /* Handle failure */
736 if (fail) {
737 for (i = 0; i < numentries; i++) {
738 if (names[i])
739 free(names[i]);
740 if (entries[i])
741 free(entries[i]);
742 }
743 free(names);
744 free(entries);
745 return 0;
746 }
747
748 /* Compose the output: */
749 *out = '{';
750 ptr = out + 1;
751 if (fmt)
752 *ptr++ = '\n';
753 *ptr = 0;
754 for (i = 0; i < numentries; i++) {
755 if (fmt)
756 for (j = 0; j < depth; j++)
757 *ptr++ = '\t';
758 strcpy(ptr, names[i]);
759 ptr += strlen(names[i]);
760 *ptr++ = ':';
761 if (fmt)
762 *ptr++ = '\t';
763 strcpy(ptr, entries[i]);
764 ptr += strlen(entries[i]);
765 if (i != numentries - 1)
766 *ptr++ = ',';
767 if (fmt)
768 *ptr++ = '\n';
769 *ptr = 0;
770 cJSON_free(names[i]);
771 cJSON_free(entries[i]);
772 }
773
774 cJSON_free(names);
775 cJSON_free(entries);
776 if (fmt)
777 for (i = 0; i < depth - 1; i++)
778 *ptr++ = '\t';
779 *ptr++ = '}';
780 *ptr++ = 0;
781 return out;
782 }
783
784 /* Get Array size/item / object item. */
cJSON_GetArraySize(cJSON * array)785 int cJSON_GetArraySize(cJSON *array)
786 {
787 cJSON *c = array->child;
788 int i = 0;
789 while (c)
790 i++, c = c->next;
791 return i;
792 }
cJSON_GetArrayItem(cJSON * array,int item)793 cJSON *cJSON_GetArrayItem(cJSON *array, int item)
794 {
795 cJSON *c = array->child;
796 while (c && item > 0)
797 item--, c = c->next;
798 return c;
799 }
cJSON_GetObjectItem(cJSON * object,const char * string)800 cJSON *cJSON_GetObjectItem(cJSON *object, const char *string)
801 {
802 cJSON *c = object->child;
803 while (c && cJSON_strcasecmp(c->string, string))
804 c = c->next;
805 return c;
806 }
807
808 /* Utility for array list handling. */
suffix_object(cJSON * prev,cJSON * item)809 static void suffix_object(cJSON *prev, cJSON *item)
810 {
811 prev->next = item;
812 item->prev = prev;
813 }
814 /* Utility for handling references. */
create_reference(cJSON * item)815 static cJSON *create_reference(cJSON *item)
816 {
817 cJSON *ref = cJSON_New_Item(item);
818 memcpy(ref, item, sizeof(cJSON));
819 ref->string = 0;
820 ref->type |= cJSON_IsReference;
821 ref->next = ref->prev = 0;
822 return ref;
823 }
824
825 /* Add item to array/object. */
cJSON_AddItemToArray(cJSON * array,cJSON * item)826 void cJSON_AddItemToArray(cJSON *array, cJSON *item)
827 {
828 cJSON *c = array->child;
829 if (!c) {
830 array->child = item;
831 } else {
832 while (c && c->next)
833 c = c->next;
834 suffix_object(c, item);
835 }
836 }
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)837 void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
838 {
839 if (item->string)
840 cJSON_free(item->string);
841 item->string = cJSON_strdup(string);
842 cJSON_AddItemToArray(object, item);
843 }
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)844 void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
845 {
846 cJSON_AddItemToArray(array, create_reference(item));
847 }
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)848 void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
849 {
850 cJSON_AddItemToObject(object, string, create_reference(item));
851 }
852
cJSON_DetachItemFromArray(cJSON * array,int which)853 cJSON *cJSON_DetachItemFromArray(cJSON *array, int which)
854 {
855 cJSON *c = array->child;
856 while (c && which > 0)
857 c = c->next, which--;
858 if (!c)
859 return 0;
860 if (c->prev)
861 c->prev->next = c->next;
862 if (c->next)
863 c->next->prev = c->prev;
864 if (c == array->child)
865 array->child = c->next;
866 c->prev = c->next = 0;
867 return c;
868 }
cJSON_DeleteItemFromArray(cJSON * array,int which)869 void cJSON_DeleteItemFromArray(cJSON *array, int which)
870 {
871 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
872 }
cJSON_DetachItemFromObject(cJSON * object,const char * string)873 cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string)
874 {
875 int i = 0;
876 cJSON *c = object->child;
877 while (c && cJSON_strcasecmp(c->string, string))
878 i++, c = c->next;
879 if (c)
880 return cJSON_DetachItemFromArray(object, i);
881 return 0;
882 }
cJSON_DeleteItemFromObject(cJSON * object,const char * string)883 void cJSON_DeleteItemFromObject(cJSON *object, const char *string)
884 {
885 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
886 }
887
888 /* Replace array/object items with new ones. */
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)889 void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
890 {
891 cJSON *c = array->child;
892 while (c && which > 0)
893 c = c->next, which--;
894 if (!c)
895 return;
896 newitem->next = c->next;
897 newitem->prev = c->prev;
898 if (newitem->next)
899 newitem->next->prev = newitem;
900 if (c == array->child)
901 array->child = newitem;
902 else
903 newitem->prev->next = newitem;
904 c->next = c->prev = 0;
905 cJSON_Delete(c);
906 }
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)907 void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
908 {
909 int i = 0;
910 cJSON *c = object->child;
911 while (c && cJSON_strcasecmp(c->string, string))
912 i++, c = c->next;
913 if (c) {
914 newitem->string = cJSON_strdup(string);
915 cJSON_ReplaceItemInArray(object, i, newitem);
916 }
917 }
918
919 /* Create basic types: */
cJSON_CreateNull()920 cJSON *cJSON_CreateNull()
921 {
922 cJSON *item = cJSON_New_Item(0);
923 item->type = cJSON_NULL;
924 return item;
925 }
cJSON_CreateTrue()926 cJSON *cJSON_CreateTrue()
927 {
928 cJSON *item = cJSON_New_Item(0);
929 item->type = cJSON_True;
930 return item;
931 }
cJSON_CreateFalse()932 cJSON *cJSON_CreateFalse()
933 {
934 cJSON *item = cJSON_New_Item(0);
935 item->type = cJSON_False;
936 return item;
937 }
cJSON_CreateNumber(double num)938 cJSON *cJSON_CreateNumber(double num)
939 {
940 cJSON *item = cJSON_New_Item(0);
941 item->type = cJSON_Number;
942 item->valuedouble = num;
943 item->valueint = (int)num;
944 return item;
945 }
cJSON_CreateString(const char * string)946 cJSON *cJSON_CreateString(const char *string)
947 {
948 cJSON *item = cJSON_New_Item(0);
949 item->type = cJSON_String;
950 item->valuestring = cJSON_strdup(string);
951 return item;
952 }
cJSON_CreateArray()953 cJSON *cJSON_CreateArray()
954 {
955 cJSON *item = cJSON_New_Item(0);
956 item->type = cJSON_Array;
957 return item;
958 }
cJSON_CreateObject()959 cJSON *cJSON_CreateObject()
960 {
961 cJSON *item = cJSON_New_Item(0);
962 item->type = cJSON_Object;
963 return item;
964 }
965
966 /* Create Arrays: */
cJSON_CreateIntArray(int * numbers,int count)967 cJSON *cJSON_CreateIntArray(int *numbers, int count)
968 {
969 int i;
970 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
971 for (i = 0; i < count; i++) {
972 n = cJSON_CreateNumber(numbers[i]);
973 if (!i)
974 a->child = n;
975 else
976 suffix_object(p, n);
977 p = n;
978 }
979 return a;
980 }
cJSON_CreateFloatArray(float * numbers,int count)981 cJSON *cJSON_CreateFloatArray(float *numbers, int count)
982 {
983 int i;
984 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
985 for (i = 0; i < count; i++) {
986 n = cJSON_CreateNumber(numbers[i]);
987 if (!i)
988 a->child = n;
989 else
990 suffix_object(p, n);
991 p = n;
992 }
993 return a;
994 }
cJSON_CreateDoubleArray(double * numbers,int count)995 cJSON *cJSON_CreateDoubleArray(double *numbers, int count)
996 {
997 int i;
998 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
999 for (i = 0; i < count; i++) {
1000 n = cJSON_CreateNumber(numbers[i]);
1001 if (!i)
1002 a->child = n;
1003 else
1004 suffix_object(p, n);
1005 p = n;
1006 }
1007 return a;
1008 }
cJSON_CreateStringArray(const char ** strings,int count)1009 cJSON *cJSON_CreateStringArray(const char **strings, int count)
1010 {
1011 int i;
1012 cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
1013 for (i = 0; i < count; i++) {
1014 n = cJSON_CreateString(strings[i]);
1015 if (!i)
1016 a->child = n;
1017 else
1018 suffix_object(p, n);
1019 p = n;
1020 }
1021 return a;
1022 }
1023