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