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