Coverage Report

Created: 2026-01-25 07:02

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.65M
#define true ((cJSON_bool)1)
66
67
#ifdef false
68
#undef false
69
#endif
70
97.3k
#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
23.8k
#define isinf(d) (isnan((d - d)) && !isnan(d))
75
#endif
76
#ifndef isnan
77
96.2k
#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
60.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
898k
{
243
898k
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
244
898k
    if (node)
245
898k
    {
246
898k
        memset(node, '\0', sizeof(cJSON));
247
898k
    }
248
249
898k
    return node;
250
898k
}
251
252
/* Delete a cJSON structure. */
253
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
254
351k
{
255
351k
    cJSON *next = NULL;
256
1.24M
    while (item != NULL)
257
898k
    {
258
898k
        next = item->next;
259
898k
        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
260
298k
        {
261
298k
            cJSON_Delete(item->child);
262
298k
        }
263
898k
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
264
3.73k
        {
265
3.73k
            global_hooks.deallocate(item->valuestring);
266
3.73k
            item->valuestring = NULL;
267
3.73k
        }
268
898k
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
269
21.0k
        {
270
21.0k
            global_hooks.deallocate(item->string);
271
21.0k
            item->string = NULL;
272
21.0k
        }
273
898k
        global_hooks.deallocate(item);
274
898k
        item = next;
275
898k
    }
276
351k
}
277
278
/* get the decimal point character of the current locale */
279
static unsigned char get_decimal_point(void)
280
68.2k
{
281
68.2k
#ifdef ENABLE_LOCALES
282
68.2k
    struct lconv *lconv = localeconv();
283
68.2k
    return (unsigned char) lconv->decimal_point[0];
284
#else
285
    return '.';
286
#endif
287
68.2k
}
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.38M
#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.2M
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
302
4.65M
#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.6M
#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
44.3k
{
309
44.3k
    double number = 0;
310
44.3k
    unsigned char *after_end = NULL;
311
44.3k
    unsigned char *number_c_string;
312
44.3k
    unsigned char decimal_point = get_decimal_point();
313
44.3k
    size_t i = 0;
314
44.3k
    size_t number_string_length = 0;
315
44.3k
    cJSON_bool has_decimal_point = false;
316
317
44.3k
    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
1.32M
    for (i = 0; can_access_at_index(input_buffer, i); i++)
326
1.32M
    {
327
1.32M
        switch (buffer_at_offset(input_buffer)[i])
328
1.32M
        {
329
749k
            case '0':
330
795k
            case '1':
331
831k
            case '2':
332
847k
            case '3':
333
862k
            case '4':
334
896k
            case '5':
335
1.03M
            case '6':
336
1.06M
            case '7':
337
1.09M
            case '8':
338
1.16M
            case '9':
339
1.16M
            case '+':
340
1.26M
            case '-':
341
1.26M
            case 'e':
342
1.26M
            case 'E':
343
1.26M
                number_string_length++;
344
1.26M
                break;
345
346
15.6k
            case '.':
347
15.6k
                number_string_length++;
348
15.6k
                has_decimal_point = true;
349
15.6k
                break;
350
351
44.3k
            default:
352
44.3k
                goto loop_end;
353
1.32M
        }
354
1.32M
    }
355
44.3k
loop_end:
356
    /* malloc for temporary buffer, add 1 for '\0' */
357
44.3k
    number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1);
358
44.3k
    if (number_c_string == NULL)
359
0
    {
360
0
        return false; /* allocation failure */
361
0
    }
362
363
44.3k
    memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length);
364
44.3k
    number_c_string[number_string_length] = '\0';
365
366
44.3k
    if (has_decimal_point)
367
2.56k
    {
368
979k
        for (i = 0; i < number_string_length; i++)
369
976k
        {
370
976k
            if (number_c_string[i] == '.')
371
15.6k
            {
372
                /* replace '.' with the decimal point of the current locale (for strtod) */
373
15.6k
                number_c_string[i] = decimal_point;
374
15.6k
            }
375
976k
        }
376
2.56k
    }
377
378
44.3k
    number = strtod((const char*)number_c_string, (char**)&after_end);
379
44.3k
    if (number_c_string == after_end)
380
21
    {
381
        /* free the temporary buffer */
382
21
        input_buffer->hooks.deallocate(number_c_string);
383
21
        return false; /* parse_error */
384
21
    }
385
386
44.3k
    item->valuedouble = number;
387
388
    /* use saturation in case of overflow */
389
44.3k
    if (number >= INT_MAX)
390
18.4k
    {
391
18.4k
        item->valueint = INT_MAX;
392
18.4k
    }
393
25.9k
    else if (number <= (double)INT_MIN)
394
233
    {
395
233
        item->valueint = INT_MIN;
396
233
    }
397
25.7k
    else
398
25.7k
    {
399
25.7k
        item->valueint = (int)number;
400
25.7k
    }
401
402
44.3k
    item->type = cJSON_Number;
403
404
44.3k
    input_buffer->offset += (size_t)(after_end - number_c_string);
405
    /* free the temporary buffer */
406
44.3k
    input_buffer->hooks.deallocate(number_c_string);
407
44.3k
    return true;
408
44.3k
}
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.02M
{
487
2.02M
    unsigned char *newbuffer = NULL;
488
2.02M
    size_t newsize = 0;
489
490
2.02M
    if ((p == NULL) || (p->buffer == NULL))
491
0
    {
492
0
        return NULL;
493
0
    }
494
495
2.02M
    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.02M
    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.02M
    needed += p->offset + 1;
508
2.02M
    if (needed <= p->length)
509
2.02M
    {
510
2.02M
        return p->buffer + p->offset;
511
2.02M
    }
512
513
1.72k
    if (p->noalloc) {
514
0
        return NULL;
515
0
    }
516
517
    /* calculate new buffer size */
518
1.72k
    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.72k
    else
531
1.72k
    {
532
1.72k
        newsize = needed * 2;
533
1.72k
    }
534
535
1.72k
    if (p->hooks.reallocate != NULL)
536
1.72k
    {
537
        /* reallocate with realloc if available */
538
1.72k
        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
539
1.72k
        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.72k
    }
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.72k
    p->length = newsize;
565
1.72k
    p->buffer = newbuffer;
566
567
1.72k
    return newbuffer + p->offset;
568
1.72k
}
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
770k
{
573
770k
    const unsigned char *buffer_pointer = NULL;
574
770k
    if ((buffer == NULL) || (buffer->buffer == NULL))
575
0
    {
576
0
        return;
577
0
    }
578
770k
    buffer_pointer = buffer->buffer + buffer->offset;
579
580
770k
    buffer->offset += strlen((const char*)buffer_pointer);
581
770k
}
582
583
/* securely comparison of floating-point variables */
584
static cJSON_bool compare_double(double a, double b)
585
9.92k
{
586
9.92k
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
587
9.92k
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
588
9.92k
}
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
23.8k
{
593
23.8k
    unsigned char *output_pointer = NULL;
594
23.8k
    double d = item->valuedouble;
595
23.8k
    int length = 0;
596
23.8k
    size_t i = 0;
597
23.8k
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
598
23.8k
    unsigned char decimal_point = get_decimal_point();
599
23.8k
    double test = 0.0;
600
601
23.8k
    if (output_buffer == NULL)
602
0
    {
603
0
        return false;
604
0
    }
605
606
    /* This checks for NaN and Infinity */
607
23.8k
    if (isnan(d) || isinf(d))
608
790
    {
609
790
        length = sprintf((char*)number_buffer, "null");
610
790
    }
611
23.0k
    else if(d == (double)item->valueint)
612
13.1k
    {
613
13.1k
        length = sprintf((char*)number_buffer, "%d", item->valueint);
614
13.1k
    }
615
9.92k
    else
616
9.92k
    {
617
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
618
9.92k
        length = sprintf((char*)number_buffer, "%1.15g", d);
619
620
        /* Check whether the original double can be recovered */
621
9.92k
        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
622
8.65k
        {
623
            /* If not, print with 17 decimal places of precision */
624
8.65k
            length = sprintf((char*)number_buffer, "%1.17g", d);
625
8.65k
        }
626
9.92k
    }
627
628
    /* sprintf failed or buffer overrun occurred */
629
23.8k
    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
23.8k
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
636
23.8k
    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
200k
    for (i = 0; i < ((size_t)length); i++)
644
176k
    {
645
176k
        if (number_buffer[i] == decimal_point)
646
1.68k
        {
647
1.68k
            output_pointer[i] = '.';
648
1.68k
            continue;
649
1.68k
        }
650
651
175k
        output_pointer[i] = number_buffer[i];
652
175k
    }
653
23.8k
    output_pointer[i] = '\0';
654
655
23.8k
    output_buffer->offset += (size_t)length;
656
657
23.8k
    return true;
658
23.8k
}
659
660
/* parse 4 digit hexadecimal number */
661
static unsigned parse_hex4(const unsigned char * const input)
662
47.3k
{
663
47.3k
    unsigned int h = 0;
664
47.3k
    size_t i = 0;
665
666
186k
    for (i = 0; i < 4; i++)
667
157k
    {
668
        /* parse digit */
669
157k
        if ((input[i] >= '0') && (input[i] <= '9'))
670
50.6k
        {
671
50.6k
            h += (unsigned int) input[i] - '0';
672
50.6k
        }
673
106k
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
674
20.6k
        {
675
20.6k
            h += (unsigned int) 10 + input[i] - 'A';
676
20.6k
        }
677
85.8k
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
678
67.4k
        {
679
67.4k
            h += (unsigned int) 10 + input[i] - 'a';
680
67.4k
        }
681
18.3k
        else /* invalid */
682
18.3k
        {
683
18.3k
            return 0;
684
18.3k
        }
685
686
138k
        if (i < 3)
687
109k
        {
688
            /* shift left to make place for the next nibble */
689
109k
            h = h << 4;
690
109k
        }
691
138k
    }
692
693
29.0k
    return h;
694
47.3k
}
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
42.5k
{
700
42.5k
    long unsigned int codepoint = 0;
701
42.5k
    unsigned int first_code = 0;
702
42.5k
    const unsigned char *first_sequence = input_pointer;
703
42.5k
    unsigned char utf8_length = 0;
704
42.5k
    unsigned char utf8_position = 0;
705
42.5k
    unsigned char sequence_length = 0;
706
42.5k
    unsigned char first_byte_mark = 0;
707
708
42.5k
    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
42.5k
    first_code = parse_hex4(first_sequence + 2);
716
717
    /* check that the code is valid */
718
42.5k
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
719
14
    {
720
14
        goto fail;
721
14
    }
722
723
    /* UTF16 surrogate pair */
724
42.4k
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
725
4.86k
    {
726
4.86k
        const unsigned char *second_sequence = first_sequence + 6;
727
4.86k
        unsigned int second_code = 0;
728
4.86k
        sequence_length = 12; /* \uXXXX\uXXXX */
729
730
4.86k
        if ((input_end - second_sequence) < 6)
731
16
        {
732
            /* input ends unexpectedly */
733
16
            goto fail;
734
16
        }
735
736
4.85k
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
737
25
        {
738
            /* missing second half of the surrogate pair */
739
25
            goto fail;
740
25
        }
741
742
        /* get the second utf16 sequence */
743
4.82k
        second_code = parse_hex4(second_sequence + 2);
744
        /* check that the code is valid */
745
4.82k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
746
55
        {
747
            /* invalid second half of the surrogate pair */
748
55
            goto fail;
749
55
        }
750
751
752
        /* calculate the unicode codepoint from the surrogate pair */
753
4.77k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
754
4.77k
    }
755
37.6k
    else
756
37.6k
    {
757
37.6k
        sequence_length = 6; /* \uXXXX */
758
37.6k
        codepoint = first_code;
759
37.6k
    }
760
761
    /* encode as UTF-8
762
     * takes at maximum 4 bytes to encode:
763
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
764
42.3k
    if (codepoint < 0x80)
765
20.3k
    {
766
        /* normal ascii, encoding 0xxxxxxx */
767
20.3k
        utf8_length = 1;
768
20.3k
    }
769
22.0k
    else if (codepoint < 0x800)
770
4.61k
    {
771
        /* two bytes, encoding 110xxxxx 10xxxxxx */
772
4.61k
        utf8_length = 2;
773
4.61k
        first_byte_mark = 0xC0; /* 11000000 */
774
4.61k
    }
775
17.3k
    else if (codepoint < 0x10000)
776
12.6k
    {
777
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
778
12.6k
        utf8_length = 3;
779
12.6k
        first_byte_mark = 0xE0; /* 11100000 */
780
12.6k
    }
781
4.77k
    else if (codepoint <= 0x10FFFF)
782
4.77k
    {
783
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
784
4.77k
        utf8_length = 4;
785
4.77k
        first_byte_mark = 0xF0; /* 11110000 */
786
4.77k
    }
787
0
    else
788
0
    {
789
        /* invalid unicode codepoint */
790
0
        goto fail;
791
0
    }
792
793
    /* encode as utf8 */
794
86.5k
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
795
44.1k
    {
796
        /* 10xxxxxx */
797
44.1k
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
798
44.1k
        codepoint >>= 6;
799
44.1k
    }
800
    /* encode first byte */
801
42.3k
    if (utf8_length > 1)
802
22.0k
    {
803
22.0k
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
804
22.0k
    }
805
20.3k
    else
806
20.3k
    {
807
20.3k
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
808
20.3k
    }
809
810
42.3k
    *output_pointer += utf8_length;
811
812
42.3k
    return sequence_length;
813
814
114
fail:
815
114
    return 0;
816
42.3k
}
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
25.0k
{
821
25.0k
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
822
25.0k
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
823
25.0k
    unsigned char *output_pointer = NULL;
824
25.0k
    unsigned char *output = NULL;
825
826
    /* not a string */
827
25.0k
    if (buffer_at_offset(input_buffer)[0] != '\"')
828
142
    {
829
142
        goto fail;
830
142
    }
831
832
24.9k
    {
833
        /* calculate approximate size of the output (overestimate) */
834
24.9k
        size_t allocation_length = 0;
835
24.9k
        size_t skipped_bytes = 0;
836
22.6M
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
837
22.5M
        {
838
            /* is escape sequence */
839
22.5M
            if (input_end[0] == '\\')
840
152k
            {
841
152k
                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
152k
                skipped_bytes++;
847
152k
                input_end++;
848
152k
            }
849
22.5M
            input_end++;
850
22.5M
        }
851
24.9k
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
852
62
        {
853
62
            goto fail; /* string ended unexpectedly */
854
62
        }
855
856
        /* This is at most how much we need for the output */
857
24.8k
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
858
24.8k
        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
859
24.8k
        if (output == NULL)
860
0
        {
861
0
            goto fail; /* allocation failure */
862
0
        }
863
24.8k
    }
864
865
24.8k
    output_pointer = output;
866
    /* loop through the string literal */
867
20.8M
    while (input_pointer < input_end)
868
20.8M
    {
869
20.8M
        if (*input_pointer != '\\')
870
20.6M
        {
871
20.6M
            *output_pointer++ = *input_pointer++;
872
20.6M
        }
873
        /* escape sequence */
874
132k
        else
875
132k
        {
876
132k
            unsigned char sequence_length = 2;
877
132k
            if ((input_end - input_pointer) < 1)
878
0
            {
879
0
                goto fail;
880
0
            }
881
882
132k
            switch (input_pointer[1])
883
132k
            {
884
9.80k
                case 'b':
885
9.80k
                    *output_pointer++ = '\b';
886
9.80k
                    break;
887
2.57k
                case 'f':
888
2.57k
                    *output_pointer++ = '\f';
889
2.57k
                    break;
890
13.9k
                case 'n':
891
13.9k
                    *output_pointer++ = '\n';
892
13.9k
                    break;
893
12.3k
                case 'r':
894
12.3k
                    *output_pointer++ = '\r';
895
12.3k
                    break;
896
7.26k
                case 't':
897
7.26k
                    *output_pointer++ = '\t';
898
7.26k
                    break;
899
15.3k
                case '\"':
900
28.9k
                case '\\':
901
43.6k
                case '/':
902
43.6k
                    *output_pointer++ = input_pointer[1];
903
43.6k
                    break;
904
905
                /* UTF-16 literal */
906
42.5k
                case 'u':
907
42.5k
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
908
42.5k
                    if (sequence_length == 0)
909
114
                    {
910
                        /* failed to convert UTF16-literal to UTF-8 */
911
114
                        goto fail;
912
114
                    }
913
42.3k
                    break;
914
915
42.3k
                default:
916
15
                    goto fail;
917
132k
            }
918
131k
            input_pointer += sequence_length;
919
131k
        }
920
20.8M
    }
921
922
    /* zero terminate the output */
923
24.7k
    *output_pointer = '\0';
924
925
24.7k
    item->type = cJSON_String;
926
24.7k
    item->valuestring = (char*)output;
927
928
24.7k
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
929
24.7k
    input_buffer->offset++;
930
931
24.7k
    return true;
932
933
333
fail:
934
333
    if (output != NULL)
935
129
    {
936
129
        input_buffer->hooks.deallocate(output);
937
129
        output = NULL;
938
129
    }
939
940
333
    if (input_pointer != NULL)
941
333
    {
942
333
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
943
333
    }
944
945
333
    return false;
946
24.8k
}
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
13.2k
{
951
13.2k
    const unsigned char *input_pointer = NULL;
952
13.2k
    unsigned char *output = NULL;
953
13.2k
    unsigned char *output_pointer = NULL;
954
13.2k
    size_t output_length = 0;
955
    /* numbers of additional characters needed for escaping */
956
13.2k
    size_t escape_characters = 0;
957
958
13.2k
    if (output_buffer == NULL)
959
0
    {
960
0
        return false;
961
0
    }
962
963
    /* empty string */
964
13.2k
    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
10.2M
    for (input_pointer = input; *input_pointer; input_pointer++)
978
10.2M
    {
979
10.2M
        switch (*input_pointer)
980
10.2M
        {
981
2.28k
            case '\"':
982
5.24k
            case '\\':
983
17.0k
            case '\b':
984
50.5k
            case '\f':
985
204k
            case '\n':
986
232k
            case '\r':
987
234k
            case '\t':
988
                /* one character escape sequence */
989
234k
                escape_characters++;
990
234k
                break;
991
10.0M
            default:
992
10.0M
                if (*input_pointer < 32)
993
7.46M
                {
994
                    /* UTF-16 escape sequence uXXXX */
995
7.46M
                    escape_characters += 5;
996
7.46M
                }
997
10.0M
                break;
998
10.2M
        }
999
10.2M
    }
1000
13.2k
    output_length = (size_t)(input_pointer - input) + escape_characters;
1001
1002
13.2k
    output = ensure(output_buffer, output_length + sizeof("\"\""));
1003
13.2k
    if (output == NULL)
1004
0
    {
1005
0
        return false;
1006
0
    }
1007
1008
    /* no characters have to be escaped */
1009
13.2k
    if (escape_characters == 0)
1010
12.6k
    {
1011
12.6k
        output[0] = '\"';
1012
12.6k
        memcpy(output + 1, input, output_length);
1013
12.6k
        output[output_length + 1] = '\"';
1014
12.6k
        output[output_length + 2] = '\0';
1015
1016
12.6k
        return true;
1017
12.6k
    }
1018
1019
609
    output[0] = '\"';
1020
609
    output_pointer = output + 1;
1021
    /* copy the string */
1022
10.2M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1023
10.2M
    {
1024
10.2M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1025
2.56M
        {
1026
            /* normal character, copy */
1027
2.56M
            *output_pointer = *input_pointer;
1028
2.56M
        }
1029
7.69M
        else
1030
7.69M
        {
1031
            /* character needs to be escaped */
1032
7.69M
            *output_pointer++ = '\\';
1033
7.69M
            switch (*input_pointer)
1034
7.69M
            {
1035
2.96k
                case '\\':
1036
2.96k
                    *output_pointer = '\\';
1037
2.96k
                    break;
1038
2.28k
                case '\"':
1039
2.28k
                    *output_pointer = '\"';
1040
2.28k
                    break;
1041
11.8k
                case '\b':
1042
11.8k
                    *output_pointer = 'b';
1043
11.8k
                    break;
1044
33.5k
                case '\f':
1045
33.5k
                    *output_pointer = 'f';
1046
33.5k
                    break;
1047
153k
                case '\n':
1048
153k
                    *output_pointer = 'n';
1049
153k
                    break;
1050
28.5k
                case '\r':
1051
28.5k
                    *output_pointer = 'r';
1052
28.5k
                    break;
1053
1.96k
                case '\t':
1054
1.96k
                    *output_pointer = 't';
1055
1.96k
                    break;
1056
7.46M
                default:
1057
                    /* escape and print as unicode codepoint */
1058
7.46M
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
1059
7.46M
                    output_pointer += 4;
1060
7.46M
                    break;
1061
7.69M
            }
1062
7.69M
        }
1063
10.2M
    }
1064
609
    output[output_length + 1] = '\"';
1065
609
    output[output_length + 2] = '\0';
1066
1067
609
    return true;
1068
609
}
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
913
{
1073
913
    return print_string_ptr((unsigned char*)item->valuestring, p);
1074
913
}
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.63M
{
1087
2.63M
    if ((buffer == NULL) || (buffer->content == NULL))
1088
0
    {
1089
0
        return NULL;
1090
0
    }
1091
1092
2.63M
    if (cannot_access_at_index(buffer, 0))
1093
0
    {
1094
0
        return buffer;
1095
0
    }
1096
1097
3.69M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1098
1.06M
    {
1099
1.06M
       buffer->offset++;
1100
1.06M
    }
1101
1102
2.63M
    if (buffer->offset == buffer->length)
1103
962
    {
1104
962
        buffer->offset--;
1105
962
    }
1106
1107
2.63M
    return buffer;
1108
2.63M
}
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.94k
{
1113
1.94k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1114
0
    {
1115
0
        return NULL;
1116
0
    }
1117
1118
1.94k
    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1119
75
    {
1120
75
        buffer->offset += 3;
1121
75
    }
1122
1123
1.94k
    return buffer;
1124
1.94k
}
1125
1126
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1127
1.94k
{
1128
1.94k
    size_t buffer_length;
1129
1130
1.94k
    if (NULL == value)
1131
0
    {
1132
0
        return NULL;
1133
0
    }
1134
1135
    /* Adding null character size due to require_null_terminated. */
1136
1.94k
    buffer_length = strlen(value) + sizeof("");
1137
1138
1.94k
    return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1139
1.94k
}
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.94k
{
1144
1.94k
    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1145
1.94k
    cJSON *item = NULL;
1146
1147
    /* reset error position */
1148
1.94k
    global_error.json = NULL;
1149
1.94k
    global_error.position = 0;
1150
1151
1.94k
    if (value == NULL || 0 == buffer_length)
1152
0
    {
1153
0
        goto fail;
1154
0
    }
1155
1156
1.94k
    buffer.content = (const unsigned char*)value;
1157
1.94k
    buffer.length = buffer_length;
1158
1.94k
    buffer.offset = 0;
1159
1.94k
    buffer.hooks = global_hooks;
1160
1161
1.94k
    item = cJSON_New_Item(&global_hooks);
1162
1.94k
    if (item == NULL) /* memory fail */
1163
0
    {
1164
0
        goto fail;
1165
0
    }
1166
1167
1.94k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1168
833
    {
1169
        /* parse failure. ep is set. */
1170
833
        goto fail;
1171
833
    }
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
444
    {
1176
444
        buffer_skip_whitespace(&buffer);
1177
444
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1178
54
        {
1179
54
            goto fail;
1180
54
        }
1181
444
    }
1182
1.06k
    if (return_parse_end)
1183
0
    {
1184
0
        *return_parse_end = (const char*)buffer_at_offset(&buffer);
1185
0
    }
1186
1187
1.06k
    return item;
1188
1189
887
fail:
1190
887
    if (item != NULL)
1191
887
    {
1192
887
        cJSON_Delete(item);
1193
887
    }
1194
1195
887
    if (value != NULL)
1196
887
    {
1197
887
        error local_error;
1198
887
        local_error.json = (const unsigned char*)value;
1199
887
        local_error.position = 0;
1200
1201
887
        if (buffer.offset < buffer.length)
1202
768
        {
1203
768
            local_error.position = buffer.offset;
1204
768
        }
1205
119
        else if (buffer.length > 0)
1206
119
        {
1207
119
            local_error.position = buffer.length - 1;
1208
119
        }
1209
1210
887
        if (return_parse_end != NULL)
1211
0
        {
1212
0
            *return_parse_end = (const char*)local_error.json + local_error.position;
1213
0
        }
1214
1215
887
        global_error = local_error;
1216
887
    }
1217
1218
887
    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
518
{
1236
518
    static const size_t default_buffer_size = 256;
1237
518
    printbuffer buffer[1];
1238
518
    unsigned char *printed = NULL;
1239
1240
518
    memset(buffer, 0, sizeof(buffer));
1241
1242
    /* create buffer */
1243
518
    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1244
518
    buffer->length = default_buffer_size;
1245
518
    buffer->format = format;
1246
518
    buffer->hooks = *hooks;
1247
518
    if (buffer->buffer == NULL)
1248
0
    {
1249
0
        goto fail;
1250
0
    }
1251
1252
    /* print the value */
1253
518
    if (!print_value(item, buffer))
1254
0
    {
1255
0
        goto fail;
1256
0
    }
1257
518
    update_offset(buffer);
1258
1259
    /* check if reallocate is available */
1260
518
    if (hooks->reallocate != NULL)
1261
518
    {
1262
518
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1263
518
        if (printed == NULL) {
1264
0
            goto fail;
1265
0
        }
1266
518
        buffer->buffer = NULL;
1267
518
    }
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
518
    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
518
}
1300
1301
/* Render a cJSON item/entity/structure to text. */
1302
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1303
193
{
1304
193
    return (char*)print(item, true, &global_hooks);
1305
193
}
1306
1307
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1308
325
{
1309
325
    return (char*)print(item, false, &global_hooks);
1310
325
}
1311
1312
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1313
543
{
1314
543
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1315
1316
543
    if (prebuffer < 0)
1317
0
    {
1318
0
        return NULL;
1319
0
    }
1320
1321
543
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1322
543
    if (!p.buffer)
1323
0
    {
1324
0
        return NULL;
1325
0
    }
1326
1327
543
    p.length = (size_t)prebuffer;
1328
543
    p.offset = 0;
1329
543
    p.noalloc = false;
1330
543
    p.format = fmt;
1331
543
    p.hooks = global_hooks;
1332
1333
543
    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
543
    return (char*)p.buffer;
1341
543
}
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
897k
{
1365
897k
    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
897k
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1373
635
    {
1374
635
        item->type = cJSON_NULL;
1375
635
        input_buffer->offset += 4;
1376
635
        return true;
1377
635
    }
1378
    /* false */
1379
897k
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1380
1.01k
    {
1381
1.01k
        item->type = cJSON_False;
1382
1.01k
        input_buffer->offset += 5;
1383
1.01k
        return true;
1384
1.01k
    }
1385
    /* true */
1386
896k
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1387
555
    {
1388
555
        item->type = cJSON_True;
1389
555
        item->valueint = 1;
1390
555
        input_buffer->offset += 4;
1391
555
        return true;
1392
555
    }
1393
    /* string */
1394
895k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1395
3.91k
    {
1396
3.91k
        return parse_string(item, input_buffer);
1397
3.91k
    }
1398
    /* number */
1399
891k
    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
44.3k
    {
1401
44.3k
        return parse_number(item, input_buffer);
1402
44.3k
    }
1403
    /* array */
1404
847k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1405
339k
    {
1406
339k
        return parse_array(item, input_buffer);
1407
339k
    }
1408
    /* object */
1409
507k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1410
507k
    {
1411
507k
        return parse_object(item, input_buffer);
1412
507k
    }
1413
1414
293
    return false;
1415
507k
}
1416
1417
/* Render a value to text. */
1418
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1419
758k
{
1420
758k
    unsigned char *output = NULL;
1421
1422
758k
    if ((item == NULL) || (output_buffer == NULL))
1423
0
    {
1424
0
        return false;
1425
0
    }
1426
1427
758k
    switch ((item->type) & 0xFF)
1428
758k
    {
1429
391
        case cJSON_NULL:
1430
391
            output = ensure(output_buffer, 5);
1431
391
            if (output == NULL)
1432
0
            {
1433
0
                return false;
1434
0
            }
1435
391
            strcpy((char*)output, "null");
1436
391
            return true;
1437
1438
540
        case cJSON_False:
1439
540
            output = ensure(output_buffer, 6);
1440
540
            if (output == NULL)
1441
0
            {
1442
0
                return false;
1443
0
            }
1444
540
            strcpy((char*)output, "false");
1445
540
            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
23.8k
        case cJSON_Number:
1457
23.8k
            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
913
        case cJSON_String:
1478
913
            return print_string(item, output_buffer);
1479
1480
263k
        case cJSON_Array:
1481
263k
            return print_array(item, output_buffer);
1482
1483
469k
        case cJSON_Object:
1484
469k
            return print_object(item, output_buffer);
1485
1486
0
        default:
1487
0
            return false;
1488
758k
    }
1489
758k
}
1490
1491
/* Build an array from input text. */
1492
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1493
339k
{
1494
339k
    cJSON *head = NULL; /* head of the linked list */
1495
339k
    cJSON *current_item = NULL;
1496
1497
339k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1498
3
    {
1499
3
        return false; /* to deeply nested */
1500
3
    }
1501
339k
    input_buffer->depth++;
1502
1503
339k
    if (buffer_at_offset(input_buffer)[0] != '[')
1504
0
    {
1505
        /* not an array */
1506
0
        goto fail;
1507
0
    }
1508
1509
339k
    input_buffer->offset++;
1510
339k
    buffer_skip_whitespace(input_buffer);
1511
339k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1512
4.15k
    {
1513
        /* empty array */
1514
4.15k
        goto success;
1515
4.15k
    }
1516
1517
    /* check if we skipped to the end of the buffer */
1518
335k
    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
335k
    input_buffer->offset--;
1526
    /* loop through the comma separated array elements */
1527
335k
    do
1528
874k
    {
1529
        /* allocate next item */
1530
874k
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1531
874k
        if (new_item == NULL)
1532
0
        {
1533
0
            goto fail; /* allocation failure */
1534
0
        }
1535
1536
        /* attach next item to list */
1537
874k
        if (head == NULL)
1538
335k
        {
1539
            /* start the linked list */
1540
335k
            current_item = head = new_item;
1541
335k
        }
1542
539k
        else
1543
539k
        {
1544
            /* add to the end and advance */
1545
539k
            current_item->next = new_item;
1546
539k
            new_item->prev = current_item;
1547
539k
            current_item = new_item;
1548
539k
        }
1549
1550
        /* parse next value */
1551
874k
        input_buffer->offset++;
1552
874k
        buffer_skip_whitespace(input_buffer);
1553
874k
        if (!parse_value(current_item, input_buffer))
1554
48.9k
        {
1555
48.9k
            goto fail; /* failed to parse value */
1556
48.9k
        }
1557
826k
        buffer_skip_whitespace(input_buffer);
1558
826k
    }
1559
826k
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1560
1561
286k
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1562
116
    {
1563
116
        goto fail; /* expected end of array */
1564
116
    }
1565
1566
290k
success:
1567
290k
    input_buffer->depth--;
1568
1569
290k
    if (head != NULL) {
1570
286k
        head->prev = current_item;
1571
286k
    }
1572
1573
290k
    item->type = cJSON_Array;
1574
290k
    item->child = head;
1575
1576
290k
    input_buffer->offset++;
1577
1578
290k
    return true;
1579
1580
49.0k
fail:
1581
49.0k
    if (head != NULL)
1582
49.0k
    {
1583
49.0k
        cJSON_Delete(head);
1584
49.0k
    }
1585
1586
49.0k
    return false;
1587
286k
}
1588
1589
/* Render an array to text */
1590
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1591
263k
{
1592
263k
    unsigned char *output_pointer = NULL;
1593
263k
    size_t length = 0;
1594
263k
    cJSON *current_element = item->child;
1595
1596
263k
    if (output_buffer == NULL)
1597
0
    {
1598
0
        return false;
1599
0
    }
1600
1601
    /* Compose the output array. */
1602
    /* opening square bracket */
1603
263k
    output_pointer = ensure(output_buffer, 1);
1604
263k
    if (output_pointer == NULL)
1605
0
    {
1606
0
        return false;
1607
0
    }
1608
1609
263k
    *output_pointer = '[';
1610
263k
    output_buffer->offset++;
1611
263k
    output_buffer->depth++;
1612
1613
1.00M
    while (current_element != NULL)
1614
745k
    {
1615
745k
        if (!print_value(current_element, output_buffer))
1616
0
        {
1617
0
            return false;
1618
0
        }
1619
745k
        update_offset(output_buffer);
1620
745k
        if (current_element->next)
1621
485k
        {
1622
485k
            length = (size_t) (output_buffer->format ? 2 : 1);
1623
485k
            output_pointer = ensure(output_buffer, length + 1);
1624
485k
            if (output_pointer == NULL)
1625
0
            {
1626
0
                return false;
1627
0
            }
1628
485k
            *output_pointer++ = ',';
1629
485k
            if(output_buffer->format)
1630
477k
            {
1631
477k
                *output_pointer++ = ' ';
1632
477k
            }
1633
485k
            *output_pointer = '\0';
1634
485k
            output_buffer->offset += length;
1635
485k
        }
1636
745k
        current_element = current_element->next;
1637
745k
    }
1638
1639
263k
    output_pointer = ensure(output_buffer, 2);
1640
263k
    if (output_pointer == NULL)
1641
0
    {
1642
0
        return false;
1643
0
    }
1644
263k
    *output_pointer++ = ']';
1645
263k
    *output_pointer = '\0';
1646
263k
    output_buffer->depth--;
1647
1648
263k
    return true;
1649
263k
}
1650
1651
/* Build an object from the text. */
1652
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1653
507k
{
1654
507k
    cJSON *head = NULL; /* linked list head */
1655
507k
    cJSON *current_item = NULL;
1656
1657
507k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1658
1
    {
1659
1
        return false; /* to deeply nested */
1660
1
    }
1661
507k
    input_buffer->depth++;
1662
1663
507k
    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
507k
    input_buffer->offset++;
1669
507k
    buffer_skip_whitespace(input_buffer);
1670
507k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1671
493k
    {
1672
493k
        goto success; /* empty object */
1673
493k
    }
1674
1675
    /* check if we skipped to the end of the buffer */
1676
13.6k
    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
13.6k
    input_buffer->offset--;
1684
    /* loop through the comma separated array elements */
1685
13.6k
    do
1686
21.1k
    {
1687
        /* allocate next item */
1688
21.1k
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1689
21.1k
        if (new_item == NULL)
1690
0
        {
1691
0
            goto fail; /* allocation failure */
1692
0
        }
1693
1694
        /* attach next item to list */
1695
21.1k
        if (head == NULL)
1696
13.6k
        {
1697
            /* start the linked list */
1698
13.6k
            current_item = head = new_item;
1699
13.6k
        }
1700
7.54k
        else
1701
7.54k
        {
1702
            /* add to the end and advance */
1703
7.54k
            current_item->next = new_item;
1704
7.54k
            new_item->prev = current_item;
1705
7.54k
            current_item = new_item;
1706
7.54k
        }
1707
1708
21.1k
        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
21.1k
        input_buffer->offset++;
1715
21.1k
        buffer_skip_whitespace(input_buffer);
1716
21.1k
        if (!parse_string(current_item, input_buffer))
1717
149
        {
1718
149
            goto fail; /* failed to parse name */
1719
149
        }
1720
21.0k
        buffer_skip_whitespace(input_buffer);
1721
1722
        /* swap valuestring and string, because we parsed the name */
1723
21.0k
        current_item->string = current_item->valuestring;
1724
21.0k
        current_item->valuestring = NULL;
1725
1726
21.0k
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1727
25
        {
1728
25
            goto fail; /* invalid object */
1729
25
        }
1730
1731
        /* parse the value */
1732
21.0k
        input_buffer->offset++;
1733
21.0k
        buffer_skip_whitespace(input_buffer);
1734
21.0k
        if (!parse_value(current_item, input_buffer))
1735
2.08k
        {
1736
2.08k
            goto fail; /* failed to parse value */
1737
2.08k
        }
1738
18.9k
        buffer_skip_whitespace(input_buffer);
1739
18.9k
    }
1740
18.9k
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1741
1742
11.3k
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1743
41
    {
1744
41
        goto fail; /* expected end of object */
1745
41
    }
1746
1747
504k
success:
1748
504k
    input_buffer->depth--;
1749
1750
504k
    if (head != NULL) {
1751
11.3k
        head->prev = current_item;
1752
11.3k
    }
1753
1754
504k
    item->type = cJSON_Object;
1755
504k
    item->child = head;
1756
1757
504k
    input_buffer->offset++;
1758
504k
    return true;
1759
1760
2.30k
fail:
1761
2.30k
    if (head != NULL)
1762
2.30k
    {
1763
2.30k
        cJSON_Delete(head);
1764
2.30k
    }
1765
1766
2.30k
    return false;
1767
11.3k
}
1768
1769
/* Render an object to text. */
1770
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1771
469k
{
1772
469k
    unsigned char *output_pointer = NULL;
1773
469k
    size_t length = 0;
1774
469k
    cJSON *current_item = item->child;
1775
1776
469k
    if (output_buffer == NULL)
1777
0
    {
1778
0
        return false;
1779
0
    }
1780
1781
    /* Compose the output: */
1782
469k
    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1783
469k
    output_pointer = ensure(output_buffer, length + 1);
1784
469k
    if (output_pointer == NULL)
1785
0
    {
1786
0
        return false;
1787
0
    }
1788
1789
469k
    *output_pointer++ = '{';
1790
469k
    output_buffer->depth++;
1791
469k
    if (output_buffer->format)
1792
468k
    {
1793
468k
        *output_pointer++ = '\n';
1794
468k
    }
1795
469k
    output_buffer->offset += length;
1796
1797
481k
    while (current_item)
1798
12.3k
    {
1799
12.3k
        if (output_buffer->format)
1800
11.7k
        {
1801
11.7k
            size_t i;
1802
11.7k
            output_pointer = ensure(output_buffer, output_buffer->depth);
1803
11.7k
            if (output_pointer == NULL)
1804
0
            {
1805
0
                return false;
1806
0
            }
1807
4.84M
            for (i = 0; i < output_buffer->depth; i++)
1808
4.83M
            {
1809
4.83M
                *output_pointer++ = '\t';
1810
4.83M
            }
1811
11.7k
            output_buffer->offset += output_buffer->depth;
1812
11.7k
        }
1813
1814
        /* print key */
1815
12.3k
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1816
0
        {
1817
0
            return false;
1818
0
        }
1819
12.3k
        update_offset(output_buffer);
1820
1821
12.3k
        length = (size_t) (output_buffer->format ? 2 : 1);
1822
12.3k
        output_pointer = ensure(output_buffer, length);
1823
12.3k
        if (output_pointer == NULL)
1824
0
        {
1825
0
            return false;
1826
0
        }
1827
12.3k
        *output_pointer++ = ':';
1828
12.3k
        if (output_buffer->format)
1829
11.7k
        {
1830
11.7k
            *output_pointer++ = '\t';
1831
11.7k
        }
1832
12.3k
        output_buffer->offset += length;
1833
1834
        /* print value */
1835
12.3k
        if (!print_value(current_item, output_buffer))
1836
0
        {
1837
0
            return false;
1838
0
        }
1839
12.3k
        update_offset(output_buffer);
1840
1841
        /* print comma if not last */
1842
12.3k
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1843
12.3k
        output_pointer = ensure(output_buffer, length + 1);
1844
12.3k
        if (output_pointer == NULL)
1845
0
        {
1846
0
            return false;
1847
0
        }
1848
12.3k
        if (current_item->next)
1849
2.95k
        {
1850
2.95k
            *output_pointer++ = ',';
1851
2.95k
        }
1852
1853
12.3k
        if (output_buffer->format)
1854
11.7k
        {
1855
11.7k
            *output_pointer++ = '\n';
1856
11.7k
        }
1857
12.3k
        *output_pointer = '\0';
1858
12.3k
        output_buffer->offset += length;
1859
1860
12.3k
        current_item = current_item->next;
1861
12.3k
    }
1862
1863
469k
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1864
469k
    if (output_pointer == NULL)
1865
0
    {
1866
0
        return false;
1867
0
    }
1868
469k
    if (output_buffer->format)
1869
468k
    {
1870
468k
        size_t i;
1871
253M
        for (i = 0; i < (output_buffer->depth - 1); i++)
1872
252M
        {
1873
252M
            *output_pointer++ = '\t';
1874
252M
        }
1875
468k
    }
1876
469k
    *output_pointer++ = '}';
1877
469k
    *output_pointer = '\0';
1878
469k
    output_buffer->depth--;
1879
1880
469k
    return true;
1881
469k
}
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
255
{
2862
255
    *input += static_strlen("//");
2863
2864
593
    for (; (*input)[0] != '\0'; ++(*input))
2865
570
    {
2866
570
        if ((*input)[0] == '\n') {
2867
232
            *input += static_strlen("\n");
2868
232
            return;
2869
232
        }
2870
570
    }
2871
255
}
2872
2873
static void skip_multiline_comment(char **input)
2874
368
{
2875
368
    *input += static_strlen("/*");
2876
2877
525k
    for (; (*input)[0] != '\0'; ++(*input))
2878
525k
    {
2879
525k
        if (((*input)[0] == '*') && ((*input)[1] == '/'))
2880
323
        {
2881
323
            *input += static_strlen("*/");
2882
323
            return;
2883
323
        }
2884
525k
    }
2885
368
}
2886
2887
13.6k
static void minify_string(char **input, char **output) {
2888
13.6k
    (*output)[0] = (*input)[0];
2889
13.6k
    *input += static_strlen("\"");
2890
13.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
13.5k
            (*output)[0] = '\"';
2898
13.5k
            *input += static_strlen("\"");
2899
13.5k
            *output += static_strlen("\"");
2900
13.5k
            return;
2901
10.6M
        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2902
2.60k
            (*output)[1] = (*input)[1];
2903
2.60k
            *input += static_strlen("\"");
2904
2.60k
            *output += static_strlen("\"");
2905
2.60k
        }
2906
10.6M
    }
2907
13.6k
}
2908
2909
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2910
915
{
2911
915
    char *into = json;
2912
2913
915
    if (json == NULL)
2914
0
    {
2915
0
        return;
2916
0
    }
2917
2918
3.17M
    while (json[0] != '\0')
2919
3.17M
    {
2920
3.17M
        switch (json[0])
2921
3.17M
        {
2922
491
            case ' ':
2923
718
            case '\t':
2924
1.05k
            case '\r':
2925
2.37k
            case '\n':
2926
2.37k
                json++;
2927
2.37k
                break;
2928
2929
933
            case '/':
2930
933
                if (json[1] == '/')
2931
255
                {
2932
255
                    skip_oneline_comment(&json);
2933
255
                }
2934
678
                else if (json[1] == '*')
2935
368
                {
2936
368
                    skip_multiline_comment(&json);
2937
368
                } else {
2938
310
                    json++;
2939
310
                }
2940
933
                break;
2941
2942
13.6k
            case '\"':
2943
13.6k
                minify_string(&json, (char**)&into);
2944
13.6k
                break;
2945
2946
3.15M
            default:
2947
3.15M
                into[0] = json[0];
2948
3.15M
                json++;
2949
3.15M
                into++;
2950
3.17M
        }
2951
3.17M
    }
2952
2953
    /* and null-terminate. */
2954
915
    *into = '\0';
2955
915
}
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
}