Coverage Report

Created: 2024-09-08 07:41

/src/vulkan-loader/loader/cJSON.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
  Copyright (c) 2009 Dave Gamble
3
  Copyright (c) 2015-2021 The Khronos Group Inc.
4
  Copyright (c) 2015-2021 Valve Corporation
5
  Copyright (c) 2015-2021 LunarG, Inc.
6
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
8
  of this software and associated documentation files (the "Software"), to deal
9
  in the Software without restriction, including without limitation the rights
10
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
  copies of the Software, and to permit persons to whom the Software is
12
  furnished to do so, subject to the following conditions:
13
14
  The above copyright notice and this permission notice shall be included in
15
  all copies or substantial portions of the Software.
16
17
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
  THE SOFTWARE.
24
*/
25
26
/* cJSON */
27
/* JSON parser in C. */
28
29
#include <ctype.h>
30
#include <float.h>
31
#include <limits.h>
32
#include <math.h>
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
37
#include "cJSON.h"
38
39
#include "allocation.h"
40
#include "loader.h"
41
#include "log.h"
42
43
5.09M
static void *cJSON_malloc(const VkAllocationCallbacks *pAllocator, size_t size) {
44
5.09M
    return loader_calloc(pAllocator, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
45
5.09M
}
46
47
165k
static void *cJSON_malloc_instance_scope(const VkAllocationCallbacks *pAllocator, size_t size) {
48
165k
    return loader_calloc(pAllocator, size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
49
165k
}
50
51
5.02M
static void cJSON_Free(const VkAllocationCallbacks *pAllocator, void *pMemory) { loader_free(pAllocator, pMemory); }
52
53
/*
54
// commented out as it is unused - static error code channel requires external locks to be used.
55
static const char *ep;
56
57
const char *cJSON_GetErrorPtr(void) { return ep; }
58
*/
59
60
22.2k
static char *cJSON_strdup(const VkAllocationCallbacks *pAllocator, const char *str) {
61
22.2k
    size_t len;
62
22.2k
    char *copy;
63
64
22.2k
    len = strlen(str) + 1;
65
22.2k
    copy = (char *)cJSON_malloc(pAllocator, len);
66
22.2k
    if (!copy) return 0;
67
22.2k
    memcpy(copy, str, len);
68
22.2k
    return copy;
69
22.2k
}
70
71
/* Internal constructor. */
72
2.35M
static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
73
2.35M
    cJSON *node = (cJSON *)cJSON_malloc(pAllocator, sizeof(cJSON));
74
2.35M
    if (node) {
75
2.35M
        memset(node, 0, sizeof(cJSON));
76
2.35M
        node->pAllocator = (VkAllocationCallbacks *)pAllocator;
77
2.35M
    }
78
2.35M
    return node;
79
2.35M
}
80
81
/* Delete a cJSON structure. */
82
872k
void loader_cJSON_Delete(cJSON *c) {
83
872k
    cJSON *next;
84
3.22M
    while (c) {
85
2.35M
        next = c->next;
86
2.35M
        if (!(c->type & cJSON_IsReference) && c->child) loader_cJSON_Delete(c->child);
87
2.35M
        if (!(c->type & cJSON_IsReference) && c->valuestring) cJSON_Free(c->pAllocator, c->valuestring);
88
2.35M
        if (!(c->type & cJSON_StringIsConst) && c->string) cJSON_Free(c->pAllocator, c->string);
89
2.35M
        cJSON_Free(c->pAllocator, c);
90
2.35M
        c = next;
91
2.35M
    }
92
872k
}
93
94
/* Parse the input text to generate a number, and populate the result into item.
95
 */
96
1.23M
static const char *parse_number(cJSON *item, const char *num) {
97
1.23M
    double n = 0, sign = 1, scale = 0;
98
1.23M
    int subscale = 0, signsubscale = 1;
99
100
1.23M
    if (*num == '-') sign = -1, num++; /* Has sign? */
101
1.23M
    if (*num == '0') num++;            /* is zero */
102
1.23M
    if (*num >= '1' && *num <= '9') do
103
741k
            n = (n * 10.0) + (*num++ - '0');
104
741k
        while (*num >= '0' && *num <= '9'); /* Number? */
105
1.23M
    if (*num == '.' && num[1] >= '0' && num[1] <= '9') {
106
2.55k
        num++;
107
2.57k
        do n = (n * 10.0) + (*num++ - '0'), scale--;
108
2.57k
        while (*num >= '0' && *num <= '9');
109
2.55k
    }                               /* Fractional part? */
110
1.23M
    if (*num == 'e' || *num == 'E') /* Exponent? */
111
9.54k
    {
112
9.54k
        num++;
113
9.54k
        if (*num == '+')
114
796
            num++;
115
8.74k
        else if (*num == '-')
116
1.12k
            signsubscale = -1, num++;                                                   /* With sign? */
117
25.7k
        while (*num >= '0' && *num <= '9') subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
118
9.54k
    }
119
120
1.23M
    n = sign * n * pow(10.0, (scale + subscale * signsubscale)); /* number = +/-
121
                                                                    number.fraction *
122
                                                                    10^+/- exponent */
123
124
1.23M
    item->valuedouble = n;
125
1.23M
    item->valueint = (int)n;
126
1.23M
    item->type = cJSON_Number;
127
1.23M
    return num;
128
1.23M
}
129
130
0
static size_t pow2gt(size_t x) {
131
0
    --x;
132
0
    x |= x >> 1;
133
0
    x |= x >> 2;
134
0
    x |= x >> 4;
135
0
    x |= x >> 8;
136
0
    x |= x >> 16;
137
0
    return x + 1;
138
0
}
139
140
typedef struct {
141
    char *buffer;
142
    size_t length;
143
    size_t offset;
144
} printbuffer;
145
146
0
static char *ensure(const VkAllocationCallbacks *pAllocator, printbuffer *p, size_t needed) {
147
0
    char *newbuffer;
148
0
    size_t newsize;
149
0
    if (!p || !p->buffer) return 0;
150
0
    needed += p->offset;
151
0
    if (needed <= p->length) return p->buffer + p->offset;
152
153
0
    newsize = pow2gt(needed);
154
0
    newbuffer = (char *)cJSON_malloc(pAllocator, newsize);
155
0
    if (!newbuffer) {
156
0
        cJSON_Free(pAllocator, p->buffer);
157
0
        p->length = 0, p->buffer = 0;
158
0
        return 0;
159
0
    }
160
0
    if (newbuffer) memcpy(newbuffer, p->buffer, p->length);
161
0
    cJSON_Free(pAllocator, p->buffer);
162
0
    p->length = newsize;
163
0
    p->buffer = newbuffer;
164
0
    return newbuffer + p->offset;
165
0
}
166
167
0
static size_t cJSON_update(printbuffer *p) {
168
0
    char *str;
169
0
    if (!p || !p->buffer) return 0;
170
0
    str = p->buffer + p->offset;
171
0
    return p->offset + strlen(str);
172
0
}
173
174
/* Render the number nicely from the given item into a string. */
175
1.08M
static char *print_number(cJSON *item, printbuffer *p) {
176
1.08M
    char *str = 0;
177
1.08M
    size_t str_buf_size;
178
1.08M
    double d = item->valuedouble;
179
1.08M
    if (d == 0) {
180
394k
        str_buf_size = 2; /* special case for 0. */
181
394k
        if (p)
182
0
            str = ensure(item->pAllocator, p, str_buf_size);
183
394k
        else
184
394k
            str = (char *)cJSON_malloc(item->pAllocator, str_buf_size);
185
394k
        if (str) loader_strncpy(str, str_buf_size, "0", 2);
186
691k
    } else if (fabs(((double)item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) {
187
686k
        str_buf_size = 21; /* 2^64+1 can be represented in 21 chars. */
188
686k
        if (p)
189
0
            str = ensure(item->pAllocator, p, str_buf_size);
190
686k
        else
191
686k
            str = (char *)cJSON_malloc(item->pAllocator, str_buf_size);
192
686k
        if (str) snprintf(str, str_buf_size, "%d", item->valueint);
193
686k
    } else {
194
5.28k
        str_buf_size = 64; /* This is a nice tradeoff. */
195
5.28k
        if (p)
196
0
            str = ensure(item->pAllocator, p, str_buf_size);
197
5.28k
        else
198
5.28k
            str = (char *)cJSON_malloc(item->pAllocator, str_buf_size);
199
5.28k
        if (str) {
200
5.28k
            if (fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60)
201
1.10k
                snprintf(str, str_buf_size, "%.0f", d);
202
4.17k
            else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)
203
2.69k
                snprintf(str, str_buf_size, "%e", d);
204
1.48k
            else
205
1.48k
                snprintf(str, str_buf_size, "%f", d);
206
5.28k
        }
207
5.28k
    }
208
1.08M
    return str;
209
1.08M
}
210
211
31.1k
static unsigned parse_hex4(const char *str) {
212
31.1k
    unsigned h = 0;
213
31.1k
    if (*str >= '0' && *str <= '9')
214
5.34k
        h += (*str) - '0';
215
25.7k
    else if (*str >= 'A' && *str <= 'F')
216
12.6k
        h += 10 + (*str) - 'A';
217
13.1k
    else if (*str >= 'a' && *str <= 'f')
218
9.89k
        h += 10 + (*str) - 'a';
219
3.24k
    else
220
3.24k
        return 0;
221
27.8k
    h = h << 4;
222
27.8k
    str++;
223
27.8k
    if (*str >= '0' && *str <= '9')
224
11.3k
        h += (*str) - '0';
225
16.5k
    else if (*str >= 'A' && *str <= 'F')
226
5.07k
        h += 10 + (*str) - 'A';
227
11.4k
    else if (*str >= 'a' && *str <= 'f')
228
6.46k
        h += 10 + (*str) - 'a';
229
4.97k
    else
230
4.97k
        return 0;
231
22.9k
    h = h << 4;
232
22.9k
    str++;
233
22.9k
    if (*str >= '0' && *str <= '9')
234
6.04k
        h += (*str) - '0';
235
16.8k
    else if (*str >= 'A' && *str <= 'F')
236
6.45k
        h += 10 + (*str) - 'A';
237
10.4k
    else if (*str >= 'a' && *str <= 'f')
238
6.98k
        h += 10 + (*str) - 'a';
239
3.43k
    else
240
3.43k
        return 0;
241
19.4k
    h = h << 4;
242
19.4k
    str++;
243
19.4k
    if (*str >= '0' && *str <= '9')
244
6.78k
        h += (*str) - '0';
245
12.6k
    else if (*str >= 'A' && *str <= 'F')
246
5.26k
        h += 10 + (*str) - 'A';
247
7.43k
    else if (*str >= 'a' && *str <= 'f')
248
2.72k
        h += 10 + (*str) - 'a';
249
4.71k
    else
250
4.71k
        return 0;
251
14.7k
    return h;
252
19.4k
}
253
254
/* Parse the input text into an unescaped cstring, and populate item. */
255
static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
256
365k
static const char *parse_string(cJSON *item, const char *str, bool *out_of_memory) {
257
365k
    const char *ptr = str + 1;
258
365k
    char *ptr2;
259
365k
    char *out;
260
365k
    int len = 0;
261
365k
    unsigned uc, uc2;
262
365k
    if (*str != '\"') {
263
        // ep = str; // commented out as it is unused
264
6
        return 0;
265
6
    } /* not a string! */
266
267
2.71M
    while (*ptr != '\"' && *ptr && ++len)
268
2.35M
        if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
269
270
365k
    out = (char *)cJSON_malloc(item->pAllocator, len + 1); /* This is how long we need for the string, roughly. */
271
365k
    if (!out) {
272
0
        *out_of_memory = true;
273
0
        return 0;
274
0
    }
275
276
365k
    ptr = str + 1;
277
365k
    ptr2 = out;
278
2.61M
    while (*ptr != '\"' && *ptr) {
279
2.25M
        if (*ptr != '\\')
280
2.22M
            *ptr2++ = *ptr++;
281
30.3k
        else {
282
30.3k
            ptr++;
283
30.3k
            switch (*ptr) {
284
3
                case 'b':
285
3
                    *ptr2++ = '\b';
286
3
                    break;
287
66
                case 'f':
288
66
                    *ptr2++ = '\f';
289
66
                    break;
290
3
                case 'n':
291
3
                    *ptr2++ = '\n';
292
3
                    break;
293
196
                case 'r':
294
196
                    *ptr2++ = '\r';
295
196
                    break;
296
12
                case 't':
297
12
                    *ptr2++ = '\t';
298
12
                    break;
299
27.8k
                case 'u': /* transcode utf16 to utf8. */
300
27.8k
                    uc = parse_hex4(ptr + 1);
301
27.8k
                    ptr += 4; /* get the unicode char. */
302
303
27.8k
                    if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) break; /* check for invalid.  */
304
305
10.5k
                    if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs.  */
306
5.06k
                    {
307
5.06k
                        if (ptr[1] != '\\' || ptr[2] != 'u') break; /* missing second-half of surrogate. */
308
3.25k
                        uc2 = parse_hex4(ptr + 3);
309
3.25k
                        ptr += 6;
310
3.25k
                        if (uc2 < 0xDC00 || uc2 > 0xDFFF) break; /* invalid second-half of surrogate. */
311
1.36k
                        uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
312
1.36k
                    }
313
314
6.87k
                    len = 4;
315
6.87k
                    if (uc < 0x80)
316
783
                        len = 1;
317
6.09k
                    else if (uc < 0x800)
318
774
                        len = 2;
319
5.31k
                    else if (uc < 0x10000)
320
3.95k
                        len = 3;
321
6.87k
                    ptr2 += len;
322
323
26.5k
                    for (size_t i = len; i > 0; i--) {
324
19.6k
                        if (i == 1) {
325
6.87k
                            *--ptr2 = ((unsigned char)uc | firstByteMark[len]);
326
12.7k
                        } else if (i >= 2) {
327
12.7k
                            *--ptr2 = ((uc | 0x80) & 0xBF);
328
12.7k
                            uc >>= 6;
329
12.7k
                        }
330
19.6k
                    }
331
6.87k
                    ptr2 += len;
332
6.87k
                    break;
333
2.15k
                default:
334
2.15k
                    *ptr2++ = *ptr;
335
2.15k
                    break;
336
30.3k
            }
337
30.3k
            ptr++;
338
30.3k
        }
339
2.25M
    }
340
365k
    *ptr2 = 0;
341
365k
    if (*ptr == '\"') ptr++;
342
365k
    item->valuestring = out;
343
365k
    item->type = cJSON_String;
344
365k
    return ptr;
345
365k
}
346
347
/* Render the cstring provided to an escaped version that can be printed. */
348
165k
static char *print_string_ptr(const VkAllocationCallbacks *pAllocator, const char *str, printbuffer *p) {
349
165k
    const char *ptr;
350
165k
    char *ptr2;
351
165k
    char *out;
352
165k
    size_t out_buf_size, len = 0, flag = 0;
353
165k
    unsigned char token;
354
355
1.49M
    for (ptr = str; *ptr; ptr++) flag |= ((*ptr > 0 && *ptr < 32) || (*ptr == '\"') || (*ptr == '\\')) ? 1 : 0;
356
165k
    if (!flag) {
357
159k
        len = ptr - str;
358
159k
        out_buf_size = len + 1;
359
        // out_buf_size = len + 3; // Modified to not put quotes around the string
360
159k
        if (p)
361
0
            out = ensure(pAllocator, p, out_buf_size);
362
159k
        else
363
159k
            out = (char *)cJSON_malloc_instance_scope(pAllocator, out_buf_size);
364
159k
        if (!out) return 0;
365
159k
        ptr2 = out;
366
        // *ptr2++ = '\"'; // Modified to not put quotes around the string
367
159k
        loader_strncpy(ptr2, out_buf_size, str, out_buf_size);
368
        // ptr2[len] = '\"'; // Modified to not put quotes around the string
369
159k
        ptr2[len] = 0;  // ptr2[len + 1] = 0; // Modified to not put quotes around the string
370
159k
        return out;
371
159k
    }
372
373
6.40k
    if (!str) {
374
0
        out_buf_size = 3;
375
0
        if (p)
376
0
            out = ensure(pAllocator, p, out_buf_size);
377
0
        else
378
0
            out = (char *)cJSON_malloc_instance_scope(pAllocator, out_buf_size);
379
0
        if (!out) return 0;
380
0
        loader_strncpy(out, out_buf_size, "\"\"", 3);
381
0
        return out;
382
0
    }
383
6.40k
    ptr = str;
384
6.40k
    token = *ptr;
385
526k
    while (token && ++len) {
386
520k
        if (strchr("\"\\\b\f\n\r\t", token))
387
8.83k
            len++;
388
511k
        else if (token < 32)
389
355k
            len += 5;
390
520k
        ptr++;
391
520k
        token = *ptr;
392
520k
    }
393
394
6.40k
    out_buf_size = len + 1;
395
    // out_buf_size = len + 3; // Modified to not put quotes around the string
396
6.40k
    if (p)
397
0
        out = ensure(pAllocator, p, out_buf_size);
398
6.40k
    else
399
6.40k
        out = (char *)cJSON_malloc_instance_scope(pAllocator, out_buf_size);
400
6.40k
    if (!out) return 0;
401
402
6.40k
    ptr2 = out;
403
6.40k
    ptr = str;
404
    // *ptr2++ = '\"'; // Modified to not put quotes around the string
405
526k
    while (*ptr) {
406
520k
        if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
407
155k
            *ptr2++ = *ptr++;
408
364k
        else {
409
364k
            switch (token = *ptr++) {
410
386
                case '\\':
411
386
                    *ptr2++ = '\\';
412
386
                    break;
413
513
                case '\"':
414
513
                    *ptr2++ = '\"';
415
513
                    break;
416
4.17k
                case '\b':
417
4.17k
                    *ptr2++ = '\b';
418
4.17k
                    break;
419
3.01k
                case '\f':
420
3.01k
                    *ptr2++ = '\f';
421
3.01k
                    break;
422
421
                case '\n':
423
421
                    *ptr2++ = '\n';
424
421
                    break;
425
311
                case '\r':
426
311
                    *ptr2++ = '\r';
427
311
                    break;
428
17
                case '\t':
429
17
                    *ptr2++ = '\t';
430
17
                    break;
431
355k
                default:
432
355k
                    snprintf(ptr2, out_buf_size - (ptr2 - out), "u%04x", token);
433
355k
                    ptr2 += 5;
434
355k
                    break; /* escape and print */
435
364k
            }
436
364k
        }
437
520k
    }
438
    // *ptr2++ = '\"'; // Modified to not put quotes around the string
439
6.40k
    *ptr2++ = 0;
440
6.40k
    return out;
441
6.40k
}
442
/* Invoke print_string_ptr (which is useful) on an item. */
443
124k
static char *print_string(cJSON *item, printbuffer *p) { return print_string_ptr(item->pAllocator, item->valuestring, p); }
444
445
/* Declare these prototypes. */
446
static const char *parse_value(cJSON *item, const char *value, bool *out_of_memory);
447
static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p);
448
static const char *parse_array(cJSON *item, const char *value, bool *out_of_memory);
449
static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p);
450
static const char *parse_object(cJSON *item, const char *value, bool *out_of_memory);
451
static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p);
452
453
/* Utility to jump whitespace and cr/lf */
454
5.97M
static const char *skip(const char *in) {
455
7.63M
    while (in && *in && (unsigned char)*in <= 32) in++;
456
5.97M
    return in;
457
5.97M
}
458
459
/* Parse an object - create a new root, and populate. */
460
static cJSON *cJSON_ParseWithOpts(const VkAllocationCallbacks *pAllocator, const char *value, const char **return_parse_end,
461
1.32k
                                  int require_null_terminated, bool *out_of_memory) {
462
1.32k
    const char *end = 0;
463
1.32k
    cJSON *c = cJSON_New_Item(pAllocator);
464
    // ep = 0; // commented out as it is unused
465
1.32k
    if (!c) {
466
0
        *out_of_memory = true;
467
0
        return 0; /* memory fail */
468
0
    }
469
470
1.32k
    end = parse_value(c, skip(value), out_of_memory);
471
1.32k
    if (!end) {
472
138
        loader_cJSON_Delete(c);
473
138
        return 0;
474
138
    } /* parse failure. ep is set. */
475
476
    /* if we require null-terminated JSON without appended garbage, skip and
477
     * then check for a null terminator */
478
1.18k
    if (require_null_terminated) {
479
0
        end = skip(end);
480
0
        if (*end) {
481
0
            loader_cJSON_Delete(c);
482
            // ep = end; // commented out as it is unused
483
0
            return 0;
484
0
        }
485
0
    }
486
1.18k
    if (return_parse_end) *return_parse_end = end;
487
1.18k
    return c;
488
1.18k
}
489
/* Default options for cJSON_Parse */
490
1.32k
static cJSON *cJSON_Parse(const VkAllocationCallbacks *pAllocator, const char *value, bool *out_of_memory) {
491
1.32k
    return cJSON_ParseWithOpts(pAllocator, value, 0, 0, out_of_memory);
492
1.32k
}
493
494
/* Render a cJSON item/entity/structure to text. */
495
237k
char *loader_cJSON_Print(cJSON *item) { return print_value(item, 0, 1, 0); }
496
0
char *loader_cJSON_PrintUnformatted(cJSON *item) { return print_value(item, 0, 0, 0); }
497
498
/* Parser core - when encountering text, process appropriately. */
499
2.35M
static const char *parse_value(cJSON *item, const char *value, bool *out_of_memory) {
500
2.35M
    if (!value) return 0; /* Fail on null. */
501
2.35M
    if (!strncmp(value, "null", 4)) {
502
3.59k
        item->type = cJSON_NULL;
503
3.59k
        return value + 4;
504
3.59k
    }
505
2.35M
    if (!strncmp(value, "false", 5)) {
506
1.54k
        item->type = cJSON_False;
507
1.54k
        return value + 5;
508
1.54k
    }
509
2.35M
    if (!strncmp(value, "true", 4)) {
510
24.2k
        item->type = cJSON_True;
511
24.2k
        item->valueint = 1;
512
24.2k
        return value + 4;
513
24.2k
    }
514
2.32M
    if (*value == '\"') {
515
188k
        return parse_string(item, value, out_of_memory);
516
188k
    }
517
2.13M
    if (*value == '-' || (*value >= '0' && *value <= '9')) {
518
1.23M
        return parse_number(item, value);
519
1.23M
    }
520
905k
    if (*value == '[') {
521
795k
        return parse_array(item, value, out_of_memory);
522
795k
    }
523
109k
    if (*value == '{') {
524
109k
        return parse_object(item, value, out_of_memory);
525
109k
    }
526
527
    // ep = value; // commented out as it is unused
528
42
    return 0; /* failure. */
529
109k
}
530
531
/* Render a value to text. */
532
1.87M
static char *print_value(cJSON *item, int depth, int fmt, printbuffer *p) {
533
1.87M
    char *out = 0;
534
1.87M
    if (!item) return 0;
535
1.87M
    if (p) {
536
0
        switch ((item->type) & 255) {
537
0
            case cJSON_NULL: {
538
0
                out = ensure(item->pAllocator, p, 5);
539
0
                if (out) loader_strncpy(out, 5, "null", 5);
540
0
                break;
541
0
            }
542
0
            case cJSON_False: {
543
0
                out = ensure(item->pAllocator, p, 6);
544
0
                if (out) loader_strncpy(out, 6, "false", 6);
545
0
                break;
546
0
            }
547
0
            case cJSON_True: {
548
0
                out = ensure(item->pAllocator, p, 5);
549
0
                if (out) loader_strncpy(out, 5, "true", 5);
550
0
                break;
551
0
            }
552
0
            case cJSON_Number:
553
0
                out = print_number(item, p);
554
0
                break;
555
0
            case cJSON_String:
556
0
                out = print_string(item, p);
557
0
                break;
558
0
            case cJSON_Array:
559
0
                out = print_array(item, depth, fmt, p);
560
0
                break;
561
0
            case cJSON_Object:
562
0
                out = print_object(item, depth, fmt, p);
563
0
                break;
564
0
        }
565
1.87M
    } else {
566
1.87M
        switch ((item->type) & 255) {
567
3.08k
            case cJSON_NULL:
568
3.08k
                out = cJSON_strdup(item->pAllocator, "null");
569
3.08k
                break;
570
774
            case cJSON_False:
571
774
                out = cJSON_strdup(item->pAllocator, "false");
572
774
                break;
573
18.3k
            case cJSON_True:
574
18.3k
                out = cJSON_strdup(item->pAllocator, "true");
575
18.3k
                break;
576
1.08M
            case cJSON_Number:
577
1.08M
                out = print_number(item, 0);
578
1.08M
                break;
579
124k
            case cJSON_String:
580
124k
                out = print_string(item, 0);
581
124k
                break;
582
609k
            case cJSON_Array:
583
609k
                out = print_array(item, depth, fmt, 0);
584
609k
                break;
585
33.7k
            case cJSON_Object:
586
33.7k
                out = print_object(item, depth, fmt, 0);
587
33.7k
                break;
588
1.87M
        }
589
1.87M
    }
590
1.87M
    return out;
591
1.87M
}
592
593
/* Build an array from input text. */
594
795k
static const char *parse_array(cJSON *item, const char *value, bool *out_of_memory) {
595
795k
    cJSON *child;
596
795k
    if (*value != '[') {
597
        // ep = value; // commented out as it is unused
598
0
        return 0;
599
0
    } /* not an array! */
600
601
795k
    item->type = cJSON_Array;
602
795k
    value = skip(value + 1);
603
795k
    if (*value == ']') return value + 1; /* empty array. */
604
605
785k
    item->child = child = cJSON_New_Item(item->pAllocator);
606
785k
    if (!item->child) {
607
0
        *out_of_memory = true;
608
0
        return 0; /* memory fail */
609
0
    }
610
785k
    value = skip(parse_value(child, skip(value), out_of_memory)); /* skip any spacing, get the value. */
611
785k
    if (!value) return 0;
612
613
2.04M
    while (*value == ',') {
614
1.39M
        cJSON *new_item;
615
1.39M
        new_item = cJSON_New_Item(item->pAllocator);
616
1.39M
        if (!new_item) {
617
0
            *out_of_memory = true;
618
0
            return 0; /* memory fail */
619
0
        }
620
1.39M
        child->next = new_item;
621
1.39M
        new_item->prev = child;
622
1.39M
        child = new_item;
623
1.39M
        value = skip(parse_value(child, skip(value + 1), out_of_memory));
624
1.39M
        if (!value) return 0; /* memory fail */
625
1.39M
    }
626
627
651k
    if (*value == ']') return value + 1; /* end of array */
628
    // ep = value; // commented out as it is unused
629
46
    return 0; /* malformed. */
630
651k
}
631
632
/* Render an array to text */
633
609k
static char *print_array(cJSON *item, int depth, int fmt, printbuffer *p) {
634
609k
    char **entries;
635
609k
    char *out = 0, *ptr, *ret;
636
609k
    size_t len = 5;
637
609k
    cJSON *child = item->child;
638
609k
    int numentries = 0, fail = 0, j = 0;
639
609k
    size_t tmplen = 0, i = 0;
640
641
    /* How many entries in the array? */
642
2.20M
    while (child) numentries++, child = child->next;
643
    /* Explicitly handle numentries==0 */
644
609k
    if (!numentries) {
645
7.25k
        if (p)
646
0
            out = ensure(item->pAllocator, p, 3);
647
7.25k
        else
648
7.25k
            out = (char *)cJSON_malloc(item->pAllocator, 3);
649
7.25k
        if (out) loader_strncpy(out, 3, "[]", 3);
650
7.25k
        return out;
651
7.25k
    }
652
653
602k
    if (p) {
654
        /* Compose the output array. */
655
0
        i = p->offset;
656
0
        ptr = ensure(item->pAllocator, p, 1);
657
0
        if (!ptr) return 0;
658
0
        *ptr = '[';
659
0
        p->offset++;
660
0
        child = item->child;
661
0
        while (child && !fail) {
662
0
            print_value(child, depth + 1, fmt, p);
663
0
            p->offset = cJSON_update(p);
664
0
            if (child->next) {
665
0
                len = fmt ? 2 : 1;
666
0
                ptr = ensure(item->pAllocator, p, len + 1);
667
0
                if (!ptr) return 0;
668
0
                *ptr++ = ',';
669
0
                if (fmt) *ptr++ = ' ';
670
0
                *ptr = 0;
671
0
                p->offset += len;
672
0
            }
673
0
            child = child->next;
674
0
        }
675
0
        ptr = ensure(item->pAllocator, p, 2);
676
0
        if (!ptr) return 0;
677
0
        *ptr++ = ']';
678
0
        *ptr = 0;
679
0
        out = (p->buffer) + i;
680
602k
    } else {
681
        /* Allocate an array to hold the values for each */
682
602k
        entries = (char **)cJSON_malloc(item->pAllocator, numentries * sizeof(char *));
683
602k
        if (!entries) return 0;
684
602k
        memset(entries, 0, numentries * sizeof(char *));
685
        /* Retrieve all the results: */
686
602k
        child = item->child;
687
2.20M
        while (child && !fail) {
688
1.59M
            ret = print_value(child, depth + 1, fmt, 0);
689
1.59M
            entries[i++] = ret;
690
1.59M
            if (ret)
691
1.59M
                len += strlen(ret) + 2 + (fmt ? 1 : 0);
692
0
            else
693
0
                fail = 1;
694
1.59M
            child = child->next;
695
1.59M
        }
696
697
        /* If we didn't fail, try to malloc the output string */
698
602k
        if (!fail) out = (char *)cJSON_malloc(item->pAllocator, len);
699
        /* If that fails, we fail. */
700
602k
        if (!out) fail = 1;
701
702
        /* Handle failure. */
703
602k
        if (fail) {
704
0
            for (j = 0; j < numentries; j++)
705
0
                if (entries[j]) cJSON_Free(item->pAllocator, entries[j]);
706
0
            cJSON_Free(item->pAllocator, entries);
707
0
            return 0;
708
0
        }
709
710
        /* Compose the output array. */
711
602k
        *out = '[';
712
602k
        ptr = out + 1;
713
602k
        *ptr = 0;
714
2.20M
        for (j = 0; j < numentries; j++) {
715
1.59M
            tmplen = strlen(entries[j]);
716
1.59M
            memcpy(ptr, entries[j], tmplen);
717
1.59M
            ptr += tmplen;
718
1.59M
            if (j != numentries - 1) {
719
996k
                *ptr++ = ',';
720
996k
                if (fmt) *ptr++ = ' ';
721
996k
                *ptr = 0;
722
996k
            }
723
1.59M
            cJSON_Free(item->pAllocator, entries[j]);
724
1.59M
        }
725
602k
        cJSON_Free(item->pAllocator, entries);
726
602k
        *ptr++ = ']';
727
602k
        *ptr++ = 0;
728
602k
    }
729
602k
    return out;
730
602k
}
731
732
/* Build an object from the text. */
733
109k
static const char *parse_object(cJSON *item, const char *value, bool *out_of_memory) {
734
109k
    cJSON *child;
735
109k
    if (*value != '{') {
736
        // ep = value; // commented out as it is unused
737
0
        return 0;
738
0
    } /* not an object! */
739
740
109k
    item->type = cJSON_Object;
741
109k
    value = skip(value + 1);
742
109k
    if (*value == '}') return value + 1; /* empty array. */
743
744
85.3k
    item->child = child = cJSON_New_Item(item->pAllocator);
745
85.3k
    if (!item->child) {
746
0
        *out_of_memory = true;
747
0
        return 0;
748
0
    }
749
85.3k
    value = skip(parse_string(child, skip(value), out_of_memory));
750
85.3k
    if (!value) return 0;
751
85.3k
    child->string = child->valuestring;
752
85.3k
    child->valuestring = 0;
753
85.3k
    if (*value != ':') {
754
        // ep = value; // commented out as it is unused
755
9
        return 0;
756
9
    }                                                                 /* fail! */
757
85.3k
    value = skip(parse_value(child, skip(value + 1), out_of_memory)); /* skip any spacing, get the value. */
758
85.3k
    if (!value) return 0;
759
760
175k
    while (*value == ',') {
761
91.6k
        cJSON *new_item;
762
91.6k
        new_item = cJSON_New_Item(item->pAllocator);
763
91.6k
        if (!new_item) {
764
0
            *out_of_memory = true;
765
0
            return 0; /* memory fail */
766
0
        }
767
91.6k
        child->next = new_item;
768
91.6k
        new_item->prev = child;
769
91.6k
        child = new_item;
770
91.6k
        value = skip(parse_string(child, skip(value + 1), out_of_memory));
771
91.6k
        if (!value) return 0;
772
91.6k
        child->string = child->valuestring;
773
91.6k
        child->valuestring = 0;
774
91.6k
        if (*value != ':') {
775
            // ep = value; // commented out as it is unused
776
0
            return 0;
777
0
        }                                                                 /* fail! */
778
91.6k
        value = skip(parse_value(child, skip(value + 1), out_of_memory)); /* skip any spacing, get the value. */
779
91.6k
        if (!value) return 0;
780
91.6k
    }
781
782
83.4k
    if (*value == '}') return value + 1; /* end of array */
783
    // ep = value; // commented out as it is unused
784
35
    return 0; /* malformed. */
785
83.4k
}
786
787
/* Render an object to text. */
788
33.7k
static char *print_object(cJSON *item, int depth, int fmt, printbuffer *p) {
789
33.7k
    char **entries = 0, **names = 0;
790
33.7k
    char *out = 0, *ptr, *ret, *str;
791
33.7k
    int j;
792
33.7k
    cJSON *child = item->child;
793
33.7k
    int numentries = 0, fail = 0, k;
794
33.7k
    size_t tmplen = 0, i = 0, len = 7;
795
    /* Count the number of entries. */
796
74.5k
    while (child) numentries++, child = child->next;
797
    /* Explicitly handle empty object case */
798
33.7k
    if (!numentries) {
799
24.0k
        if (p)
800
0
            out = ensure(item->pAllocator, p, fmt ? depth + 4 : 3);
801
24.0k
        else
802
24.0k
            out = (char *)cJSON_malloc(item->pAllocator, fmt ? depth + 4 : 3);
803
24.0k
        if (!out) return 0;
804
24.0k
        ptr = out;
805
24.0k
        *ptr++ = '{';
806
24.0k
        if (fmt) {
807
24.0k
            *ptr++ = '\n';
808
293k
            for (j = 0; j < depth - 1; j++) *ptr++ = '\t';
809
24.0k
        }
810
24.0k
        *ptr++ = '}';
811
24.0k
        *ptr++ = 0;
812
24.0k
        return out;
813
24.0k
    }
814
9.63k
    if (p) {
815
        /* Compose the output: */
816
0
        i = p->offset;
817
0
        len = fmt ? 2 : 1;
818
0
        ptr = ensure(item->pAllocator, p, len + 1);
819
0
        if (!ptr) return 0;
820
0
        *ptr++ = '{';
821
0
        if (fmt) *ptr++ = '\n';
822
0
        *ptr = 0;
823
0
        p->offset += len;
824
0
        child = item->child;
825
0
        depth++;
826
0
        while (child) {
827
0
            if (fmt) {
828
0
                ptr = ensure(item->pAllocator, p, depth);
829
0
                if (!ptr) return 0;
830
0
                for (j = 0; j < depth; j++) *ptr++ = '\t';
831
0
                p->offset += depth;
832
0
            }
833
0
            print_string_ptr(item->pAllocator, child->string, p);
834
0
            p->offset = cJSON_update(p);
835
836
0
            len = fmt ? 2 : 1;
837
0
            ptr = ensure(item->pAllocator, p, len);
838
0
            if (!ptr) return 0;
839
0
            *ptr++ = ':';
840
0
            if (fmt) *ptr++ = '\t';
841
0
            p->offset += len;
842
843
0
            print_value(child, depth, fmt, p);
844
0
            p->offset = cJSON_update(p);
845
846
0
            len = (fmt ? 1 : 0) + (child->next ? 1 : 0);
847
0
            ptr = ensure(item->pAllocator, p, len + 1);
848
0
            if (!ptr) return 0;
849
0
            if (child->next) *ptr++ = ',';
850
0
            if (fmt) *ptr++ = '\n';
851
0
            *ptr = 0;
852
0
            p->offset += len;
853
0
            child = child->next;
854
0
        }
855
0
        ptr = ensure(item->pAllocator, p, fmt ? (depth + 1) : 2);
856
0
        if (!ptr) return 0;
857
0
        if (fmt)
858
0
            for (j = 0; j < depth - 1; j++) *ptr++ = '\t';
859
0
        *ptr++ = '}';
860
0
        *ptr = 0;
861
0
        out = (p->buffer) + i;
862
9.63k
    } else {
863
        /* Allocate space for the names and the objects */
864
9.63k
        entries = (char **)cJSON_malloc(item->pAllocator, numentries * sizeof(char *));
865
9.63k
        if (!entries) return 0;
866
9.63k
        names = (char **)cJSON_malloc(item->pAllocator, numentries * sizeof(char *));
867
9.63k
        if (!names) {
868
0
            cJSON_Free(item->pAllocator, entries);
869
0
            return 0;
870
0
        }
871
9.63k
        memset(entries, 0, sizeof(char *) * numentries);
872
9.63k
        memset(names, 0, sizeof(char *) * numentries);
873
874
        /* Collect all the results into our arrays: */
875
9.63k
        child = item->child;
876
9.63k
        depth++;
877
9.63k
        if (fmt) len += depth;
878
50.4k
        while (child) {
879
40.8k
            names[i] = str = print_string_ptr(item->pAllocator, child->string, 0);
880
40.8k
            entries[i++] = ret = print_value(child, depth, fmt, 0);
881
40.8k
            if (str && ret)
882
40.8k
                len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
883
0
            else
884
0
                fail = 1;
885
40.8k
            child = child->next;
886
40.8k
        }
887
888
        /* Try to allocate the output string */
889
9.63k
        if (!fail) out = (char *)cJSON_malloc(item->pAllocator, len);
890
9.63k
        if (!out) fail = 1;
891
892
        /* Handle failure */
893
9.63k
        if (fail) {
894
0
            for (j = 0; j < numentries; j++) {
895
0
                if (names[i]) cJSON_Free(item->pAllocator, names[j]);
896
0
                if (entries[j]) cJSON_Free(item->pAllocator, entries[j]);
897
0
            }
898
0
            cJSON_Free(item->pAllocator, names);
899
0
            cJSON_Free(item->pAllocator, entries);
900
0
            return 0;
901
0
        }
902
903
        /* Compose the output: */
904
9.63k
        *out = '{';
905
9.63k
        ptr = out + 1;
906
9.63k
        if (fmt) *ptr++ = '\n';
907
9.63k
        *ptr = 0;
908
50.4k
        for (j = 0; j < numentries; j++) {
909
40.8k
            if (fmt)
910
2.52M
                for (k = 0; k < depth; k++) *ptr++ = '\t';
911
40.8k
            tmplen = strlen(names[j]);
912
40.8k
            memcpy(ptr, names[j], tmplen);
913
40.8k
            ptr += tmplen;
914
40.8k
            *ptr++ = ':';
915
40.8k
            if (fmt) *ptr++ = '\t';
916
40.8k
            size_t entries_size = strlen(entries[j]);
917
40.8k
            loader_strncpy(ptr, len - (ptr - out), entries[j], entries_size);
918
40.8k
            ptr += entries_size;
919
40.8k
            if (j != numentries - 1) *ptr++ = ',';
920
40.8k
            if (fmt) *ptr++ = '\n';
921
40.8k
            *ptr = 0;
922
40.8k
            cJSON_Free(item->pAllocator, names[j]);
923
40.8k
            cJSON_Free(item->pAllocator, entries[j]);
924
40.8k
        }
925
926
9.63k
        cJSON_Free(item->pAllocator, names);
927
9.63k
        cJSON_Free(item->pAllocator, entries);
928
9.63k
        if (fmt)
929
2.18M
            for (j = 0; j < depth - 1; j++) *ptr++ = '\t';
930
9.63k
        *ptr++ = '}';
931
9.63k
        *ptr++ = 0;
932
9.63k
    }
933
9.63k
    return out;
934
9.63k
}
935
936
/* Get Array size/item / object item. */
937
24.3k
int loader_cJSON_GetArraySize(cJSON *array) {
938
24.3k
    cJSON *c = array->child;
939
24.3k
    int i = 0;
940
428k
    while (c) i++, c = c->next;
941
24.3k
    return i;
942
24.3k
}
943
365k
cJSON *loader_cJSON_GetArrayItem(cJSON *array, int item) {
944
365k
    cJSON *c = array->child;
945
1.44G
    while (c && item > 0) item--, c = c->next;
946
365k
    return c;
947
365k
}
948
352k
cJSON *loader_cJSON_GetObjectItem(cJSON *object, const char *string) {
949
352k
    cJSON *c = object->child;
950
512k
    while (c && strcmp(c->string, string)) c = c->next;
951
352k
    return c;
952
352k
}
953
954
5.42k
VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
955
5.42k
    FILE *file = NULL;
956
5.42k
    char *json_buf = NULL;
957
5.42k
    size_t len;
958
5.42k
    VkResult res = VK_SUCCESS;
959
960
5.42k
    assert(json != NULL);
961
962
5.42k
    *json = NULL;
963
964
#if defined(_WIN32)
965
    int filename_utf16_size = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
966
    if (filename_utf16_size > 0) {
967
        wchar_t *filename_utf16 = (wchar_t *)loader_stack_alloc(filename_utf16_size * sizeof(wchar_t));
968
        if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_utf16, filename_utf16_size) == filename_utf16_size) {
969
            errno_t wfopen_error = _wfopen_s(&file, filename_utf16, L"rb");
970
            if (0 != wfopen_error) {
971
                loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
972
            }
973
        }
974
    }
975
#elif COMMON_UNIX_PLATFORMS
976
    file = fopen(filename, "rb");
977
#else
978
#warning fopen not available on this platform
979
#endif
980
981
5.42k
    if (!file) {
982
3.24k
        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
983
3.24k
        res = VK_ERROR_INITIALIZATION_FAILED;
984
3.24k
        goto out;
985
3.24k
    }
986
    // NOTE: We can't just use fseek(file, 0, SEEK_END) because that isn't guaranteed to be supported on all systems
987
2.17k
    size_t fread_ret_count = 0;
988
67.9k
    do {
989
67.9k
        char buffer[256];
990
67.9k
        fread_ret_count = fread(buffer, 1, 256, file);
991
67.9k
    } while (fread_ret_count == 256 && !feof(file));
992
2.17k
    len = ftell(file);
993
2.17k
    fseek(file, 0, SEEK_SET);
994
2.17k
    json_buf = (char *)loader_instance_heap_calloc(inst, len + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
995
2.17k
    if (json_buf == NULL) {
996
0
        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
997
0
                   "loader_get_json: Failed to allocate space for JSON file %s buffer of length %lu", filename, len);
998
0
        res = VK_ERROR_OUT_OF_HOST_MEMORY;
999
0
        goto out;
1000
0
    }
1001
2.17k
    if (fread(json_buf, sizeof(char), len, file) != len) {
1002
2
        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read JSON file %s.", filename);
1003
2
        res = VK_ERROR_INITIALIZATION_FAILED;
1004
2
        goto out;
1005
2
    }
1006
2.17k
    json_buf[len] = '\0';
1007
1008
    // Can't be a valid json if the string is of length zero
1009
2.17k
    if (len == 0) {
1010
856
        res = VK_ERROR_INITIALIZATION_FAILED;
1011
856
        goto out;
1012
856
    }
1013
    // Parse text from file
1014
1.32k
    bool out_of_memory = false;
1015
1.32k
    *json = cJSON_Parse(inst ? &inst->alloc_callbacks : NULL, json_buf, &out_of_memory);
1016
1.32k
    if (out_of_memory) {
1017
0
        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Out of Memory error occurred while parsing JSON file %s.",
1018
0
                   filename);
1019
0
        res = VK_ERROR_OUT_OF_HOST_MEMORY;
1020
0
        goto out;
1021
1.32k
    } else if (*json == NULL) {
1022
138
        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Invalid JSON file %s.", filename);
1023
138
        goto out;
1024
138
    }
1025
1026
5.42k
out:
1027
5.42k
    loader_instance_heap_free(inst, json_buf);
1028
5.42k
    if (NULL != file) {
1029
2.17k
        fclose(file);
1030
2.17k
    }
1031
5.42k
    if (res != VK_SUCCESS && *json != NULL) {
1032
0
        loader_cJSON_Delete(*json);
1033
0
        *json = NULL;
1034
0
    }
1035
1036
5.42k
    return res;
1037
1.32k
}
1038
1039
VkResult loader_parse_json_string_to_existing_str(const struct loader_instance *inst, cJSON *object, const char *key,
1040
0
                                                  size_t out_str_len, char *out_string) {
1041
0
    cJSON *item = loader_cJSON_GetObjectItem(object, key);
1042
0
    if (NULL == item) {
1043
0
        return VK_ERROR_INITIALIZATION_FAILED;
1044
0
    }
1045
1046
0
    char *str = loader_cJSON_Print(item);
1047
0
    if (str == NULL) {
1048
0
        return VK_ERROR_OUT_OF_HOST_MEMORY;
1049
0
    }
1050
0
    if (NULL != out_string) {
1051
0
        loader_strncpy(out_string, out_str_len, str, out_str_len);
1052
0
        if (out_str_len > 0) {
1053
0
            out_string[out_str_len - 1] = '\0';
1054
0
        }
1055
0
    }
1056
0
    loader_instance_heap_free(inst, str);
1057
0
    return VK_SUCCESS;
1058
0
}
1059
1060
94.5k
VkResult loader_parse_json_string(cJSON *object, const char *key, char **out_string) {
1061
94.5k
    cJSON *item = loader_cJSON_GetObjectItem(object, key);
1062
94.5k
    if (NULL == item) {
1063
92
        return VK_ERROR_INITIALIZATION_FAILED;
1064
92
    }
1065
1066
94.4k
    char *str = loader_cJSON_Print(item);
1067
94.4k
    if (str == NULL) {
1068
0
        return VK_ERROR_OUT_OF_HOST_MEMORY;
1069
0
    }
1070
94.4k
    if (NULL != out_string) {
1071
94.4k
        *out_string = str;
1072
94.4k
    }
1073
94.4k
    return VK_SUCCESS;
1074
94.4k
}
1075
VkResult loader_parse_json_array_of_strings(const struct loader_instance *inst, cJSON *object, const char *key,
1076
107k
                                            struct loader_string_list *string_list) {
1077
107k
    VkResult res = VK_SUCCESS;
1078
107k
    cJSON *item = loader_cJSON_GetObjectItem(object, key);
1079
107k
    if (NULL == item) {
1080
107k
        return VK_ERROR_INITIALIZATION_FAILED;
1081
107k
    }
1082
1083
151
    uint32_t count = loader_cJSON_GetArraySize(item);
1084
151
    if (count == 0) {
1085
11
        return VK_SUCCESS;
1086
11
    }
1087
1088
140
    res = create_string_list(inst, count, string_list);
1089
140
    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
1090
0
        goto out;
1091
0
    }
1092
106k
    for (uint32_t i = 0; i < count; i++) {
1093
106k
        cJSON *element = loader_cJSON_GetArrayItem(item, i);
1094
106k
        if (element == NULL) {
1095
0
            return VK_ERROR_INITIALIZATION_FAILED;
1096
0
        }
1097
106k
        char *out_data = loader_cJSON_Print(element);
1098
106k
        if (out_data == NULL) {
1099
0
            res = VK_ERROR_OUT_OF_HOST_MEMORY;
1100
0
            goto out;
1101
0
        }
1102
106k
        res = append_str_to_string_list(inst, string_list, out_data);
1103
106k
        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
1104
0
            goto out;
1105
0
        }
1106
106k
    }
1107
140
out:
1108
140
    if (res == VK_ERROR_OUT_OF_HOST_MEMORY && NULL != string_list->list) {
1109
0
        free_string_list(inst, string_list);
1110
0
    }
1111
1112
140
    return res;
1113
140
}