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