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