Coverage Report

Created: 2026-02-03 06:58

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