Coverage Report

Created: 2026-10-16 06:49

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