Subversion Repositories ESP8266_P1_Meter

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 raymond 1
/*
2
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
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
/* disable warnings about old C89 functions in MSVC */
27
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
28
#define _CRT_SECURE_NO_DEPRECATE
29
#endif
30
 
31
#ifdef __GNUC__
32
#pragma GCC visibility push(default)
33
#endif
34
#if defined(_MSC_VER)
35
#pragma warning (push)
36
/* disable warning about single line comments in system headers */
37
#pragma warning (disable : 4001)
38
#endif
39
 
40
#include <string.h>
41
#include <stdio.h>
42
#include <math.h>
43
#include <stdlib.h>
44
#include <limits.h>
45
#include <ctype.h>
46
#include <float.h>
47
 
48
#ifdef ENABLE_LOCALES
49
#include <locale.h>
50
#endif
51
 
52
#if defined(_MSC_VER)
53
#pragma warning (pop)
54
#endif
55
#ifdef __GNUC__
56
#pragma GCC visibility pop
57
#endif
58
 
59
#include "cJSON.h"
60
 
61
/* define our own boolean type */
62
#ifdef true
63
#undef true
64
#endif
65
#define true ((cJSON_bool)1)
66
 
67
#ifdef false
68
#undef false
69
#endif
70
#define false ((cJSON_bool)0)
71
 
72
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
73
#ifndef isinf
74
#define isinf(d) (isnan((d - d)) && !isnan(d))
75
#endif
76
#ifndef isnan
77
#define isnan(d) (d != d)
78
#endif
79
 
80
#ifndef NAN
81
#ifdef _WIN32
82
#define NAN sqrt(-1.0)
83
#else
84
#define NAN 0.0/0.0
85
#endif
86
#endif
87
 
88
typedef struct {
89
    const unsigned char *json;
90
    size_t position;
91
} error;
92
static error global_error = { NULL, 0 };
93
 
94
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
95
{
96
    return (const char*) (global_error.json + global_error.position);
97
}
98
 
99
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
100
{
101
    if (!cJSON_IsString(item))
102
    {
103
        return NULL;
104
    }
105
 
106
    return item->valuestring;
107
}
108
 
109
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
110
{
111
    if (!cJSON_IsNumber(item))
112
    {
113
        return (double) NAN;
114
    }
115
 
116
    return item->valuedouble;
117
}
118
 
119
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
120
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 19)
121
    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
122
#endif
123
 
124
CJSON_PUBLIC(const char*) cJSON_Version(void)
125
{
126
    static char version[15];
127
    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
128
 
129
    return version;
130
}
131
 
132
/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
133
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
134
{
135
    if ((string1 == NULL) || (string2 == NULL))
136
    {
137
        return 1;
138
    }
139
 
140
    if (string1 == string2)
141
    {
142
        return 0;
143
    }
144
 
145
    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
146
    {
147
        if (*string1 == '\0')
148
        {
149
            return 0;
150
        }
151
    }
152
 
153
    return tolower(*string1) - tolower(*string2);
154
}
155
 
156
typedef struct internal_hooks
157
{
158
    void *(CJSON_CDECL *allocate)(size_t size);
159
    void (CJSON_CDECL *deallocate)(void *pointer);
160
    void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
161
} internal_hooks;
162
 
163
#if defined(_MSC_VER)
164
/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
165
static void * CJSON_CDECL internal_malloc(size_t size)
166
{
167
    return malloc(size);
168
}
169
static void CJSON_CDECL internal_free(void *pointer)
170
{
171
    free(pointer);
172
}
173
static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
174
{
175
    return realloc(pointer, size);
176
}
177
#else
178
#define internal_malloc malloc
179
#define internal_free free
180
#define internal_realloc realloc
181
#endif
182
 
183
/* strlen of character literals resolved at compile time */
184
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
185
 
186
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
187
 
188
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
189
{
190
    size_t length = 0;
191
    unsigned char *copy = NULL;
192
 
193
    if (string == NULL)
194
    {
195
        return NULL;
196
    }
197
 
198
    length = strlen((const char*)string) + sizeof("");
199
    copy = (unsigned char*)hooks->allocate(length);
200
    if (copy == NULL)
201
    {
202
        return NULL;
203
    }
204
    memcpy(copy, string, length);
205
 
206
    return copy;
207
}
208
 
209
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
210
{
211
    if (hooks == NULL)
212
    {
213
        /* Reset hooks */
214
        global_hooks.allocate = malloc;
215
        global_hooks.deallocate = free;
216
        global_hooks.reallocate = realloc;
217
        return;
218
    }
219
 
220
    global_hooks.allocate = malloc;
221
    if (hooks->malloc_fn != NULL)
222
    {
223
        global_hooks.allocate = hooks->malloc_fn;
224
    }
225
 
226
    global_hooks.deallocate = free;
227
    if (hooks->free_fn != NULL)
228
    {
229
        global_hooks.deallocate = hooks->free_fn;
230
    }
231
 
232
    /* use realloc only if both free and malloc are used */
233
    global_hooks.reallocate = NULL;
234
    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
235
    {
236
        global_hooks.reallocate = realloc;
237
    }
238
}
239
 
240
/* Internal constructor. */
241
static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
242
{
243
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
244
    if (node)
245
    {
246
        memset(node, '\0', sizeof(cJSON));
247
    }
248
 
249
    return node;
250
}
251
 
252
/* Delete a cJSON structure. */
253
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
254
{
255
    cJSON *next = NULL;
256
    while (item != NULL)
257
    {
258
        next = item->next;
259
        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
260
        {
261
            cJSON_Delete(item->child);
262
        }
263
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
264
        {
265
            global_hooks.deallocate(item->valuestring);
266
            item->valuestring = NULL;
267
        }
268
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
269
        {
270
            global_hooks.deallocate(item->string);
271
            item->string = NULL;
272
        }
273
        global_hooks.deallocate(item);
274
        item = next;
275
    }
276
}
277
 
278
/* get the decimal point character of the current locale */
279
static unsigned char get_decimal_point(void)
280
{
281
#ifdef ENABLE_LOCALES
282
    struct lconv *lconv = localeconv();
283
    return (unsigned char) lconv->decimal_point[0];
284
#else
285
    return '.';
286
#endif
287
}
288
 
289
typedef struct
290
{
291
    const unsigned char *content;
292
    size_t length;
293
    size_t offset;
294
    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
295
    internal_hooks hooks;
296
} parse_buffer;
297
 
298
/* check if the given size is left to read in a given parse buffer (starting with 1) */
299
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
300
/* check if the buffer can be accessed at the given index (starting with 0) */
301
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
302
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
303
/* get a pointer to the buffer at the position */
304
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
305
 
306
/* Parse the input text to generate a number, and populate the result into item. */
307
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
308
{
309
    double number = 0;
310
    unsigned char *after_end = NULL;
311
    unsigned char *number_c_string;
312
    unsigned char decimal_point = get_decimal_point();
313
    size_t i = 0;
314
    size_t number_string_length = 0;
315
    cJSON_bool has_decimal_point = false;
316
 
317
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
318
    {
319
        return false;
320
    }
321
 
322
    /* copy the number into a temporary buffer and replace '.' with the decimal point
323
     * of the current locale (for strtod)
324
     * This also takes care of '\0' not necessarily being available for marking the end of the input */
325
    for (i = 0; can_access_at_index(input_buffer, i); i++)
326
    {
327
        switch (buffer_at_offset(input_buffer)[i])
328
        {
329
            case '0':
330
            case '1':
331
            case '2':
332
            case '3':
333
            case '4':
334
            case '5':
335
            case '6':
336
            case '7':
337
            case '8':
338
            case '9':
339
            case '+':
340
            case '-':
341
            case 'e':
342
            case 'E':
343
                number_string_length++;
344
                break;
345
 
346
            case '.':
347
                number_string_length++;
348
                has_decimal_point = true;
349
                break;
350
 
351
            default:
352
                goto loop_end;
353
        }
354
    }
355
loop_end:
356
    /* malloc for temporary buffer, add 1 for '\0' */
357
    number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1);
358
    if (number_c_string == NULL)
359
    {
360
        return false; /* allocation failure */
361
    }
362
 
363
    memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length);
364
    number_c_string[number_string_length] = '\0';
365
 
366
    if (has_decimal_point)
367
    {
368
        for (i = 0; i < number_string_length; i++)
369
        {
370
            if (number_c_string[i] == '.')
371
            {
372
                /* replace '.' with the decimal point of the current locale (for strtod) */
373
                number_c_string[i] = decimal_point;
374
            }
375
        }
376
    }
377
 
378
    number = strtod((const char*)number_c_string, (char**)&after_end);
379
    if (number_c_string == after_end)
380
    {
381
        /* free the temporary buffer */
382
        input_buffer->hooks.deallocate(number_c_string);
383
        return false; /* parse_error */
384
    }
385
 
386
    item->valuedouble = number;
387
 
388
    /* use saturation in case of overflow */
389
    if (number >= INT_MAX)
390
    {
391
        item->valueint = INT_MAX;
392
    }
393
    else if (number <= (double)INT_MIN)
394
    {
395
        item->valueint = INT_MIN;
396
    }
397
    else
398
    {
399
        item->valueint = (int)number;
400
    }
401
 
402
    item->type = cJSON_Number;
403
 
404
    input_buffer->offset += (size_t)(after_end - number_c_string);
405
    /* free the temporary buffer */
406
    input_buffer->hooks.deallocate(number_c_string);
407
    return true;
408
}
409
 
410
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
411
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
412
{
413
    if (number >= INT_MAX)
414
    {
415
        object->valueint = INT_MAX;
416
    }
417
    else if (number <= (double)INT_MIN)
418
    {
419
        object->valueint = INT_MIN;
420
    }
421
    else
422
    {
423
        object->valueint = (int)number;
424
    }
425
 
426
    return object->valuedouble = number;
427
}
428
 
429
/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */
430
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
431
{
432
    char *copy = NULL;
433
    size_t v1_len;
434
    size_t v2_len;
435
    /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
436
    if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
437
    {
438
        return NULL;
439
    }
440
    /* return NULL if the object is corrupted or valuestring is NULL */
441
    if (object->valuestring == NULL || valuestring == NULL)
442
    {
443
        return NULL;
444
    }
445
 
446
    v1_len = strlen(valuestring);
447
    v2_len = strlen(object->valuestring);
448
 
449
    if (v1_len <= v2_len)
450
    {
451
        /* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */
452
        if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring ))
453
        {
454
            return NULL;
455
        }
456
        strcpy(object->valuestring, valuestring);
457
        return object->valuestring;
458
    }
459
    copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
460
    if (copy == NULL)
461
    {
462
        return NULL;
463
    }
464
    if (object->valuestring != NULL)
465
    {
466
        cJSON_free(object->valuestring);
467
    }
468
    object->valuestring = copy;
469
 
470
    return copy;
471
}
472
 
473
typedef struct
474
{
475
    unsigned char *buffer;
476
    size_t length;
477
    size_t offset;
478
    size_t depth; /* current nesting depth (for formatted printing) */
479
    cJSON_bool noalloc;
480
    cJSON_bool format; /* is this print a formatted print */
481
    internal_hooks hooks;
482
} printbuffer;
483
 
484
/* realloc printbuffer if necessary to have at least "needed" bytes more */
485
static unsigned char* ensure(printbuffer * const p, size_t needed)
486
{
487
    unsigned char *newbuffer = NULL;
488
    size_t newsize = 0;
489
 
490
    if ((p == NULL) || (p->buffer == NULL))
491
    {
492
        return NULL;
493
    }
494
 
495
    if ((p->length > 0) && (p->offset >= p->length))
496
    {
497
        /* make sure that offset is valid */
498
        return NULL;
499
    }
500
 
501
    if (needed > INT_MAX)
502
    {
503
        /* sizes bigger than INT_MAX are currently not supported */
504
        return NULL;
505
    }
506
 
507
    needed += p->offset + 1;
508
    if (needed <= p->length)
509
    {
510
        return p->buffer + p->offset;
511
    }
512
 
513
    if (p->noalloc) {
514
        return NULL;
515
    }
516
 
517
    /* calculate new buffer size */
518
    if (needed > (INT_MAX / 2))
519
    {
520
        /* overflow of int, use INT_MAX if possible */
521
        if (needed <= INT_MAX)
522
        {
523
            newsize = INT_MAX;
524
        }
525
        else
526
        {
527
            return NULL;
528
        }
529
    }
530
    else
531
    {
532
        newsize = needed * 2;
533
    }
534
 
535
    if (p->hooks.reallocate != NULL)
536
    {
537
        /* reallocate with realloc if available */
538
        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
539
        if (newbuffer == NULL)
540
        {
541
            p->hooks.deallocate(p->buffer);
542
            p->length = 0;
543
            p->buffer = NULL;
544
 
545
            return NULL;
546
        }
547
    }
548
    else
549
    {
550
        /* otherwise reallocate manually */
551
        newbuffer = (unsigned char*)p->hooks.allocate(newsize);
552
        if (!newbuffer)
553
        {
554
            p->hooks.deallocate(p->buffer);
555
            p->length = 0;
556
            p->buffer = NULL;
557
 
558
            return NULL;
559
        }
560
 
561
        memcpy(newbuffer, p->buffer, p->offset + 1);
562
        p->hooks.deallocate(p->buffer);
563
    }
564
    p->length = newsize;
565
    p->buffer = newbuffer;
566
 
567
    return newbuffer + p->offset;
568
}
569
 
570
/* calculate the new length of the string in a printbuffer and update the offset */
571
static void update_offset(printbuffer * const buffer)
572
{
573
    const unsigned char *buffer_pointer = NULL;
574
    if ((buffer == NULL) || (buffer->buffer == NULL))
575
    {
576
        return;
577
    }
578
    buffer_pointer = buffer->buffer + buffer->offset;
579
 
580
    buffer->offset += strlen((const char*)buffer_pointer);
581
}
582
 
583
/* securely comparison of floating-point variables */
584
static cJSON_bool compare_double(double a, double b)
585
{
586
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
587
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
588
}
589
 
590
/* Render the number nicely from the given item into a string. */
591
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
592
{
593
    unsigned char *output_pointer = NULL;
594
    double d = item->valuedouble;
595
    int length = 0;
596
    size_t i = 0;
597
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
598
    unsigned char decimal_point = get_decimal_point();
599
    double test = 0.0;
600
 
601
    if (output_buffer == NULL)
602
    {
603
        return false;
604
    }
605
 
606
    /* This checks for NaN and Infinity */
607
    if (isnan(d) || isinf(d))
608
    {
609
        length = sprintf((char*)number_buffer, "null");
610
    }
611
    else if(d == (double)item->valueint)
612
    {
613
        length = sprintf((char*)number_buffer, "%d", item->valueint);
614
    }
615
    else
616
    {
617
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
618
        length = sprintf((char*)number_buffer, "%1.15g", d);
619
 
620
        /* Check whether the original double can be recovered */
621
        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
622
        {
623
            /* If not, print with 17 decimal places of precision */
624
            length = sprintf((char*)number_buffer, "%1.17g", d);
625
        }
626
    }
627
 
628
    /* sprintf failed or buffer overrun occurred */
629
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
630
    {
631
        return false;
632
    }
633
 
634
    /* reserve appropriate space in the output */
635
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
636
    if (output_pointer == NULL)
637
    {
638
        return false;
639
    }
640
 
641
    /* copy the printed number to the output and replace locale
642
     * dependent decimal point with '.' */
643
    for (i = 0; i < ((size_t)length); i++)
644
    {
645
        if (number_buffer[i] == decimal_point)
646
        {
647
            output_pointer[i] = '.';
648
            continue;
649
        }
650
 
651
        output_pointer[i] = number_buffer[i];
652
    }
653
    output_pointer[i] = '\0';
654
 
655
    output_buffer->offset += (size_t)length;
656
 
657
    return true;
658
}
659
 
660
/* parse 4 digit hexadecimal number */
661
static unsigned parse_hex4(const unsigned char * const input)
662
{
663
    unsigned int h = 0;
664
    size_t i = 0;
665
 
666
    for (i = 0; i < 4; i++)
667
    {
668
        /* parse digit */
669
        if ((input[i] >= '0') && (input[i] <= '9'))
670
        {
671
            h += (unsigned int) input[i] - '0';
672
        }
673
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
674
        {
675
            h += (unsigned int) 10 + input[i] - 'A';
676
        }
677
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
678
        {
679
            h += (unsigned int) 10 + input[i] - 'a';
680
        }
681
        else /* invalid */
682
        {
683
            return 0;
684
        }
685
 
686
        if (i < 3)
687
        {
688
            /* shift left to make place for the next nibble */
689
            h = h << 4;
690
        }
691
    }
692
 
693
    return h;
694
}
695
 
696
/* converts a UTF-16 literal to UTF-8
697
 * A literal can be one or two sequences of the form \uXXXX */
698
static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
699
{
700
    long unsigned int codepoint = 0;
701
    unsigned int first_code = 0;
702
    const unsigned char *first_sequence = input_pointer;
703
    unsigned char utf8_length = 0;
704
    unsigned char utf8_position = 0;
705
    unsigned char sequence_length = 0;
706
    unsigned char first_byte_mark = 0;
707
 
708
    if ((input_end - first_sequence) < 6)
709
    {
710
        /* input ends unexpectedly */
711
        goto fail;
712
    }
713
 
714
    /* get the first utf16 sequence */
715
    first_code = parse_hex4(first_sequence + 2);
716
 
717
    /* check that the code is valid */
718
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
719
    {
720
        goto fail;
721
    }
722
 
723
    /* UTF16 surrogate pair */
724
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
725
    {
726
        const unsigned char *second_sequence = first_sequence + 6;
727
        unsigned int second_code = 0;
728
        sequence_length = 12; /* \uXXXX\uXXXX */
729
 
730
        if ((input_end - second_sequence) < 6)
731
        {
732
            /* input ends unexpectedly */
733
            goto fail;
734
        }
735
 
736
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
737
        {
738
            /* missing second half of the surrogate pair */
739
            goto fail;
740
        }
741
 
742
        /* get the second utf16 sequence */
743
        second_code = parse_hex4(second_sequence + 2);
744
        /* check that the code is valid */
745
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
746
        {
747
            /* invalid second half of the surrogate pair */
748
            goto fail;
749
        }
750
 
751
 
752
        /* calculate the unicode codepoint from the surrogate pair */
753
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
754
    }
755
    else
756
    {
757
        sequence_length = 6; /* \uXXXX */
758
        codepoint = first_code;
759
    }
760
 
761
    /* encode as UTF-8
762
     * takes at maximum 4 bytes to encode:
763
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
764
    if (codepoint < 0x80)
765
    {
766
        /* normal ascii, encoding 0xxxxxxx */
767
        utf8_length = 1;
768
    }
769
    else if (codepoint < 0x800)
770
    {
771
        /* two bytes, encoding 110xxxxx 10xxxxxx */
772
        utf8_length = 2;
773
        first_byte_mark = 0xC0; /* 11000000 */
774
    }
775
    else if (codepoint < 0x10000)
776
    {
777
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
778
        utf8_length = 3;
779
        first_byte_mark = 0xE0; /* 11100000 */
780
    }
781
    else if (codepoint <= 0x10FFFF)
782
    {
783
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
784
        utf8_length = 4;
785
        first_byte_mark = 0xF0; /* 11110000 */
786
    }
787
    else
788
    {
789
        /* invalid unicode codepoint */
790
        goto fail;
791
    }
792
 
793
    /* encode as utf8 */
794
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
795
    {
796
        /* 10xxxxxx */
797
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
798
        codepoint >>= 6;
799
    }
800
    /* encode first byte */
801
    if (utf8_length > 1)
802
    {
803
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
804
    }
805
    else
806
    {
807
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
808
    }
809
 
810
    *output_pointer += utf8_length;
811
 
812
    return sequence_length;
813
 
814
fail:
815
    return 0;
816
}
817
 
818
/* Parse the input text into an unescaped cinput, and populate item. */
819
static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
820
{
821
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
822
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
823
    unsigned char *output_pointer = NULL;
824
    unsigned char *output = NULL;
825
 
826
    /* not a string */
827
    if (buffer_at_offset(input_buffer)[0] != '\"')
828
    {
829
        goto fail;
830
    }
831
 
832
    {
833
        /* calculate approximate size of the output (overestimate) */
834
        size_t allocation_length = 0;
835
        size_t skipped_bytes = 0;
836
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
837
        {
838
            /* is escape sequence */
839
            if (input_end[0] == '\\')
840
            {
841
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
842
                {
843
                    /* prevent buffer overflow when last input character is a backslash */
844
                    goto fail;
845
                }
846
                skipped_bytes++;
847
                input_end++;
848
            }
849
            input_end++;
850
        }
851
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
852
        {
853
            goto fail; /* string ended unexpectedly */
854
        }
855
 
856
        /* This is at most how much we need for the output */
857
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
858
        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
859
        if (output == NULL)
860
        {
861
            goto fail; /* allocation failure */
862
        }
863
    }
864
 
865
    output_pointer = output;
866
    /* loop through the string literal */
867
    while (input_pointer < input_end)
868
    {
869
        if (*input_pointer != '\\')
870
        {
871
            *output_pointer++ = *input_pointer++;
872
        }
873
        /* escape sequence */
874
        else
875
        {
876
            unsigned char sequence_length = 2;
877
            if ((input_end - input_pointer) < 1)
878
            {
879
                goto fail;
880
            }
881
 
882
            switch (input_pointer[1])
883
            {
884
                case 'b':
885
                    *output_pointer++ = '\b';
886
                    break;
887
                case 'f':
888
                    *output_pointer++ = '\f';
889
                    break;
890
                case 'n':
891
                    *output_pointer++ = '\n';
892
                    break;
893
                case 'r':
894
                    *output_pointer++ = '\r';
895
                    break;
896
                case 't':
897
                    *output_pointer++ = '\t';
898
                    break;
899
                case '\"':
900
                case '\\':
901
                case '/':
902
                    *output_pointer++ = input_pointer[1];
903
                    break;
904
 
905
                /* UTF-16 literal */
906
                case 'u':
907
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
908
                    if (sequence_length == 0)
909
                    {
910
                        /* failed to convert UTF16-literal to UTF-8 */
911
                        goto fail;
912
                    }
913
                    break;
914
 
915
                default:
916
                    goto fail;
917
            }
918
            input_pointer += sequence_length;
919
        }
920
    }
921
 
922
    /* zero terminate the output */
923
    *output_pointer = '\0';
924
 
925
    item->type = cJSON_String;
926
    item->valuestring = (char*)output;
927
 
928
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
929
    input_buffer->offset++;
930
 
931
    return true;
932
 
933
fail:
934
    if (output != NULL)
935
    {
936
        input_buffer->hooks.deallocate(output);
937
        output = NULL;
938
    }
939
 
940
    if (input_pointer != NULL)
941
    {
942
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
943
    }
944
 
945
    return false;
946
}
947
 
948
/* Render the cstring provided to an escaped version that can be printed. */
949
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
950
{
951
    const unsigned char *input_pointer = NULL;
952
    unsigned char *output = NULL;
953
    unsigned char *output_pointer = NULL;
954
    size_t output_length = 0;
955
    /* numbers of additional characters needed for escaping */
956
    size_t escape_characters = 0;
957
 
958
    if (output_buffer == NULL)
959
    {
960
        return false;
961
    }
962
 
963
    /* empty string */
964
    if (input == NULL)
965
    {
966
        output = ensure(output_buffer, sizeof("\"\""));
967
        if (output == NULL)
968
        {
969
            return false;
970
        }
971
        strcpy((char*)output, "\"\"");
972
 
973
        return true;
974
    }
975
 
976
    /* set "flag" to 1 if something needs to be escaped */
977
    for (input_pointer = input; *input_pointer; input_pointer++)
978
    {
979
        switch (*input_pointer)
980
        {
981
            case '\"':
982
            case '\\':
983
            case '\b':
984
            case '\f':
985
            case '\n':
986
            case '\r':
987
            case '\t':
988
                /* one character escape sequence */
989
                escape_characters++;
990
                break;
991
            default:
992
                if (*input_pointer < 32)
993
                {
994
                    /* UTF-16 escape sequence uXXXX */
995
                    escape_characters += 5;
996
                }
997
                break;
998
        }
999
    }
1000
    output_length = (size_t)(input_pointer - input) + escape_characters;
1001
 
1002
    output = ensure(output_buffer, output_length + sizeof("\"\""));
1003
    if (output == NULL)
1004
    {
1005
        return false;
1006
    }
1007
 
1008
    /* no characters have to be escaped */
1009
    if (escape_characters == 0)
1010
    {
1011
        output[0] = '\"';
1012
        memcpy(output + 1, input, output_length);
1013
        output[output_length + 1] = '\"';
1014
        output[output_length + 2] = '\0';
1015
 
1016
        return true;
1017
    }
1018
 
1019
    output[0] = '\"';
1020
    output_pointer = output + 1;
1021
    /* copy the string */
1022
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1023
    {
1024
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1025
        {
1026
            /* normal character, copy */
1027
            *output_pointer = *input_pointer;
1028
        }
1029
        else
1030
        {
1031
            /* character needs to be escaped */
1032
            *output_pointer++ = '\\';
1033
            switch (*input_pointer)
1034
            {
1035
                case '\\':
1036
                    *output_pointer = '\\';
1037
                    break;
1038
                case '\"':
1039
                    *output_pointer = '\"';
1040
                    break;
1041
                case '\b':
1042
                    *output_pointer = 'b';
1043
                    break;
1044
                case '\f':
1045
                    *output_pointer = 'f';
1046
                    break;
1047
                case '\n':
1048
                    *output_pointer = 'n';
1049
                    break;
1050
                case '\r':
1051
                    *output_pointer = 'r';
1052
                    break;
1053
                case '\t':
1054
                    *output_pointer = 't';
1055
                    break;
1056
                default:
1057
                    /* escape and print as unicode codepoint */
1058
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
1059
                    output_pointer += 4;
1060
                    break;
1061
            }
1062
        }
1063
    }
1064
    output[output_length + 1] = '\"';
1065
    output[output_length + 2] = '\0';
1066
 
1067
    return true;
1068
}
1069
 
1070
/* Invoke print_string_ptr (which is useful) on an item. */
1071
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1072
{
1073
    return print_string_ptr((unsigned char*)item->valuestring, p);
1074
}
1075
 
1076
/* Predeclare these prototypes. */
1077
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1078
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1079
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1080
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1081
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1082
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1083
 
1084
/* Utility to jump whitespace and cr/lf */
1085
static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1086
{
1087
    if ((buffer == NULL) || (buffer->content == NULL))
1088
    {
1089
        return NULL;
1090
    }
1091
 
1092
    if (cannot_access_at_index(buffer, 0))
1093
    {
1094
        return buffer;
1095
    }
1096
 
1097
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1098
    {
1099
       buffer->offset++;
1100
    }
1101
 
1102
    if (buffer->offset == buffer->length)
1103
    {
1104
        buffer->offset--;
1105
    }
1106
 
1107
    return buffer;
1108
}
1109
 
1110
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1111
static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1112
{
1113
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1114
    {
1115
        return NULL;
1116
    }
1117
 
1118
    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1119
    {
1120
        buffer->offset += 3;
1121
    }
1122
 
1123
    return buffer;
1124
}
1125
 
1126
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1127
{
1128
    size_t buffer_length;
1129
 
1130
    if (NULL == value)
1131
    {
1132
        return NULL;
1133
    }
1134
 
1135
    /* Adding null character size due to require_null_terminated. */
1136
    buffer_length = strlen(value) + sizeof("");
1137
 
1138
    return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1139
}
1140
 
1141
/* Parse an object - create a new root, and populate. */
1142
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1143
{
1144
    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1145
    cJSON *item = NULL;
1146
 
1147
    /* reset error position */
1148
    global_error.json = NULL;
1149
    global_error.position = 0;
1150
 
1151
    if (value == NULL || 0 == buffer_length)
1152
    {
1153
        goto fail;
1154
    }
1155
 
1156
    buffer.content = (const unsigned char*)value;
1157
    buffer.length = buffer_length;
1158
    buffer.offset = 0;
1159
    buffer.hooks = global_hooks;
1160
 
1161
    item = cJSON_New_Item(&global_hooks);
1162
    if (item == NULL) /* memory fail */
1163
    {
1164
        goto fail;
1165
    }
1166
 
1167
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1168
    {
1169
        /* parse failure. ep is set. */
1170
        goto fail;
1171
    }
1172
 
1173
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1174
    if (require_null_terminated)
1175
    {
1176
        buffer_skip_whitespace(&buffer);
1177
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1178
        {
1179
            goto fail;
1180
        }
1181
    }
1182
    if (return_parse_end)
1183
    {
1184
        *return_parse_end = (const char*)buffer_at_offset(&buffer);
1185
    }
1186
 
1187
    return item;
1188
 
1189
fail:
1190
    if (item != NULL)
1191
    {
1192
        cJSON_Delete(item);
1193
    }
1194
 
1195
    if (value != NULL)
1196
    {
1197
        error local_error;
1198
        local_error.json = (const unsigned char*)value;
1199
        local_error.position = 0;
1200
 
1201
        if (buffer.offset < buffer.length)
1202
        {
1203
            local_error.position = buffer.offset;
1204
        }
1205
        else if (buffer.length > 0)
1206
        {
1207
            local_error.position = buffer.length - 1;
1208
        }
1209
 
1210
        if (return_parse_end != NULL)
1211
        {
1212
            *return_parse_end = (const char*)local_error.json + local_error.position;
1213
        }
1214
 
1215
        global_error = local_error;
1216
    }
1217
 
1218
    return NULL;
1219
}
1220
 
1221
/* Default options for cJSON_Parse */
1222
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1223
{
1224
    return cJSON_ParseWithOpts(value, 0, 0);
1225
}
1226
 
1227
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1228
{
1229
    return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1230
}
1231
 
1232
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1233
 
1234
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1235
{
1236
    static const size_t default_buffer_size = 256;
1237
    printbuffer buffer[1];
1238
    unsigned char *printed = NULL;
1239
 
1240
    memset(buffer, 0, sizeof(buffer));
1241
 
1242
    /* create buffer */
1243
    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1244
    buffer->length = default_buffer_size;
1245
    buffer->format = format;
1246
    buffer->hooks = *hooks;
1247
    if (buffer->buffer == NULL)
1248
    {
1249
        goto fail;
1250
    }
1251
 
1252
    /* print the value */
1253
    if (!print_value(item, buffer))
1254
    {
1255
        goto fail;
1256
    }
1257
    update_offset(buffer);
1258
 
1259
    /* check if reallocate is available */
1260
    if (hooks->reallocate != NULL)
1261
    {
1262
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1263
        if (printed == NULL) {
1264
            goto fail;
1265
        }
1266
        buffer->buffer = NULL;
1267
    }
1268
    else /* otherwise copy the JSON over to a new buffer */
1269
    {
1270
        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1271
        if (printed == NULL)
1272
        {
1273
            goto fail;
1274
        }
1275
        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1276
        printed[buffer->offset] = '\0'; /* just to be sure */
1277
 
1278
        /* free the buffer */
1279
        hooks->deallocate(buffer->buffer);
1280
        buffer->buffer = NULL;
1281
    }
1282
 
1283
    return printed;
1284
 
1285
fail:
1286
    if (buffer->buffer != NULL)
1287
    {
1288
        hooks->deallocate(buffer->buffer);
1289
        buffer->buffer = NULL;
1290
    }
1291
 
1292
    if (printed != NULL)
1293
    {
1294
        hooks->deallocate(printed);
1295
        printed = NULL;
1296
    }
1297
 
1298
    return NULL;
1299
}
1300
 
1301
/* Render a cJSON item/entity/structure to text. */
1302
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1303
{
1304
    return (char*)print(item, true, &global_hooks);
1305
}
1306
 
1307
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1308
{
1309
    return (char*)print(item, false, &global_hooks);
1310
}
1311
 
1312
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1313
{
1314
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1315
 
1316
    if (prebuffer < 0)
1317
    {
1318
        return NULL;
1319
    }
1320
 
1321
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1322
    if (!p.buffer)
1323
    {
1324
        return NULL;
1325
    }
1326
 
1327
    p.length = (size_t)prebuffer;
1328
    p.offset = 0;
1329
    p.noalloc = false;
1330
    p.format = fmt;
1331
    p.hooks = global_hooks;
1332
 
1333
    if (!print_value(item, &p))
1334
    {
1335
        global_hooks.deallocate(p.buffer);
1336
        p.buffer = NULL;
1337
        return NULL;
1338
    }
1339
 
1340
    return (char*)p.buffer;
1341
}
1342
 
1343
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1344
{
1345
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1346
 
1347
    if ((length < 0) || (buffer == NULL))
1348
    {
1349
        return false;
1350
    }
1351
 
1352
    p.buffer = (unsigned char*)buffer;
1353
    p.length = (size_t)length;
1354
    p.offset = 0;
1355
    p.noalloc = true;
1356
    p.format = format;
1357
    p.hooks = global_hooks;
1358
 
1359
    return print_value(item, &p);
1360
}
1361
 
1362
/* Parser core - when encountering text, process appropriately. */
1363
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1364
{
1365
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
1366
    {
1367
        return false; /* no input */
1368
    }
1369
 
1370
    /* parse the different types of values */
1371
    /* null */
1372
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1373
    {
1374
        item->type = cJSON_NULL;
1375
        input_buffer->offset += 4;
1376
        return true;
1377
    }
1378
    /* false */
1379
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1380
    {
1381
        item->type = cJSON_False;
1382
        input_buffer->offset += 5;
1383
        return true;
1384
    }
1385
    /* true */
1386
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1387
    {
1388
        item->type = cJSON_True;
1389
        item->valueint = 1;
1390
        input_buffer->offset += 4;
1391
        return true;
1392
    }
1393
    /* string */
1394
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1395
    {
1396
        return parse_string(item, input_buffer);
1397
    }
1398
    /* number */
1399
    if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
1400
    {
1401
        return parse_number(item, input_buffer);
1402
    }
1403
    /* array */
1404
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1405
    {
1406
        return parse_array(item, input_buffer);
1407
    }
1408
    /* object */
1409
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1410
    {
1411
        return parse_object(item, input_buffer);
1412
    }
1413
 
1414
    return false;
1415
}
1416
 
1417
/* Render a value to text. */
1418
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1419
{
1420
    unsigned char *output = NULL;
1421
 
1422
    if ((item == NULL) || (output_buffer == NULL))
1423
    {
1424
        return false;
1425
    }
1426
 
1427
    switch ((item->type) & 0xFF)
1428
    {
1429
        case cJSON_NULL:
1430
            output = ensure(output_buffer, 5);
1431
            if (output == NULL)
1432
            {
1433
                return false;
1434
            }
1435
            strcpy((char*)output, "null");
1436
            return true;
1437
 
1438
        case cJSON_False:
1439
            output = ensure(output_buffer, 6);
1440
            if (output == NULL)
1441
            {
1442
                return false;
1443
            }
1444
            strcpy((char*)output, "false");
1445
            return true;
1446
 
1447
        case cJSON_True:
1448
            output = ensure(output_buffer, 5);
1449
            if (output == NULL)
1450
            {
1451
                return false;
1452
            }
1453
            strcpy((char*)output, "true");
1454
            return true;
1455
 
1456
        case cJSON_Number:
1457
            return print_number(item, output_buffer);
1458
 
1459
        case cJSON_Raw:
1460
        {
1461
            size_t raw_length = 0;
1462
            if (item->valuestring == NULL)
1463
            {
1464
                return false;
1465
            }
1466
 
1467
            raw_length = strlen(item->valuestring) + sizeof("");
1468
            output = ensure(output_buffer, raw_length);
1469
            if (output == NULL)
1470
            {
1471
                return false;
1472
            }
1473
            memcpy(output, item->valuestring, raw_length);
1474
            return true;
1475
        }
1476
 
1477
        case cJSON_String:
1478
            return print_string(item, output_buffer);
1479
 
1480
        case cJSON_Array:
1481
            return print_array(item, output_buffer);
1482
 
1483
        case cJSON_Object:
1484
            return print_object(item, output_buffer);
1485
 
1486
        default:
1487
            return false;
1488
    }
1489
}
1490
 
1491
/* Build an array from input text. */
1492
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1493
{
1494
    cJSON *head = NULL; /* head of the linked list */
1495
    cJSON *current_item = NULL;
1496
 
1497
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1498
    {
1499
        return false; /* to deeply nested */
1500
    }
1501
    input_buffer->depth++;
1502
 
1503
    if (buffer_at_offset(input_buffer)[0] != '[')
1504
    {
1505
        /* not an array */
1506
        goto fail;
1507
    }
1508
 
1509
    input_buffer->offset++;
1510
    buffer_skip_whitespace(input_buffer);
1511
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1512
    {
1513
        /* empty array */
1514
        goto success;
1515
    }
1516
 
1517
    /* check if we skipped to the end of the buffer */
1518
    if (cannot_access_at_index(input_buffer, 0))
1519
    {
1520
        input_buffer->offset--;
1521
        goto fail;
1522
    }
1523
 
1524
    /* step back to character in front of the first element */
1525
    input_buffer->offset--;
1526
    /* loop through the comma separated array elements */
1527
    do
1528
    {
1529
        /* allocate next item */
1530
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1531
        if (new_item == NULL)
1532
        {
1533
            goto fail; /* allocation failure */
1534
        }
1535
 
1536
        /* attach next item to list */
1537
        if (head == NULL)
1538
        {
1539
            /* start the linked list */
1540
            current_item = head = new_item;
1541
        }
1542
        else
1543
        {
1544
            /* add to the end and advance */
1545
            current_item->next = new_item;
1546
            new_item->prev = current_item;
1547
            current_item = new_item;
1548
        }
1549
 
1550
        /* parse next value */
1551
        input_buffer->offset++;
1552
        buffer_skip_whitespace(input_buffer);
1553
        if (!parse_value(current_item, input_buffer))
1554
        {
1555
            goto fail; /* failed to parse value */
1556
        }
1557
        buffer_skip_whitespace(input_buffer);
1558
    }
1559
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1560
 
1561
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1562
    {
1563
        goto fail; /* expected end of array */
1564
    }
1565
 
1566
success:
1567
    input_buffer->depth--;
1568
 
1569
    if (head != NULL) {
1570
        head->prev = current_item;
1571
    }
1572
 
1573
    item->type = cJSON_Array;
1574
    item->child = head;
1575
 
1576
    input_buffer->offset++;
1577
 
1578
    return true;
1579
 
1580
fail:
1581
    if (head != NULL)
1582
    {
1583
        cJSON_Delete(head);
1584
    }
1585
 
1586
    return false;
1587
}
1588
 
1589
/* Render an array to text */
1590
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1591
{
1592
    unsigned char *output_pointer = NULL;
1593
    size_t length = 0;
1594
    cJSON *current_element = item->child;
1595
 
1596
    if (output_buffer == NULL)
1597
    {
1598
        return false;
1599
    }
1600
 
1601
    /* Compose the output array. */
1602
    /* opening square bracket */
1603
    output_pointer = ensure(output_buffer, 1);
1604
    if (output_pointer == NULL)
1605
    {
1606
        return false;
1607
    }
1608
 
1609
    *output_pointer = '[';
1610
    output_buffer->offset++;
1611
    output_buffer->depth++;
1612
 
1613
    while (current_element != NULL)
1614
    {
1615
        if (!print_value(current_element, output_buffer))
1616
        {
1617
            return false;
1618
        }
1619
        update_offset(output_buffer);
1620
        if (current_element->next)
1621
        {
1622
            length = (size_t) (output_buffer->format ? 2 : 1);
1623
            output_pointer = ensure(output_buffer, length + 1);
1624
            if (output_pointer == NULL)
1625
            {
1626
                return false;
1627
            }
1628
            *output_pointer++ = ',';
1629
            if(output_buffer->format)
1630
            {
1631
                *output_pointer++ = ' ';
1632
            }
1633
            *output_pointer = '\0';
1634
            output_buffer->offset += length;
1635
        }
1636
        current_element = current_element->next;
1637
    }
1638
 
1639
    output_pointer = ensure(output_buffer, 2);
1640
    if (output_pointer == NULL)
1641
    {
1642
        return false;
1643
    }
1644
    *output_pointer++ = ']';
1645
    *output_pointer = '\0';
1646
    output_buffer->depth--;
1647
 
1648
    return true;
1649
}
1650
 
1651
/* Build an object from the text. */
1652
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1653
{
1654
    cJSON *head = NULL; /* linked list head */
1655
    cJSON *current_item = NULL;
1656
 
1657
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1658
    {
1659
        return false; /* to deeply nested */
1660
    }
1661
    input_buffer->depth++;
1662
 
1663
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1664
    {
1665
        goto fail; /* not an object */
1666
    }
1667
 
1668
    input_buffer->offset++;
1669
    buffer_skip_whitespace(input_buffer);
1670
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1671
    {
1672
        goto success; /* empty object */
1673
    }
1674
 
1675
    /* check if we skipped to the end of the buffer */
1676
    if (cannot_access_at_index(input_buffer, 0))
1677
    {
1678
        input_buffer->offset--;
1679
        goto fail;
1680
    }
1681
 
1682
    /* step back to character in front of the first element */
1683
    input_buffer->offset--;
1684
    /* loop through the comma separated array elements */
1685
    do
1686
    {
1687
        /* allocate next item */
1688
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1689
        if (new_item == NULL)
1690
        {
1691
            goto fail; /* allocation failure */
1692
        }
1693
 
1694
        /* attach next item to list */
1695
        if (head == NULL)
1696
        {
1697
            /* start the linked list */
1698
            current_item = head = new_item;
1699
        }
1700
        else
1701
        {
1702
            /* add to the end and advance */
1703
            current_item->next = new_item;
1704
            new_item->prev = current_item;
1705
            current_item = new_item;
1706
        }
1707
 
1708
        if (cannot_access_at_index(input_buffer, 1))
1709
        {
1710
            goto fail; /* nothing comes after the comma */
1711
        }
1712
 
1713
        /* parse the name of the child */
1714
        input_buffer->offset++;
1715
        buffer_skip_whitespace(input_buffer);
1716
        if (!parse_string(current_item, input_buffer))
1717
        {
1718
            goto fail; /* failed to parse name */
1719
        }
1720
        buffer_skip_whitespace(input_buffer);
1721
 
1722
        /* swap valuestring and string, because we parsed the name */
1723
        current_item->string = current_item->valuestring;
1724
        current_item->valuestring = NULL;
1725
 
1726
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1727
        {
1728
            goto fail; /* invalid object */
1729
        }
1730
 
1731
        /* parse the value */
1732
        input_buffer->offset++;
1733
        buffer_skip_whitespace(input_buffer);
1734
        if (!parse_value(current_item, input_buffer))
1735
        {
1736
            goto fail; /* failed to parse value */
1737
        }
1738
        buffer_skip_whitespace(input_buffer);
1739
    }
1740
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1741
 
1742
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1743
    {
1744
        goto fail; /* expected end of object */
1745
    }
1746
 
1747
success:
1748
    input_buffer->depth--;
1749
 
1750
    if (head != NULL) {
1751
        head->prev = current_item;
1752
    }
1753
 
1754
    item->type = cJSON_Object;
1755
    item->child = head;
1756
 
1757
    input_buffer->offset++;
1758
    return true;
1759
 
1760
fail:
1761
    if (head != NULL)
1762
    {
1763
        cJSON_Delete(head);
1764
    }
1765
 
1766
    return false;
1767
}
1768
 
1769
/* Render an object to text. */
1770
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1771
{
1772
    unsigned char *output_pointer = NULL;
1773
    size_t length = 0;
1774
    cJSON *current_item = item->child;
1775
 
1776
    if (output_buffer == NULL)
1777
    {
1778
        return false;
1779
    }
1780
 
1781
    /* Compose the output: */
1782
    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1783
    output_pointer = ensure(output_buffer, length + 1);
1784
    if (output_pointer == NULL)
1785
    {
1786
        return false;
1787
    }
1788
 
1789
    *output_pointer++ = '{';
1790
    output_buffer->depth++;
1791
    if (output_buffer->format)
1792
    {
1793
        *output_pointer++ = '\n';
1794
    }
1795
    output_buffer->offset += length;
1796
 
1797
    while (current_item)
1798
    {
1799
        if (output_buffer->format)
1800
        {
1801
            size_t i;
1802
            output_pointer = ensure(output_buffer, output_buffer->depth);
1803
            if (output_pointer == NULL)
1804
            {
1805
                return false;
1806
            }
1807
            for (i = 0; i < output_buffer->depth; i++)
1808
            {
1809
                *output_pointer++ = '\t';
1810
            }
1811
            output_buffer->offset += output_buffer->depth;
1812
        }
1813
 
1814
        /* print key */
1815
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1816
        {
1817
            return false;
1818
        }
1819
        update_offset(output_buffer);
1820
 
1821
        length = (size_t) (output_buffer->format ? 2 : 1);
1822
        output_pointer = ensure(output_buffer, length);
1823
        if (output_pointer == NULL)
1824
        {
1825
            return false;
1826
        }
1827
        *output_pointer++ = ':';
1828
        if (output_buffer->format)
1829
        {
1830
            *output_pointer++ = '\t';
1831
        }
1832
        output_buffer->offset += length;
1833
 
1834
        /* print value */
1835
        if (!print_value(current_item, output_buffer))
1836
        {
1837
            return false;
1838
        }
1839
        update_offset(output_buffer);
1840
 
1841
        /* print comma if not last */
1842
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1843
        output_pointer = ensure(output_buffer, length + 1);
1844
        if (output_pointer == NULL)
1845
        {
1846
            return false;
1847
        }
1848
        if (current_item->next)
1849
        {
1850
            *output_pointer++ = ',';
1851
        }
1852
 
1853
        if (output_buffer->format)
1854
        {
1855
            *output_pointer++ = '\n';
1856
        }
1857
        *output_pointer = '\0';
1858
        output_buffer->offset += length;
1859
 
1860
        current_item = current_item->next;
1861
    }
1862
 
1863
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1864
    if (output_pointer == NULL)
1865
    {
1866
        return false;
1867
    }
1868
    if (output_buffer->format)
1869
    {
1870
        size_t i;
1871
        for (i = 0; i < (output_buffer->depth - 1); i++)
1872
        {
1873
            *output_pointer++ = '\t';
1874
        }
1875
    }
1876
    *output_pointer++ = '}';
1877
    *output_pointer = '\0';
1878
    output_buffer->depth--;
1879
 
1880
    return true;
1881
}
1882
 
1883
/* Get Array size/item / object item. */
1884
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1885
{
1886
    cJSON *child = NULL;
1887
    size_t size = 0;
1888
 
1889
    if (array == NULL)
1890
    {
1891
        return 0;
1892
    }
1893
 
1894
    child = array->child;
1895
 
1896
    while(child != NULL)
1897
    {
1898
        size++;
1899
        child = child->next;
1900
    }
1901
 
1902
    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1903
 
1904
    return (int)size;
1905
}
1906
 
1907
static cJSON* get_array_item(const cJSON *array, size_t index)
1908
{
1909
    cJSON *current_child = NULL;
1910
 
1911
    if (array == NULL)
1912
    {
1913
        return NULL;
1914
    }
1915
 
1916
    current_child = array->child;
1917
    while ((current_child != NULL) && (index > 0))
1918
    {
1919
        index--;
1920
        current_child = current_child->next;
1921
    }
1922
 
1923
    return current_child;
1924
}
1925
 
1926
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1927
{
1928
    if (index < 0)
1929
    {
1930
        return NULL;
1931
    }
1932
 
1933
    return get_array_item(array, (size_t)index);
1934
}
1935
 
1936
static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1937
{
1938
    cJSON *current_element = NULL;
1939
 
1940
    if ((object == NULL) || (name == NULL))
1941
    {
1942
        return NULL;
1943
    }
1944
 
1945
    current_element = object->child;
1946
    if (case_sensitive)
1947
    {
1948
        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1949
        {
1950
            current_element = current_element->next;
1951
        }
1952
    }
1953
    else
1954
    {
1955
        while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1956
        {
1957
            current_element = current_element->next;
1958
        }
1959
    }
1960
 
1961
    if ((current_element == NULL) || (current_element->string == NULL)) {
1962
        return NULL;
1963
    }
1964
 
1965
    return current_element;
1966
}
1967
 
1968
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1969
{
1970
    return get_object_item(object, string, false);
1971
}
1972
 
1973
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1974
{
1975
    return get_object_item(object, string, true);
1976
}
1977
 
1978
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1979
{
1980
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
1981
}
1982
 
1983
/* Utility for array list handling. */
1984
static void suffix_object(cJSON *prev, cJSON *item)
1985
{
1986
    prev->next = item;
1987
    item->prev = prev;
1988
}
1989
 
1990
/* Utility for handling references. */
1991
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1992
{
1993
    cJSON *reference = NULL;
1994
    if (item == NULL)
1995
    {
1996
        return NULL;
1997
    }
1998
 
1999
    reference = cJSON_New_Item(hooks);
2000
    if (reference == NULL)
2001
    {
2002
        return NULL;
2003
    }
2004
 
2005
    memcpy(reference, item, sizeof(cJSON));
2006
    reference->string = NULL;
2007
    reference->type |= cJSON_IsReference;
2008
    reference->next = reference->prev = NULL;
2009
    return reference;
2010
}
2011
 
2012
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
2013
{
2014
    cJSON *child = NULL;
2015
 
2016
    if ((item == NULL) || (array == NULL) || (array == item))
2017
    {
2018
        return false;
2019
    }
2020
 
2021
    child = array->child;
2022
    /*
2023
     * To find the last item in array quickly, we use prev in array
2024
     */
2025
    if (child == NULL)
2026
    {
2027
        /* list is empty, start new one */
2028
        array->child = item;
2029
        item->prev = item;
2030
        item->next = NULL;
2031
    }
2032
    else
2033
    {
2034
        /* append to the end */
2035
        if (child->prev)
2036
        {
2037
            suffix_object(child->prev, item);
2038
            array->child->prev = item;
2039
        }
2040
    }
2041
 
2042
    return true;
2043
}
2044
 
2045
/* Add item to array/object. */
2046
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
2047
{
2048
    return add_item_to_array(array, item);
2049
}
2050
 
2051
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2052
    #pragma GCC diagnostic push
2053
#endif
2054
#ifdef __GNUC__
2055
#pragma GCC diagnostic ignored "-Wcast-qual"
2056
#endif
2057
/* helper function to cast away const */
2058
static void* cast_away_const(const void* string)
2059
{
2060
    return (void*)string;
2061
}
2062
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2063
    #pragma GCC diagnostic pop
2064
#endif
2065
 
2066
 
2067
static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
2068
{
2069
    char *new_key = NULL;
2070
    int new_type = cJSON_Invalid;
2071
 
2072
    if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2073
    {
2074
        return false;
2075
    }
2076
 
2077
    if (constant_key)
2078
    {
2079
        new_key = (char*)cast_away_const(string);
2080
        new_type = item->type | cJSON_StringIsConst;
2081
    }
2082
    else
2083
    {
2084
        new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2085
        if (new_key == NULL)
2086
        {
2087
            return false;
2088
        }
2089
 
2090
        new_type = item->type & ~cJSON_StringIsConst;
2091
    }
2092
 
2093
    if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2094
    {
2095
        hooks->deallocate(item->string);
2096
    }
2097
 
2098
    item->string = new_key;
2099
    item->type = new_type;
2100
 
2101
    return add_item_to_array(object, item);
2102
}
2103
 
2104
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2105
{
2106
    return add_item_to_object(object, string, item, &global_hooks, false);
2107
}
2108
 
2109
/* Add an item to an object with constant string as key */
2110
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2111
{
2112
    return add_item_to_object(object, string, item, &global_hooks, true);
2113
}
2114
 
2115
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2116
{
2117
    if (array == NULL)
2118
    {
2119
        return false;
2120
    }
2121
 
2122
    return add_item_to_array(array, create_reference(item, &global_hooks));
2123
}
2124
 
2125
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2126
{
2127
    if ((object == NULL) || (string == NULL))
2128
    {
2129
        return false;
2130
    }
2131
 
2132
    return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2133
}
2134
 
2135
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2136
{
2137
    cJSON *null = cJSON_CreateNull();
2138
    if (add_item_to_object(object, name, null, &global_hooks, false))
2139
    {
2140
        return null;
2141
    }
2142
 
2143
    cJSON_Delete(null);
2144
    return NULL;
2145
}
2146
 
2147
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2148
{
2149
    cJSON *true_item = cJSON_CreateTrue();
2150
    if (add_item_to_object(object, name, true_item, &global_hooks, false))
2151
    {
2152
        return true_item;
2153
    }
2154
 
2155
    cJSON_Delete(true_item);
2156
    return NULL;
2157
}
2158
 
2159
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2160
{
2161
    cJSON *false_item = cJSON_CreateFalse();
2162
    if (add_item_to_object(object, name, false_item, &global_hooks, false))
2163
    {
2164
        return false_item;
2165
    }
2166
 
2167
    cJSON_Delete(false_item);
2168
    return NULL;
2169
}
2170
 
2171
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2172
{
2173
    cJSON *bool_item = cJSON_CreateBool(boolean);
2174
    if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2175
    {
2176
        return bool_item;
2177
    }
2178
 
2179
    cJSON_Delete(bool_item);
2180
    return NULL;
2181
}
2182
 
2183
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2184
{
2185
    cJSON *number_item = cJSON_CreateNumber(number);
2186
    if (add_item_to_object(object, name, number_item, &global_hooks, false))
2187
    {
2188
        return number_item;
2189
    }
2190
 
2191
    cJSON_Delete(number_item);
2192
    return NULL;
2193
}
2194
 
2195
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2196
{
2197
    cJSON *string_item = cJSON_CreateString(string);
2198
    if (add_item_to_object(object, name, string_item, &global_hooks, false))
2199
    {
2200
        return string_item;
2201
    }
2202
 
2203
    cJSON_Delete(string_item);
2204
    return NULL;
2205
}
2206
 
2207
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2208
{
2209
    cJSON *raw_item = cJSON_CreateRaw(raw);
2210
    if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2211
    {
2212
        return raw_item;
2213
    }
2214
 
2215
    cJSON_Delete(raw_item);
2216
    return NULL;
2217
}
2218
 
2219
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2220
{
2221
    cJSON *object_item = cJSON_CreateObject();
2222
    if (add_item_to_object(object, name, object_item, &global_hooks, false))
2223
    {
2224
        return object_item;
2225
    }
2226
 
2227
    cJSON_Delete(object_item);
2228
    return NULL;
2229
}
2230
 
2231
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2232
{
2233
    cJSON *array = cJSON_CreateArray();
2234
    if (add_item_to_object(object, name, array, &global_hooks, false))
2235
    {
2236
        return array;
2237
    }
2238
 
2239
    cJSON_Delete(array);
2240
    return NULL;
2241
}
2242
 
2243
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2244
{
2245
    if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL))
2246
    {
2247
        return NULL;
2248
    }
2249
 
2250
    if (item != parent->child)
2251
    {
2252
        /* not the first element */
2253
        item->prev->next = item->next;
2254
    }
2255
    if (item->next != NULL)
2256
    {
2257
        /* not the last element */
2258
        item->next->prev = item->prev;
2259
    }
2260
 
2261
    if (item == parent->child)
2262
    {
2263
        /* first element */
2264
        parent->child = item->next;
2265
    }
2266
    else if (item->next == NULL)
2267
    {
2268
        /* last element */
2269
        parent->child->prev = item->prev;
2270
    }
2271
 
2272
    /* make sure the detached item doesn't point anywhere anymore */
2273
    item->prev = NULL;
2274
    item->next = NULL;
2275
 
2276
    return item;
2277
}
2278
 
2279
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2280
{
2281
    if (which < 0)
2282
    {
2283
        return NULL;
2284
    }
2285
 
2286
    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2287
}
2288
 
2289
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2290
{
2291
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2292
}
2293
 
2294
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2295
{
2296
    cJSON *to_detach = cJSON_GetObjectItem(object, string);
2297
 
2298
    return cJSON_DetachItemViaPointer(object, to_detach);
2299
}
2300
 
2301
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2302
{
2303
    cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2304
 
2305
    return cJSON_DetachItemViaPointer(object, to_detach);
2306
}
2307
 
2308
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2309
{
2310
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2311
}
2312
 
2313
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2314
{
2315
    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2316
}
2317
 
2318
/* Replace array/object items with new ones. */
2319
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2320
{
2321
    cJSON *after_inserted = NULL;
2322
 
2323
    if (which < 0 || newitem == NULL)
2324
    {
2325
        return false;
2326
    }
2327
 
2328
    after_inserted = get_array_item(array, (size_t)which);
2329
    if (after_inserted == NULL)
2330
    {
2331
        return add_item_to_array(array, newitem);
2332
    }
2333
 
2334
    if (after_inserted != array->child && after_inserted->prev == NULL) {
2335
        /* return false if after_inserted is a corrupted array item */
2336
        return false;
2337
    }
2338
 
2339
    newitem->next = after_inserted;
2340
    newitem->prev = after_inserted->prev;
2341
    after_inserted->prev = newitem;
2342
    if (after_inserted == array->child)
2343
    {
2344
        array->child = newitem;
2345
    }
2346
    else
2347
    {
2348
        newitem->prev->next = newitem;
2349
    }
2350
    return true;
2351
}
2352
 
2353
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2354
{
2355
    if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
2356
    {
2357
        return false;
2358
    }
2359
 
2360
    if (replacement == item)
2361
    {
2362
        return true;
2363
    }
2364
 
2365
    replacement->next = item->next;
2366
    replacement->prev = item->prev;
2367
 
2368
    if (replacement->next != NULL)
2369
    {
2370
        replacement->next->prev = replacement;
2371
    }
2372
    if (parent->child == item)
2373
    {
2374
        if (parent->child->prev == parent->child)
2375
        {
2376
            replacement->prev = replacement;
2377
        }
2378
        parent->child = replacement;
2379
    }
2380
    else
2381
    {   /*
2382
         * To find the last item in array quickly, we use prev in array.
2383
         * We can't modify the last item's next pointer where this item was the parent's child
2384
         */
2385
        if (replacement->prev != NULL)
2386
        {
2387
            replacement->prev->next = replacement;
2388
        }
2389
        if (replacement->next == NULL)
2390
        {
2391
            parent->child->prev = replacement;
2392
        }
2393
    }
2394
 
2395
    item->next = NULL;
2396
    item->prev = NULL;
2397
    cJSON_Delete(item);
2398
 
2399
    return true;
2400
}
2401
 
2402
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2403
{
2404
    if (which < 0)
2405
    {
2406
        return false;
2407
    }
2408
 
2409
    return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2410
}
2411
 
2412
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2413
{
2414
    if ((replacement == NULL) || (string == NULL))
2415
    {
2416
        return false;
2417
    }
2418
 
2419
    /* replace the name in the replacement */
2420
    if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2421
    {
2422
        cJSON_free(replacement->string);
2423
    }
2424
    replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2425
    if (replacement->string == NULL)
2426
    {
2427
        return false;
2428
    }
2429
 
2430
    replacement->type &= ~cJSON_StringIsConst;
2431
 
2432
    return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2433
}
2434
 
2435
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2436
{
2437
    return replace_item_in_object(object, string, newitem, false);
2438
}
2439
 
2440
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2441
{
2442
    return replace_item_in_object(object, string, newitem, true);
2443
}
2444
 
2445
/* Create basic types: */
2446
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2447
{
2448
    cJSON *item = cJSON_New_Item(&global_hooks);
2449
    if(item)
2450
    {
2451
        item->type = cJSON_NULL;
2452
    }
2453
 
2454
    return item;
2455
}
2456
 
2457
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2458
{
2459
    cJSON *item = cJSON_New_Item(&global_hooks);
2460
    if(item)
2461
    {
2462
        item->type = cJSON_True;
2463
    }
2464
 
2465
    return item;
2466
}
2467
 
2468
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2469
{
2470
    cJSON *item = cJSON_New_Item(&global_hooks);
2471
    if(item)
2472
    {
2473
        item->type = cJSON_False;
2474
    }
2475
 
2476
    return item;
2477
}
2478
 
2479
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2480
{
2481
    cJSON *item = cJSON_New_Item(&global_hooks);
2482
    if(item)
2483
    {
2484
        item->type = boolean ? cJSON_True : cJSON_False;
2485
    }
2486
 
2487
    return item;
2488
}
2489
 
2490
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2491
{
2492
    cJSON *item = cJSON_New_Item(&global_hooks);
2493
    if(item)
2494
    {
2495
        item->type = cJSON_Number;
2496
        item->valuedouble = num;
2497
 
2498
        /* use saturation in case of overflow */
2499
        if (num >= INT_MAX)
2500
        {
2501
            item->valueint = INT_MAX;
2502
        }
2503
        else if (num <= (double)INT_MIN)
2504
        {
2505
            item->valueint = INT_MIN;
2506
        }
2507
        else
2508
        {
2509
            item->valueint = (int)num;
2510
        }
2511
    }
2512
 
2513
    return item;
2514
}
2515
 
2516
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2517
{
2518
    cJSON *item = cJSON_New_Item(&global_hooks);
2519
    if(item)
2520
    {
2521
        item->type = cJSON_String;
2522
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2523
        if(!item->valuestring)
2524
        {
2525
            cJSON_Delete(item);
2526
            return NULL;
2527
        }
2528
    }
2529
 
2530
    return item;
2531
}
2532
 
2533
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2534
{
2535
    cJSON *item = cJSON_New_Item(&global_hooks);
2536
    if (item != NULL)
2537
    {
2538
        item->type = cJSON_String | cJSON_IsReference;
2539
        item->valuestring = (char*)cast_away_const(string);
2540
    }
2541
 
2542
    return item;
2543
}
2544
 
2545
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2546
{
2547
    cJSON *item = cJSON_New_Item(&global_hooks);
2548
    if (item != NULL) {
2549
        item->type = cJSON_Object | cJSON_IsReference;
2550
        item->child = (cJSON*)cast_away_const(child);
2551
    }
2552
 
2553
    return item;
2554
}
2555
 
2556
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2557
    cJSON *item = cJSON_New_Item(&global_hooks);
2558
    if (item != NULL) {
2559
        item->type = cJSON_Array | cJSON_IsReference;
2560
        item->child = (cJSON*)cast_away_const(child);
2561
    }
2562
 
2563
    return item;
2564
}
2565
 
2566
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2567
{
2568
    cJSON *item = cJSON_New_Item(&global_hooks);
2569
    if(item)
2570
    {
2571
        item->type = cJSON_Raw;
2572
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2573
        if(!item->valuestring)
2574
        {
2575
            cJSON_Delete(item);
2576
            return NULL;
2577
        }
2578
    }
2579
 
2580
    return item;
2581
}
2582
 
2583
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2584
{
2585
    cJSON *item = cJSON_New_Item(&global_hooks);
2586
    if(item)
2587
    {
2588
        item->type=cJSON_Array;
2589
    }
2590
 
2591
    return item;
2592
}
2593
 
2594
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2595
{
2596
    cJSON *item = cJSON_New_Item(&global_hooks);
2597
    if (item)
2598
    {
2599
        item->type = cJSON_Object;
2600
    }
2601
 
2602
    return item;
2603
}
2604
 
2605
/* Create Arrays: */
2606
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2607
{
2608
    size_t i = 0;
2609
    cJSON *n = NULL;
2610
    cJSON *p = NULL;
2611
    cJSON *a = NULL;
2612
 
2613
    if ((count < 0) || (numbers == NULL))
2614
    {
2615
        return NULL;
2616
    }
2617
 
2618
    a = cJSON_CreateArray();
2619
 
2620
    for(i = 0; a && (i < (size_t)count); i++)
2621
    {
2622
        n = cJSON_CreateNumber(numbers[i]);
2623
        if (!n)
2624
        {
2625
            cJSON_Delete(a);
2626
            return NULL;
2627
        }
2628
        if(!i)
2629
        {
2630
            a->child = n;
2631
        }
2632
        else
2633
        {
2634
            suffix_object(p, n);
2635
        }
2636
        p = n;
2637
    }
2638
 
2639
    if (a && a->child) {
2640
        a->child->prev = n;
2641
    }
2642
 
2643
    return a;
2644
}
2645
 
2646
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2647
{
2648
    size_t i = 0;
2649
    cJSON *n = NULL;
2650
    cJSON *p = NULL;
2651
    cJSON *a = NULL;
2652
 
2653
    if ((count < 0) || (numbers == NULL))
2654
    {
2655
        return NULL;
2656
    }
2657
 
2658
    a = cJSON_CreateArray();
2659
 
2660
    for(i = 0; a && (i < (size_t)count); i++)
2661
    {
2662
        n = cJSON_CreateNumber((double)numbers[i]);
2663
        if(!n)
2664
        {
2665
            cJSON_Delete(a);
2666
            return NULL;
2667
        }
2668
        if(!i)
2669
        {
2670
            a->child = n;
2671
        }
2672
        else
2673
        {
2674
            suffix_object(p, n);
2675
        }
2676
        p = n;
2677
    }
2678
 
2679
    if (a && a->child) {
2680
        a->child->prev = n;
2681
    }
2682
 
2683
    return a;
2684
}
2685
 
2686
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2687
{
2688
    size_t i = 0;
2689
    cJSON *n = NULL;
2690
    cJSON *p = NULL;
2691
    cJSON *a = NULL;
2692
 
2693
    if ((count < 0) || (numbers == NULL))
2694
    {
2695
        return NULL;
2696
    }
2697
 
2698
    a = cJSON_CreateArray();
2699
 
2700
    for(i = 0; a && (i < (size_t)count); i++)
2701
    {
2702
        n = cJSON_CreateNumber(numbers[i]);
2703
        if(!n)
2704
        {
2705
            cJSON_Delete(a);
2706
            return NULL;
2707
        }
2708
        if(!i)
2709
        {
2710
            a->child = n;
2711
        }
2712
        else
2713
        {
2714
            suffix_object(p, n);
2715
        }
2716
        p = n;
2717
    }
2718
 
2719
    if (a && a->child) {
2720
        a->child->prev = n;
2721
    }
2722
 
2723
    return a;
2724
}
2725
 
2726
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2727
{
2728
    size_t i = 0;
2729
    cJSON *n = NULL;
2730
    cJSON *p = NULL;
2731
    cJSON *a = NULL;
2732
 
2733
    if ((count < 0) || (strings == NULL))
2734
    {
2735
        return NULL;
2736
    }
2737
 
2738
    a = cJSON_CreateArray();
2739
 
2740
    for (i = 0; a && (i < (size_t)count); i++)
2741
    {
2742
        n = cJSON_CreateString(strings[i]);
2743
        if(!n)
2744
        {
2745
            cJSON_Delete(a);
2746
            return NULL;
2747
        }
2748
        if(!i)
2749
        {
2750
            a->child = n;
2751
        }
2752
        else
2753
        {
2754
            suffix_object(p,n);
2755
        }
2756
        p = n;
2757
    }
2758
 
2759
    if (a && a->child) {
2760
        a->child->prev = n;
2761
    }
2762
 
2763
    return a;
2764
}
2765
 
2766
/* Duplication */
2767
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse);
2768
 
2769
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2770
{
2771
    return cJSON_Duplicate_rec(item, 0, recurse );
2772
}
2773
 
2774
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
2775
{
2776
    cJSON *newitem = NULL;
2777
    cJSON *child = NULL;
2778
    cJSON *next = NULL;
2779
    cJSON *newchild = NULL;
2780
 
2781
    /* Bail on bad ptr */
2782
    if (!item)
2783
    {
2784
        goto fail;
2785
    }
2786
    /* Create new item */
2787
    newitem = cJSON_New_Item(&global_hooks);
2788
    if (!newitem)
2789
    {
2790
        goto fail;
2791
    }
2792
    /* Copy over all vars */
2793
    newitem->type = item->type & (~cJSON_IsReference);
2794
    newitem->valueint = item->valueint;
2795
    newitem->valuedouble = item->valuedouble;
2796
    if (item->valuestring)
2797
    {
2798
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2799
        if (!newitem->valuestring)
2800
        {
2801
            goto fail;
2802
        }
2803
    }
2804
    if (item->string)
2805
    {
2806
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2807
        if (!newitem->string)
2808
        {
2809
            goto fail;
2810
        }
2811
    }
2812
    /* If non-recursive, then we're done! */
2813
    if (!recurse)
2814
    {
2815
        return newitem;
2816
    }
2817
    /* Walk the ->next chain for the child. */
2818
    child = item->child;
2819
    while (child != NULL)
2820
    {
2821
        if(depth >= CJSON_CIRCULAR_LIMIT) {
2822
            goto fail;
2823
        }
2824
        newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */
2825
        if (!newchild)
2826
        {
2827
            goto fail;
2828
        }
2829
        if (next != NULL)
2830
        {
2831
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2832
            next->next = newchild;
2833
            newchild->prev = next;
2834
            next = newchild;
2835
        }
2836
        else
2837
        {
2838
            /* Set newitem->child and move to it */
2839
            newitem->child = newchild;
2840
            next = newchild;
2841
        }
2842
        child = child->next;
2843
    }
2844
    if (newitem && newitem->child)
2845
    {
2846
        newitem->child->prev = newchild;
2847
    }
2848
 
2849
    return newitem;
2850
 
2851
fail:
2852
    if (newitem != NULL)
2853
    {
2854
        cJSON_Delete(newitem);
2855
    }
2856
 
2857
    return NULL;
2858
}
2859
 
2860
static void skip_oneline_comment(char **input)
2861
{
2862
    *input += static_strlen("//");
2863
 
2864
    for (; (*input)[0] != '\0'; ++(*input))
2865
    {
2866
        if ((*input)[0] == '\n') {
2867
            *input += static_strlen("\n");
2868
            return;
2869
        }
2870
    }
2871
}
2872
 
2873
static void skip_multiline_comment(char **input)
2874
{
2875
    *input += static_strlen("/*");
2876
 
2877
    for (; (*input)[0] != '\0'; ++(*input))
2878
    {
2879
        if (((*input)[0] == '*') && ((*input)[1] == '/'))
2880
        {
2881
            *input += static_strlen("*/");
2882
            return;
2883
        }
2884
    }
2885
}
2886
 
2887
static void minify_string(char **input, char **output) {
2888
    (*output)[0] = (*input)[0];
2889
    *input += static_strlen("\"");
2890
    *output += static_strlen("\"");
2891
 
2892
 
2893
    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2894
        (*output)[0] = (*input)[0];
2895
 
2896
        if ((*input)[0] == '\"') {
2897
            (*output)[0] = '\"';
2898
            *input += static_strlen("\"");
2899
            *output += static_strlen("\"");
2900
            return;
2901
        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2902
            (*output)[1] = (*input)[1];
2903
            *input += static_strlen("\"");
2904
            *output += static_strlen("\"");
2905
        }
2906
    }
2907
}
2908
 
2909
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2910
{
2911
    char *into = json;
2912
 
2913
    if (json == NULL)
2914
    {
2915
        return;
2916
    }
2917
 
2918
    while (json[0] != '\0')
2919
    {
2920
        switch (json[0])
2921
        {
2922
            case ' ':
2923
            case '\t':
2924
            case '\r':
2925
            case '\n':
2926
                json++;
2927
                break;
2928
 
2929
            case '/':
2930
                if (json[1] == '/')
2931
                {
2932
                    skip_oneline_comment(&json);
2933
                }
2934
                else if (json[1] == '*')
2935
                {
2936
                    skip_multiline_comment(&json);
2937
                } else {
2938
                    json++;
2939
                }
2940
                break;
2941
 
2942
            case '\"':
2943
                minify_string(&json, (char**)&into);
2944
                break;
2945
 
2946
            default:
2947
                into[0] = json[0];
2948
                json++;
2949
                into++;
2950
        }
2951
    }
2952
 
2953
    /* and null-terminate. */
2954
    *into = '\0';
2955
}
2956
 
2957
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2958
{
2959
    if (item == NULL)
2960
    {
2961
        return false;
2962
    }
2963
 
2964
    return (item->type & 0xFF) == cJSON_Invalid;
2965
}
2966
 
2967
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2968
{
2969
    if (item == NULL)
2970
    {
2971
        return false;
2972
    }
2973
 
2974
    return (item->type & 0xFF) == cJSON_False;
2975
}
2976
 
2977
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2978
{
2979
    if (item == NULL)
2980
    {
2981
        return false;
2982
    }
2983
 
2984
    return (item->type & 0xff) == cJSON_True;
2985
}
2986
 
2987
 
2988
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2989
{
2990
    if (item == NULL)
2991
    {
2992
        return false;
2993
    }
2994
 
2995
    return (item->type & (cJSON_True | cJSON_False)) != 0;
2996
}
2997
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2998
{
2999
    if (item == NULL)
3000
    {
3001
        return false;
3002
    }
3003
 
3004
    return (item->type & 0xFF) == cJSON_NULL;
3005
}
3006
 
3007
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
3008
{
3009
    if (item == NULL)
3010
    {
3011
        return false;
3012
    }
3013
 
3014
    return (item->type & 0xFF) == cJSON_Number;
3015
}
3016
 
3017
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
3018
{
3019
    if (item == NULL)
3020
    {
3021
        return false;
3022
    }
3023
 
3024
    return (item->type & 0xFF) == cJSON_String;
3025
}
3026
 
3027
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
3028
{
3029
    if (item == NULL)
3030
    {
3031
        return false;
3032
    }
3033
 
3034
    return (item->type & 0xFF) == cJSON_Array;
3035
}
3036
 
3037
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
3038
{
3039
    if (item == NULL)
3040
    {
3041
        return false;
3042
    }
3043
 
3044
    return (item->type & 0xFF) == cJSON_Object;
3045
}
3046
 
3047
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
3048
{
3049
    if (item == NULL)
3050
    {
3051
        return false;
3052
    }
3053
 
3054
    return (item->type & 0xFF) == cJSON_Raw;
3055
}
3056
 
3057
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
3058
{
3059
    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
3060
    {
3061
        return false;
3062
    }
3063
 
3064
    /* check if type is valid */
3065
    switch (a->type & 0xFF)
3066
    {
3067
        case cJSON_False:
3068
        case cJSON_True:
3069
        case cJSON_NULL:
3070
        case cJSON_Number:
3071
        case cJSON_String:
3072
        case cJSON_Raw:
3073
        case cJSON_Array:
3074
        case cJSON_Object:
3075
            break;
3076
 
3077
        default:
3078
            return false;
3079
    }
3080
 
3081
    /* identical objects are equal */
3082
    if (a == b)
3083
    {
3084
        return true;
3085
    }
3086
 
3087
    switch (a->type & 0xFF)
3088
    {
3089
        /* in these cases and equal type is enough */
3090
        case cJSON_False:
3091
        case cJSON_True:
3092
        case cJSON_NULL:
3093
            return true;
3094
 
3095
        case cJSON_Number:
3096
            if (compare_double(a->valuedouble, b->valuedouble))
3097
            {
3098
                return true;
3099
            }
3100
            return false;
3101
 
3102
        case cJSON_String:
3103
        case cJSON_Raw:
3104
            if ((a->valuestring == NULL) || (b->valuestring == NULL))
3105
            {
3106
                return false;
3107
            }
3108
            if (strcmp(a->valuestring, b->valuestring) == 0)
3109
            {
3110
                return true;
3111
            }
3112
 
3113
            return false;
3114
 
3115
        case cJSON_Array:
3116
        {
3117
            cJSON *a_element = a->child;
3118
            cJSON *b_element = b->child;
3119
 
3120
            for (; (a_element != NULL) && (b_element != NULL);)
3121
            {
3122
                if (!cJSON_Compare(a_element, b_element, case_sensitive))
3123
                {
3124
                    return false;
3125
                }
3126
 
3127
                a_element = a_element->next;
3128
                b_element = b_element->next;
3129
            }
3130
 
3131
            /* one of the arrays is longer than the other */
3132
            if (a_element != b_element) {
3133
                return false;
3134
            }
3135
 
3136
            return true;
3137
        }
3138
 
3139
        case cJSON_Object:
3140
        {
3141
            cJSON *a_element = NULL;
3142
            cJSON *b_element = NULL;
3143
            cJSON_ArrayForEach(a_element, a)
3144
            {
3145
                /* TODO This has O(n^2) runtime, which is horrible! */
3146
                b_element = get_object_item(b, a_element->string, case_sensitive);
3147
                if (b_element == NULL)
3148
                {
3149
                    return false;
3150
                }
3151
 
3152
                if (!cJSON_Compare(a_element, b_element, case_sensitive))
3153
                {
3154
                    return false;
3155
                }
3156
            }
3157
 
3158
            /* doing this twice, once on a and b to prevent true comparison if a subset of b
3159
             * TODO: Do this the proper way, this is just a fix for now */
3160
            cJSON_ArrayForEach(b_element, b)
3161
            {
3162
                a_element = get_object_item(a, b_element->string, case_sensitive);
3163
                if (a_element == NULL)
3164
                {
3165
                    return false;
3166
                }
3167
 
3168
                if (!cJSON_Compare(b_element, a_element, case_sensitive))
3169
                {
3170
                    return false;
3171
                }
3172
            }
3173
 
3174
            return true;
3175
        }
3176
 
3177
        default:
3178
            return false;
3179
    }
3180
}
3181
 
3182
CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3183
{
3184
    return global_hooks.allocate(size);
3185
}
3186
 
3187
CJSON_PUBLIC(void) cJSON_free(void *object)
3188
{
3189
    global_hooks.deallocate(object);
3190
    object = NULL;
3191
}