Coverage Report

Created: 2026-04-01 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vulkan-loader/loader/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
#include "allocation.h"
62
63
/* define our own boolean type */
64
#ifdef true
65
#undef true
66
#endif
67
88.0M
#define true ((cJSON_bool)1)
68
69
#ifdef false
70
#undef false
71
#endif
72
22.9M
#define false ((cJSON_bool)0)
73
74
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
75
#ifndef isinf
76
#define isinf(d) (isnan((d - d)) && !isnan(d))
77
#endif
78
#ifndef isnan
79
#define isnan(d) (d != d)
80
#endif
81
82
#ifndef NAN
83
#ifdef _WIN32
84
#define NAN sqrt(-1.0)
85
#else
86
#define NAN 0.0 / 0.0
87
#endif
88
#endif
89
90
typedef struct {
91
    const unsigned char *json;
92
    size_t position;
93
} error;
94
static error global_error = {NULL, 0};
95
96
0
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { return (const char *)(global_error.json + global_error.position); }
97
98
5.81M
CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
99
5.81M
    if (!loader_cJSON_IsString(item)) {
100
2.15M
        return NULL;
101
2.15M
    }
102
103
3.65M
    return item->valuestring;
104
5.81M
}
105
106
0
CJSON_PUBLIC(double) loader_cJSON_GetNumberValue(const cJSON *const item) {
107
0
    if (!loader_cJSON_IsNumber(item)) {
108
0
        return (double)NAN;
109
0
    }
110
111
0
    return item->valuedouble;
112
0
}
113
114
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
115
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18)
116
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
117
#endif
118
119
/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
120
97.3M
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
121
97.3M
    if ((string1 == NULL) || (string2 == NULL)) {
122
1.02k
        return 1;
123
1.02k
    }
124
125
97.3M
    if (string1 == string2) {
126
0
        return 0;
127
0
    }
128
129
180M
    for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) {
130
91.5M
        if (*string1 == '\0') {
131
8.83M
            return 0;
132
8.83M
        }
133
91.5M
    }
134
135
88.5M
    return tolower(*string1) - tolower(*string2);
136
97.3M
}
137
138
/* strlen of character literals resolved at compile time */
139
0
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
140
141
/* Internal constructor. */
142
42.7M
static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
143
42.7M
    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
144
42.7M
    if (NULL != node) {
145
42.7M
        node->pAllocator = pAllocator;
146
42.7M
    }
147
42.7M
    return node;
148
42.7M
}
149
150
/* Delete a cJSON structure. */
151
8.91M
TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
152
8.91M
    cJSON *next = NULL;
153
51.6M
    while (item != NULL) {
154
42.7M
        next = item->next;
155
42.7M
        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
156
8.12M
            loader_cJSON_Delete(item->child);
157
8.12M
        }
158
42.7M
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
159
18.5M
            loader_free(item->pAllocator, item->valuestring);
160
18.5M
            item->valuestring = NULL;
161
18.5M
        }
162
42.7M
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
163
21.6M
            loader_free(item->pAllocator, item->string);
164
21.6M
            item->string = NULL;
165
21.6M
        }
166
42.7M
        loader_free(item->pAllocator, item);
167
42.7M
        item = next;
168
42.7M
    }
169
8.91M
}
170
171
/* get the decimal point character of the current locale */
172
12.2M
static unsigned char get_decimal_point(void) {
173
#ifdef ENABLE_LOCALES
174
    struct lconv *lconv = localeconv();
175
    return (unsigned char)lconv->decimal_point[0];
176
#else
177
12.2M
    return '.';
178
12.2M
#endif
179
12.2M
}
180
181
typedef struct {
182
    const unsigned char *content;
183
    size_t length;
184
    size_t offset;
185
    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
186
    const VkAllocationCallbacks *pAllocator;
187
} parse_buffer;
188
189
/* check if the given size is left to read in a given parse buffer (starting with 1) */
190
256M
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
191
/* check if the buffer can be accessed at the given index (starting with 0) */
192
1.33G
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
193
252M
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
194
/* get a pointer to the buffer at the position */
195
977M
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
196
197
/* Parse the input text to generate a number, and populate the result into item. */
198
9.69M
static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
199
9.69M
    double number = 0;
200
9.69M
    unsigned char *after_end = NULL;
201
9.69M
    unsigned char number_c_string[64];
202
9.69M
    unsigned char decimal_point = get_decimal_point();
203
9.69M
    size_t i = 0;
204
205
9.69M
    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
206
0
        return false;
207
0
    }
208
209
    /* copy the number into a temporary buffer and replace '.' with the decimal point
210
     * of the current locale (for strtod)
211
     * This also takes care of '\0' not necessarily being available for marking the end of the input */
212
32.9M
    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
213
32.9M
        switch (buffer_at_offset(input_buffer)[i]) {
214
2.35M
            case '0':
215
8.43M
            case '1':
216
10.3M
            case '2':
217
12.1M
            case '3':
218
13.9M
            case '4':
219
14.5M
            case '5':
220
17.2M
            case '6':
221
19.0M
            case '7':
222
20.2M
            case '8':
223
22.2M
            case '9':
224
22.2M
            case '+':
225
22.4M
            case '-':
226
23.0M
            case 'e':
227
23.0M
            case 'E':
228
23.0M
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
229
23.0M
                break;
230
231
167k
            case '.':
232
167k
                number_c_string[i] = decimal_point;
233
167k
                break;
234
235
9.69M
            default:
236
9.69M
                goto loop_end;
237
32.9M
        }
238
32.9M
    }
239
9.69M
loop_end:
240
9.69M
    number_c_string[i] = '\0';
241
242
9.69M
    number = strtod((const char *)number_c_string, (char **)&after_end);
243
9.69M
    if (number_c_string == after_end) {
244
722
        return false; /* parse_error */
245
722
    }
246
247
9.69M
    item->valuedouble = number;
248
249
    /* use saturation in case of overflow */
250
9.69M
    if (number >= INT_MAX) {
251
403k
        item->valueint = INT_MAX;
252
9.29M
    } else if (number <= (double)INT_MIN) {
253
155k
        item->valueint = INT_MIN;
254
9.14M
    } else {
255
9.14M
        item->valueint = (int)number;
256
9.14M
    }
257
258
9.69M
    item->type = cJSON_Number;
259
260
9.69M
    input_buffer->offset += (size_t)(after_end - number_c_string);
261
9.69M
    return true;
262
9.69M
}
263
264
typedef struct {
265
    unsigned char *buffer;
266
    size_t length;
267
    size_t offset;
268
    size_t depth; /* current nesting depth (for formatted printing) */
269
    cJSON_bool noalloc;
270
    cJSON_bool format; /* is this print a formatted print */
271
    const VkAllocationCallbacks *pAllocator;
272
} printbuffer;
273
274
/* realloc printbuffer if necessary to have at least "needed" bytes more */
275
36.4M
static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
276
36.4M
    unsigned char *newbuffer = NULL;
277
36.4M
    size_t newsize = 0;
278
279
36.4M
    if ((p == NULL) || (p->buffer == NULL)) {
280
0
        return NULL;
281
0
    }
282
283
36.4M
    if ((p->length > 0) && (p->offset >= p->length)) {
284
        /* make sure that offset is valid */
285
0
        return NULL;
286
0
    }
287
288
36.4M
    if (needed > INT_MAX) {
289
        /* sizes bigger than INT_MAX are currently not supported */
290
0
        return NULL;
291
0
    }
292
293
36.4M
    needed += p->offset + 1;
294
36.4M
    if (needed <= p->length) {
295
36.4M
        return p->buffer + p->offset;
296
36.4M
    }
297
298
28.0k
    if (p->noalloc) {
299
2.96k
        return NULL;
300
2.96k
    }
301
302
    /* calculate new buffer size */
303
25.1k
    if (needed > (INT_MAX / 2)) {
304
        /* overflow of int, use INT_MAX if possible */
305
0
        if (needed <= INT_MAX) {
306
0
            newsize = INT_MAX;
307
0
        } else {
308
0
            return NULL;
309
0
        }
310
25.1k
    } else {
311
25.1k
        newsize = needed * 2;
312
25.1k
    }
313
314
25.1k
    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
315
25.1k
    if (newbuffer == NULL) {
316
0
        *out_of_memory = true;
317
0
        loader_free(p->pAllocator, p->buffer);
318
0
        p->length = 0;
319
0
        p->buffer = NULL;
320
321
0
        return NULL;
322
0
    }
323
324
25.1k
    p->length = newsize;
325
25.1k
    p->buffer = newbuffer;
326
327
25.1k
    return newbuffer + p->offset;
328
25.1k
}
329
330
/* calculate the new length of the string in a printbuffer and update the offset */
331
14.5M
static void update_offset(printbuffer *const buffer) {
332
14.5M
    const unsigned char *buffer_pointer = NULL;
333
14.5M
    if ((buffer == NULL) || (buffer->buffer == NULL)) {
334
0
        return;
335
0
    }
336
14.5M
    buffer_pointer = buffer->buffer + buffer->offset;
337
338
14.5M
    buffer->offset += strlen((const char *)buffer_pointer);
339
14.5M
}
340
341
/* securely comparison of floating-point variables */
342
75.3k
static cJSON_bool compare_double(double a, double b) {
343
75.3k
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
344
75.3k
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
345
75.3k
}
346
347
/* Render the number nicely from the given item into a string. */
348
2.55M
static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
349
2.55M
    unsigned char *output_pointer = NULL;
350
2.55M
    double d = item->valuedouble;
351
2.55M
    int length = 0;
352
2.55M
    size_t i = 0;
353
2.55M
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
354
2.55M
    unsigned char decimal_point = get_decimal_point();
355
2.55M
    double test = 0.0;
356
357
2.55M
    if (output_buffer == NULL) {
358
0
        return false;
359
0
    }
360
361
    /* This checks for NaN and Infinity */
362
2.55M
    if (isnan(d) || isinf(d)) {
363
1.29k
        length = snprintf((char *)number_buffer, 26, "null");
364
2.55M
    } else if (d == (double)item->valueint) {
365
2.48M
        length = snprintf((char *)number_buffer, 26, "%d", item->valueint);
366
2.48M
    } else {
367
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
368
75.3k
        length = snprintf((char *)number_buffer, 26, "%1.15g", d);
369
370
        /* Check whether the original double can be recovered */
371
75.3k
        if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) {
372
            /* If not, print with 17 decimal places of precision */
373
11.2k
            length = snprintf((char *)number_buffer, 26, "%1.17g", d);
374
11.2k
        }
375
75.3k
    }
376
377
    /* snprintf failed or buffer overrun occurred */
378
2.55M
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
379
0
        return false;
380
0
    }
381
382
    /* reserve appropriate space in the output */
383
2.55M
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""), out_of_memory);
384
2.55M
    if (output_pointer == NULL) {
385
0
        return false;
386
0
    }
387
388
    /* copy the printed number to the output and replace locale
389
     * dependent decimal point with '.' */
390
5.81M
    for (i = 0; i < ((size_t)length); i++) {
391
3.25M
        if (number_buffer[i] == decimal_point) {
392
22.0k
            output_pointer[i] = '.';
393
22.0k
            continue;
394
22.0k
        }
395
396
3.23M
        output_pointer[i] = number_buffer[i];
397
3.23M
    }
398
2.55M
    output_pointer[i] = '\0';
399
400
2.55M
    output_buffer->offset += (size_t)length;
401
402
2.55M
    return true;
403
2.55M
}
404
405
/* parse 4 digit hexadecimal number */
406
4.43M
static unsigned parse_hex4(const unsigned char *const input) {
407
4.43M
    unsigned int h = 0;
408
4.43M
    size_t i = 0;
409
410
10.3M
    for (i = 0; i < 4; i++) {
411
        /* parse digit */
412
9.34M
        if ((input[i] >= '0') && (input[i] <= '9')) {
413
2.92M
            h += (unsigned int)input[i] - '0';
414
6.42M
        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
415
626k
            h += (unsigned int)10 + input[i] - 'A';
416
5.79M
        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
417
2.36M
            h += (unsigned int)10 + input[i] - 'a';
418
2.36M
        } else /* invalid */
419
3.42M
        {
420
3.42M
            return 0;
421
3.42M
        }
422
423
5.91M
        if (i < 3) {
424
            /* shift left to make place for the next nibble */
425
4.90M
            h = h << 4;
426
4.90M
        }
427
5.91M
    }
428
429
1.00M
    return h;
430
4.43M
}
431
432
/* converts a UTF-16 literal to UTF-8
433
 * A literal can be one or two sequences of the form \uXXXX */
434
static unsigned char utf16_literal_to_utf8(const unsigned char *const input_pointer, const unsigned char *const input_end,
435
4.42M
                                           unsigned char **output_pointer) {
436
4.42M
    long unsigned int codepoint = 0;
437
4.42M
    unsigned int first_code = 0;
438
4.42M
    const unsigned char *first_sequence = input_pointer;
439
4.42M
    unsigned char utf8_length = 0;
440
4.42M
    unsigned char utf8_position = 0;
441
4.42M
    unsigned char sequence_length = 0;
442
4.42M
    unsigned char first_byte_mark = 0;
443
444
4.42M
    if ((input_end - first_sequence) < 6) {
445
        /* input ends unexpectedly */
446
379
        goto fail;
447
379
    }
448
449
    /* get the first utf16 sequence */
450
4.41M
    first_code = parse_hex4(first_sequence + 2);
451
452
    /* check that the code is valid */
453
4.41M
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
454
359
        goto fail;
455
359
    }
456
457
    /* UTF16 surrogate pair */
458
4.41M
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
459
19.0k
        const unsigned char *second_sequence = first_sequence + 6;
460
19.0k
        unsigned int second_code = 0;
461
19.0k
        sequence_length = 12; /* \uXXXX\uXXXX */
462
463
19.0k
        if ((input_end - second_sequence) < 6) {
464
            /* input ends unexpectedly */
465
468
            goto fail;
466
468
        }
467
468
18.6k
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
469
            /* missing second half of the surrogate pair */
470
716
            goto fail;
471
716
        }
472
473
        /* get the second utf16 sequence */
474
17.9k
        second_code = parse_hex4(second_sequence + 2);
475
        /* check that the code is valid */
476
17.9k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
477
            /* invalid second half of the surrogate pair */
478
776
            goto fail;
479
776
        }
480
481
        /* calculate the unicode codepoint from the surrogate pair */
482
17.1k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
483
4.40M
    } else {
484
4.40M
        sequence_length = 6; /* \uXXXX */
485
4.40M
        codepoint = first_code;
486
4.40M
    }
487
488
    /* encode as UTF-8
489
     * takes at maximum 4 bytes to encode:
490
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
491
4.41M
    if (codepoint < 0x80) {
492
        /* normal ascii, encoding 0xxxxxxx */
493
3.45M
        utf8_length = 1;
494
3.45M
    } else if (codepoint < 0x800) {
495
        /* two bytes, encoding 110xxxxx 10xxxxxx */
496
338k
        utf8_length = 2;
497
338k
        first_byte_mark = 0xC0; /* 11000000 */
498
625k
    } else if (codepoint < 0x10000) {
499
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
500
608k
        utf8_length = 3;
501
608k
        first_byte_mark = 0xE0; /* 11100000 */
502
608k
    } else if (codepoint <= 0x10FFFF) {
503
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
504
17.1k
        utf8_length = 4;
505
17.1k
        first_byte_mark = 0xF0; /* 11110000 */
506
17.1k
    } else {
507
        /* invalid unicode codepoint */
508
0
        goto fail;
509
0
    }
510
511
    /* encode as utf8 */
512
6.02M
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
513
        /* 10xxxxxx */
514
1.60M
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
515
1.60M
        codepoint >>= 6;
516
1.60M
    }
517
    /* encode first byte */
518
4.41M
    if (utf8_length > 1) {
519
964k
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
520
3.45M
    } else {
521
3.45M
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
522
3.45M
    }
523
524
4.41M
    *output_pointer += utf8_length;
525
526
4.41M
    return sequence_length;
527
528
2.69k
fail:
529
2.69k
    return 0;
530
4.41M
}
531
532
/* Parse the input text into an unescaped cinput, and populate item. */
533
40.2M
static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
534
40.2M
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
535
40.2M
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
536
40.2M
    unsigned char *output_pointer = NULL;
537
40.2M
    unsigned char *output = NULL;
538
539
    /* not a string */
540
40.2M
    if (buffer_at_offset(input_buffer)[0] != '\"') {
541
1.72k
        goto fail;
542
1.72k
    }
543
544
40.2M
    {
545
        /* calculate approximate size of the output (overestimate) */
546
40.2M
        size_t allocation_length = 0;
547
40.2M
        size_t skipped_bytes = 0;
548
1.09G
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
549
            /* is escape sequence */
550
1.05G
            if (input_end[0] == '\\') {
551
7.12M
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
552
                    /* prevent buffer overflow when last input character is a backslash */
553
0
                    goto fail;
554
0
                }
555
7.12M
                skipped_bytes++;
556
7.12M
                input_end++;
557
7.12M
            }
558
1.05G
            input_end++;
559
1.05G
        }
560
40.2M
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
561
2.46k
            goto fail; /* string ended unexpectedly */
562
2.46k
        }
563
564
        /* This is at most how much we need for the output */
565
40.2M
        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
566
40.2M
        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
567
40.2M
                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
568
40.2M
        if (output == NULL) {
569
0
            *out_of_memory = true;
570
0
            goto fail; /* allocation failure */
571
0
        }
572
40.2M
    }
573
574
40.2M
    output_pointer = output;
575
    /* loop through the string literal */
576
1.01G
    while (input_pointer < input_end) {
577
972M
        if (*input_pointer != '\\') {
578
967M
            *output_pointer++ = *input_pointer++;
579
967M
        }
580
        /* escape sequence */
581
5.31M
        else {
582
5.31M
            unsigned char sequence_length = 2;
583
5.31M
            if ((input_end - input_pointer) < 1) {
584
0
                goto fail;
585
0
            }
586
587
5.31M
            switch (input_pointer[1]) {
588
46.5k
                case 'b':
589
46.5k
                    *output_pointer++ = '\b';
590
46.5k
                    break;
591
26.8k
                case 'f':
592
26.8k
                    *output_pointer++ = '\f';
593
26.8k
                    break;
594
12.2k
                case 'n':
595
12.2k
                    *output_pointer++ = '\n';
596
12.2k
                    break;
597
114k
                case 'r':
598
114k
                    *output_pointer++ = '\r';
599
114k
                    break;
600
28.8k
                case 't':
601
28.8k
                    *output_pointer++ = '\t';
602
28.8k
                    break;
603
10.9k
                case '\"':
604
656k
                case '\\':
605
662k
                case '/':
606
662k
                    *output_pointer++ = input_pointer[1];
607
662k
                    break;
608
609
                /* UTF-16 literal */
610
4.42M
                case 'u':
611
4.42M
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
612
4.42M
                    if (sequence_length == 0) {
613
                        /* failed to convert UTF16-literal to UTF-8 */
614
2.69k
                        goto fail;
615
2.69k
                    }
616
4.41M
                    break;
617
618
4.41M
                default:
619
563
                    goto fail;
620
5.31M
            }
621
5.30M
            input_pointer += sequence_length;
622
5.30M
        }
623
972M
    }
624
625
    /* zero terminate the output */
626
40.2M
    *output_pointer = '\0';
627
628
40.2M
    item->type = cJSON_String;
629
40.2M
    item->valuestring = (char *)output;
630
631
40.2M
    input_buffer->offset = (size_t)(input_end - input_buffer->content);
632
40.2M
    input_buffer->offset++;
633
634
40.2M
    return true;
635
636
7.44k
fail:
637
7.44k
    if (output != NULL) {
638
3.26k
        loader_free(input_buffer->pAllocator, output);
639
3.26k
        output = NULL;
640
3.26k
    }
641
642
7.44k
    if (input_pointer != NULL) {
643
7.44k
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
644
7.44k
    }
645
646
7.44k
    return false;
647
40.2M
}
648
649
/* Render the cstring provided to an escaped version that can be printed. */
650
9.52M
static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
651
9.52M
    const unsigned char *input_pointer = NULL;
652
9.52M
    unsigned char *output = NULL;
653
9.52M
    unsigned char *output_pointer = NULL;
654
9.52M
    size_t output_length = 0;
655
    /* numbers of additional characters needed for escaping */
656
9.52M
    size_t escape_characters = 0;
657
658
9.52M
    if (output_buffer == NULL) {
659
0
        return false;
660
0
    }
661
662
    /* empty string */
663
9.52M
    if (input == NULL) {
664
0
        output = ensure(output_buffer, sizeof(""), out_of_memory);
665
0
        if (output == NULL) {
666
0
            return false;
667
0
        }
668
669
0
        return true;
670
0
    }
671
672
    /* set "flag" to 1 if something needs to be escaped */
673
224M
    for (input_pointer = input; *input_pointer; input_pointer++) {
674
214M
        switch (*input_pointer) {
675
2.08k
            case '\"':
676
431k
            case '\\':
677
455k
            case '\b':
678
569k
            case '\f':
679
792k
            case '\n':
680
935k
            case '\r':
681
953k
            case '\t':
682
                /* one character escape sequence */
683
953k
                escape_characters++;
684
953k
                break;
685
213M
            default:
686
213M
                if (*input_pointer < 32) {
687
                    /* UTF-16 escape sequence uXXXX */
688
126M
                    escape_characters += 5;
689
126M
                }
690
213M
                break;
691
214M
        }
692
214M
    }
693
9.52M
    output_length = (size_t)(input_pointer - input) + escape_characters;
694
695
9.52M
    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
696
9.52M
    if (output == NULL) {
697
2.96k
        return false;
698
2.96k
    }
699
700
    /* no characters have to be escaped */
701
9.51M
    if (escape_characters == 0) {
702
8.69M
        memcpy(output, input, output_length);
703
8.69M
        output[output_length] = '\0';
704
705
8.69M
        return true;
706
8.69M
    }
707
708
824k
    output_pointer = output;
709
    /* copy the string */
710
156M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
711
155M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
712
            /* normal character, copy */
713
30.0M
            *output_pointer = *input_pointer;
714
125M
        } else {
715
            // Loader specific modification - don't add a backslash because that will 'double up' any existing back slashes.
716
            // This change was added right after vulkan's public release, so while it may not be a problem, there are plenty
717
            // of API calls made which might not work if the paths have "\\"" in them
718
            /* character needs to be escaped */
719
            //*output_pointer++ = '\\';
720
125M
            switch (*input_pointer) {
721
429k
                case '\\':
722
429k
                    *output_pointer = '\\';
723
429k
                    break;
724
1.98k
                case '\"':
725
1.98k
                    *output_pointer = '\"';
726
1.98k
                    break;
727
23.4k
                case '\b':
728
23.4k
                    *output_pointer = '\b';
729
23.4k
                    break;
730
111k
                case '\f':
731
111k
                    *output_pointer = '\f';
732
111k
                    break;
733
214k
                case '\n':
734
214k
                    *output_pointer = '\n';
735
214k
                    break;
736
142k
                case '\r':
737
142k
                    *output_pointer = '\r';
738
142k
                    break;
739
18.2k
                case '\t':
740
18.2k
                    *output_pointer = '\t';
741
18.2k
                    break;
742
124M
                default:
743
                    /* escape and print as unicode codepoint */
744
124M
                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
745
124M
                    output_pointer += 4;
746
124M
                    break;
747
125M
            }
748
125M
        }
749
155M
    }
750
824k
    output[output_length] = '\0';
751
752
824k
    return true;
753
824k
}
754
755
/* Invoke print_string_ptr (which is useful) on an item. */
756
6.76M
static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
757
6.76M
    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
758
6.76M
}
759
760
/* Predeclare these prototypes. */
761
static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
762
static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
763
static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
764
static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
765
static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
766
static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
767
768
/* Utility to jump whitespace and cr/lf */
769
140M
static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
770
140M
    if ((buffer == NULL) || (buffer->content == NULL)) {
771
0
        return NULL;
772
0
    }
773
774
140M
    if (cannot_access_at_index(buffer, 0)) {
775
0
        return buffer;
776
0
    }
777
778
401M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
779
260M
        buffer->offset++;
780
260M
    }
781
782
140M
    if (buffer->offset == buffer->length) {
783
16.6k
        buffer->offset--;
784
16.6k
    }
785
786
140M
    return buffer;
787
140M
}
788
789
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
790
103k
static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
791
103k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
792
0
        return NULL;
793
0
    }
794
795
103k
    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
796
887
        buffer->offset += 3;
797
887
    }
798
799
103k
    return buffer;
800
103k
}
801
802
CJSON_PUBLIC(cJSON *)
803
loader_cJSON_ParseWithOpts(const VkAllocationCallbacks *pAllocator, const char *value, const char **return_parse_end,
804
0
                           cJSON_bool require_null_terminated, bool *out_of_memory) {
805
0
    size_t buffer_length;
806
807
0
    if (NULL == value) {
808
0
        return NULL;
809
0
    }
810
811
    /* Adding null character size due to require_null_terminated. */
812
0
    buffer_length = strlen(value) + sizeof("");
813
814
0
    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, return_parse_end, require_null_terminated,
815
0
                                            out_of_memory);
816
0
}
817
818
/* Parse an object - create a new root, and populate. */
819
CJSON_PUBLIC(cJSON *)
820
loader_cJSON_ParseWithLengthOpts(const VkAllocationCallbacks *pAllocator, const char *value, size_t buffer_length,
821
103k
                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
822
103k
    parse_buffer buffer = {0, 0, 0, 0, 0};
823
103k
    cJSON *item = NULL;
824
825
    /* reset error position */
826
    // global_error.json = NULL;
827
    // global_error.position = 0;
828
829
103k
    if (value == NULL || 0 == buffer_length) {
830
0
        goto fail;
831
0
    }
832
833
103k
    buffer.content = (const unsigned char *)value;
834
103k
    buffer.length = buffer_length;
835
103k
    buffer.offset = 0;
836
103k
    buffer.pAllocator = pAllocator;
837
838
103k
    item = cJSON_New_Item(pAllocator);
839
103k
    if (item == NULL) /* memory fail */
840
0
    {
841
0
        *out_of_memory = true;
842
0
        goto fail;
843
0
    }
844
845
103k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
846
        /* parse failure. ep is set. */
847
36.5k
        goto fail;
848
36.5k
    }
849
850
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
851
66.9k
    if (require_null_terminated) {
852
0
        buffer_skip_whitespace(&buffer);
853
0
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
854
0
            goto fail;
855
0
        }
856
0
    }
857
66.9k
    if (return_parse_end) {
858
0
        *return_parse_end = (const char *)buffer_at_offset(&buffer);
859
0
    }
860
861
66.9k
    return item;
862
863
36.5k
fail:
864
36.5k
    if (item != NULL) {
865
36.5k
        loader_cJSON_Delete(item);
866
36.5k
    }
867
868
36.5k
    if (value != NULL) {
869
36.5k
        error local_error;
870
36.5k
        local_error.json = (const unsigned char *)value;
871
36.5k
        local_error.position = 0;
872
873
36.5k
        if (buffer.offset < buffer.length) {
874
34.9k
            local_error.position = buffer.offset;
875
34.9k
        } else if (buffer.length > 0) {
876
1.51k
            local_error.position = buffer.length - 1;
877
1.51k
        }
878
879
36.5k
        if (return_parse_end != NULL) {
880
0
            *return_parse_end = (const char *)local_error.json + local_error.position;
881
0
        }
882
883
        // global_error = local_error;
884
36.5k
    }
885
886
36.5k
    return NULL;
887
66.9k
}
888
889
/* Default options for loader_cJSON_Parse */
890
0
CJSON_PUBLIC(cJSON *) loader_cJSON_Parse(const VkAllocationCallbacks *pAllocator, const char *value, bool *out_of_memory) {
891
0
    return loader_cJSON_ParseWithOpts(pAllocator, value, 0, 0, out_of_memory);
892
0
}
893
894
CJSON_PUBLIC(cJSON *)
895
loader_cJSON_ParseWithLength(const VkAllocationCallbacks *pAllocator, const char *value, size_t buffer_length,
896
103k
                             bool *out_of_memory) {
897
103k
    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
898
103k
}
899
900
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
901
902
3.62M
static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
903
3.62M
    static const size_t default_buffer_size = 256;
904
3.62M
    printbuffer buffer[1];
905
3.62M
    unsigned char *printed = NULL;
906
907
3.62M
    memset(buffer, 0, sizeof(buffer));
908
909
    /* create buffer */
910
3.62M
    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
911
3.62M
    buffer->length = default_buffer_size;
912
3.62M
    buffer->format = format;
913
3.62M
    buffer->pAllocator = item->pAllocator;
914
3.62M
    if (buffer->buffer == NULL) {
915
0
        *out_of_memory = true;
916
0
        goto fail;
917
0
    }
918
919
    /* print the value */
920
3.62M
    if (!print_value(item, buffer, out_of_memory)) {
921
0
        goto fail;
922
0
    }
923
3.62M
    update_offset(buffer);
924
925
3.62M
    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
926
3.62M
                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
927
3.62M
    if (printed == NULL) {
928
0
        *out_of_memory = true;
929
0
        goto fail;
930
0
    }
931
3.62M
    buffer->buffer = NULL;
932
933
3.62M
    return printed;
934
935
0
fail:
936
0
    if (buffer->buffer != NULL) {
937
0
        loader_free(item->pAllocator, buffer->buffer);
938
0
        buffer->buffer = NULL;
939
0
    }
940
941
0
    if (printed != NULL) {
942
0
        loader_free(item->pAllocator, printed);
943
0
        printed = NULL;
944
0
    }
945
946
0
    return NULL;
947
3.62M
}
948
949
/* Render a cJSON item/entity/structure to text. */
950
3.62M
TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
951
3.62M
    return (char *)print(item, true, out_of_memory);
952
3.62M
}
953
954
0
CJSON_PUBLIC(char *) loader_cJSON_PrintUnformatted(const cJSON *item, bool *out_of_memory) {
955
0
    return (char *)print(item, false, out_of_memory);
956
0
}
957
958
CJSON_PUBLIC(char *)
959
0
loader_cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt, bool *out_of_memory) {
960
0
    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
961
962
0
    if (prebuffer < 0) {
963
0
        return NULL;
964
0
    }
965
966
0
    p.buffer = (unsigned char *)loader_alloc(item->pAllocator, (size_t)prebuffer, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
967
0
    if (!p.buffer) {
968
0
        return NULL;
969
0
    }
970
971
0
    p.length = (size_t)prebuffer;
972
0
    p.offset = 0;
973
0
    p.noalloc = false;
974
0
    p.format = fmt;
975
0
    p.pAllocator = item->pAllocator;
976
977
0
    if (!print_value(item, &p, out_of_memory)) {
978
0
        loader_free(item->pAllocator, p.buffer);
979
0
        p.buffer = NULL;
980
0
        return NULL;
981
0
    }
982
983
0
    return (char *)p.buffer;
984
0
}
985
986
CJSON_PUBLIC(cJSON_bool)
987
3.08M
loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
988
3.08M
    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
989
990
3.08M
    if ((length < 0) || (buffer == NULL)) {
991
0
        return false;
992
0
    }
993
994
3.08M
    p.buffer = (unsigned char *)buffer;
995
3.08M
    p.length = (size_t)length;
996
3.08M
    p.offset = 0;
997
3.08M
    p.noalloc = true;
998
3.08M
    p.format = format;
999
3.08M
    p.pAllocator = item->pAllocator;
1000
3.08M
    bool out_of_memory = false;
1001
3.08M
    return print_value(item, &p, &out_of_memory);
1002
3.08M
}
1003
1004
/* Parser core - when encountering text, process appropriately. */
1005
42.7M
static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1006
42.7M
    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
1007
0
        return false; /* no input */
1008
0
    }
1009
1010
    /* parse the different types of values */
1011
    /* null */
1012
42.7M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
1013
19.0k
        item->type = cJSON_NULL;
1014
19.0k
        input_buffer->offset += 4;
1015
19.0k
        return true;
1016
19.0k
    }
1017
    /* false */
1018
42.6M
    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
1019
25.1k
        item->type = cJSON_False;
1020
25.1k
        input_buffer->offset += 5;
1021
25.1k
        return true;
1022
25.1k
    }
1023
    /* true */
1024
42.6M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
1025
1.33M
        item->type = cJSON_True;
1026
1.33M
        item->valueint = 1;
1027
1.33M
        input_buffer->offset += 4;
1028
1.33M
        return true;
1029
1.33M
    }
1030
    /* string */
1031
41.3M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
1032
18.5M
        return parse_string(item, input_buffer, out_of_memory);
1033
18.5M
    }
1034
    /* number */
1035
22.7M
    if (can_access_at_index(input_buffer, 0) &&
1036
22.7M
        ((buffer_at_offset(input_buffer)[0] == '-') ||
1037
22.5M
         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
1038
9.69M
        return parse_number(item, input_buffer);
1039
9.69M
    }
1040
    /* array */
1041
13.0M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
1042
2.04M
        return parse_array(item, input_buffer, out_of_memory);
1043
2.04M
    }
1044
    /* object */
1045
11.0M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
1046
10.9M
        return parse_object(item, input_buffer, out_of_memory);
1047
10.9M
    }
1048
1049
24.6k
    return false;
1050
11.0M
}
1051
1052
/* Render a value to text. */
1053
14.9M
static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1054
14.9M
    unsigned char *output = NULL;
1055
1056
14.9M
    if ((item == NULL) || (output_buffer == NULL)) {
1057
0
        return false;
1058
0
    }
1059
1060
14.9M
    switch ((item->type) & 0xFF) {
1061
6.44k
        case cJSON_NULL:
1062
6.44k
            output = ensure(output_buffer, 5, out_of_memory);
1063
6.44k
            if (output == NULL) {
1064
0
                return false;
1065
0
            }
1066
6.44k
            strcpy((char *)output, "null");
1067
6.44k
            return true;
1068
1069
8.19k
        case cJSON_False:
1070
8.19k
            output = ensure(output_buffer, 6, out_of_memory);
1071
8.19k
            if (output == NULL) {
1072
0
                return false;
1073
0
            }
1074
8.19k
            strcpy((char *)output, "false");
1075
8.19k
            return true;
1076
1077
43.1k
        case cJSON_True:
1078
43.1k
            output = ensure(output_buffer, 5, out_of_memory);
1079
43.1k
            if (output == NULL) {
1080
0
                return false;
1081
0
            }
1082
43.1k
            strcpy((char *)output, "true");
1083
43.1k
            return true;
1084
1085
2.55M
        case cJSON_Number:
1086
2.55M
            return print_number(item, output_buffer, out_of_memory);
1087
1088
0
        case cJSON_Raw: {
1089
0
            size_t raw_length = 0;
1090
0
            if (item->valuestring == NULL) {
1091
0
                return false;
1092
0
            }
1093
1094
0
            raw_length = strlen(item->valuestring) + sizeof("");
1095
0
            output = ensure(output_buffer, raw_length, out_of_memory);
1096
0
            if (output == NULL) {
1097
0
                return false;
1098
0
            }
1099
0
            memcpy(output, item->valuestring, raw_length);
1100
0
            return true;
1101
0
        }
1102
1103
6.76M
        case cJSON_String:
1104
6.76M
            return print_string(item, output_buffer, out_of_memory);
1105
1106
445k
        case cJSON_Array:
1107
445k
            return print_array(item, output_buffer, out_of_memory);
1108
1109
5.08M
        case cJSON_Object:
1110
5.08M
            return print_object(item, output_buffer, out_of_memory);
1111
1112
0
        default:
1113
0
            return false;
1114
14.9M
    }
1115
14.9M
}
1116
1117
/* Build an array from input text. */
1118
2.04M
static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1119
2.04M
    cJSON *head = NULL; /* head of the linked list */
1120
2.04M
    cJSON *current_item = NULL;
1121
1122
2.04M
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1123
104
        return false; /* to deeply nested */
1124
104
    }
1125
2.03M
    input_buffer->depth++;
1126
1127
2.03M
    if (buffer_at_offset(input_buffer)[0] != '[') {
1128
        /* not an array */
1129
0
        goto fail;
1130
0
    }
1131
1132
2.03M
    input_buffer->offset++;
1133
2.03M
    buffer_skip_whitespace(input_buffer);
1134
2.03M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
1135
        /* empty array */
1136
121k
        goto success;
1137
121k
    }
1138
1139
    /* check if we skipped to the end of the buffer */
1140
1.91M
    if (cannot_access_at_index(input_buffer, 0)) {
1141
0
        input_buffer->offset--;
1142
0
        goto fail;
1143
0
    }
1144
1145
    /* step back to character in front of the first element */
1146
1.91M
    input_buffer->offset--;
1147
    /* loop through the comma separated array elements */
1148
20.9M
    do {
1149
        /* allocate next item */
1150
20.9M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1151
20.9M
        if (new_item == NULL) {
1152
0
            *out_of_memory = true;
1153
0
            goto fail; /* allocation failure */
1154
0
        }
1155
1156
        /* attach next item to list */
1157
20.9M
        if (head == NULL) {
1158
            /* start the linked list */
1159
1.91M
            current_item = head = new_item;
1160
19.0M
        } else {
1161
            /* add to the end and advance */
1162
19.0M
            current_item->next = new_item;
1163
19.0M
            new_item->prev = current_item;
1164
19.0M
            current_item = new_item;
1165
19.0M
        }
1166
1167
        /* parse next value */
1168
20.9M
        input_buffer->offset++;
1169
20.9M
        buffer_skip_whitespace(input_buffer);
1170
20.9M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1171
646k
            goto fail; /* failed to parse value */
1172
646k
        }
1173
20.3M
        buffer_skip_whitespace(input_buffer);
1174
20.3M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1175
1176
1.27M
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
1177
2.25k
        goto fail; /* expected end of array */
1178
2.25k
    }
1179
1180
1.39M
success:
1181
1.39M
    input_buffer->depth--;
1182
1183
1.39M
    if (head != NULL) {
1184
1.27M
        head->prev = current_item;
1185
1.27M
    }
1186
1187
1.39M
    item->type = cJSON_Array;
1188
1.39M
    item->child = head;
1189
1190
1.39M
    input_buffer->offset++;
1191
1192
1.39M
    return true;
1193
1194
648k
fail:
1195
648k
    if (head != NULL) {
1196
648k
        loader_cJSON_Delete(head);
1197
648k
    }
1198
1199
648k
    return false;
1200
1.27M
}
1201
1202
/* Render an array to text */
1203
445k
static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1204
445k
    unsigned char *output_pointer = NULL;
1205
445k
    size_t length = 0;
1206
445k
    cJSON *current_element = item->child;
1207
1208
445k
    if (output_buffer == NULL) {
1209
0
        return false;
1210
0
    }
1211
1212
    /* Compose the output array. */
1213
    /* opening square bracket */
1214
445k
    output_pointer = ensure(output_buffer, 1, out_of_memory);
1215
445k
    if (output_pointer == NULL) {
1216
0
        return false;
1217
0
    }
1218
1219
445k
    *output_pointer = '[';
1220
445k
    output_buffer->offset++;
1221
445k
    output_buffer->depth++;
1222
1223
5.88M
    while (current_element != NULL) {
1224
5.43M
        if (!print_value(current_element, output_buffer, out_of_memory)) {
1225
0
            return false;
1226
0
        }
1227
5.43M
        update_offset(output_buffer);
1228
5.43M
        if (current_element->next) {
1229
5.00M
            length = (size_t)(output_buffer->format ? 2 : 1);
1230
5.00M
            output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1231
5.00M
            if (output_pointer == NULL) {
1232
0
                return false;
1233
0
            }
1234
5.00M
            *output_pointer++ = ',';
1235
5.00M
            if (output_buffer->format) {
1236
5.00M
                *output_pointer++ = ' ';
1237
5.00M
            }
1238
5.00M
            *output_pointer = '\0';
1239
5.00M
            output_buffer->offset += length;
1240
5.00M
        }
1241
5.43M
        current_element = current_element->next;
1242
5.43M
    }
1243
1244
445k
    output_pointer = ensure(output_buffer, 2, out_of_memory);
1245
445k
    if (output_pointer == NULL) {
1246
0
        return false;
1247
0
    }
1248
445k
    *output_pointer++ = ']';
1249
445k
    *output_pointer = '\0';
1250
445k
    output_buffer->depth--;
1251
1252
445k
    return true;
1253
445k
}
1254
1255
/* Build an object from the text. */
1256
10.9M
static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1257
10.9M
    cJSON *head = NULL; /* linked list head */
1258
10.9M
    cJSON *current_item = NULL;
1259
1260
10.9M
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1261
202
        return false; /* to deeply nested */
1262
202
    }
1263
10.9M
    input_buffer->depth++;
1264
1265
10.9M
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
1266
0
        goto fail; /* not an object */
1267
0
    }
1268
1269
10.9M
    input_buffer->offset++;
1270
10.9M
    buffer_skip_whitespace(input_buffer);
1271
10.9M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
1272
4.09M
        goto success; /* empty object */
1273
4.09M
    }
1274
1275
    /* check if we skipped to the end of the buffer */
1276
6.89M
    if (cannot_access_at_index(input_buffer, 0)) {
1277
0
        input_buffer->offset--;
1278
0
        goto fail;
1279
0
    }
1280
1281
    /* step back to character in front of the first element */
1282
6.89M
    input_buffer->offset--;
1283
    /* loop through the comma separated array elements */
1284
21.6M
    do {
1285
        /* allocate next item */
1286
21.6M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1287
21.6M
        if (new_item == NULL) {
1288
0
            *out_of_memory = true;
1289
0
            goto fail; /* allocation failure */
1290
0
        }
1291
1292
        /* attach next item to list */
1293
21.6M
        if (head == NULL) {
1294
            /* start the linked list */
1295
6.89M
            current_item = head = new_item;
1296
14.7M
        } else {
1297
            /* add to the end and advance */
1298
14.7M
            current_item->next = new_item;
1299
14.7M
            new_item->prev = current_item;
1300
14.7M
            current_item = new_item;
1301
14.7M
        }
1302
1303
21.6M
        if (cannot_access_at_index(input_buffer, 1)) {
1304
0
            goto fail; /* nothing comes after the comma */
1305
0
        }
1306
1307
        /* parse the name of the child */
1308
21.6M
        input_buffer->offset++;
1309
21.6M
        buffer_skip_whitespace(input_buffer);
1310
21.6M
        if (!parse_string(current_item, input_buffer, out_of_memory)) {
1311
2.79k
            goto fail; /* failed to parse name */
1312
2.79k
        }
1313
21.6M
        buffer_skip_whitespace(input_buffer);
1314
1315
        /* swap valuestring and string, because we parsed the name */
1316
21.6M
        current_item->string = current_item->valuestring;
1317
21.6M
        current_item->valuestring = NULL;
1318
1319
21.6M
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
1320
551
            goto fail; /* invalid object */
1321
551
        }
1322
1323
        /* parse the value */
1324
21.6M
        input_buffer->offset++;
1325
21.6M
        buffer_skip_whitespace(input_buffer);
1326
21.6M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1327
34.9k
            goto fail; /* failed to parse value */
1328
34.9k
        }
1329
21.6M
        buffer_skip_whitespace(input_buffer);
1330
21.6M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1331
1332
6.85M
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
1333
618
        goto fail; /* expected end of object */
1334
618
    }
1335
1336
10.9M
success:
1337
10.9M
    input_buffer->depth--;
1338
1339
10.9M
    if (head != NULL) {
1340
6.85M
        head->prev = current_item;
1341
6.85M
    }
1342
1343
10.9M
    item->type = cJSON_Object;
1344
10.9M
    item->child = head;
1345
1346
10.9M
    input_buffer->offset++;
1347
10.9M
    return true;
1348
1349
38.8k
fail:
1350
38.8k
    if (head != NULL) {
1351
38.8k
        loader_cJSON_Delete(head);
1352
38.8k
    }
1353
1354
38.8k
    return false;
1355
6.85M
}
1356
1357
/* Render an object to text. */
1358
5.08M
static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1359
5.08M
    unsigned char *output_pointer = NULL;
1360
5.08M
    size_t length = 0;
1361
5.08M
    cJSON *current_item = item->child;
1362
1363
5.08M
    if (output_buffer == NULL) {
1364
0
        return false;
1365
0
    }
1366
1367
    /* Compose the output: */
1368
5.08M
    length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
1369
5.08M
    output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1370
5.08M
    if (output_pointer == NULL) {
1371
0
        return false;
1372
0
    }
1373
1374
5.08M
    *output_pointer++ = '{';
1375
5.08M
    output_buffer->depth++;
1376
5.08M
    if (output_buffer->format) {
1377
5.08M
        *output_pointer++ = '\n';
1378
5.08M
    }
1379
5.08M
    output_buffer->offset += length;
1380
1381
7.83M
    while (current_item) {
1382
2.75M
        if (output_buffer->format) {
1383
2.75M
            size_t i;
1384
2.75M
            output_pointer = ensure(output_buffer, output_buffer->depth, out_of_memory);
1385
2.75M
            if (output_pointer == NULL) {
1386
0
                return false;
1387
0
            }
1388
1.45G
            for (i = 0; i < output_buffer->depth; i++) {
1389
1.45G
                *output_pointer++ = '\t';
1390
1.45G
            }
1391
2.75M
            output_buffer->offset += output_buffer->depth;
1392
2.75M
        }
1393
1394
        /* print key */
1395
2.75M
        if (!print_string_ptr((unsigned char *)current_item->string, output_buffer, out_of_memory)) {
1396
0
            return false;
1397
0
        }
1398
2.75M
        update_offset(output_buffer);
1399
1400
2.75M
        length = (size_t)(output_buffer->format ? 2 : 1);
1401
2.75M
        output_pointer = ensure(output_buffer, length, out_of_memory);
1402
2.75M
        if (output_pointer == NULL) {
1403
0
            return false;
1404
0
        }
1405
2.75M
        *output_pointer++ = ':';
1406
2.75M
        if (output_buffer->format) {
1407
2.75M
            *output_pointer++ = '\t';
1408
2.75M
        }
1409
2.75M
        output_buffer->offset += length;
1410
1411
        /* print value */
1412
2.75M
        if (!print_value(current_item, output_buffer, out_of_memory)) {
1413
0
            return false;
1414
0
        }
1415
2.75M
        update_offset(output_buffer);
1416
1417
        /* print comma if not last */
1418
2.75M
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1419
2.75M
        output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1420
2.75M
        if (output_pointer == NULL) {
1421
0
            return false;
1422
0
        }
1423
2.75M
        if (current_item->next) {
1424
1.38M
            *output_pointer++ = ',';
1425
1.38M
        }
1426
1427
2.75M
        if (output_buffer->format) {
1428
2.75M
            *output_pointer++ = '\n';
1429
2.75M
        }
1430
2.75M
        *output_pointer = '\0';
1431
2.75M
        output_buffer->offset += length;
1432
1433
2.75M
        current_item = current_item->next;
1434
2.75M
    }
1435
1436
5.08M
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2, out_of_memory);
1437
5.08M
    if (output_pointer == NULL) {
1438
0
        return false;
1439
0
    }
1440
5.08M
    if (output_buffer->format) {
1441
5.08M
        size_t i;
1442
3.69G
        for (i = 0; i < (output_buffer->depth - 1); i++) {
1443
3.68G
            *output_pointer++ = '\t';
1444
3.68G
        }
1445
5.08M
    }
1446
5.08M
    *output_pointer++ = '}';
1447
5.08M
    *output_pointer = '\0';
1448
5.08M
    output_buffer->depth--;
1449
1450
5.08M
    return true;
1451
5.08M
}
1452
1453
/* Get Array size/item / object item. */
1454
89.3k
CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
1455
89.3k
    cJSON *child = NULL;
1456
89.3k
    size_t size = 0;
1457
1458
89.3k
    if (array == NULL) {
1459
0
        return 0;
1460
0
    }
1461
1462
89.3k
    child = array->child;
1463
1464
3.32M
    while (child != NULL) {
1465
3.23M
        size++;
1466
3.23M
        child = child->next;
1467
3.23M
    }
1468
1469
    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1470
1471
89.3k
    return (int)size;
1472
89.3k
}
1473
1474
0
static cJSON *get_array_item(const cJSON *array, size_t index) {
1475
0
    cJSON *current_child = NULL;
1476
1477
0
    if (array == NULL) {
1478
0
        return NULL;
1479
0
    }
1480
1481
0
    current_child = array->child;
1482
0
    while ((current_child != NULL) && (index > 0)) {
1483
0
        index--;
1484
0
        current_child = current_child->next;
1485
0
    }
1486
1487
0
    return current_child;
1488
0
}
1489
1490
0
CJSON_PUBLIC(cJSON *) loader_cJSON_GetArrayItem(const cJSON *array, int index) {
1491
0
    if (index < 0) {
1492
0
        return NULL;
1493
0
    }
1494
1495
0
    return get_array_item(array, (size_t)index);
1496
0
}
1497
1498
16.9M
static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
1499
16.9M
    cJSON *current_element = NULL;
1500
1501
16.9M
    if ((object == NULL) || (name == NULL)) {
1502
0
        return NULL;
1503
0
    }
1504
1505
16.9M
    current_element = object->child;
1506
16.9M
    if (case_sensitive) {
1507
0
        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) {
1508
0
            current_element = current_element->next;
1509
0
        }
1510
16.9M
    } else {
1511
105M
        while ((current_element != NULL) &&
1512
97.3M
               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
1513
88.5M
            current_element = current_element->next;
1514
88.5M
        }
1515
16.9M
    }
1516
1517
16.9M
    if ((current_element == NULL) || (current_element->string == NULL)) {
1518
8.12M
        return NULL;
1519
8.12M
    }
1520
1521
8.83M
    return current_element;
1522
16.9M
}
1523
1524
16.9M
CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
1525
16.9M
    return get_object_item(object, string, false);
1526
16.9M
}
1527
1528
0
CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string) {
1529
0
    return get_object_item(object, string, true);
1530
0
}
1531
1532
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_HasObjectItem(const cJSON *object, const char *string) {
1533
0
    return loader_cJSON_GetObjectItem(object, string) ? 1 : 0;
1534
0
}
1535
1536
0
static void skip_oneline_comment(char **input) {
1537
0
    *input += static_strlen("//");
1538
1539
0
    for (; (*input)[0] != '\0'; ++(*input)) {
1540
0
        if ((*input)[0] == '\n') {
1541
0
            *input += static_strlen("\n");
1542
0
            return;
1543
0
        }
1544
0
    }
1545
0
}
1546
1547
0
static void skip_multiline_comment(char **input) {
1548
0
    *input += static_strlen("/*");
1549
1550
0
    for (; (*input)[0] != '\0'; ++(*input)) {
1551
0
        if (((*input)[0] == '*') && ((*input)[1] == '/')) {
1552
0
            *input += static_strlen("*/");
1553
0
            return;
1554
0
        }
1555
0
    }
1556
0
}
1557
1558
0
static void minify_string(char **input, char **output) {
1559
0
    (*output)[0] = (*input)[0];
1560
0
    *input += static_strlen("\"");
1561
0
    *output += static_strlen("\"");
1562
1563
0
    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
1564
0
        (*output)[0] = (*input)[0];
1565
1566
0
        if ((*input)[0] == '\"') {
1567
0
            (*output)[0] = '\"';
1568
0
            *input += static_strlen("\"");
1569
0
            *output += static_strlen("\"");
1570
0
            return;
1571
0
        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
1572
0
            (*output)[1] = (*input)[1];
1573
0
            *input += static_strlen("\"");
1574
0
            *output += static_strlen("\"");
1575
0
        }
1576
0
    }
1577
0
}
1578
1579
0
CJSON_PUBLIC(void) loader_cJSON_Minify(char *json) {
1580
0
    char *into = json;
1581
1582
0
    if (json == NULL) {
1583
0
        return;
1584
0
    }
1585
1586
0
    while (json[0] != '\0') {
1587
0
        switch (json[0]) {
1588
0
            case ' ':
1589
0
            case '\t':
1590
0
            case '\r':
1591
0
            case '\n':
1592
0
                json++;
1593
0
                break;
1594
1595
0
            case '/':
1596
0
                if (json[1] == '/') {
1597
0
                    skip_oneline_comment(&json);
1598
0
                } else if (json[1] == '*') {
1599
0
                    skip_multiline_comment(&json);
1600
0
                } else {
1601
0
                    json++;
1602
0
                }
1603
0
                break;
1604
1605
0
            case '\"':
1606
0
                minify_string(&json, (char **)&into);
1607
0
                break;
1608
1609
0
            default:
1610
0
                into[0] = json[0];
1611
0
                json++;
1612
0
                into++;
1613
0
        }
1614
0
    }
1615
1616
    /* and null-terminate. */
1617
0
    *into = '\0';
1618
0
}
1619
1620
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsInvalid(const cJSON *const item) {
1621
0
    if (item == NULL) {
1622
0
        return false;
1623
0
    }
1624
1625
0
    return (item->type & 0xFF) == cJSON_Invalid;
1626
0
}
1627
1628
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsFalse(const cJSON *const item) {
1629
0
    if (item == NULL) {
1630
0
        return false;
1631
0
    }
1632
1633
0
    return (item->type & 0xFF) == cJSON_False;
1634
0
}
1635
1636
44
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsTrue(const cJSON *const item) {
1637
44
    if (item == NULL) {
1638
44
        return false;
1639
44
    }
1640
1641
0
    return (item->type & 0xff) == cJSON_True;
1642
44
}
1643
1644
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsBool(const cJSON *const item) {
1645
0
    if (item == NULL) {
1646
0
        return false;
1647
0
    }
1648
1649
0
    return (item->type & (cJSON_True | cJSON_False)) != 0;
1650
0
}
1651
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsNull(const cJSON *const item) {
1652
0
    if (item == NULL) {
1653
0
        return false;
1654
0
    }
1655
1656
0
    return (item->type & 0xFF) == cJSON_NULL;
1657
0
}
1658
1659
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsNumber(const cJSON *const item) {
1660
0
    if (item == NULL) {
1661
0
        return false;
1662
0
    }
1663
1664
0
    return (item->type & 0xFF) == cJSON_Number;
1665
0
}
1666
1667
5.81M
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
1668
5.81M
    if (item == NULL) {
1669
2.15M
        return false;
1670
2.15M
    }
1671
1672
3.66M
    return (item->type & 0xFF) == cJSON_String;
1673
5.81M
}
1674
1675
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsArray(const cJSON *const item) {
1676
0
    if (item == NULL) {
1677
0
        return false;
1678
0
    }
1679
1680
0
    return (item->type & 0xFF) == cJSON_Array;
1681
0
}
1682
1683
0
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) {
1684
0
    if (item == NULL) {
1685
0
        return false;
1686
0
    }
1687
1688
0
    return (item->type & 0xFF) == cJSON_Object;
1689
0
}
1690
1691
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsRaw(const cJSON *const item) {
1692
0
    if (item == NULL) {
1693
0
        return false;
1694
0
    }
1695
1696
0
    return (item->type & 0xFF) == cJSON_Raw;
1697
0
}
1698
1699
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) {
1700
0
    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) {
1701
0
        return false;
1702
0
    }
1703
1704
    /* check if type is valid */
1705
0
    switch (a->type & 0xFF) {
1706
0
        case cJSON_False:
1707
0
        case cJSON_True:
1708
0
        case cJSON_NULL:
1709
0
        case cJSON_Number:
1710
0
        case cJSON_String:
1711
0
        case cJSON_Raw:
1712
0
        case cJSON_Array:
1713
0
        case cJSON_Object:
1714
0
            break;
1715
1716
0
        default:
1717
0
            return false;
1718
0
    }
1719
1720
    /* identical objects are equal */
1721
0
    if (a == b) {
1722
0
        return true;
1723
0
    }
1724
1725
0
    switch (a->type & 0xFF) {
1726
        /* in these cases and equal type is enough */
1727
0
        case cJSON_False:
1728
0
        case cJSON_True:
1729
0
        case cJSON_NULL:
1730
0
            return true;
1731
1732
0
        case cJSON_Number:
1733
0
            if (compare_double(a->valuedouble, b->valuedouble)) {
1734
0
                return true;
1735
0
            }
1736
0
            return false;
1737
1738
0
        case cJSON_String:
1739
0
        case cJSON_Raw:
1740
0
            if ((a->valuestring == NULL) || (b->valuestring == NULL)) {
1741
0
                return false;
1742
0
            }
1743
0
            if (strcmp(a->valuestring, b->valuestring) == 0) {
1744
0
                return true;
1745
0
            }
1746
1747
0
            return false;
1748
1749
0
        case cJSON_Array: {
1750
0
            cJSON *a_element = a->child;
1751
0
            cJSON *b_element = b->child;
1752
1753
0
            for (; (a_element != NULL) && (b_element != NULL);) {
1754
0
                if (!loader_cJSON_Compare(a_element, b_element, case_sensitive)) {
1755
0
                    return false;
1756
0
                }
1757
1758
0
                a_element = a_element->next;
1759
0
                b_element = b_element->next;
1760
0
            }
1761
1762
            /* one of the arrays is longer than the other */
1763
0
            if (a_element != b_element) {
1764
0
                return false;
1765
0
            }
1766
1767
0
            return true;
1768
0
        }
1769
1770
0
        case cJSON_Object: {
1771
0
            cJSON *a_element = NULL;
1772
0
            cJSON *b_element = NULL;
1773
0
            cJSON_ArrayForEach(a_element, a) {
1774
                /* TODO This has O(n^2) runtime, which is horrible! */
1775
0
                b_element = get_object_item(b, a_element->string, case_sensitive);
1776
0
                if (b_element == NULL) {
1777
0
                    return false;
1778
0
                }
1779
1780
0
                if (!loader_cJSON_Compare(a_element, b_element, case_sensitive)) {
1781
0
                    return false;
1782
0
                }
1783
0
            }
1784
1785
            /* doing this twice, once on a and b to prevent true comparison if a subset of b
1786
             * TODO: Do this the proper way, this is just a fix for now */
1787
0
            cJSON_ArrayForEach(b_element, b) {
1788
0
                a_element = get_object_item(a, b_element->string, case_sensitive);
1789
0
                if (a_element == NULL) {
1790
0
                    return false;
1791
0
                }
1792
1793
0
                if (!loader_cJSON_Compare(b_element, a_element, case_sensitive)) {
1794
0
                    return false;
1795
0
                }
1796
0
            }
1797
1798
0
            return true;
1799
0
        }
1800
1801
0
        default:
1802
0
            return false;
1803
0
    }
1804
0
}