Coverage Report

Created: 2025-12-14 06:06

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