File Coverage

yyjson.h
Criterion Covered Total %
statement 240 315 76.1
branch 478 1110 43.0
condition n/a
subroutine n/a
pod n/a
total 718 1425 50.3


line stmt bran cond sub pod time code
1             /*==============================================================================
2             Copyright (c) 2020 YaoYuan
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 all
12             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 THE
20             SOFTWARE.
21             *============================================================================*/
22              
23             /**
24             @file yyjson.h
25             @date 2019-03-09
26             @author YaoYuan
27             */
28              
29             #ifndef YYJSON_H
30             #define YYJSON_H
31              
32              
33              
34             /*==============================================================================
35             * MARK: - Header Files
36             *============================================================================*/
37              
38             #include
39             #include
40             #include
41             #include
42             #include
43             #include
44              
45              
46              
47             /*==============================================================================
48             * MARK: - Compile-time Options
49             *============================================================================*/
50              
51             /*
52             Define as 1 to disable JSON reader at compile-time.
53             This disables functions with "read" in their name.
54             Reduces binary size by about 60%.
55             */
56             #ifndef YYJSON_DISABLE_READER
57             #endif
58              
59             /*
60             Define as 1 to disable JSON writer at compile-time.
61             This disables functions with "write" in their name.
62             Reduces binary size by about 30%.
63             */
64             #ifndef YYJSON_DISABLE_WRITER
65             #endif
66              
67             /*
68             Define as 1 to disable JSON incremental reader at compile-time.
69             This disables functions with "incr" in their name.
70             */
71             #ifndef YYJSON_DISABLE_INCR_READER
72             #endif
73              
74             /*
75             Define as 1 to disable JSON Pointer, JSON Patch and JSON Merge Patch supports.
76             This disables functions with "ptr" or "patch" in their name.
77             */
78             #ifndef YYJSON_DISABLE_UTILS
79             #endif
80              
81             /*
82             Define as 1 to disable the fast floating-point number conversion in yyjson.
83             Libc's `strtod/snprintf` will be used instead.
84              
85             This reduces binary size by about 30%, but significantly slows down the
86             floating-point read/write speed.
87             */
88             #ifndef YYJSON_DISABLE_FAST_FP_CONV
89             #endif
90              
91             /*
92             Define as 1 to disable non-standard JSON features support at compile-time,
93             such as YYJSON_READ_ALLOW_XXX and YYJSON_WRITE_ALLOW_XXX.
94              
95             This reduces binary size by about 10%, and slightly improves performance.
96             */
97             #ifndef YYJSON_DISABLE_NON_STANDARD
98             #endif
99              
100             /*
101             Define as 1 to disable UTF-8 validation at compile-time.
102              
103             Use this if all input strings are guaranteed to be valid UTF-8
104             (e.g. language-level String types are already validated).
105              
106             Disabling UTF-8 validation improves performance for non-ASCII strings by about
107             3% to 7%.
108              
109             Note: If this flag is enabled while passing illegal UTF-8 strings,
110             the following errors may occur:
111             - Escaped characters may be ignored when parsing JSON strings.
112             - Ending quotes may be ignored when parsing JSON strings, causing the
113             string to merge with the next value.
114             - When serializing with `yyjson_mut_val`, the string's end may be accessed
115             out of bounds, potentially causing a segmentation fault.
116             */
117             #ifndef YYJSON_DISABLE_UTF8_VALIDATION
118             #endif
119              
120             /*
121             Define as 1 to improve performance on architectures that do not support
122             unaligned memory access.
123              
124             Normally, this does not need to be set manually. See the C file for details.
125             */
126             #ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS
127             #endif
128              
129             /* Define as 1 to export symbols when building this library as a Windows DLL. */
130             #ifndef YYJSON_EXPORTS
131             #endif
132              
133             /* Define as 1 to import symbols when using this library as a Windows DLL. */
134             #ifndef YYJSON_IMPORTS
135             #endif
136              
137             /* Define as 1 to include for compilers without C99 support. */
138             #ifndef YYJSON_HAS_STDINT_H
139             #endif
140              
141             /* Define as 1 to include for compilers without C99 support. */
142             #ifndef YYJSON_HAS_STDBOOL_H
143             #endif
144              
145              
146              
147             /*==============================================================================
148             * MARK: - Compiler Macros
149             *============================================================================*/
150              
151             /** compiler version (MSVC) */
152             #ifdef _MSC_VER
153             # define YYJSON_MSC_VER _MSC_VER
154             #else
155             # define YYJSON_MSC_VER 0
156             #endif
157              
158             /** compiler version (GCC) */
159             #ifdef __GNUC__
160             # define YYJSON_GCC_VER __GNUC__
161             # if defined(__GNUC_PATCHLEVEL__)
162             # define yyjson_gcc_available(major, minor, patch) \
163             ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
164             >= (major * 10000 + minor * 100 + patch))
165             # else
166             # define yyjson_gcc_available(major, minor, patch) \
167             ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) \
168             >= (major * 10000 + minor * 100 + patch))
169             # endif
170             #else
171             # define YYJSON_GCC_VER 0
172             # define yyjson_gcc_available(major, minor, patch) 0
173             #endif
174              
175             /** real gcc check */
176             #if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
177             !defined(__clang__) && !defined(__llvm__) && \
178             !defined(__INTEL_COMPILER) && !defined(__ICC) && \
179             !defined(__NVCC__) && !defined(__PGI) && !defined(__TINYC__)
180             # define YYJSON_IS_REAL_GCC 1
181             #else
182             # define YYJSON_IS_REAL_GCC 0
183             #endif
184              
185             /** C version (STDC) */
186             #if defined(__STDC__) && (__STDC__ >= 1) && defined(__STDC_VERSION__)
187             # define YYJSON_STDC_VER __STDC_VERSION__
188             #else
189             # define YYJSON_STDC_VER 0
190             #endif
191              
192             /** C++ version */
193             #if defined(__cplusplus)
194             # define YYJSON_CPP_VER __cplusplus
195             #else
196             # define YYJSON_CPP_VER 0
197             #endif
198              
199             /** compiler builtin check (since gcc 10.0, clang 2.6, icc 2021) */
200             #ifndef yyjson_has_builtin
201             # ifdef __has_builtin
202             # define yyjson_has_builtin(x) __has_builtin(x)
203             # else
204             # define yyjson_has_builtin(x) 0
205             # endif
206             #endif
207              
208             /** compiler attribute check (since gcc 5.0, clang 2.9, icc 17) */
209             #ifndef yyjson_has_attribute
210             # ifdef __has_attribute
211             # define yyjson_has_attribute(x) __has_attribute(x)
212             # else
213             # define yyjson_has_attribute(x) 0
214             # endif
215             #endif
216              
217             /** compiler feature check (since clang 2.6, icc 17) */
218             #ifndef yyjson_has_feature
219             # ifdef __has_feature
220             # define yyjson_has_feature(x) __has_feature(x)
221             # else
222             # define yyjson_has_feature(x) 0
223             # endif
224             #endif
225              
226             /** include check (since gcc 5.0, clang 2.7, icc 16, msvc 2017 15.3) */
227             #ifndef yyjson_has_include
228             # ifdef __has_include
229             # define yyjson_has_include(x) __has_include(x)
230             # else
231             # define yyjson_has_include(x) 0
232             # endif
233             #endif
234              
235             /** inline for compiler */
236             #ifndef yyjson_inline
237             # if YYJSON_MSC_VER >= 1200
238             # define yyjson_inline __forceinline
239             # elif defined(_MSC_VER)
240             # define yyjson_inline __inline
241             # elif yyjson_has_attribute(always_inline) || YYJSON_GCC_VER >= 4
242             # define yyjson_inline __inline__ __attribute__((always_inline))
243             # elif defined(__clang__) || defined(__GNUC__)
244             # define yyjson_inline __inline__
245             # elif defined(__cplusplus) || YYJSON_STDC_VER >= 199901L
246             # define yyjson_inline inline
247             # else
248             # define yyjson_inline
249             # endif
250             #endif
251              
252             /** noinline for compiler */
253             #ifndef yyjson_noinline
254             # if YYJSON_MSC_VER >= 1400
255             # define yyjson_noinline __declspec(noinline)
256             # elif yyjson_has_attribute(noinline) || YYJSON_GCC_VER >= 4
257             # define yyjson_noinline __attribute__((noinline))
258             # else
259             # define yyjson_noinline
260             # endif
261             #endif
262              
263             /** align for compiler */
264             #ifndef yyjson_align
265             # if YYJSON_MSC_VER >= 1300
266             # define yyjson_align(x) __declspec(align(x))
267             # elif yyjson_has_attribute(aligned) || defined(__GNUC__)
268             # define yyjson_align(x) __attribute__((aligned(x)))
269             # elif YYJSON_CPP_VER >= 201103L
270             # define yyjson_align(x) alignas(x)
271             # else
272             # define yyjson_align(x)
273             # endif
274             #endif
275              
276             /** likely for compiler */
277             #ifndef yyjson_likely
278             # if yyjson_has_builtin(__builtin_expect) || \
279             (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5)
280             # define yyjson_likely(expr) __builtin_expect(!!(expr), 1)
281             # else
282             # define yyjson_likely(expr) (expr)
283             # endif
284             #endif
285              
286             /** unlikely for compiler */
287             #ifndef yyjson_unlikely
288             # if yyjson_has_builtin(__builtin_expect) || \
289             (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5)
290             # define yyjson_unlikely(expr) __builtin_expect(!!(expr), 0)
291             # else
292             # define yyjson_unlikely(expr) (expr)
293             # endif
294             #endif
295              
296             /** compile-time constant check for compiler */
297             #ifndef yyjson_constant_p
298             # if yyjson_has_builtin(__builtin_constant_p) || (YYJSON_GCC_VER >= 3)
299             # define YYJSON_HAS_CONSTANT_P 1
300             # define yyjson_constant_p(value) __builtin_constant_p(value)
301             # else
302             # define YYJSON_HAS_CONSTANT_P 0
303             # define yyjson_constant_p(value) 0
304             # endif
305             #endif
306              
307             /** deprecate warning */
308             #ifndef yyjson_deprecated
309             # if YYJSON_MSC_VER >= 1400
310             # define yyjson_deprecated(msg) __declspec(deprecated(msg))
311             # elif yyjson_has_feature(attribute_deprecated_with_message) || \
312             (YYJSON_GCC_VER > 4 || (YYJSON_GCC_VER == 4 && __GNUC_MINOR__ >= 5))
313             # define yyjson_deprecated(msg) __attribute__((deprecated(msg)))
314             # elif YYJSON_GCC_VER >= 3
315             # define yyjson_deprecated(msg) __attribute__((deprecated))
316             # else
317             # define yyjson_deprecated(msg)
318             # endif
319             #endif
320              
321             /** function export */
322             #ifndef yyjson_api
323             # if defined(_WIN32)
324             # if defined(YYJSON_EXPORTS) && YYJSON_EXPORTS
325             # define yyjson_api __declspec(dllexport)
326             # elif defined(YYJSON_IMPORTS) && YYJSON_IMPORTS
327             # define yyjson_api __declspec(dllimport)
328             # else
329             # define yyjson_api
330             # endif
331             # elif yyjson_has_attribute(visibility) || YYJSON_GCC_VER >= 4
332             # define yyjson_api __attribute__((visibility("default")))
333             # else
334             # define yyjson_api
335             # endif
336             #endif
337              
338             /** inline function export */
339             #ifndef yyjson_api_inline
340             # define yyjson_api_inline static yyjson_inline
341             #endif
342              
343             /** stdint (C89 compatible) */
344             #if (defined(YYJSON_HAS_STDINT_H) && YYJSON_HAS_STDINT_H) || \
345             YYJSON_MSC_VER >= 1600 || YYJSON_STDC_VER >= 199901L || \
346             defined(_STDINT_H) || defined(_STDINT_H_) || \
347             defined(__CLANG_STDINT_H) || defined(_STDINT_H_INCLUDED) || \
348             yyjson_has_include()
349             # include
350             #elif defined(_MSC_VER)
351             # if _MSC_VER < 1300
352             typedef signed char int8_t;
353             typedef signed short int16_t;
354             typedef signed int int32_t;
355             typedef unsigned char uint8_t;
356             typedef unsigned short uint16_t;
357             typedef unsigned int uint32_t;
358             typedef signed __int64 int64_t;
359             typedef unsigned __int64 uint64_t;
360             # else
361             typedef signed __int8 int8_t;
362             typedef signed __int16 int16_t;
363             typedef signed __int32 int32_t;
364             typedef unsigned __int8 uint8_t;
365             typedef unsigned __int16 uint16_t;
366             typedef unsigned __int32 uint32_t;
367             typedef signed __int64 int64_t;
368             typedef unsigned __int64 uint64_t;
369             # endif
370             #else
371             # if UCHAR_MAX == 0xFFU
372             typedef signed char int8_t;
373             typedef unsigned char uint8_t;
374             # else
375             # error cannot find 8-bit integer type
376             # endif
377             # if USHRT_MAX == 0xFFFFU
378             typedef unsigned short uint16_t;
379             typedef signed short int16_t;
380             # elif UINT_MAX == 0xFFFFU
381             typedef unsigned int uint16_t;
382             typedef signed int int16_t;
383             # else
384             # error cannot find 16-bit integer type
385             # endif
386             # if UINT_MAX == 0xFFFFFFFFUL
387             typedef unsigned int uint32_t;
388             typedef signed int int32_t;
389             # elif ULONG_MAX == 0xFFFFFFFFUL
390             typedef unsigned long uint32_t;
391             typedef signed long int32_t;
392             # elif USHRT_MAX == 0xFFFFFFFFUL
393             typedef unsigned short uint32_t;
394             typedef signed short int32_t;
395             # else
396             # error cannot find 32-bit integer type
397             # endif
398             # if defined(__INT64_TYPE__) && defined(__UINT64_TYPE__)
399             typedef __INT64_TYPE__ int64_t;
400             typedef __UINT64_TYPE__ uint64_t;
401             # elif defined(__GNUC__) || defined(__clang__)
402             # if !defined(_SYS_TYPES_H) && !defined(__int8_t_defined)
403             __extension__ typedef long long int64_t;
404             # endif
405             __extension__ typedef unsigned long long uint64_t;
406             # elif defined(_LONG_LONG) || defined(__MWERKS__) || defined(_CRAYC) || \
407             defined(__SUNPRO_C) || defined(__SUNPRO_CC)
408             typedef long long int64_t;
409             typedef unsigned long long uint64_t;
410             # elif (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || \
411             defined(__WATCOM_INT64__) || defined (__alpha) || defined (__DECC)
412             typedef __int64 int64_t;
413             typedef unsigned __int64 uint64_t;
414             # else
415             # error cannot find 64-bit integer type
416             # endif
417             #endif
418              
419             /** stdbool (C89 compatible) */
420             #if (defined(YYJSON_HAS_STDBOOL_H) && YYJSON_HAS_STDBOOL_H) || \
421             (yyjson_has_include() && !defined(__STRICT_ANSI__)) || \
422             YYJSON_MSC_VER >= 1800 || YYJSON_STDC_VER >= 199901L
423             # include
424             #elif !defined(__bool_true_false_are_defined)
425             # define __bool_true_false_are_defined 1
426             # if defined(__cplusplus)
427             # if defined(__GNUC__) && !defined(__STRICT_ANSI__)
428             # define _Bool bool
429             # if __cplusplus < 201103L
430             # define bool bool
431             # define false false
432             # define true true
433             # endif
434             # endif
435             # else
436             # define bool unsigned char
437             # define true 1
438             # define false 0
439             # endif
440             #endif
441              
442             /** char bit check */
443             #if defined(CHAR_BIT)
444             # if CHAR_BIT != 8
445             # error non 8-bit char is not supported
446             # endif
447             #endif
448              
449             /**
450             Microsoft Visual C++ 6.0 doesn't support converting number from u64 to f64:
451             error C2520: conversion from unsigned __int64 to double not implemented.
452             */
453             #ifndef YYJSON_U64_TO_F64_NO_IMPL
454             # if (0 < YYJSON_MSC_VER) && (YYJSON_MSC_VER <= 1200)
455             # define YYJSON_U64_TO_F64_NO_IMPL 1
456             # else
457             # define YYJSON_U64_TO_F64_NO_IMPL 0
458             # endif
459             #endif
460              
461              
462              
463             /*==============================================================================
464             * MARK: - Compile Hint Begin
465             *============================================================================*/
466              
467             /* extern "C" begin */
468             #ifdef __cplusplus
469             extern "C" {
470             #endif
471              
472             /* warning suppress begin */
473             #if defined(__clang__)
474             # pragma clang diagnostic push
475             # pragma clang diagnostic ignored "-Wunused-function"
476             # pragma clang diagnostic ignored "-Wunused-parameter"
477             #elif defined(__GNUC__)
478             # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
479             # pragma GCC diagnostic push
480             # endif
481             # pragma GCC diagnostic ignored "-Wunused-function"
482             # pragma GCC diagnostic ignored "-Wunused-parameter"
483             #elif defined(_MSC_VER)
484             # pragma warning(push)
485             # pragma warning(disable:4800) /* 'int': forcing value to 'true' or 'false' */
486             #endif
487              
488              
489              
490             /*==============================================================================
491             * MARK: - Version
492             *============================================================================*/
493              
494             /** The major version of yyjson. */
495             #define YYJSON_VERSION_MAJOR 0
496              
497             /** The minor version of yyjson. */
498             #define YYJSON_VERSION_MINOR 12
499              
500             /** The patch version of yyjson. */
501             #define YYJSON_VERSION_PATCH 0
502              
503             /** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */
504             #define YYJSON_VERSION_HEX 0x000C00
505              
506             /** The version string of yyjson. */
507             #define YYJSON_VERSION_STRING "0.12.0"
508              
509             /** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */
510             yyjson_api uint32_t yyjson_version(void);
511              
512              
513              
514             /*==============================================================================
515             * MARK: - JSON Types
516             *============================================================================*/
517              
518             /** Type of a JSON value (3 bit). */
519             typedef uint8_t yyjson_type;
520             /** No type, invalid. */
521             #define YYJSON_TYPE_NONE ((uint8_t)0) /* _____000 */
522             /** Raw string type, no subtype. */
523             #define YYJSON_TYPE_RAW ((uint8_t)1) /* _____001 */
524             /** Null type: `null` literal, no subtype. */
525             #define YYJSON_TYPE_NULL ((uint8_t)2) /* _____010 */
526             /** Boolean type, subtype: TRUE, FALSE. */
527             #define YYJSON_TYPE_BOOL ((uint8_t)3) /* _____011 */
528             /** Number type, subtype: UINT, SINT, REAL. */
529             #define YYJSON_TYPE_NUM ((uint8_t)4) /* _____100 */
530             /** String type, subtype: NONE, NOESC. */
531             #define YYJSON_TYPE_STR ((uint8_t)5) /* _____101 */
532             /** Array type, no subtype. */
533             #define YYJSON_TYPE_ARR ((uint8_t)6) /* _____110 */
534             /** Object type, no subtype. */
535             #define YYJSON_TYPE_OBJ ((uint8_t)7) /* _____111 */
536              
537             /** Subtype of a JSON value (2 bit). */
538             typedef uint8_t yyjson_subtype;
539             /** No subtype. */
540             #define YYJSON_SUBTYPE_NONE ((uint8_t)(0 << 3)) /* ___00___ */
541             /** False subtype: `false` literal. */
542             #define YYJSON_SUBTYPE_FALSE ((uint8_t)(0 << 3)) /* ___00___ */
543             /** True subtype: `true` literal. */
544             #define YYJSON_SUBTYPE_TRUE ((uint8_t)(1 << 3)) /* ___01___ */
545             /** Unsigned integer subtype: `uint64_t`. */
546             #define YYJSON_SUBTYPE_UINT ((uint8_t)(0 << 3)) /* ___00___ */
547             /** Signed integer subtype: `int64_t`. */
548             #define YYJSON_SUBTYPE_SINT ((uint8_t)(1 << 3)) /* ___01___ */
549             /** Real number subtype: `double`. */
550             #define YYJSON_SUBTYPE_REAL ((uint8_t)(2 << 3)) /* ___10___ */
551             /** String that do not need to be escaped for writing (internal use). */
552             #define YYJSON_SUBTYPE_NOESC ((uint8_t)(1 << 3)) /* ___01___ */
553              
554             /** The mask used to extract the type of a JSON value. */
555             #define YYJSON_TYPE_MASK ((uint8_t)0x07) /* _____111 */
556             /** The number of bits used by the type. */
557             #define YYJSON_TYPE_BIT ((uint8_t)3)
558             /** The mask used to extract the subtype of a JSON value. */
559             #define YYJSON_SUBTYPE_MASK ((uint8_t)0x18) /* ___11___ */
560             /** The number of bits used by the subtype. */
561             #define YYJSON_SUBTYPE_BIT ((uint8_t)2)
562             /** The mask used to extract the reserved bits of a JSON value. */
563             #define YYJSON_RESERVED_MASK ((uint8_t)0xE0) /* 111_____ */
564             /** The number of reserved bits. */
565             #define YYJSON_RESERVED_BIT ((uint8_t)3)
566             /** The mask used to extract the tag of a JSON value. */
567             #define YYJSON_TAG_MASK ((uint8_t)0xFF) /* 11111111 */
568             /** The number of bits used by the tag. */
569             #define YYJSON_TAG_BIT ((uint8_t)8)
570              
571             /** Padding size for JSON reader. */
572             #define YYJSON_PADDING_SIZE 4
573              
574              
575              
576             /*==============================================================================
577             * MARK: - Allocator
578             *============================================================================*/
579              
580             /**
581             A memory allocator.
582              
583             Typically you don't need to use it, unless you want to customize your own
584             memory allocator.
585             */
586             typedef struct yyjson_alc {
587             /** Same as libc's malloc(size), should not be NULL. */
588             void *(*malloc)(void *ctx, size_t size);
589             /** Same as libc's realloc(ptr, size), should not be NULL. */
590             void *(*realloc)(void *ctx, void *ptr, size_t old_size, size_t size);
591             /** Same as libc's free(ptr), should not be NULL. */
592             void (*free)(void *ctx, void *ptr);
593             /** A context for malloc/realloc/free, can be NULL. */
594             void *ctx;
595             } yyjson_alc;
596              
597             /**
598             A pool allocator uses fixed length pre-allocated memory.
599              
600             This allocator may be used to avoid malloc/realloc calls. The pre-allocated
601             memory should be held by the caller. The maximum amount of memory required to
602             read a JSON can be calculated using the `yyjson_read_max_memory_usage()`
603             function, but the amount of memory required to write a JSON cannot be directly
604             calculated.
605              
606             This is not a general-purpose allocator. It is designed to handle a single JSON
607             data at a time. If it is used for overly complex memory tasks, such as parsing
608             multiple JSON documents using the same allocator but releasing only a few of
609             them, it may cause memory fragmentation, resulting in performance degradation
610             and memory waste.
611              
612             @param alc The allocator to be initialized.
613             If this parameter is NULL, the function will fail and return false.
614             If `buf` or `size` is invalid, this will be set to an empty allocator.
615             @param buf The buffer memory for this allocator.
616             If this parameter is NULL, the function will fail and return false.
617             @param size The size of `buf`, in bytes.
618             If this parameter is less than 8 words (32/64 bytes on 32/64-bit OS), the
619             function will fail and return false.
620             @return true if the `alc` has been successfully initialized.
621              
622             @b Example
623             @code
624             // parse JSON with stack memory
625             char buf[1024];
626             yyjson_alc alc;
627             yyjson_alc_pool_init(&alc, buf, 1024);
628              
629             const char *json = "{\"name\":\"Helvetica\",\"size\":16}"
630             yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL);
631             // the memory of `doc` is on the stack
632             @endcode
633              
634             @warning This Allocator is not thread-safe.
635             */
636             yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size);
637              
638             /**
639             A dynamic allocator.
640              
641             This allocator has a similar usage to the pool allocator above. However, when
642             there is not enough memory, this allocator will dynamically request more memory
643             using libc's `malloc` function, and frees it all at once when it is destroyed.
644              
645             @return A new dynamic allocator, or NULL if memory allocation failed.
646             @note The returned value should be freed with `yyjson_alc_dyn_free()`.
647              
648             @warning This Allocator is not thread-safe.
649             */
650             yyjson_api yyjson_alc *yyjson_alc_dyn_new(void);
651              
652             /**
653             Free a dynamic allocator which is created by `yyjson_alc_dyn_new()`.
654             @param alc The dynamic allocator to be destroyed.
655             */
656             yyjson_api void yyjson_alc_dyn_free(yyjson_alc *alc);
657              
658              
659              
660             /*==============================================================================
661             * MARK: - Text Locating
662             *============================================================================*/
663              
664             /**
665             Locate the line and column number for a byte position in a string.
666             This can be used to get better description for error position.
667              
668             @param str The input string.
669             @param len The byte length of the input string.
670             @param pos The byte position within the input string.
671             @param line A pointer to receive the line number, starting from 1.
672             @param col A pointer to receive the column number, starting from 1.
673             @param chr A pointer to receive the character index, starting from 0.
674             @return true on success, false if `str` is NULL or `pos` is out of bounds.
675             @note Line/column/character are calculated based on Unicode characters for
676             compatibility with text editors. For multi-byte UTF-8 characters,
677             the returned value may not directly correspond to the byte position.
678             */
679             yyjson_api bool yyjson_locate_pos(const char *str, size_t len, size_t pos,
680             size_t *line, size_t *col, size_t *chr);
681              
682              
683              
684             /*==============================================================================
685             * MARK: - JSON Structure
686             *============================================================================*/
687              
688             /**
689             An immutable document for reading JSON.
690             This document holds memory for all its JSON values and strings. When it is no
691             longer used, the user should call `yyjson_doc_free()` to free its memory.
692             */
693             typedef struct yyjson_doc yyjson_doc;
694              
695             /**
696             An immutable value for reading JSON.
697             A JSON Value has the same lifetime as its document. The memory is held by its
698             document and and cannot be freed alone.
699             */
700             typedef struct yyjson_val yyjson_val;
701              
702             /**
703             A mutable document for building JSON.
704             This document holds memory for all its JSON values and strings. When it is no
705             longer used, the user should call `yyjson_mut_doc_free()` to free its memory.
706             */
707             typedef struct yyjson_mut_doc yyjson_mut_doc;
708              
709             /**
710             A mutable value for building JSON.
711             A JSON Value has the same lifetime as its document. The memory is held by its
712             document and and cannot be freed alone.
713             */
714             typedef struct yyjson_mut_val yyjson_mut_val;
715              
716              
717              
718             /*==============================================================================
719             * MARK: - JSON Reader API
720             *============================================================================*/
721              
722             /** Run-time options for JSON reader. */
723             typedef uint32_t yyjson_read_flag;
724              
725             /** Default option (RFC 8259 compliant):
726             - Read positive integer as uint64_t.
727             - Read negative integer as int64_t.
728             - Read floating-point number as double with round-to-nearest mode.
729             - Read integer which cannot fit in uint64_t or int64_t as double.
730             - Report error if double number is infinity.
731             - Report error if string contains invalid UTF-8 character or BOM.
732             - Report error on trailing commas, comments, inf and nan literals. */
733             static const yyjson_read_flag YYJSON_READ_NOFLAG = 0;
734              
735             /** Read the input data in-situ.
736             This option allows the reader to modify and use input data to store string
737             values, which can increase reading speed slightly.
738             The caller should hold the input data before free the document.
739             The input data must be padded by at least `YYJSON_PADDING_SIZE` bytes.
740             For example: `[1,2]` should be `[1,2]\0\0\0\0`, input length should be 5. */
741             static const yyjson_read_flag YYJSON_READ_INSITU = 1 << 0;
742              
743             /** Stop when done instead of issuing an error if there's additional content
744             after a JSON document. This option may be used to parse small pieces of JSON
745             in larger data, such as `NDJSON`. */
746             static const yyjson_read_flag YYJSON_READ_STOP_WHEN_DONE = 1 << 1;
747              
748             /** Allow single trailing comma at the end of an object or array,
749             such as `[1,2,3,]`, `{"a":1,"b":2,}` (non-standard). */
750             static const yyjson_read_flag YYJSON_READ_ALLOW_TRAILING_COMMAS = 1 << 2;
751              
752             /** Allow C-style single-line and mult-line comments (non-standard). */
753             static const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS = 1 << 3;
754              
755             /** Allow inf/nan number and literal, case-insensitive,
756             such as 1e999, NaN, inf, -Infinity (non-standard). */
757             static const yyjson_read_flag YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4;
758              
759             /** Read all numbers as raw strings (value with `YYJSON_TYPE_RAW` type),
760             inf/nan literal is also read as raw with `ALLOW_INF_AND_NAN` flag. */
761             static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5;
762              
763             /** Allow reading invalid unicode when parsing string values (non-standard).
764             Invalid characters will be allowed to appear in the string values, but
765             invalid escape sequences will still be reported as errors.
766             This flag does not affect the performance of correctly encoded strings.
767              
768             @warning Strings in JSON values may contain incorrect encoding when this
769             option is used, you need to handle these strings carefully to avoid security
770             risks. */
771             static const yyjson_read_flag YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6;
772              
773             /** Read big numbers as raw strings. These big numbers include integers that
774             cannot be represented by `int64_t` and `uint64_t`, and floating-point
775             numbers that cannot be represented by finite `double`.
776             The flag will be overridden by `YYJSON_READ_NUMBER_AS_RAW` flag. */
777             static const yyjson_read_flag YYJSON_READ_BIGNUM_AS_RAW = 1 << 7;
778              
779             /** Allow UTF-8 BOM and skip it before parsing if any (non-standard). */
780             static const yyjson_read_flag YYJSON_READ_ALLOW_BOM = 1 << 8;
781              
782             /** Allow extended number formats (non-standard):
783             - Hexadecimal numbers, such as `0x7B`.
784             - Numbers with leading or trailing decimal point, such as `.123`, `123.`.
785             - Numbers with a leading plus sign, such as `+123`. */
786             static const yyjson_read_flag YYJSON_READ_ALLOW_EXT_NUMBER = 1 << 9;
787              
788             /** Allow extended escape sequences in strings (non-standard):
789             - Additional escapes: `\a`, `\e`, `\v`, ``\'``, `\?`, `\0`.
790             - Hex escapes: `\xNN`, such as `\x7B`.
791             - Line continuation: backslash followed by line terminator sequences.
792             - Unknown escape: if backslash is followed by an unsupported character,
793             the backslash will be removed and the character will be kept as-is.
794             However, `\1`-`\9` will still trigger an error. */
795             static const yyjson_read_flag YYJSON_READ_ALLOW_EXT_ESCAPE = 1 << 10;
796              
797             /** Allow extended whitespace characters (non-standard):
798             - Vertical tab `\v` and form feed `\f`.
799             - Line separator `\u2028` and paragraph separator `\u2029`.
800             - Non-breaking space `\xA0`.
801             - Byte order mark: `\uFEFF`.
802             - Other Unicode characters in the Zs (Separator, space) category. */
803             static const yyjson_read_flag YYJSON_READ_ALLOW_EXT_WHITESPACE = 1 << 11;
804              
805             /** Allow strings enclosed in single quotes (non-standard), such as ``'ab'``. */
806             static const yyjson_read_flag YYJSON_READ_ALLOW_SINGLE_QUOTED_STR = 1 << 12;
807              
808             /** Allow object keys without quotes (non-standard), such as `{a:1,b:2}`.
809             This extends the ECMAScript IdentifierName rule by allowing any
810             non-whitespace character with code point above `U+007F`. */
811             static const yyjson_read_flag YYJSON_READ_ALLOW_UNQUOTED_KEY = 1 << 13;
812              
813             /** Allow JSON5 format, see: [https://json5.org].
814             This flag supports all JSON5 features with some additional extensions:
815             - Accepts more escape sequences than JSON5 (e.g. `\a`, `\e`).
816             - Unquoted keys are not limited to ECMAScript IdentifierName.
817             - Allow case-insensitive `NaN`, `Inf` and `Infinity` literals. */
818             static const yyjson_read_flag YYJSON_READ_JSON5 =
819             (1 << 2) | /* YYJSON_READ_ALLOW_TRAILING_COMMAS */
820             (1 << 3) | /* YYJSON_READ_ALLOW_COMMENTS */
821             (1 << 4) | /* YYJSON_READ_ALLOW_INF_AND_NAN */
822             (1 << 9) | /* YYJSON_READ_ALLOW_EXT_NUMBER */
823             (1 << 10) | /* YYJSON_READ_ALLOW_EXT_ESCAPE */
824             (1 << 11) | /* YYJSON_READ_ALLOW_EXT_WHITESPACE */
825             (1 << 12) | /* YYJSON_READ_ALLOW_SINGLE_QUOTED_STR */
826             (1 << 13); /* YYJSON_READ_ALLOW_UNQUOTED_KEY */
827              
828              
829              
830             /** Result code for JSON reader. */
831             typedef uint32_t yyjson_read_code;
832              
833             /** Success, no error. */
834             static const yyjson_read_code YYJSON_READ_SUCCESS = 0;
835              
836             /** Invalid parameter, such as NULL input string or 0 input length. */
837             static const yyjson_read_code YYJSON_READ_ERROR_INVALID_PARAMETER = 1;
838              
839             /** Memory allocation failed. */
840             static const yyjson_read_code YYJSON_READ_ERROR_MEMORY_ALLOCATION = 2;
841              
842             /** Input JSON string is empty. */
843             static const yyjson_read_code YYJSON_READ_ERROR_EMPTY_CONTENT = 3;
844              
845             /** Unexpected content after document, such as `[123]abc`. */
846             static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CONTENT = 4;
847              
848             /** Unexpected end of input, the parsed part is valid, such as `[123`. */
849             static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_END = 5;
850              
851             /** Unexpected character inside the document, such as `[abc]`. */
852             static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CHARACTER = 6;
853              
854             /** Invalid JSON structure, such as `[1,]`. */
855             static const yyjson_read_code YYJSON_READ_ERROR_JSON_STRUCTURE = 7;
856              
857             /** Invalid comment, deprecated, use `UNEXPECTED_END` for unclosed comment. */
858             static const yyjson_read_code YYJSON_READ_ERROR_INVALID_COMMENT = 8;
859              
860             /** Invalid number, such as `123.e12`, `000`. */
861             static const yyjson_read_code YYJSON_READ_ERROR_INVALID_NUMBER = 9;
862              
863             /** Invalid string, such as invalid escaped character inside a string. */
864             static const yyjson_read_code YYJSON_READ_ERROR_INVALID_STRING = 10;
865              
866             /** Invalid JSON literal, such as `truu`. */
867             static const yyjson_read_code YYJSON_READ_ERROR_LITERAL = 11;
868              
869             /** Failed to open a file. */
870             static const yyjson_read_code YYJSON_READ_ERROR_FILE_OPEN = 12;
871              
872             /** Failed to read a file. */
873             static const yyjson_read_code YYJSON_READ_ERROR_FILE_READ = 13;
874              
875             /** Incomplete input during incremental parsing; parsing state is preserved. */
876             static const yyjson_read_code YYJSON_READ_ERROR_MORE = 14;
877              
878             /** Error information for JSON reader. */
879             typedef struct yyjson_read_err {
880             /** Error code, see `yyjson_read_code` for all possible values. */
881             yyjson_read_code code;
882             /** Error message, constant, no need to free (NULL if success). */
883             const char *msg;
884             /** Error byte position for input data (0 if success). */
885             size_t pos;
886             } yyjson_read_err;
887              
888              
889              
890             #if !defined(YYJSON_DISABLE_READER) || !YYJSON_DISABLE_READER
891              
892             /**
893             Read JSON with options.
894              
895             This function is thread-safe when:
896             1. The `dat` is not modified by other threads.
897             2. The `alc` is thread-safe or NULL.
898              
899             @param dat The JSON data (UTF-8 without BOM), null-terminator is not required.
900             If this parameter is NULL, the function will fail and return NULL.
901             The `dat` will not be modified without the flag `YYJSON_READ_INSITU`, so you
902             can pass a `const char *` string and case it to `char *` if you don't use
903             the `YYJSON_READ_INSITU` flag.
904             @param len The length of JSON data in bytes.
905             If this parameter is 0, the function will fail and return NULL.
906             @param flg The JSON read options.
907             Multiple options can be combined with `|` operator. 0 means no options.
908             @param alc The memory allocator used by JSON reader.
909             Pass NULL to use the libc's default allocator.
910             @param err A pointer to receive error information.
911             Pass NULL if you don't need error information.
912             @return A new JSON document, or NULL if an error occurs.
913             When it's no longer needed, it should be freed with `yyjson_doc_free()`.
914             */
915             yyjson_api yyjson_doc *yyjson_read_opts(char *dat,
916             size_t len,
917             yyjson_read_flag flg,
918             const yyjson_alc *alc,
919             yyjson_read_err *err);
920              
921             /**
922             Read a JSON file.
923              
924             This function is thread-safe when:
925             1. The file is not modified by other threads.
926             2. The `alc` is thread-safe or NULL.
927              
928             @param path The JSON file's path.
929             This should be a null-terminated string using the system's native encoding.
930             If this path is NULL or invalid, the function will fail and return NULL.
931             @param flg The JSON read options.
932             Multiple options can be combined with `|` operator. 0 means no options.
933             @param alc The memory allocator used by JSON reader.
934             Pass NULL to use the libc's default allocator.
935             @param err A pointer to receive error information.
936             Pass NULL if you don't need error information.
937             @return A new JSON document, or NULL if an error occurs.
938             When it's no longer needed, it should be freed with `yyjson_doc_free()`.
939              
940             @warning On 32-bit operating system, files larger than 2GB may fail to read.
941             */
942             yyjson_api yyjson_doc *yyjson_read_file(const char *path,
943             yyjson_read_flag flg,
944             const yyjson_alc *alc,
945             yyjson_read_err *err);
946              
947             /**
948             Read JSON from a file pointer.
949              
950             @param fp The file pointer.
951             The data will be read from the current position of the FILE to the end.
952             If this fp is NULL or invalid, the function will fail and return NULL.
953             @param flg The JSON read options.
954             Multiple options can be combined with `|` operator. 0 means no options.
955             @param alc The memory allocator used by JSON reader.
956             Pass NULL to use the libc's default allocator.
957             @param err A pointer to receive error information.
958             Pass NULL if you don't need error information.
959             @return A new JSON document, or NULL if an error occurs.
960             When it's no longer needed, it should be freed with `yyjson_doc_free()`.
961              
962             @warning On 32-bit operating system, files larger than 2GB may fail to read.
963             */
964             yyjson_api yyjson_doc *yyjson_read_fp(FILE *fp,
965             yyjson_read_flag flg,
966             const yyjson_alc *alc,
967             yyjson_read_err *err);
968              
969             /**
970             Read a JSON string.
971              
972             This function is thread-safe.
973              
974             @param dat The JSON data (UTF-8 without BOM), null-terminator is not required.
975             If this parameter is NULL, the function will fail and return NULL.
976             @param len The length of JSON data in bytes.
977             If this parameter is 0, the function will fail and return NULL.
978             @param flg The JSON read options.
979             Multiple options can be combined with `|` operator. 0 means no options.
980             @return A new JSON document, or NULL if an error occurs.
981             When it's no longer needed, it should be freed with `yyjson_doc_free()`.
982             */
983             yyjson_api_inline yyjson_doc *yyjson_read(const char *dat,
984             size_t len,
985             yyjson_read_flag flg) {
986 4           flg &= ~YYJSON_READ_INSITU; /* const string cannot be modified */
987 4           return yyjson_read_opts((char *)(void *)(size_t)(const void *)dat,
988             len, flg, NULL, NULL);
989             }
990              
991              
992              
993             #if !defined(YYJSON_DISABLE_INCR_READER) || !YYJSON_DISABLE_INCR_READER
994              
995             /** Opaque state for incremental JSON reader. */
996             typedef struct yyjson_incr_state yyjson_incr_state;
997              
998             /**
999             Initialize state for incremental read.
1000              
1001             To read a large JSON document incrementally:
1002             1. Call `yyjson_incr_new()` to create the state for incremental reading.
1003             2. Call `yyjson_incr_read()` repeatedly.
1004             3. Call `yyjson_incr_free()` to free the state.
1005              
1006             Note: The incremental JSON reader only supports standard JSON.
1007             Flags for non-standard features (e.g. comments, trailing commas) are ignored.
1008              
1009             @param buf The JSON data, null-terminator is not required.
1010             If this parameter is NULL, the function will fail and return NULL.
1011             @param buf_len The length of the JSON data in `buf`.
1012             If use `YYJSON_READ_INSITU`, `buf_len` should not include the padding size.
1013             @param flg The JSON read options.
1014             Multiple options can be combined with `|` operator.
1015             @param alc The memory allocator used by JSON reader.
1016             Pass NULL to use the libc's default allocator.
1017             @return A state for incremental reading.
1018             It should be freed with `yyjson_incr_free()`.
1019             NULL is returned if memory allocation fails.
1020             */
1021             yyjson_api yyjson_incr_state *yyjson_incr_new(char *buf, size_t buf_len,
1022             yyjson_read_flag flg,
1023             const yyjson_alc *alc);
1024              
1025             /**
1026             Performs incremental read of up to `len` bytes.
1027              
1028             If NULL is returned and `err->code` is set to `YYJSON_READ_ERROR_MORE`, it
1029             indicates that more data is required to continue parsing. Then, call this
1030             function again with incremented `len`. Continue until a document is returned or
1031             an error other than `YYJSON_READ_ERROR_MORE` is returned.
1032              
1033             Note: Parsing in very small increments is not efficient. An increment of
1034             several kilobytes or megabytes is recommended.
1035              
1036             @param state The state for incremental reading, created using
1037             `yyjson_incr_new()`.
1038             @param len The number of bytes of JSON data available to parse.
1039             If this parameter is 0, the function will fail and return NULL.
1040             @param err A pointer to receive error information.
1041             @return A new JSON document, or NULL if an error occurs.
1042             When the document is no longer needed, it should be freed with
1043             `yyjson_doc_free()`.
1044             */
1045             yyjson_api yyjson_doc *yyjson_incr_read(yyjson_incr_state *state, size_t len,
1046             yyjson_read_err *err);
1047              
1048             /** Release the incremental read state and free the memory. */
1049             yyjson_api void yyjson_incr_free(yyjson_incr_state *state);
1050              
1051             #endif /* YYJSON_DISABLE_INCR_READER */
1052              
1053             /**
1054             Returns the size of maximum memory usage to read a JSON data.
1055              
1056             You may use this value to avoid malloc() or calloc() call inside the reader
1057             to get better performance, or read multiple JSON with one piece of memory.
1058              
1059             @param len The length of JSON data in bytes.
1060             @param flg The JSON read options.
1061             @return The maximum memory size to read this JSON, or 0 if overflow.
1062              
1063             @b Example
1064             @code
1065             // read multiple JSON with same pre-allocated memory
1066              
1067             char *dat1, *dat2, *dat3; // JSON data
1068             size_t len1, len2, len3; // JSON length
1069             size_t max_len = MAX(len1, MAX(len2, len3));
1070             yyjson_doc *doc;
1071              
1072             // use one allocator for multiple JSON
1073             size_t size = yyjson_read_max_memory_usage(max_len, 0);
1074             void *buf = malloc(size);
1075             yyjson_alc alc;
1076             yyjson_alc_pool_init(&alc, buf, size);
1077              
1078             // no more alloc() or realloc() call during reading
1079             doc = yyjson_read_opts(dat1, len1, 0, &alc, NULL);
1080             yyjson_doc_free(doc);
1081             doc = yyjson_read_opts(dat2, len2, 0, &alc, NULL);
1082             yyjson_doc_free(doc);
1083             doc = yyjson_read_opts(dat3, len3, 0, &alc, NULL);
1084             yyjson_doc_free(doc);
1085              
1086             free(buf);
1087             @endcode
1088             @see yyjson_alc_pool_init()
1089             */
1090             yyjson_api_inline size_t yyjson_read_max_memory_usage(size_t len,
1091             yyjson_read_flag flg) {
1092             /*
1093             1. The max value count is (json_size / 2 + 1),
1094             for example: "[1,2,3,4]" size is 9, value count is 5.
1095             2. Some broken JSON may cost more memory during reading, but fail at end,
1096             for example: "[[[[[[[[".
1097             3. yyjson use 16 bytes per value, see struct yyjson_val.
1098             4. yyjson use dynamic memory with a growth factor of 1.5.
1099              
1100             The max memory size is (json_size / 2 * 16 * 1.5 + padding).
1101             */
1102             size_t mul = (size_t)12 + !(flg & YYJSON_READ_INSITU);
1103             size_t pad = 256;
1104             size_t max = (size_t)(~(size_t)0);
1105             if (flg & YYJSON_READ_STOP_WHEN_DONE) len = len < 256 ? 256 : len;
1106             if (len >= (max - pad - mul) / mul) return 0;
1107             return len * mul + pad;
1108             }
1109              
1110             /**
1111             Read a JSON number.
1112              
1113             This function is thread-safe when data is not modified by other threads.
1114              
1115             @param dat The JSON data (UTF-8 without BOM), null-terminator is required.
1116             If this parameter is NULL, the function will fail and return NULL.
1117             @param val The output value where result is stored.
1118             If this parameter is NULL, the function will fail and return NULL.
1119             The value will hold either UINT or SINT or REAL number;
1120             @param flg The JSON read options.
1121             Multiple options can be combined with `|` operator. 0 means no options.
1122             Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`.
1123             @param alc The memory allocator used for long number.
1124             It is only used when the built-in floating point reader is disabled.
1125             Pass NULL to use the libc's default allocator.
1126             @param err A pointer to receive error information.
1127             Pass NULL if you don't need error information.
1128             @return If successful, a pointer to the character after the last character
1129             used in the conversion, NULL if an error occurs.
1130             */
1131             yyjson_api const char *yyjson_read_number(const char *dat,
1132             yyjson_val *val,
1133             yyjson_read_flag flg,
1134             const yyjson_alc *alc,
1135             yyjson_read_err *err);
1136              
1137             /** Same as `yyjson_read_number()`. */
1138             yyjson_api_inline const char *yyjson_mut_read_number(const char *dat,
1139             yyjson_mut_val *val,
1140             yyjson_read_flag flg,
1141             const yyjson_alc *alc,
1142             yyjson_read_err *err) {
1143             return yyjson_read_number(dat, (yyjson_val *)val, flg, alc, err);
1144             }
1145              
1146             #endif /* YYJSON_DISABLE_READER) */
1147              
1148              
1149              
1150             /*==============================================================================
1151             * MARK: - JSON Writer API
1152             *============================================================================*/
1153              
1154             /** Run-time options for JSON writer. */
1155             typedef uint32_t yyjson_write_flag;
1156              
1157             /** Default option:
1158             - Write JSON minify.
1159             - Report error on inf or nan number.
1160             - Report error on invalid UTF-8 string.
1161             - Do not escape unicode or slash. */
1162             static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0;
1163              
1164             /** Write JSON pretty with 4 space indent. */
1165             static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0;
1166              
1167             /** Escape unicode as `uXXXX`, make the output ASCII only. */
1168             static const yyjson_write_flag YYJSON_WRITE_ESCAPE_UNICODE = 1 << 1;
1169              
1170             /** Escape '/' as '\/'. */
1171             static const yyjson_write_flag YYJSON_WRITE_ESCAPE_SLASHES = 1 << 2;
1172              
1173             /** Write inf and nan number as 'Infinity' and 'NaN' literal (non-standard). */
1174             static const yyjson_write_flag YYJSON_WRITE_ALLOW_INF_AND_NAN = 1 << 3;
1175              
1176             /** Write inf and nan number as null literal.
1177             This flag will override `YYJSON_WRITE_ALLOW_INF_AND_NAN` flag. */
1178             static const yyjson_write_flag YYJSON_WRITE_INF_AND_NAN_AS_NULL = 1 << 4;
1179              
1180             /** Allow invalid unicode when encoding string values (non-standard).
1181             Invalid characters in string value will be copied byte by byte.
1182             If `YYJSON_WRITE_ESCAPE_UNICODE` flag is also set, invalid character will be
1183             escaped as `U+FFFD` (replacement character).
1184             This flag does not affect the performance of correctly encoded strings. */
1185             static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5;
1186              
1187             /** Write JSON pretty with 2 space indent.
1188             This flag will override `YYJSON_WRITE_PRETTY` flag. */
1189             static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6;
1190              
1191             /** Adds a newline character `\n` at the end of the JSON.
1192             This can be helpful for text editors or NDJSON. */
1193             static const yyjson_write_flag YYJSON_WRITE_NEWLINE_AT_END = 1 << 7;
1194              
1195              
1196              
1197             /** The highest 8 bits of `yyjson_write_flag` and real number value's `tag`
1198             are reserved for controlling the output format of floating-point numbers. */
1199             #define YYJSON_WRITE_FP_FLAG_BITS 8
1200              
1201             /** The highest 4 bits of flag are reserved for precision value. */
1202             #define YYJSON_WRITE_FP_PREC_BITS 4
1203              
1204             /** Write floating-point number using fixed-point notation.
1205             - This is similar to ECMAScript `Number.prototype.toFixed(prec)`,
1206             but with trailing zeros removed. The `prec` ranges from 1 to 15.
1207             - This will produce shorter output but may lose some precision. */
1208             #define YYJSON_WRITE_FP_TO_FIXED(prec) ((yyjson_write_flag)( \
1209             (uint32_t)((uint32_t)(prec)) << (32 - 4) ))
1210              
1211             /** Write floating-point numbers using single-precision (float).
1212             - This casts `double` to `float` before serialization.
1213             - This will produce shorter output, but may lose some precision.
1214             - This flag is ignored if `YYJSON_WRITE_FP_TO_FIXED(prec)` is also used. */
1215             #define YYJSON_WRITE_FP_TO_FLOAT ((yyjson_write_flag)(1 << (32 - 5)))
1216              
1217              
1218              
1219             /** Result code for JSON writer */
1220             typedef uint32_t yyjson_write_code;
1221              
1222             /** Success, no error. */
1223             static const yyjson_write_code YYJSON_WRITE_SUCCESS = 0;
1224              
1225             /** Invalid parameter, such as NULL document. */
1226             static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_PARAMETER = 1;
1227              
1228             /** Memory allocation failure occurs. */
1229             static const yyjson_write_code YYJSON_WRITE_ERROR_MEMORY_ALLOCATION = 2;
1230              
1231             /** Invalid value type in JSON document. */
1232             static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_VALUE_TYPE = 3;
1233              
1234             /** NaN or Infinity number occurs. */
1235             static const yyjson_write_code YYJSON_WRITE_ERROR_NAN_OR_INF = 4;
1236              
1237             /** Failed to open a file. */
1238             static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_OPEN = 5;
1239              
1240             /** Failed to write a file. */
1241             static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_WRITE = 6;
1242              
1243             /** Invalid unicode in string. */
1244             static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_STRING = 7;
1245              
1246             /** Error information for JSON writer. */
1247             typedef struct yyjson_write_err {
1248             /** Error code, see `yyjson_write_code` for all possible values. */
1249             yyjson_write_code code;
1250             /** Error message, constant, no need to free (NULL if success). */
1251             const char *msg;
1252             } yyjson_write_err;
1253              
1254              
1255              
1256             #if !defined(YYJSON_DISABLE_WRITER) || !YYJSON_DISABLE_WRITER
1257              
1258             /*==============================================================================
1259             * MARK: - JSON Document Writer API
1260             *============================================================================*/
1261              
1262             /**
1263             Write a document to JSON string with options.
1264              
1265             This function is thread-safe when:
1266             The `alc` is thread-safe or NULL.
1267              
1268             @param doc The JSON document.
1269             If this doc is NULL or has no root, the function will fail and return false.
1270             @param flg The JSON write options.
1271             Multiple options can be combined with `|` operator. 0 means no options.
1272             @param alc The memory allocator used by JSON writer.
1273             Pass NULL to use the libc's default allocator.
1274             @param len A pointer to receive output length in bytes (not including the
1275             null-terminator). Pass NULL if you don't need length information.
1276             @param err A pointer to receive error information.
1277             Pass NULL if you don't need error information.
1278             @return A new JSON string, or NULL if an error occurs.
1279             This string is encoded as UTF-8 with a null-terminator.
1280             When it's no longer needed, it should be freed with free() or alc->free().
1281             */
1282             yyjson_api char *yyjson_write_opts(const yyjson_doc *doc,
1283             yyjson_write_flag flg,
1284             const yyjson_alc *alc,
1285             size_t *len,
1286             yyjson_write_err *err);
1287              
1288             /**
1289             Write a document to JSON file with options.
1290              
1291             This function is thread-safe when:
1292             1. The file is not accessed by other threads.
1293             2. The `alc` is thread-safe or NULL.
1294              
1295             @param path The JSON file's path.
1296             This should be a null-terminated string using the system's native encoding.
1297             If this path is NULL or invalid, the function will fail and return false.
1298             If this file is not empty, the content will be discarded.
1299             @param doc The JSON document.
1300             If this doc is NULL or has no root, the function will fail and return false.
1301             @param flg The JSON write options.
1302             Multiple options can be combined with `|` operator. 0 means no options.
1303             @param alc The memory allocator used by JSON writer.
1304             Pass NULL to use the libc's default allocator.
1305             @param err A pointer to receive error information.
1306             Pass NULL if you don't need error information.
1307             @return true if successful, false if an error occurs.
1308              
1309             @warning On 32-bit operating system, files larger than 2GB may fail to write.
1310             */
1311             yyjson_api bool yyjson_write_file(const char *path,
1312             const yyjson_doc *doc,
1313             yyjson_write_flag flg,
1314             const yyjson_alc *alc,
1315             yyjson_write_err *err);
1316              
1317             /**
1318             Write a document to file pointer with options.
1319              
1320             @param fp The file pointer.
1321             The data will be written to the current position of the file.
1322             If this fp is NULL or invalid, the function will fail and return false.
1323             @param doc The JSON document.
1324             If this doc is NULL or has no root, the function will fail and return false.
1325             @param flg The JSON write options.
1326             Multiple options can be combined with `|` operator. 0 means no options.
1327             @param alc The memory allocator used by JSON writer.
1328             Pass NULL to use the libc's default allocator.
1329             @param err A pointer to receive error information.
1330             Pass NULL if you don't need error information.
1331             @return true if successful, false if an error occurs.
1332              
1333             @warning On 32-bit operating system, files larger than 2GB may fail to write.
1334             */
1335             yyjson_api bool yyjson_write_fp(FILE *fp,
1336             const yyjson_doc *doc,
1337             yyjson_write_flag flg,
1338             const yyjson_alc *alc,
1339             yyjson_write_err *err);
1340              
1341             /**
1342             Write a document to JSON string.
1343              
1344             This function is thread-safe.
1345              
1346             @param doc The JSON document.
1347             If this doc is NULL or has no root, the function will fail and return false.
1348             @param flg The JSON write options.
1349             Multiple options can be combined with `|` operator. 0 means no options.
1350             @param len A pointer to receive output length in bytes (not including the
1351             null-terminator). Pass NULL if you don't need length information.
1352             @return A new JSON string, or NULL if an error occurs.
1353             This string is encoded as UTF-8 with a null-terminator.
1354             When it's no longer needed, it should be freed with free().
1355             */
1356             yyjson_api_inline char *yyjson_write(const yyjson_doc *doc,
1357             yyjson_write_flag flg,
1358             size_t *len) {
1359             return yyjson_write_opts(doc, flg, NULL, len, NULL);
1360             }
1361              
1362              
1363              
1364             /**
1365             Write a document to JSON string with options.
1366              
1367             This function is thread-safe when:
1368             1. The `doc` is not modified by other threads.
1369             2. The `alc` is thread-safe or NULL.
1370              
1371             @param doc The mutable JSON document.
1372             If this doc is NULL or has no root, the function will fail and return false.
1373             @param flg The JSON write options.
1374             Multiple options can be combined with `|` operator. 0 means no options.
1375             @param alc The memory allocator used by JSON writer.
1376             Pass NULL to use the libc's default allocator.
1377             @param len A pointer to receive output length in bytes (not including the
1378             null-terminator). Pass NULL if you don't need length information.
1379             @param err A pointer to receive error information.
1380             Pass NULL if you don't need error information.
1381             @return A new JSON string, or NULL if an error occurs.
1382             This string is encoded as UTF-8 with a null-terminator.
1383             When it's no longer needed, it should be freed with free() or alc->free().
1384             */
1385             yyjson_api char *yyjson_mut_write_opts(const yyjson_mut_doc *doc,
1386             yyjson_write_flag flg,
1387             const yyjson_alc *alc,
1388             size_t *len,
1389             yyjson_write_err *err);
1390              
1391             /**
1392             Write a document to JSON file with options.
1393              
1394             This function is thread-safe when:
1395             1. The file is not accessed by other threads.
1396             2. The `doc` is not modified by other threads.
1397             3. The `alc` is thread-safe or NULL.
1398              
1399             @param path The JSON file's path.
1400             This should be a null-terminated string using the system's native encoding.
1401             If this path is NULL or invalid, the function will fail and return false.
1402             If this file is not empty, the content will be discarded.
1403             @param doc The mutable JSON document.
1404             If this doc is NULL or has no root, the function will fail and return false.
1405             @param flg The JSON write options.
1406             Multiple options can be combined with `|` operator. 0 means no options.
1407             @param alc The memory allocator used by JSON writer.
1408             Pass NULL to use the libc's default allocator.
1409             @param err A pointer to receive error information.
1410             Pass NULL if you don't need error information.
1411             @return true if successful, false if an error occurs.
1412              
1413             @warning On 32-bit operating system, files larger than 2GB may fail to write.
1414             */
1415             yyjson_api bool yyjson_mut_write_file(const char *path,
1416             const yyjson_mut_doc *doc,
1417             yyjson_write_flag flg,
1418             const yyjson_alc *alc,
1419             yyjson_write_err *err);
1420              
1421             /**
1422             Write a document to file pointer with options.
1423              
1424             @param fp The file pointer.
1425             The data will be written to the current position of the file.
1426             If this fp is NULL or invalid, the function will fail and return false.
1427             @param doc The mutable JSON document.
1428             If this doc is NULL or has no root, the function will fail and return false.
1429             @param flg The JSON write options.
1430             Multiple options can be combined with `|` operator. 0 means no options.
1431             @param alc The memory allocator used by JSON writer.
1432             Pass NULL to use the libc's default allocator.
1433             @param err A pointer to receive error information.
1434             Pass NULL if you don't need error information.
1435             @return true if successful, false if an error occurs.
1436              
1437             @warning On 32-bit operating system, files larger than 2GB may fail to write.
1438             */
1439             yyjson_api bool yyjson_mut_write_fp(FILE *fp,
1440             const yyjson_mut_doc *doc,
1441             yyjson_write_flag flg,
1442             const yyjson_alc *alc,
1443             yyjson_write_err *err);
1444              
1445             /**
1446             Write a document to JSON string.
1447              
1448             This function is thread-safe when:
1449             The `doc` is not modified by other threads.
1450              
1451             @param doc The JSON document.
1452             If this doc is NULL or has no root, the function will fail and return false.
1453             @param flg The JSON write options.
1454             Multiple options can be combined with `|` operator. 0 means no options.
1455             @param len A pointer to receive output length in bytes (not including the
1456             null-terminator). Pass NULL if you don't need length information.
1457             @return A new JSON string, or NULL if an error occurs.
1458             This string is encoded as UTF-8 with a null-terminator.
1459             When it's no longer needed, it should be freed with free().
1460             */
1461             yyjson_api_inline char *yyjson_mut_write(const yyjson_mut_doc *doc,
1462             yyjson_write_flag flg,
1463             size_t *len) {
1464             return yyjson_mut_write_opts(doc, flg, NULL, len, NULL);
1465             }
1466              
1467              
1468              
1469             /*==============================================================================
1470             * MARK: - JSON Value Writer API
1471             *============================================================================*/
1472              
1473             /**
1474             Write a value to JSON string with options.
1475              
1476             This function is thread-safe when:
1477             The `alc` is thread-safe or NULL.
1478              
1479             @param val The JSON root value.
1480             If this parameter is NULL, the function will fail and return NULL.
1481             @param flg The JSON write options.
1482             Multiple options can be combined with `|` operator. 0 means no options.
1483             @param alc The memory allocator used by JSON writer.
1484             Pass NULL to use the libc's default allocator.
1485             @param len A pointer to receive output length in bytes (not including the
1486             null-terminator). Pass NULL if you don't need length information.
1487             @param err A pointer to receive error information.
1488             Pass NULL if you don't need error information.
1489             @return A new JSON string, or NULL if an error occurs.
1490             This string is encoded as UTF-8 with a null-terminator.
1491             When it's no longer needed, it should be freed with free() or alc->free().
1492             */
1493             yyjson_api char *yyjson_val_write_opts(const yyjson_val *val,
1494             yyjson_write_flag flg,
1495             const yyjson_alc *alc,
1496             size_t *len,
1497             yyjson_write_err *err);
1498              
1499             /**
1500             Write a value to JSON file with options.
1501              
1502             This function is thread-safe when:
1503             1. The file is not accessed by other threads.
1504             2. The `alc` is thread-safe or NULL.
1505              
1506             @param path The JSON file's path.
1507             This should be a null-terminated string using the system's native encoding.
1508             If this path is NULL or invalid, the function will fail and return false.
1509             If this file is not empty, the content will be discarded.
1510             @param val The JSON root value.
1511             If this parameter is NULL, the function will fail and return NULL.
1512             @param flg The JSON write options.
1513             Multiple options can be combined with `|` operator. 0 means no options.
1514             @param alc The memory allocator used by JSON writer.
1515             Pass NULL to use the libc's default allocator.
1516             @param err A pointer to receive error information.
1517             Pass NULL if you don't need error information.
1518             @return true if successful, false if an error occurs.
1519              
1520             @warning On 32-bit operating system, files larger than 2GB may fail to write.
1521             */
1522             yyjson_api bool yyjson_val_write_file(const char *path,
1523             const yyjson_val *val,
1524             yyjson_write_flag flg,
1525             const yyjson_alc *alc,
1526             yyjson_write_err *err);
1527              
1528             /**
1529             Write a value to file pointer with options.
1530              
1531             @param fp The file pointer.
1532             The data will be written to the current position of the file.
1533             If this path is NULL or invalid, the function will fail and return false.
1534             @param val The JSON root value.
1535             If this parameter is NULL, the function will fail and return NULL.
1536             @param flg The JSON write options.
1537             Multiple options can be combined with `|` operator. 0 means no options.
1538             @param alc The memory allocator used by JSON writer.
1539             Pass NULL to use the libc's default allocator.
1540             @param err A pointer to receive error information.
1541             Pass NULL if you don't need error information.
1542             @return true if successful, false if an error occurs.
1543              
1544             @warning On 32-bit operating system, files larger than 2GB may fail to write.
1545             */
1546             yyjson_api bool yyjson_val_write_fp(FILE *fp,
1547             const yyjson_val *val,
1548             yyjson_write_flag flg,
1549             const yyjson_alc *alc,
1550             yyjson_write_err *err);
1551              
1552             /**
1553             Write a value to JSON string.
1554              
1555             This function is thread-safe.
1556              
1557             @param val The JSON root value.
1558             If this parameter is NULL, the function will fail and return NULL.
1559             @param flg The JSON write options.
1560             Multiple options can be combined with `|` operator. 0 means no options.
1561             @param len A pointer to receive output length in bytes (not including the
1562             null-terminator). Pass NULL if you don't need length information.
1563             @return A new JSON string, or NULL if an error occurs.
1564             This string is encoded as UTF-8 with a null-terminator.
1565             When it's no longer needed, it should be freed with free().
1566             */
1567             yyjson_api_inline char *yyjson_val_write(const yyjson_val *val,
1568             yyjson_write_flag flg,
1569             size_t *len) {
1570             return yyjson_val_write_opts(val, flg, NULL, len, NULL);
1571             }
1572              
1573             /**
1574             Write a value to JSON string with options.
1575              
1576             This function is thread-safe when:
1577             1. The `val` is not modified by other threads.
1578             2. The `alc` is thread-safe or NULL.
1579              
1580             @param val The mutable JSON root value.
1581             If this parameter is NULL, the function will fail and return NULL.
1582             @param flg The JSON write options.
1583             Multiple options can be combined with `|` operator. 0 means no options.
1584             @param alc The memory allocator used by JSON writer.
1585             Pass NULL to use the libc's default allocator.
1586             @param len A pointer to receive output length in bytes (not including the
1587             null-terminator). Pass NULL if you don't need length information.
1588             @param err A pointer to receive error information.
1589             Pass NULL if you don't need error information.
1590             @return A new JSON string, or NULL if an error occurs.
1591             This string is encoded as UTF-8 with a null-terminator.
1592             When it's no longer needed, it should be freed with free() or alc->free().
1593             */
1594             yyjson_api char *yyjson_mut_val_write_opts(const yyjson_mut_val *val,
1595             yyjson_write_flag flg,
1596             const yyjson_alc *alc,
1597             size_t *len,
1598             yyjson_write_err *err);
1599              
1600             /**
1601             Write a value to JSON file with options.
1602              
1603             This function is thread-safe when:
1604             1. The file is not accessed by other threads.
1605             2. The `val` is not modified by other threads.
1606             3. The `alc` is thread-safe or NULL.
1607              
1608             @param path The JSON file's path.
1609             This should be a null-terminated string using the system's native encoding.
1610             If this path is NULL or invalid, the function will fail and return false.
1611             If this file is not empty, the content will be discarded.
1612             @param val The mutable JSON root value.
1613             If this parameter is NULL, the function will fail and return NULL.
1614             @param flg The JSON write options.
1615             Multiple options can be combined with `|` operator. 0 means no options.
1616             @param alc The memory allocator used by JSON writer.
1617             Pass NULL to use the libc's default allocator.
1618             @param err A pointer to receive error information.
1619             Pass NULL if you don't need error information.
1620             @return true if successful, false if an error occurs.
1621              
1622             @warning On 32-bit operating system, files larger than 2GB may fail to write.
1623             */
1624             yyjson_api bool yyjson_mut_val_write_file(const char *path,
1625             const yyjson_mut_val *val,
1626             yyjson_write_flag flg,
1627             const yyjson_alc *alc,
1628             yyjson_write_err *err);
1629              
1630             /**
1631             Write a value to JSON file with options.
1632              
1633             @param fp The file pointer.
1634             The data will be written to the current position of the file.
1635             If this path is NULL or invalid, the function will fail and return false.
1636             @param val The mutable JSON root value.
1637             If this parameter is NULL, the function will fail and return NULL.
1638             @param flg The JSON write options.
1639             Multiple options can be combined with `|` operator. 0 means no options.
1640             @param alc The memory allocator used by JSON writer.
1641             Pass NULL to use the libc's default allocator.
1642             @param err A pointer to receive error information.
1643             Pass NULL if you don't need error information.
1644             @return true if successful, false if an error occurs.
1645              
1646             @warning On 32-bit operating system, files larger than 2GB may fail to write.
1647             */
1648             yyjson_api bool yyjson_mut_val_write_fp(FILE *fp,
1649             const yyjson_mut_val *val,
1650             yyjson_write_flag flg,
1651             const yyjson_alc *alc,
1652             yyjson_write_err *err);
1653              
1654             /**
1655             Write a value to JSON string.
1656              
1657             This function is thread-safe when:
1658             The `val` is not modified by other threads.
1659              
1660             @param val The JSON root value.
1661             If this parameter is NULL, the function will fail and return NULL.
1662             @param flg The JSON write options.
1663             Multiple options can be combined with `|` operator. 0 means no options.
1664             @param len A pointer to receive output length in bytes (not including the
1665             null-terminator). Pass NULL if you don't need length information.
1666             @return A new JSON string, or NULL if an error occurs.
1667             This string is encoded as UTF-8 with a null-terminator.
1668             When it's no longer needed, it should be freed with free().
1669             */
1670             yyjson_api_inline char *yyjson_mut_val_write(const yyjson_mut_val *val,
1671             yyjson_write_flag flg,
1672             size_t *len) {
1673             return yyjson_mut_val_write_opts(val, flg, NULL, len, NULL);
1674             }
1675              
1676             /**
1677             Write a JSON number.
1678              
1679             @param val A JSON number value to be converted to a string.
1680             If this parameter is invalid, the function will fail and return NULL.
1681             @param buf A buffer to store the resulting null-terminated string.
1682             If this parameter is NULL, the function will fail and return NULL.
1683             For integer values, the buffer must be at least 21 bytes.
1684             For floating-point values, the buffer must be at least 40 bytes.
1685             @return On success, returns a pointer to the character after the last
1686             written character. On failure, returns NULL.
1687             @note
1688             - This function is thread-safe and does not allocate memory
1689             (when `YYJSON_DISABLE_FAST_FP_CONV` is not defined).
1690             - This function will fail and return NULL only in the following cases:
1691             1) `val` or `buf` is NULL;
1692             2) `val` is not a number type;
1693             3) `val` is `inf` or `nan`, and non-standard JSON is explicitly disabled
1694             via the `YYJSON_DISABLE_NON_STANDARD` flag.
1695             */
1696             yyjson_api char *yyjson_write_number(const yyjson_val *val, char *buf);
1697              
1698             /** Same as `yyjson_write_number()`. */
1699             yyjson_api_inline char *yyjson_mut_write_number(const yyjson_mut_val *val,
1700             char *buf) {
1701             return yyjson_write_number((const yyjson_val *)val, buf);
1702             }
1703              
1704             #endif /* YYJSON_DISABLE_WRITER */
1705              
1706              
1707              
1708             /*==============================================================================
1709             * MARK: - JSON Document API
1710             *============================================================================*/
1711              
1712             /** Returns the root value of this JSON document.
1713             Returns NULL if `doc` is NULL. */
1714             yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc);
1715              
1716             /** Returns read size of input JSON data.
1717             Returns 0 if `doc` is NULL.
1718             For example: the read size of `[1,2,3]` is 7 bytes. */
1719             yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc);
1720              
1721             /** Returns total value count in this JSON document.
1722             Returns 0 if `doc` is NULL.
1723             For example: the value count of `[1,2,3]` is 4. */
1724             yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc);
1725              
1726             /** Release the JSON document and free the memory.
1727             After calling this function, the `doc` and all values from the `doc` are no
1728             longer available. This function will do nothing if the `doc` is NULL. */
1729             yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc);
1730              
1731              
1732              
1733             /*==============================================================================
1734             * MARK: - JSON Value Type API
1735             *============================================================================*/
1736              
1737             /** Returns whether the JSON value is raw.
1738             Returns false if `val` is NULL. */
1739             yyjson_api_inline bool yyjson_is_raw(yyjson_val *val);
1740              
1741             /** Returns whether the JSON value is `null`.
1742             Returns false if `val` is NULL. */
1743             yyjson_api_inline bool yyjson_is_null(yyjson_val *val);
1744              
1745             /** Returns whether the JSON value is `true`.
1746             Returns false if `val` is NULL. */
1747             yyjson_api_inline bool yyjson_is_true(yyjson_val *val);
1748              
1749             /** Returns whether the JSON value is `false`.
1750             Returns false if `val` is NULL. */
1751             yyjson_api_inline bool yyjson_is_false(yyjson_val *val);
1752              
1753             /** Returns whether the JSON value is bool (true/false).
1754             Returns false if `val` is NULL. */
1755             yyjson_api_inline bool yyjson_is_bool(yyjson_val *val);
1756              
1757             /** Returns whether the JSON value is unsigned integer (uint64_t).
1758             Returns false if `val` is NULL. */
1759             yyjson_api_inline bool yyjson_is_uint(yyjson_val *val);
1760              
1761             /** Returns whether the JSON value is signed integer (int64_t).
1762             Returns false if `val` is NULL. */
1763             yyjson_api_inline bool yyjson_is_sint(yyjson_val *val);
1764              
1765             /** Returns whether the JSON value is integer (uint64_t/int64_t).
1766             Returns false if `val` is NULL. */
1767             yyjson_api_inline bool yyjson_is_int(yyjson_val *val);
1768              
1769             /** Returns whether the JSON value is real number (double).
1770             Returns false if `val` is NULL. */
1771             yyjson_api_inline bool yyjson_is_real(yyjson_val *val);
1772              
1773             /** Returns whether the JSON value is number (uint64_t/int64_t/double).
1774             Returns false if `val` is NULL. */
1775             yyjson_api_inline bool yyjson_is_num(yyjson_val *val);
1776              
1777             /** Returns whether the JSON value is string.
1778             Returns false if `val` is NULL. */
1779             yyjson_api_inline bool yyjson_is_str(yyjson_val *val);
1780              
1781             /** Returns whether the JSON value is array.
1782             Returns false if `val` is NULL. */
1783             yyjson_api_inline bool yyjson_is_arr(yyjson_val *val);
1784              
1785             /** Returns whether the JSON value is object.
1786             Returns false if `val` is NULL. */
1787             yyjson_api_inline bool yyjson_is_obj(yyjson_val *val);
1788              
1789             /** Returns whether the JSON value is container (array/object).
1790             Returns false if `val` is NULL. */
1791             yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val);
1792              
1793              
1794              
1795             /*==============================================================================
1796             * MARK: - JSON Value Content API
1797             *============================================================================*/
1798              
1799             /** Returns the JSON value's type.
1800             Returns YYJSON_TYPE_NONE if `val` is NULL. */
1801             yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val);
1802              
1803             /** Returns the JSON value's subtype.
1804             Returns YYJSON_SUBTYPE_NONE if `val` is NULL. */
1805             yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val);
1806              
1807             /** Returns the JSON value's tag.
1808             Returns 0 if `val` is NULL. */
1809             yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val);
1810              
1811             /** Returns the JSON value's type description.
1812             The return value should be one of these strings: "raw", "null", "string",
1813             "array", "object", "true", "false", "uint", "sint", "real", "unknown". */
1814             yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val);
1815              
1816             /** Returns the content if the value is raw.
1817             Returns NULL if `val` is NULL or type is not raw. */
1818             yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val);
1819              
1820             /** Returns the content if the value is bool.
1821             Returns false if `val` is NULL or type is not bool. */
1822             yyjson_api_inline bool yyjson_get_bool(yyjson_val *val);
1823              
1824             /** Returns the content and cast to uint64_t.
1825             Returns 0 if `val` is NULL or type is not integer(sint/uint). */
1826             yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val);
1827              
1828             /** Returns the content and cast to int64_t.
1829             Returns 0 if `val` is NULL or type is not integer(sint/uint). */
1830             yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val);
1831              
1832             /** Returns the content and cast to int.
1833             Returns 0 if `val` is NULL or type is not integer(sint/uint). */
1834             yyjson_api_inline int yyjson_get_int(yyjson_val *val);
1835              
1836             /** Returns the content if the value is real number, or 0.0 on error.
1837             Returns 0.0 if `val` is NULL or type is not real(double). */
1838             yyjson_api_inline double yyjson_get_real(yyjson_val *val);
1839              
1840             /** Returns the content and typecast to `double` if the value is number.
1841             Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */
1842             yyjson_api_inline double yyjson_get_num(yyjson_val *val);
1843              
1844             /** Returns the content if the value is string.
1845             Returns NULL if `val` is NULL or type is not string. */
1846             yyjson_api_inline const char *yyjson_get_str(yyjson_val *val);
1847              
1848             /** Returns the content length (string length, array size, object size.
1849             Returns 0 if `val` is NULL or type is not string/array/object. */
1850             yyjson_api_inline size_t yyjson_get_len(yyjson_val *val);
1851              
1852             /** Returns whether the JSON value is equals to a string.
1853             Returns false if input is NULL or type is not string. */
1854             yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str);
1855              
1856             /** Returns whether the JSON value is equals to a string.
1857             The `str` should be a UTF-8 string, null-terminator is not required.
1858             Returns false if input is NULL or type is not string. */
1859             yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str,
1860             size_t len);
1861              
1862             /** Returns whether two JSON values are equal (deep compare).
1863             Returns false if input is NULL.
1864             @note the result may be inaccurate if object has duplicate keys.
1865             @warning This function is recursive and may cause a stack overflow
1866             if the object level is too deep. */
1867             yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs);
1868              
1869             /** Set the value to raw.
1870             Returns false if input is NULL or `val` is object or array.
1871             @warning This will modify the `immutable` value, use with caution. */
1872             yyjson_api_inline bool yyjson_set_raw(yyjson_val *val,
1873             const char *raw, size_t len);
1874              
1875             /** Set the value to null.
1876             Returns false if input is NULL or `val` is object or array.
1877             @warning This will modify the `immutable` value, use with caution. */
1878             yyjson_api_inline bool yyjson_set_null(yyjson_val *val);
1879              
1880             /** Set the value to bool.
1881             Returns false if input is NULL or `val` is object or array.
1882             @warning This will modify the `immutable` value, use with caution. */
1883             yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num);
1884              
1885             /** Set the value to uint.
1886             Returns false if input is NULL or `val` is object or array.
1887             @warning This will modify the `immutable` value, use with caution. */
1888             yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num);
1889              
1890             /** Set the value to sint.
1891             Returns false if input is NULL or `val` is object or array.
1892             @warning This will modify the `immutable` value, use with caution. */
1893             yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num);
1894              
1895             /** Set the value to int.
1896             Returns false if input is NULL or `val` is object or array.
1897             @warning This will modify the `immutable` value, use with caution. */
1898             yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num);
1899              
1900             /** Set the value to float.
1901             Returns false if input is NULL or `val` is object or array.
1902             @warning This will modify the `immutable` value, use with caution. */
1903             yyjson_api_inline bool yyjson_set_float(yyjson_val *val, float num);
1904              
1905             /** Set the value to double.
1906             Returns false if input is NULL or `val` is object or array.
1907             @warning This will modify the `immutable` value, use with caution. */
1908             yyjson_api_inline bool yyjson_set_double(yyjson_val *val, double num);
1909              
1910             /** Set the value to real.
1911             Returns false if input is NULL or `val` is object or array.
1912             @warning This will modify the `immutable` value, use with caution. */
1913             yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num);
1914              
1915             /** Set the floating-point number's output format to fixed-point notation.
1916             Returns false if input is NULL or `val` is not real type.
1917             @see YYJSON_WRITE_FP_TO_FIXED flag.
1918             @warning This will modify the `immutable` value, use with caution. */
1919             yyjson_api_inline bool yyjson_set_fp_to_fixed(yyjson_val *val, int prec);
1920              
1921             /** Set the floating-point number's output format to single-precision.
1922             Returns false if input is NULL or `val` is not real type.
1923             @see YYJSON_WRITE_FP_TO_FLOAT flag.
1924             @warning This will modify the `immutable` value, use with caution. */
1925             yyjson_api_inline bool yyjson_set_fp_to_float(yyjson_val *val, bool flt);
1926              
1927             /** Set the value to string (null-terminated).
1928             Returns false if input is NULL or `val` is object or array.
1929             @warning This will modify the `immutable` value, use with caution. */
1930             yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str);
1931              
1932             /** Set the value to string (with length).
1933             Returns false if input is NULL or `val` is object or array.
1934             @warning This will modify the `immutable` value, use with caution. */
1935             yyjson_api_inline bool yyjson_set_strn(yyjson_val *val,
1936             const char *str, size_t len);
1937              
1938             /** Marks this string as not needing to be escaped during JSON writing.
1939             This can be used to avoid the overhead of escaping if the string contains
1940             only characters that do not require escaping.
1941             Returns false if input is NULL or `val` is not string.
1942             @see YYJSON_SUBTYPE_NOESC subtype.
1943             @warning This will modify the `immutable` value, use with caution. */
1944             yyjson_api_inline bool yyjson_set_str_noesc(yyjson_val *val, bool noesc);
1945              
1946              
1947              
1948             /*==============================================================================
1949             * MARK: - JSON Array API
1950             *============================================================================*/
1951              
1952             /** Returns the number of elements in this array.
1953             Returns 0 if `arr` is NULL or type is not array. */
1954             yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr);
1955              
1956             /** Returns the element at the specified position in this array.
1957             Returns NULL if array is NULL/empty or the index is out of bounds.
1958             @warning This function takes a linear search time if array is not flat.
1959             For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat. */
1960             yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx);
1961              
1962             /** Returns the first element of this array.
1963             Returns NULL if `arr` is NULL/empty or type is not array. */
1964             yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr);
1965              
1966             /** Returns the last element of this array.
1967             Returns NULL if `arr` is NULL/empty or type is not array.
1968             @warning This function takes a linear search time if array is not flat.
1969             For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat.*/
1970             yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr);
1971              
1972              
1973              
1974             /*==============================================================================
1975             * MARK: - JSON Array Iterator API
1976             *============================================================================*/
1977              
1978             /**
1979             A JSON array iterator.
1980              
1981             @b Example
1982             @code
1983             yyjson_val *val;
1984             yyjson_arr_iter iter = yyjson_arr_iter_with(arr);
1985             while ((val = yyjson_arr_iter_next(&iter))) {
1986             your_func(val);
1987             }
1988             @endcode
1989             */
1990             typedef struct yyjson_arr_iter {
1991             size_t idx; /**< next value's index */
1992             size_t max; /**< maximum index (arr.size) */
1993             yyjson_val *cur; /**< next value */
1994             } yyjson_arr_iter;
1995              
1996             /**
1997             Initialize an iterator for this array.
1998              
1999             @param arr The array to be iterated over.
2000             If this parameter is NULL or not an array, `iter` will be set to empty.
2001             @param iter The iterator to be initialized.
2002             If this parameter is NULL, the function will fail and return false.
2003             @return true if the `iter` has been successfully initialized.
2004              
2005             @note The iterator does not need to be destroyed.
2006             */
2007             yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr,
2008             yyjson_arr_iter *iter);
2009              
2010             /**
2011             Create an iterator with an array , same as `yyjson_arr_iter_init()`.
2012              
2013             @param arr The array to be iterated over.
2014             If this parameter is NULL or not an array, an empty iterator will returned.
2015             @return A new iterator for the array.
2016              
2017             @note The iterator does not need to be destroyed.
2018             */
2019             yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr);
2020              
2021             /**
2022             Returns whether the iteration has more elements.
2023             If `iter` is NULL, this function will return false.
2024             */
2025             yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter);
2026              
2027             /**
2028             Returns the next element in the iteration, or NULL on end.
2029             If `iter` is NULL, this function will return NULL.
2030             */
2031             yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter);
2032              
2033             /**
2034             Macro for iterating over an array.
2035             It works like iterator, but with a more intuitive API.
2036              
2037             @b Example
2038             @code
2039             size_t idx, max;
2040             yyjson_val *val;
2041             yyjson_arr_foreach(arr, idx, max, val) {
2042             your_func(idx, val);
2043             }
2044             @endcode
2045             */
2046             #define yyjson_arr_foreach(arr, idx, max, val) \
2047             for ((idx) = 0, \
2048             (max) = yyjson_arr_size(arr), \
2049             (val) = yyjson_arr_get_first(arr); \
2050             (idx) < (max); \
2051             (idx)++, \
2052             (val) = unsafe_yyjson_get_next(val))
2053              
2054              
2055              
2056             /*==============================================================================
2057             * MARK: - JSON Object API
2058             *============================================================================*/
2059              
2060             /** Returns the number of key-value pairs in this object.
2061             Returns 0 if `obj` is NULL or type is not object. */
2062             yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj);
2063              
2064             /** Returns the value to which the specified key is mapped.
2065             Returns NULL if this object contains no mapping for the key.
2066             Returns NULL if `obj/key` is NULL, or type is not object.
2067              
2068             The `key` should be a null-terminated UTF-8 string.
2069              
2070             @warning This function takes a linear search time. */
2071             yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj, const char *key);
2072              
2073             /** Returns the value to which the specified key is mapped.
2074             Returns NULL if this object contains no mapping for the key.
2075             Returns NULL if `obj/key` is NULL, or type is not object.
2076              
2077             The `key` should be a UTF-8 string, null-terminator is not required.
2078             The `key_len` should be the length of the key, in bytes.
2079              
2080             @warning This function takes a linear search time. */
2081             yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *key,
2082             size_t key_len);
2083              
2084              
2085              
2086             /*==============================================================================
2087             * MARK: - JSON Object Iterator API
2088             *============================================================================*/
2089              
2090             /**
2091             A JSON object iterator.
2092              
2093             @b Example
2094             @code
2095             yyjson_val *key, *val;
2096             yyjson_obj_iter iter = yyjson_obj_iter_with(obj);
2097             while ((key = yyjson_obj_iter_next(&iter))) {
2098             val = yyjson_obj_iter_get_val(key);
2099             your_func(key, val);
2100             }
2101             @endcode
2102              
2103             If the ordering of the keys is known at compile-time, you can use this method
2104             to speed up value lookups:
2105             @code
2106             // {"k1":1, "k2": 3, "k3": 3}
2107             yyjson_val *key, *val;
2108             yyjson_obj_iter iter = yyjson_obj_iter_with(obj);
2109             yyjson_val *v1 = yyjson_obj_iter_get(&iter, "k1");
2110             yyjson_val *v3 = yyjson_obj_iter_get(&iter, "k3");
2111             @endcode
2112             @see yyjson_obj_iter_get() and yyjson_obj_iter_getn()
2113             */
2114             typedef struct yyjson_obj_iter {
2115             size_t idx; /**< next key's index */
2116             size_t max; /**< maximum key index (obj.size) */
2117             yyjson_val *cur; /**< next key */
2118             yyjson_val *obj; /**< the object being iterated */
2119             } yyjson_obj_iter;
2120              
2121             /**
2122             Initialize an iterator for this object.
2123              
2124             @param obj The object to be iterated over.
2125             If this parameter is NULL or not an object, `iter` will be set to empty.
2126             @param iter The iterator to be initialized.
2127             If this parameter is NULL, the function will fail and return false.
2128             @return true if the `iter` has been successfully initialized.
2129              
2130             @note The iterator does not need to be destroyed.
2131             */
2132             yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj,
2133             yyjson_obj_iter *iter);
2134              
2135             /**
2136             Create an iterator with an object, same as `yyjson_obj_iter_init()`.
2137              
2138             @param obj The object to be iterated over.
2139             If this parameter is NULL or not an object, an empty iterator will returned.
2140             @return A new iterator for the object.
2141              
2142             @note The iterator does not need to be destroyed.
2143             */
2144             yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj);
2145              
2146             /**
2147             Returns whether the iteration has more elements.
2148             If `iter` is NULL, this function will return false.
2149             */
2150             yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter);
2151              
2152             /**
2153             Returns the next key in the iteration, or NULL on end.
2154             If `iter` is NULL, this function will return NULL.
2155             */
2156             yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter);
2157              
2158             /**
2159             Returns the value for key inside the iteration.
2160             If `iter` is NULL, this function will return NULL.
2161             */
2162             yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key);
2163              
2164             /**
2165             Iterates to a specified key and returns the value.
2166              
2167             This function does the same thing as `yyjson_obj_get()`, but is much faster
2168             if the ordering of the keys is known at compile-time and you are using the same
2169             order to look up the values. If the key exists in this object, then the
2170             iterator will stop at the next key, otherwise the iterator will not change and
2171             NULL is returned.
2172              
2173             @param iter The object iterator, should not be NULL.
2174             @param key The key, should be a UTF-8 string with null-terminator.
2175             @return The value to which the specified key is mapped.
2176             NULL if this object contains no mapping for the key or input is invalid.
2177              
2178             @warning This function takes a linear search time if the key is not nearby.
2179             */
2180             yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter,
2181             const char *key);
2182              
2183             /**
2184             Iterates to a specified key and returns the value.
2185              
2186             This function does the same thing as `yyjson_obj_getn()`, but is much faster
2187             if the ordering of the keys is known at compile-time and you are using the same
2188             order to look up the values. If the key exists in this object, then the
2189             iterator will stop at the next key, otherwise the iterator will not change and
2190             NULL is returned.
2191              
2192             @param iter The object iterator, should not be NULL.
2193             @param key The key, should be a UTF-8 string, null-terminator is not required.
2194             @param key_len The the length of `key`, in bytes.
2195             @return The value to which the specified key is mapped.
2196             NULL if this object contains no mapping for the key or input is invalid.
2197              
2198             @warning This function takes a linear search time if the key is not nearby.
2199             */
2200             yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter,
2201             const char *key,
2202             size_t key_len);
2203              
2204             /**
2205             Macro for iterating over an object.
2206             It works like iterator, but with a more intuitive API.
2207              
2208             @b Example
2209             @code
2210             size_t idx, max;
2211             yyjson_val *key, *val;
2212             yyjson_obj_foreach(obj, idx, max, key, val) {
2213             your_func(key, val);
2214             }
2215             @endcode
2216             */
2217             #define yyjson_obj_foreach(obj, idx, max, key, val) \
2218             for ((idx) = 0, \
2219             (max) = yyjson_obj_size(obj), \
2220             (key) = (obj) ? unsafe_yyjson_get_first(obj) : NULL, \
2221             (val) = (key) + 1; \
2222             (idx) < (max); \
2223             (idx)++, \
2224             (key) = unsafe_yyjson_get_next(val), \
2225             (val) = (key) + 1)
2226              
2227              
2228              
2229             /*==============================================================================
2230             * MARK: - Mutable JSON Document API
2231             *============================================================================*/
2232              
2233             /** Returns the root value of this JSON document.
2234             Returns NULL if `doc` is NULL. */
2235             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc);
2236              
2237             /** Sets the root value of this JSON document.
2238             Pass NULL to clear root value of the document. */
2239             yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc,
2240             yyjson_mut_val *root);
2241              
2242             /**
2243             Set the string pool size for a mutable document.
2244             This function does not allocate memory immediately, but uses the size when
2245             the next memory allocation is needed.
2246              
2247             If the caller knows the approximate bytes of strings that the document needs to
2248             store (e.g. copy string with `yyjson_mut_strcpy` function), setting a larger
2249             size can avoid multiple memory allocations and improve performance.
2250              
2251             @param doc The mutable document.
2252             @param len The desired string pool size in bytes (total string length).
2253             @return true if successful, false if size is 0 or overflow.
2254             */
2255             yyjson_api bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc,
2256             size_t len);
2257              
2258             /**
2259             Set the value pool size for a mutable document.
2260             This function does not allocate memory immediately, but uses the size when
2261             the next memory allocation is needed.
2262              
2263             If the caller knows the approximate number of values that the document needs to
2264             store (e.g. create new value with `yyjson_mut_xxx` functions), setting a larger
2265             size can avoid multiple memory allocations and improve performance.
2266              
2267             @param doc The mutable document.
2268             @param count The desired value pool size (number of `yyjson_mut_val`).
2269             @return true if successful, false if size is 0 or overflow.
2270             */
2271             yyjson_api bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc,
2272             size_t count);
2273              
2274             /** Release the JSON document and free the memory.
2275             After calling this function, the `doc` and all values from the `doc` are no
2276             longer available. This function will do nothing if the `doc` is NULL. */
2277             yyjson_api void yyjson_mut_doc_free(yyjson_mut_doc *doc);
2278              
2279             /** Creates and returns a new mutable JSON document, returns NULL on error.
2280             If allocator is NULL, the default allocator will be used. */
2281             yyjson_api yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc);
2282              
2283             /** Copies and returns a new mutable document from input, returns NULL on error.
2284             This makes a `deep-copy` on the immutable document.
2285             If allocator is NULL, the default allocator will be used.
2286             @note `imut_doc` -> `mut_doc`. */
2287             yyjson_api yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc,
2288             const yyjson_alc *alc);
2289              
2290             /** Copies and returns a new mutable document from input, returns NULL on error.
2291             This makes a `deep-copy` on the mutable document.
2292             If allocator is NULL, the default allocator will be used.
2293             @note `mut_doc` -> `mut_doc`. */
2294             yyjson_api yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc,
2295             const yyjson_alc *alc);
2296              
2297             /** Copies and returns a new mutable value from input, returns NULL on error.
2298             This makes a `deep-copy` on the immutable value.
2299             The memory was managed by mutable document.
2300             @note `imut_val` -> `mut_val`. */
2301             yyjson_api yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *doc,
2302             yyjson_val *val);
2303              
2304             /** Copies and returns a new mutable value from input, returns NULL on error.
2305             This makes a `deep-copy` on the mutable value.
2306             The memory was managed by mutable document.
2307             @note `mut_val` -> `mut_val`.
2308             @warning This function is recursive and may cause a stack overflow
2309             if the object level is too deep. */
2310             yyjson_api yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc,
2311             yyjson_mut_val *val);
2312              
2313             /** Copies and returns a new immutable document from input,
2314             returns NULL on error. This makes a `deep-copy` on the mutable document.
2315             The returned document should be freed with `yyjson_doc_free()`.
2316             @note `mut_doc` -> `imut_doc`.
2317             @warning This function is recursive and may cause a stack overflow
2318             if the object level is too deep. */
2319             yyjson_api yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *doc,
2320             const yyjson_alc *alc);
2321              
2322             /** Copies and returns a new immutable document from input,
2323             returns NULL on error. This makes a `deep-copy` on the mutable value.
2324             The returned document should be freed with `yyjson_doc_free()`.
2325             @note `mut_val` -> `imut_doc`.
2326             @warning This function is recursive and may cause a stack overflow
2327             if the object level is too deep. */
2328             yyjson_api yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *val,
2329             const yyjson_alc *alc);
2330              
2331              
2332              
2333             /*==============================================================================
2334             * MARK: - Mutable JSON Value Type API
2335             *============================================================================*/
2336              
2337             /** Returns whether the JSON value is raw.
2338             Returns false if `val` is NULL. */
2339             yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val);
2340              
2341             /** Returns whether the JSON value is `null`.
2342             Returns false if `val` is NULL. */
2343             yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val);
2344              
2345             /** Returns whether the JSON value is `true`.
2346             Returns false if `val` is NULL. */
2347             yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val);
2348              
2349             /** Returns whether the JSON value is `false`.
2350             Returns false if `val` is NULL. */
2351             yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val);
2352              
2353             /** Returns whether the JSON value is bool (true/false).
2354             Returns false if `val` is NULL. */
2355             yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val);
2356              
2357             /** Returns whether the JSON value is unsigned integer (uint64_t).
2358             Returns false if `val` is NULL. */
2359             yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val);
2360              
2361             /** Returns whether the JSON value is signed integer (int64_t).
2362             Returns false if `val` is NULL. */
2363             yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val);
2364              
2365             /** Returns whether the JSON value is integer (uint64_t/int64_t).
2366             Returns false if `val` is NULL. */
2367             yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val);
2368              
2369             /** Returns whether the JSON value is real number (double).
2370             Returns false if `val` is NULL. */
2371             yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val);
2372              
2373             /** Returns whether the JSON value is number (uint/sint/real).
2374             Returns false if `val` is NULL. */
2375             yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val);
2376              
2377             /** Returns whether the JSON value is string.
2378             Returns false if `val` is NULL. */
2379             yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val);
2380              
2381             /** Returns whether the JSON value is array.
2382             Returns false if `val` is NULL. */
2383             yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val);
2384              
2385             /** Returns whether the JSON value is object.
2386             Returns false if `val` is NULL. */
2387             yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val);
2388              
2389             /** Returns whether the JSON value is container (array/object).
2390             Returns false if `val` is NULL. */
2391             yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val);
2392              
2393              
2394              
2395             /*==============================================================================
2396             * MARK: - Mutable JSON Value Content API
2397             *============================================================================*/
2398              
2399             /** Returns the JSON value's type.
2400             Returns `YYJSON_TYPE_NONE` if `val` is NULL. */
2401             yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val);
2402              
2403             /** Returns the JSON value's subtype.
2404             Returns `YYJSON_SUBTYPE_NONE` if `val` is NULL. */
2405             yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val);
2406              
2407             /** Returns the JSON value's tag.
2408             Returns 0 if `val` is NULL. */
2409             yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val);
2410              
2411             /** Returns the JSON value's type description.
2412             The return value should be one of these strings: "raw", "null", "string",
2413             "array", "object", "true", "false", "uint", "sint", "real", "unknown". */
2414             yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val);
2415              
2416             /** Returns the content if the value is raw.
2417             Returns NULL if `val` is NULL or type is not raw. */
2418             yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val);
2419              
2420             /** Returns the content if the value is bool.
2421             Returns NULL if `val` is NULL or type is not bool. */
2422             yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val);
2423              
2424             /** Returns the content and cast to uint64_t.
2425             Returns 0 if `val` is NULL or type is not integer(sint/uint). */
2426             yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val);
2427              
2428             /** Returns the content and cast to int64_t.
2429             Returns 0 if `val` is NULL or type is not integer(sint/uint). */
2430             yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val);
2431              
2432             /** Returns the content and cast to int.
2433             Returns 0 if `val` is NULL or type is not integer(sint/uint). */
2434             yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val);
2435              
2436             /** Returns the content if the value is real number.
2437             Returns 0.0 if `val` is NULL or type is not real(double). */
2438             yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val);
2439              
2440             /** Returns the content and typecast to `double` if the value is number.
2441             Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */
2442             yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val);
2443              
2444             /** Returns the content if the value is string.
2445             Returns NULL if `val` is NULL or type is not string. */
2446             yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val);
2447              
2448             /** Returns the content length (string length, array size, object size.
2449             Returns 0 if `val` is NULL or type is not string/array/object. */
2450             yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val);
2451              
2452             /** Returns whether the JSON value is equals to a string.
2453             The `str` should be a null-terminated UTF-8 string.
2454             Returns false if input is NULL or type is not string. */
2455             yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val,
2456             const char *str);
2457              
2458             /** Returns whether the JSON value is equals to a string.
2459             The `str` should be a UTF-8 string, null-terminator is not required.
2460             Returns false if input is NULL or type is not string. */
2461             yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val,
2462             const char *str, size_t len);
2463              
2464             /** Returns whether two JSON values are equal (deep compare).
2465             Returns false if input is NULL.
2466             @note the result may be inaccurate if object has duplicate keys.
2467             @warning This function is recursive and may cause a stack overflow
2468             if the object level is too deep. */
2469             yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs,
2470             yyjson_mut_val *rhs);
2471              
2472             /** Set the value to raw.
2473             Returns false if input is NULL.
2474             @warning This function should not be used on an existing object or array. */
2475             yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val,
2476             const char *raw, size_t len);
2477              
2478             /** Set the value to null.
2479             Returns false if input is NULL.
2480             @warning This function should not be used on an existing object or array. */
2481             yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val);
2482              
2483             /** Set the value to bool.
2484             Returns false if input is NULL.
2485             @warning This function should not be used on an existing object or array. */
2486             yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num);
2487              
2488             /** Set the value to uint.
2489             Returns false if input is NULL.
2490             @warning This function should not be used on an existing object or array. */
2491             yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num);
2492              
2493             /** Set the value to sint.
2494             Returns false if input is NULL.
2495             @warning This function should not be used on an existing object or array. */
2496             yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num);
2497              
2498             /** Set the value to int.
2499             Returns false if input is NULL.
2500             @warning This function should not be used on an existing object or array. */
2501             yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num);
2502              
2503             /** Set the value to float.
2504             Returns false if input is NULL.
2505             @warning This function should not be used on an existing object or array. */
2506             yyjson_api_inline bool yyjson_mut_set_float(yyjson_mut_val *val, float num);
2507              
2508             /** Set the value to double.
2509             Returns false if input is NULL.
2510             @warning This function should not be used on an existing object or array. */
2511             yyjson_api_inline bool yyjson_mut_set_double(yyjson_mut_val *val, double num);
2512              
2513             /** Set the value to real.
2514             Returns false if input is NULL.
2515             @warning This function should not be used on an existing object or array. */
2516             yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num);
2517              
2518             /** Set the floating-point number's output format to fixed-point notation.
2519             Returns false if input is NULL or `val` is not real type.
2520             @see YYJSON_WRITE_FP_TO_FIXED flag.
2521             @warning This will modify the `immutable` value, use with caution. */
2522             yyjson_api_inline bool yyjson_mut_set_fp_to_fixed(yyjson_mut_val *val,
2523             int prec);
2524              
2525             /** Set the floating-point number's output format to single-precision.
2526             Returns false if input is NULL or `val` is not real type.
2527             @see YYJSON_WRITE_FP_TO_FLOAT flag.
2528             @warning This will modify the `immutable` value, use with caution. */
2529             yyjson_api_inline bool yyjson_mut_set_fp_to_float(yyjson_mut_val *val,
2530             bool flt);
2531              
2532             /** Set the value to string (null-terminated).
2533             Returns false if input is NULL.
2534             @warning This function should not be used on an existing object or array. */
2535             yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val, const char *str);
2536              
2537             /** Set the value to string (with length).
2538             Returns false if input is NULL.
2539             @warning This function should not be used on an existing object or array. */
2540             yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val,
2541             const char *str, size_t len);
2542              
2543             /** Marks this string as not needing to be escaped during JSON writing.
2544             This can be used to avoid the overhead of escaping if the string contains
2545             only characters that do not require escaping.
2546             Returns false if input is NULL or `val` is not string.
2547             @see YYJSON_SUBTYPE_NOESC subtype.
2548             @warning This will modify the `immutable` value, use with caution. */
2549             yyjson_api_inline bool yyjson_mut_set_str_noesc(yyjson_mut_val *val,
2550             bool noesc);
2551              
2552             /** Set the value to array.
2553             Returns false if input is NULL.
2554             @warning This function should not be used on an existing object or array. */
2555             yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val);
2556              
2557             /** Set the value to array.
2558             Returns false if input is NULL.
2559             @warning This function should not be used on an existing object or array. */
2560             yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val);
2561              
2562              
2563              
2564             /*==============================================================================
2565             * MARK: - Mutable JSON Value Creation API
2566             *============================================================================*/
2567              
2568             /** Creates and returns a raw value, returns NULL on error.
2569             The `str` should be a null-terminated UTF-8 string.
2570              
2571             @warning The input string is not copied, you should keep this string
2572             unmodified for the lifetime of this JSON document. */
2573             yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc,
2574             const char *str);
2575              
2576             /** Creates and returns a raw value, returns NULL on error.
2577             The `str` should be a UTF-8 string, null-terminator is not required.
2578              
2579             @warning The input string is not copied, you should keep this string
2580             unmodified for the lifetime of this JSON document. */
2581             yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc,
2582             const char *str,
2583             size_t len);
2584              
2585             /** Creates and returns a raw value, returns NULL on error.
2586             The `str` should be a null-terminated UTF-8 string.
2587             The input string is copied and held by the document. */
2588             yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc,
2589             const char *str);
2590              
2591             /** Creates and returns a raw value, returns NULL on error.
2592             The `str` should be a UTF-8 string, null-terminator is not required.
2593             The input string is copied and held by the document. */
2594             yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc,
2595             const char *str,
2596             size_t len);
2597              
2598             /** Creates and returns a null value, returns NULL on error. */
2599             yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc);
2600              
2601             /** Creates and returns a true value, returns NULL on error. */
2602             yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc);
2603              
2604             /** Creates and returns a false value, returns NULL on error. */
2605             yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc);
2606              
2607             /** Creates and returns a bool value, returns NULL on error. */
2608             yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc,
2609             bool val);
2610              
2611             /** Creates and returns an unsigned integer value, returns NULL on error. */
2612             yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc,
2613             uint64_t num);
2614              
2615             /** Creates and returns a signed integer value, returns NULL on error. */
2616             yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc,
2617             int64_t num);
2618              
2619             /** Creates and returns a signed integer value, returns NULL on error. */
2620             yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc,
2621             int64_t num);
2622              
2623             /** Creates and returns a float number value, returns NULL on error. */
2624             yyjson_api_inline yyjson_mut_val *yyjson_mut_float(yyjson_mut_doc *doc,
2625             float num);
2626              
2627             /** Creates and returns a double number value, returns NULL on error. */
2628             yyjson_api_inline yyjson_mut_val *yyjson_mut_double(yyjson_mut_doc *doc,
2629             double num);
2630              
2631             /** Creates and returns a real number value, returns NULL on error. */
2632             yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc,
2633             double num);
2634              
2635             /** Creates and returns a string value, returns NULL on error.
2636             The `str` should be a null-terminated UTF-8 string.
2637             @warning The input string is not copied, you should keep this string
2638             unmodified for the lifetime of this JSON document. */
2639             yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc,
2640             const char *str);
2641              
2642             /** Creates and returns a string value, returns NULL on error.
2643             The `str` should be a UTF-8 string, null-terminator is not required.
2644             @warning The input string is not copied, you should keep this string
2645             unmodified for the lifetime of this JSON document. */
2646             yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc,
2647             const char *str,
2648             size_t len);
2649              
2650             /** Creates and returns a string value, returns NULL on error.
2651             The `str` should be a null-terminated UTF-8 string.
2652             The input string is copied and held by the document. */
2653             yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc,
2654             const char *str);
2655              
2656             /** Creates and returns a string value, returns NULL on error.
2657             The `str` should be a UTF-8 string, null-terminator is not required.
2658             The input string is copied and held by the document. */
2659             yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc,
2660             const char *str,
2661             size_t len);
2662              
2663              
2664              
2665             /*==============================================================================
2666             * MARK: - Mutable JSON Array API
2667             *============================================================================*/
2668              
2669             /** Returns the number of elements in this array.
2670             Returns 0 if `arr` is NULL or type is not array. */
2671             yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr);
2672              
2673             /** Returns the element at the specified position in this array.
2674             Returns NULL if array is NULL/empty or the index is out of bounds.
2675             @warning This function takes a linear search time. */
2676             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr,
2677             size_t idx);
2678              
2679             /** Returns the first element of this array.
2680             Returns NULL if `arr` is NULL/empty or type is not array. */
2681             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first(yyjson_mut_val *arr);
2682              
2683             /** Returns the last element of this array.
2684             Returns NULL if `arr` is NULL/empty or type is not array. */
2685             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(yyjson_mut_val *arr);
2686              
2687              
2688              
2689             /*==============================================================================
2690             * MARK: - Mutable JSON Array Iterator API
2691             *============================================================================*/
2692              
2693             /**
2694             A mutable JSON array iterator.
2695              
2696             @warning You should not modify the array while iterating over it, but you can
2697             use `yyjson_mut_arr_iter_remove()` to remove current value.
2698              
2699             @b Example
2700             @code
2701             yyjson_mut_val *val;
2702             yyjson_mut_arr_iter iter = yyjson_mut_arr_iter_with(arr);
2703             while ((val = yyjson_mut_arr_iter_next(&iter))) {
2704             your_func(val);
2705             if (your_val_is_unused(val)) {
2706             yyjson_mut_arr_iter_remove(&iter);
2707             }
2708             }
2709             @endcode
2710             */
2711             typedef struct yyjson_mut_arr_iter {
2712             size_t idx; /**< next value's index */
2713             size_t max; /**< maximum index (arr.size) */
2714             yyjson_mut_val *cur; /**< current value */
2715             yyjson_mut_val *pre; /**< previous value */
2716             yyjson_mut_val *arr; /**< the array being iterated */
2717             } yyjson_mut_arr_iter;
2718              
2719             /**
2720             Initialize an iterator for this array.
2721              
2722             @param arr The array to be iterated over.
2723             If this parameter is NULL or not an array, `iter` will be set to empty.
2724             @param iter The iterator to be initialized.
2725             If this parameter is NULL, the function will fail and return false.
2726             @return true if the `iter` has been successfully initialized.
2727              
2728             @note The iterator does not need to be destroyed.
2729             */
2730             yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr,
2731             yyjson_mut_arr_iter *iter);
2732              
2733             /**
2734             Create an iterator with an array , same as `yyjson_mut_arr_iter_init()`.
2735              
2736             @param arr The array to be iterated over.
2737             If this parameter is NULL or not an array, an empty iterator will returned.
2738             @return A new iterator for the array.
2739              
2740             @note The iterator does not need to be destroyed.
2741             */
2742             yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with(
2743             yyjson_mut_val *arr);
2744              
2745             /**
2746             Returns whether the iteration has more elements.
2747             If `iter` is NULL, this function will return false.
2748             */
2749             yyjson_api_inline bool yyjson_mut_arr_iter_has_next(
2750             yyjson_mut_arr_iter *iter);
2751              
2752             /**
2753             Returns the next element in the iteration, or NULL on end.
2754             If `iter` is NULL, this function will return NULL.
2755             */
2756             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next(
2757             yyjson_mut_arr_iter *iter);
2758              
2759             /**
2760             Removes and returns current element in the iteration.
2761             If `iter` is NULL, this function will return NULL.
2762             */
2763             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove(
2764             yyjson_mut_arr_iter *iter);
2765              
2766             /**
2767             Macro for iterating over an array.
2768             It works like iterator, but with a more intuitive API.
2769              
2770             @warning You should not modify the array while iterating over it.
2771              
2772             @b Example
2773             @code
2774             size_t idx, max;
2775             yyjson_mut_val *val;
2776             yyjson_mut_arr_foreach(arr, idx, max, val) {
2777             your_func(idx, val);
2778             }
2779             @endcode
2780             */
2781             #define yyjson_mut_arr_foreach(arr, idx, max, val) \
2782             for ((idx) = 0, \
2783             (max) = yyjson_mut_arr_size(arr), \
2784             (val) = yyjson_mut_arr_get_first(arr); \
2785             (idx) < (max); \
2786             (idx)++, \
2787             (val) = (val)->next)
2788              
2789              
2790              
2791             /*==============================================================================
2792             * MARK: - Mutable JSON Array Creation API
2793             *============================================================================*/
2794              
2795             /**
2796             Creates and returns an empty mutable array.
2797             @param doc A mutable document, used for memory allocation only.
2798             @return The new array. NULL if input is NULL or memory allocation failed.
2799             */
2800             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc);
2801              
2802             /**
2803             Creates and returns a new mutable array with the given boolean values.
2804              
2805             @param doc A mutable document, used for memory allocation only.
2806             If this parameter is NULL, the function will fail and return NULL.
2807             @param vals A C array of boolean values.
2808             @param count The value count. If this value is 0, an empty array will return.
2809             @return The new array. NULL if input is invalid or memory allocation failed.
2810              
2811             @b Example
2812             @code
2813             const bool vals[3] = { true, false, true };
2814             yyjson_mut_val *arr = yyjson_mut_arr_with_bool(doc, vals, 3);
2815             @endcode
2816             */
2817             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool(
2818             yyjson_mut_doc *doc, const bool *vals, size_t count);
2819              
2820             /**
2821             Creates and returns a new mutable array with the given sint numbers.
2822              
2823             @param doc A mutable document, used for memory allocation only.
2824             If this parameter is NULL, the function will fail and return NULL.
2825             @param vals A C array of sint numbers.
2826             @param count The number count. If this value is 0, an empty array will return.
2827             @return The new array. NULL if input is invalid or memory allocation failed.
2828              
2829             @b Example
2830             @code
2831             const int64_t vals[3] = { -1, 0, 1 };
2832             yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3);
2833             @endcode
2834             */
2835             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint(
2836             yyjson_mut_doc *doc, const int64_t *vals, size_t count);
2837              
2838             /**
2839             Creates and returns a new mutable array with the given uint numbers.
2840              
2841             @param doc A mutable document, used for memory allocation only.
2842             If this parameter is NULL, the function will fail and return NULL.
2843             @param vals A C array of uint numbers.
2844             @param count The number count. If this value is 0, an empty array will return.
2845             @return The new array. NULL if input is invalid or memory allocation failed.
2846              
2847             @b Example
2848             @code
2849             const uint64_t vals[3] = { 0, 1, 0 };
2850             yyjson_mut_val *arr = yyjson_mut_arr_with_uint(doc, vals, 3);
2851             @endcode
2852             */
2853             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint(
2854             yyjson_mut_doc *doc, const uint64_t *vals, size_t count);
2855              
2856             /**
2857             Creates and returns a new mutable array with the given real numbers.
2858              
2859             @param doc A mutable document, used for memory allocation only.
2860             If this parameter is NULL, the function will fail and return NULL.
2861             @param vals A C array of real numbers.
2862             @param count The number count. If this value is 0, an empty array will return.
2863             @return The new array. NULL if input is invalid or memory allocation failed.
2864              
2865             @b Example
2866             @code
2867             const double vals[3] = { 0.1, 0.2, 0.3 };
2868             yyjson_mut_val *arr = yyjson_mut_arr_with_real(doc, vals, 3);
2869             @endcode
2870             */
2871             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real(
2872             yyjson_mut_doc *doc, const double *vals, size_t count);
2873              
2874             /**
2875             Creates and returns a new mutable array with the given int8 numbers.
2876              
2877             @param doc A mutable document, used for memory allocation only.
2878             If this parameter is NULL, the function will fail and return NULL.
2879             @param vals A C array of int8 numbers.
2880             @param count The number count. If this value is 0, an empty array will return.
2881             @return The new array. NULL if input is invalid or memory allocation failed.
2882              
2883             @b Example
2884             @code
2885             const int8_t vals[3] = { -1, 0, 1 };
2886             yyjson_mut_val *arr = yyjson_mut_arr_with_sint8(doc, vals, 3);
2887             @endcode
2888             */
2889             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8(
2890             yyjson_mut_doc *doc, const int8_t *vals, size_t count);
2891              
2892             /**
2893             Creates and returns a new mutable array with the given int16 numbers.
2894              
2895             @param doc A mutable document, used for memory allocation only.
2896             If this parameter is NULL, the function will fail and return NULL.
2897             @param vals A C array of int16 numbers.
2898             @param count The number count. If this value is 0, an empty array will return.
2899             @return The new array. NULL if input is invalid or memory allocation failed.
2900              
2901             @b Example
2902             @code
2903             const int16_t vals[3] = { -1, 0, 1 };
2904             yyjson_mut_val *arr = yyjson_mut_arr_with_sint16(doc, vals, 3);
2905             @endcode
2906             */
2907             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16(
2908             yyjson_mut_doc *doc, const int16_t *vals, size_t count);
2909              
2910             /**
2911             Creates and returns a new mutable array with the given int32 numbers.
2912              
2913             @param doc A mutable document, used for memory allocation only.
2914             If this parameter is NULL, the function will fail and return NULL.
2915             @param vals A C array of int32 numbers.
2916             @param count The number count. If this value is 0, an empty array will return.
2917             @return The new array. NULL if input is invalid or memory allocation failed.
2918              
2919             @b Example
2920             @code
2921             const int32_t vals[3] = { -1, 0, 1 };
2922             yyjson_mut_val *arr = yyjson_mut_arr_with_sint32(doc, vals, 3);
2923             @endcode
2924             */
2925             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32(
2926             yyjson_mut_doc *doc, const int32_t *vals, size_t count);
2927              
2928             /**
2929             Creates and returns a new mutable array with the given int64 numbers.
2930              
2931             @param doc A mutable document, used for memory allocation only.
2932             If this parameter is NULL, the function will fail and return NULL.
2933             @param vals A C array of int64 numbers.
2934             @param count The number count. If this value is 0, an empty array will return.
2935             @return The new array. NULL if input is invalid or memory allocation failed.
2936              
2937             @b Example
2938             @code
2939             const int64_t vals[3] = { -1, 0, 1 };
2940             yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3);
2941             @endcode
2942             */
2943             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64(
2944             yyjson_mut_doc *doc, const int64_t *vals, size_t count);
2945              
2946             /**
2947             Creates and returns a new mutable array with the given uint8 numbers.
2948              
2949             @param doc A mutable document, used for memory allocation only.
2950             If this parameter is NULL, the function will fail and return NULL.
2951             @param vals A C array of uint8 numbers.
2952             @param count The number count. If this value is 0, an empty array will return.
2953             @return The new array. NULL if input is invalid or memory allocation failed.
2954              
2955             @b Example
2956             @code
2957             const uint8_t vals[3] = { 0, 1, 0 };
2958             yyjson_mut_val *arr = yyjson_mut_arr_with_uint8(doc, vals, 3);
2959             @endcode
2960             */
2961             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8(
2962             yyjson_mut_doc *doc, const uint8_t *vals, size_t count);
2963              
2964             /**
2965             Creates and returns a new mutable array with the given uint16 numbers.
2966              
2967             @param doc A mutable document, used for memory allocation only.
2968             If this parameter is NULL, the function will fail and return NULL.
2969             @param vals A C array of uint16 numbers.
2970             @param count The number count. If this value is 0, an empty array will return.
2971             @return The new array. NULL if input is invalid or memory allocation failed.
2972              
2973             @b Example
2974             @code
2975             const uint16_t vals[3] = { 0, 1, 0 };
2976             yyjson_mut_val *arr = yyjson_mut_arr_with_uint16(doc, vals, 3);
2977             @endcode
2978             */
2979             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16(
2980             yyjson_mut_doc *doc, const uint16_t *vals, size_t count);
2981              
2982             /**
2983             Creates and returns a new mutable array with the given uint32 numbers.
2984              
2985             @param doc A mutable document, used for memory allocation only.
2986             If this parameter is NULL, the function will fail and return NULL.
2987             @param vals A C array of uint32 numbers.
2988             @param count The number count. If this value is 0, an empty array will return.
2989             @return The new array. NULL if input is invalid or memory allocation failed.
2990              
2991             @b Example
2992             @code
2993             const uint32_t vals[3] = { 0, 1, 0 };
2994             yyjson_mut_val *arr = yyjson_mut_arr_with_uint32(doc, vals, 3);
2995             @endcode
2996             */
2997             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32(
2998             yyjson_mut_doc *doc, const uint32_t *vals, size_t count);
2999              
3000             /**
3001             Creates and returns a new mutable array with the given uint64 numbers.
3002              
3003             @param doc A mutable document, used for memory allocation only.
3004             If this parameter is NULL, the function will fail and return NULL.
3005             @param vals A C array of uint64 numbers.
3006             @param count The number count. If this value is 0, an empty array will return.
3007             @return The new array. NULL if input is invalid or memory allocation failed.
3008              
3009             @b Example
3010             @code
3011             const uint64_t vals[3] = { 0, 1, 0 };
3012             yyjson_mut_val *arr = yyjson_mut_arr_with_uint64(doc, vals, 3);
3013             @endcode
3014             */
3015             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64(
3016             yyjson_mut_doc *doc, const uint64_t *vals, size_t count);
3017              
3018             /**
3019             Creates and returns a new mutable array with the given float numbers.
3020              
3021             @param doc A mutable document, used for memory allocation only.
3022             If this parameter is NULL, the function will fail and return NULL.
3023             @param vals A C array of float numbers.
3024             @param count The number count. If this value is 0, an empty array will return.
3025             @return The new array. NULL if input is invalid or memory allocation failed.
3026              
3027             @b Example
3028             @code
3029             const float vals[3] = { -1.0f, 0.0f, 1.0f };
3030             yyjson_mut_val *arr = yyjson_mut_arr_with_float(doc, vals, 3);
3031             @endcode
3032             */
3033             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float(
3034             yyjson_mut_doc *doc, const float *vals, size_t count);
3035              
3036             /**
3037             Creates and returns a new mutable array with the given double numbers.
3038              
3039             @param doc A mutable document, used for memory allocation only.
3040             If this parameter is NULL, the function will fail and return NULL.
3041             @param vals A C array of double numbers.
3042             @param count The number count. If this value is 0, an empty array will return.
3043             @return The new array. NULL if input is invalid or memory allocation failed.
3044              
3045             @b Example
3046             @code
3047             const double vals[3] = { -1.0, 0.0, 1.0 };
3048             yyjson_mut_val *arr = yyjson_mut_arr_with_double(doc, vals, 3);
3049             @endcode
3050             */
3051             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double(
3052             yyjson_mut_doc *doc, const double *vals, size_t count);
3053              
3054             /**
3055             Creates and returns a new mutable array with the given strings, these strings
3056             will not be copied.
3057              
3058             @param doc A mutable document, used for memory allocation only.
3059             If this parameter is NULL, the function will fail and return NULL.
3060             @param vals A C array of UTF-8 null-terminator strings.
3061             If this array contains NULL, the function will fail and return NULL.
3062             @param count The number of values in `vals`.
3063             If this value is 0, an empty array will return.
3064             @return The new array. NULL if input is invalid or memory allocation failed.
3065              
3066             @warning The input strings are not copied, you should keep these strings
3067             unmodified for the lifetime of this JSON document. If these strings will be
3068             modified, you should use `yyjson_mut_arr_with_strcpy()` instead.
3069              
3070             @b Example
3071             @code
3072             const char *vals[3] = { "a", "b", "c" };
3073             yyjson_mut_val *arr = yyjson_mut_arr_with_str(doc, vals, 3);
3074             @endcode
3075             */
3076             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str(
3077             yyjson_mut_doc *doc, const char **vals, size_t count);
3078              
3079             /**
3080             Creates and returns a new mutable array with the given strings and string
3081             lengths, these strings will not be copied.
3082              
3083             @param doc A mutable document, used for memory allocation only.
3084             If this parameter is NULL, the function will fail and return NULL.
3085             @param vals A C array of UTF-8 strings, null-terminator is not required.
3086             If this array contains NULL, the function will fail and return NULL.
3087             @param lens A C array of string lengths, in bytes.
3088             @param count The number of strings in `vals`.
3089             If this value is 0, an empty array will return.
3090             @return The new array. NULL if input is invalid or memory allocation failed.
3091              
3092             @warning The input strings are not copied, you should keep these strings
3093             unmodified for the lifetime of this JSON document. If these strings will be
3094             modified, you should use `yyjson_mut_arr_with_strncpy()` instead.
3095              
3096             @b Example
3097             @code
3098             const char *vals[3] = { "a", "bb", "c" };
3099             const size_t lens[3] = { 1, 2, 1 };
3100             yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3);
3101             @endcode
3102             */
3103             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn(
3104             yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count);
3105              
3106             /**
3107             Creates and returns a new mutable array with the given strings, these strings
3108             will be copied.
3109              
3110             @param doc A mutable document, used for memory allocation only.
3111             If this parameter is NULL, the function will fail and return NULL.
3112             @param vals A C array of UTF-8 null-terminator strings.
3113             If this array contains NULL, the function will fail and return NULL.
3114             @param count The number of values in `vals`.
3115             If this value is 0, an empty array will return.
3116             @return The new array. NULL if input is invalid or memory allocation failed.
3117              
3118             @b Example
3119             @code
3120             const char *vals[3] = { "a", "b", "c" };
3121             yyjson_mut_val *arr = yyjson_mut_arr_with_strcpy(doc, vals, 3);
3122             @endcode
3123             */
3124             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy(
3125             yyjson_mut_doc *doc, const char **vals, size_t count);
3126              
3127             /**
3128             Creates and returns a new mutable array with the given strings and string
3129             lengths, these strings will be copied.
3130              
3131             @param doc A mutable document, used for memory allocation only.
3132             If this parameter is NULL, the function will fail and return NULL.
3133             @param vals A C array of UTF-8 strings, null-terminator is not required.
3134             If this array contains NULL, the function will fail and return NULL.
3135             @param lens A C array of string lengths, in bytes.
3136             @param count The number of strings in `vals`.
3137             If this value is 0, an empty array will return.
3138             @return The new array. NULL if input is invalid or memory allocation failed.
3139              
3140             @b Example
3141             @code
3142             const char *vals[3] = { "a", "bb", "c" };
3143             const size_t lens[3] = { 1, 2, 1 };
3144             yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3);
3145             @endcode
3146             */
3147             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy(
3148             yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count);
3149              
3150              
3151              
3152             /*==============================================================================
3153             * MARK: - Mutable JSON Array Modification API
3154             *============================================================================*/
3155              
3156             /**
3157             Inserts a value into an array at a given index.
3158             @param arr The array to which the value is to be inserted.
3159             Returns false if it is NULL or not an array.
3160             @param val The value to be inserted. Returns false if it is NULL.
3161             @param idx The index to which to insert the new value.
3162             Returns false if the index is out of range.
3163             @return Whether successful.
3164             @warning This function takes a linear search time.
3165             */
3166             yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr,
3167             yyjson_mut_val *val, size_t idx);
3168              
3169             /**
3170             Inserts a value at the end of the array.
3171             @param arr The array to which the value is to be inserted.
3172             Returns false if it is NULL or not an array.
3173             @param val The value to be inserted. Returns false if it is NULL.
3174             @return Whether successful.
3175             */
3176             yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr,
3177             yyjson_mut_val *val);
3178              
3179             /**
3180             Inserts a value at the head of the array.
3181             @param arr The array to which the value is to be inserted.
3182             Returns false if it is NULL or not an array.
3183             @param val The value to be inserted. Returns false if it is NULL.
3184             @return Whether successful.
3185             */
3186             yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr,
3187             yyjson_mut_val *val);
3188              
3189             /**
3190             Replaces a value at index and returns old value.
3191             @param arr The array to which the value is to be replaced.
3192             Returns false if it is NULL or not an array.
3193             @param idx The index to which to replace the value.
3194             Returns false if the index is out of range.
3195             @param val The new value to replace. Returns false if it is NULL.
3196             @return Old value, or NULL on error.
3197             @warning This function takes a linear search time.
3198             */
3199             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr,
3200             size_t idx,
3201             yyjson_mut_val *val);
3202              
3203             /**
3204             Removes and returns a value at index.
3205             @param arr The array from which the value is to be removed.
3206             Returns false if it is NULL or not an array.
3207             @param idx The index from which to remove the value.
3208             Returns false if the index is out of range.
3209             @return Old value, or NULL on error.
3210             @warning This function takes a linear search time.
3211             */
3212             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr,
3213             size_t idx);
3214              
3215             /**
3216             Removes and returns the first value in this array.
3217             @param arr The array from which the value is to be removed.
3218             Returns false if it is NULL or not an array.
3219             @return The first value, or NULL on error.
3220             */
3221             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first(
3222             yyjson_mut_val *arr);
3223              
3224             /**
3225             Removes and returns the last value in this array.
3226             @param arr The array from which the value is to be removed.
3227             Returns false if it is NULL or not an array.
3228             @return The last value, or NULL on error.
3229             */
3230             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last(
3231             yyjson_mut_val *arr);
3232              
3233             /**
3234             Removes all values within a specified range in the array.
3235             @param arr The array from which the value is to be removed.
3236             Returns false if it is NULL or not an array.
3237             @param idx The start index of the range (0 is the first).
3238             @param len The number of items in the range (can be 0).
3239             @return Whether successful.
3240             @warning This function takes a linear search time.
3241             */
3242             yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr,
3243             size_t idx, size_t len);
3244              
3245             /**
3246             Removes all values in this array.
3247             @param arr The array from which all of the values are to be removed.
3248             Returns false if it is NULL or not an array.
3249             @return Whether successful.
3250             */
3251             yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr);
3252              
3253             /**
3254             Rotates values in this array for the given number of times.
3255             For example: `[1,2,3,4,5]` rotate 2 is `[3,4,5,1,2]`.
3256             @param arr The array to be rotated.
3257             @param idx Index (or times) to rotate.
3258             @warning This function takes a linear search time.
3259             */
3260             yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr,
3261             size_t idx);
3262              
3263              
3264              
3265             /*==============================================================================
3266             * MARK: - Mutable JSON Array Modification Convenience API
3267             *============================================================================*/
3268              
3269             /**
3270             Adds a value at the end of the array.
3271             @param arr The array to which the value is to be inserted.
3272             Returns false if it is NULL or not an array.
3273             @param val The value to be inserted. Returns false if it is NULL.
3274             @return Whether successful.
3275             */
3276             yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr,
3277             yyjson_mut_val *val);
3278              
3279             /**
3280             Adds a `null` value at the end of the array.
3281             @param doc The `doc` is only used for memory allocation.
3282             @param arr The array to which the value is to be inserted.
3283             Returns false if it is NULL or not an array.
3284             @return Whether successful.
3285             */
3286             yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc,
3287             yyjson_mut_val *arr);
3288              
3289             /**
3290             Adds a `true` value at the end of the array.
3291             @param doc The `doc` is only used for memory allocation.
3292             @param arr The array to which the value is to be inserted.
3293             Returns false if it is NULL or not an array.
3294             @return Whether successful.
3295             */
3296             yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc,
3297             yyjson_mut_val *arr);
3298              
3299             /**
3300             Adds a `false` value at the end of the array.
3301             @param doc The `doc` is only used for memory allocation.
3302             @param arr The array to which the value is to be inserted.
3303             Returns false if it is NULL or not an array.
3304             @return Whether successful.
3305             */
3306             yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc,
3307             yyjson_mut_val *arr);
3308              
3309             /**
3310             Adds a bool value at the end of the array.
3311             @param doc The `doc` is only used for memory allocation.
3312             @param arr The array to which the value is to be inserted.
3313             Returns false if it is NULL or not an array.
3314             @param val The bool value to be added.
3315             @return Whether successful.
3316             */
3317             yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc,
3318             yyjson_mut_val *arr,
3319             bool val);
3320              
3321             /**
3322             Adds an unsigned integer value at the end of the array.
3323             @param doc The `doc` is only used for memory allocation.
3324             @param arr The array to which the value is to be inserted.
3325             Returns false if it is NULL or not an array.
3326             @param num The number to be added.
3327             @return Whether successful.
3328             */
3329             yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc,
3330             yyjson_mut_val *arr,
3331             uint64_t num);
3332              
3333             /**
3334             Adds a signed integer value at the end of the array.
3335             @param doc The `doc` is only used for memory allocation.
3336             @param arr The array to which the value is to be inserted.
3337             Returns false if it is NULL or not an array.
3338             @param num The number to be added.
3339             @return Whether successful.
3340             */
3341             yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc,
3342             yyjson_mut_val *arr,
3343             int64_t num);
3344              
3345             /**
3346             Adds an integer value at the end of the array.
3347             @param doc The `doc` is only used for memory allocation.
3348             @param arr The array to which the value is to be inserted.
3349             Returns false if it is NULL or not an array.
3350             @param num The number to be added.
3351             @return Whether successful.
3352             */
3353             yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc,
3354             yyjson_mut_val *arr,
3355             int64_t num);
3356              
3357             /**
3358             Adds a float value at the end of the array.
3359             @param doc The `doc` is only used for memory allocation.
3360             @param arr The array to which the value is to be inserted.
3361             Returns false if it is NULL or not an array.
3362             @param num The number to be added.
3363             @return Whether successful.
3364             */
3365             yyjson_api_inline bool yyjson_mut_arr_add_float(yyjson_mut_doc *doc,
3366             yyjson_mut_val *arr,
3367             float num);
3368              
3369             /**
3370             Adds a double value at the end of the array.
3371             @param doc The `doc` is only used for memory allocation.
3372             @param arr The array to which the value is to be inserted.
3373             Returns false if it is NULL or not an array.
3374             @param num The number to be added.
3375             @return Whether successful.
3376             */
3377             yyjson_api_inline bool yyjson_mut_arr_add_double(yyjson_mut_doc *doc,
3378             yyjson_mut_val *arr,
3379             double num);
3380              
3381             /**
3382             Adds a double value at the end of the array.
3383             @param doc The `doc` is only used for memory allocation.
3384             @param arr The array to which the value is to be inserted.
3385             Returns false if it is NULL or not an array.
3386             @param num The number to be added.
3387             @return Whether successful.
3388             */
3389             yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc,
3390             yyjson_mut_val *arr,
3391             double num);
3392              
3393             /**
3394             Adds a string value at the end of the array (no copy).
3395             @param doc The `doc` is only used for memory allocation.
3396             @param arr The array to which the value is to be inserted.
3397             Returns false if it is NULL or not an array.
3398             @param str A null-terminated UTF-8 string.
3399             @return Whether successful.
3400             @warning The input string is not copied, you should keep this string unmodified
3401             for the lifetime of this JSON document.
3402             */
3403             yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc,
3404             yyjson_mut_val *arr,
3405             const char *str);
3406              
3407             /**
3408             Adds a string value at the end of the array (no copy).
3409             @param doc The `doc` is only used for memory allocation.
3410             @param arr The array to which the value is to be inserted.
3411             Returns false if it is NULL or not an array.
3412             @param str A UTF-8 string, null-terminator is not required.
3413             @param len The length of the string, in bytes.
3414             @return Whether successful.
3415             @warning The input string is not copied, you should keep this string unmodified
3416             for the lifetime of this JSON document.
3417             */
3418             yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc,
3419             yyjson_mut_val *arr,
3420             const char *str,
3421             size_t len);
3422              
3423             /**
3424             Adds a string value at the end of the array (copied).
3425             @param doc The `doc` is only used for memory allocation.
3426             @param arr The array to which the value is to be inserted.
3427             Returns false if it is NULL or not an array.
3428             @param str A null-terminated UTF-8 string.
3429             @return Whether successful.
3430             */
3431             yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc,
3432             yyjson_mut_val *arr,
3433             const char *str);
3434              
3435             /**
3436             Adds a string value at the end of the array (copied).
3437             @param doc The `doc` is only used for memory allocation.
3438             @param arr The array to which the value is to be inserted.
3439             Returns false if it is NULL or not an array.
3440             @param str A UTF-8 string, null-terminator is not required.
3441             @param len The length of the string, in bytes.
3442             @return Whether successful.
3443             */
3444             yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc,
3445             yyjson_mut_val *arr,
3446             const char *str,
3447             size_t len);
3448              
3449             /**
3450             Creates and adds a new array at the end of the array.
3451             @param doc The `doc` is only used for memory allocation.
3452             @param arr The array to which the value is to be inserted.
3453             Returns false if it is NULL or not an array.
3454             @return The new array, or NULL on error.
3455             */
3456             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc,
3457             yyjson_mut_val *arr);
3458              
3459             /**
3460             Creates and adds a new object at the end of the array.
3461             @param doc The `doc` is only used for memory allocation.
3462             @param arr The array to which the value is to be inserted.
3463             Returns false if it is NULL or not an array.
3464             @return The new object, or NULL on error.
3465             */
3466             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc,
3467             yyjson_mut_val *arr);
3468              
3469              
3470              
3471             /*==============================================================================
3472             * MARK: - Mutable JSON Object API
3473             *============================================================================*/
3474              
3475             /** Returns the number of key-value pairs in this object.
3476             Returns 0 if `obj` is NULL or type is not object. */
3477             yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj);
3478              
3479             /** Returns the value to which the specified key is mapped.
3480             Returns NULL if this object contains no mapping for the key.
3481             Returns NULL if `obj/key` is NULL, or type is not object.
3482              
3483             The `key` should be a null-terminated UTF-8 string.
3484              
3485             @warning This function takes a linear search time. */
3486             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj,
3487             const char *key);
3488              
3489             /** Returns the value to which the specified key is mapped.
3490             Returns NULL if this object contains no mapping for the key.
3491             Returns NULL if `obj/key` is NULL, or type is not object.
3492              
3493             The `key` should be a UTF-8 string, null-terminator is not required.
3494             The `key_len` should be the length of the key, in bytes.
3495              
3496             @warning This function takes a linear search time. */
3497             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj,
3498             const char *key,
3499             size_t key_len);
3500              
3501              
3502              
3503             /*==============================================================================
3504             * MARK: - Mutable JSON Object Iterator API
3505             *============================================================================*/
3506              
3507             /**
3508             A mutable JSON object iterator.
3509              
3510             @warning You should not modify the object while iterating over it, but you can
3511             use `yyjson_mut_obj_iter_remove()` to remove current value.
3512              
3513             @b Example
3514             @code
3515             yyjson_mut_val *key, *val;
3516             yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj);
3517             while ((key = yyjson_mut_obj_iter_next(&iter))) {
3518             val = yyjson_mut_obj_iter_get_val(key);
3519             your_func(key, val);
3520             if (your_val_is_unused(key, val)) {
3521             yyjson_mut_obj_iter_remove(&iter);
3522             }
3523             }
3524             @endcode
3525              
3526             If the ordering of the keys is known at compile-time, you can use this method
3527             to speed up value lookups:
3528             @code
3529             // {"k1":1, "k2": 3, "k3": 3}
3530             yyjson_mut_val *key, *val;
3531             yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj);
3532             yyjson_mut_val *v1 = yyjson_mut_obj_iter_get(&iter, "k1");
3533             yyjson_mut_val *v3 = yyjson_mut_obj_iter_get(&iter, "k3");
3534             @endcode
3535             @see `yyjson_mut_obj_iter_get()` and `yyjson_mut_obj_iter_getn()`
3536             */
3537             typedef struct yyjson_mut_obj_iter {
3538             size_t idx; /**< next key's index */
3539             size_t max; /**< maximum key index (obj.size) */
3540             yyjson_mut_val *cur; /**< current key */
3541             yyjson_mut_val *pre; /**< previous key */
3542             yyjson_mut_val *obj; /**< the object being iterated */
3543             } yyjson_mut_obj_iter;
3544              
3545             /**
3546             Initialize an iterator for this object.
3547              
3548             @param obj The object to be iterated over.
3549             If this parameter is NULL or not an array, `iter` will be set to empty.
3550             @param iter The iterator to be initialized.
3551             If this parameter is NULL, the function will fail and return false.
3552             @return true if the `iter` has been successfully initialized.
3553              
3554             @note The iterator does not need to be destroyed.
3555             */
3556             yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj,
3557             yyjson_mut_obj_iter *iter);
3558              
3559             /**
3560             Create an iterator with an object, same as `yyjson_obj_iter_init()`.
3561              
3562             @param obj The object to be iterated over.
3563             If this parameter is NULL or not an object, an empty iterator will returned.
3564             @return A new iterator for the object.
3565              
3566             @note The iterator does not need to be destroyed.
3567             */
3568             yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with(
3569             yyjson_mut_val *obj);
3570              
3571             /**
3572             Returns whether the iteration has more elements.
3573             If `iter` is NULL, this function will return false.
3574             */
3575             yyjson_api_inline bool yyjson_mut_obj_iter_has_next(
3576             yyjson_mut_obj_iter *iter);
3577              
3578             /**
3579             Returns the next key in the iteration, or NULL on end.
3580             If `iter` is NULL, this function will return NULL.
3581             */
3582             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next(
3583             yyjson_mut_obj_iter *iter);
3584              
3585             /**
3586             Returns the value for key inside the iteration.
3587             If `iter` is NULL, this function will return NULL.
3588             */
3589             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val(
3590             yyjson_mut_val *key);
3591              
3592             /**
3593             Removes current key-value pair in the iteration, returns the removed value.
3594             If `iter` is NULL, this function will return NULL.
3595             */
3596             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove(
3597             yyjson_mut_obj_iter *iter);
3598              
3599             /**
3600             Iterates to a specified key and returns the value.
3601              
3602             This function does the same thing as `yyjson_mut_obj_get()`, but is much faster
3603             if the ordering of the keys is known at compile-time and you are using the same
3604             order to look up the values. If the key exists in this object, then the
3605             iterator will stop at the next key, otherwise the iterator will not change and
3606             NULL is returned.
3607              
3608             @param iter The object iterator, should not be NULL.
3609             @param key The key, should be a UTF-8 string with null-terminator.
3610             @return The value to which the specified key is mapped.
3611             NULL if this object contains no mapping for the key or input is invalid.
3612              
3613             @warning This function takes a linear search time if the key is not nearby.
3614             */
3615             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get(
3616             yyjson_mut_obj_iter *iter, const char *key);
3617              
3618             /**
3619             Iterates to a specified key and returns the value.
3620              
3621             This function does the same thing as `yyjson_mut_obj_getn()` but is much faster
3622             if the ordering of the keys is known at compile-time and you are using the same
3623             order to look up the values. If the key exists in this object, then the
3624             iterator will stop at the next key, otherwise the iterator will not change and
3625             NULL is returned.
3626              
3627             @param iter The object iterator, should not be NULL.
3628             @param key The key, should be a UTF-8 string, null-terminator is not required.
3629             @param key_len The the length of `key`, in bytes.
3630             @return The value to which the specified key is mapped.
3631             NULL if this object contains no mapping for the key or input is invalid.
3632              
3633             @warning This function takes a linear search time if the key is not nearby.
3634             */
3635             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn(
3636             yyjson_mut_obj_iter *iter, const char *key, size_t key_len);
3637              
3638             /**
3639             Macro for iterating over an object.
3640             It works like iterator, but with a more intuitive API.
3641              
3642             @warning You should not modify the object while iterating over it.
3643              
3644             @b Example
3645             @code
3646             size_t idx, max;
3647             yyjson_mut_val *key, *val;
3648             yyjson_mut_obj_foreach(obj, idx, max, key, val) {
3649             your_func(key, val);
3650             }
3651             @endcode
3652             */
3653             #define yyjson_mut_obj_foreach(obj, idx, max, key, val) \
3654             for ((idx) = 0, \
3655             (max) = yyjson_mut_obj_size(obj), \
3656             (key) = (max) ? ((yyjson_mut_val *)(obj)->uni.ptr)->next->next : NULL, \
3657             (val) = (key) ? (key)->next : NULL; \
3658             (idx) < (max); \
3659             (idx)++, \
3660             (key) = (val)->next, \
3661             (val) = (key)->next)
3662              
3663              
3664              
3665             /*==============================================================================
3666             * MARK: - Mutable JSON Object Creation API
3667             *============================================================================*/
3668              
3669             /** Creates and returns a mutable object, returns NULL on error. */
3670             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc);
3671              
3672             /**
3673             Creates and returns a mutable object with keys and values, returns NULL on
3674             error. The keys and values are not copied. The strings should be a
3675             null-terminated UTF-8 string.
3676              
3677             @warning The input string is not copied, you should keep this string
3678             unmodified for the lifetime of this JSON document.
3679              
3680             @b Example
3681             @code
3682             const char *keys[2] = { "id", "name" };
3683             const char *vals[2] = { "01", "Harry" };
3684             yyjson_mut_val *obj = yyjson_mut_obj_with_str(doc, keys, vals, 2);
3685             @endcode
3686             */
3687             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc,
3688             const char **keys,
3689             const char **vals,
3690             size_t count);
3691              
3692             /**
3693             Creates and returns a mutable object with key-value pairs and pair count,
3694             returns NULL on error. The keys and values are not copied. The strings should
3695             be a null-terminated UTF-8 string.
3696              
3697             @warning The input string is not copied, you should keep this string
3698             unmodified for the lifetime of this JSON document.
3699              
3700             @b Example
3701             @code
3702             const char *kv_pairs[4] = { "id", "01", "name", "Harry" };
3703             yyjson_mut_val *obj = yyjson_mut_obj_with_kv(doc, kv_pairs, 2);
3704             @endcode
3705             */
3706             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc,
3707             const char **kv_pairs,
3708             size_t pair_count);
3709              
3710              
3711              
3712             /*==============================================================================
3713             * MARK: - Mutable JSON Object Modification API
3714             *============================================================================*/
3715              
3716             /**
3717             Adds a key-value pair at the end of the object.
3718             This function allows duplicated key in one object.
3719             @param obj The object to which the new key-value pair is to be added.
3720             @param key The key, should be a string which is created by `yyjson_mut_str()`,
3721             `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
3722             @param val The value to add to the object.
3723             @return Whether successful.
3724             */
3725             yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj,
3726             yyjson_mut_val *key,
3727             yyjson_mut_val *val);
3728             /**
3729             Sets a key-value pair at the end of the object.
3730             This function may remove all key-value pairs for the given key before add.
3731             @param obj The object to which the new key-value pair is to be added.
3732             @param key The key, should be a string which is created by `yyjson_mut_str()`,
3733             `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
3734             @param val The value to add to the object. If this value is null, the behavior
3735             is same as `yyjson_mut_obj_remove()`.
3736             @return Whether successful.
3737             */
3738             yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj,
3739             yyjson_mut_val *key,
3740             yyjson_mut_val *val);
3741              
3742             /**
3743             Inserts a key-value pair to the object at the given position.
3744             This function allows duplicated key in one object.
3745             @param obj The object to which the new key-value pair is to be added.
3746             @param key The key, should be a string which is created by `yyjson_mut_str()`,
3747             `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
3748             @param val The value to add to the object.
3749             @param idx The index to which to insert the new pair.
3750             @return Whether successful.
3751             */
3752             yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj,
3753             yyjson_mut_val *key,
3754             yyjson_mut_val *val,
3755             size_t idx);
3756              
3757             /**
3758             Removes all key-value pair from the object with given key.
3759             @param obj The object from which the key-value pair is to be removed.
3760             @param key The key, should be a string value.
3761             @return The first matched value, or NULL if no matched value.
3762             @warning This function takes a linear search time.
3763             */
3764             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj,
3765             yyjson_mut_val *key);
3766              
3767             /**
3768             Removes all key-value pair from the object with given key.
3769             @param obj The object from which the key-value pair is to be removed.
3770             @param key The key, should be a UTF-8 string with null-terminator.
3771             @return The first matched value, or NULL if no matched value.
3772             @warning This function takes a linear search time.
3773             */
3774             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key(
3775             yyjson_mut_val *obj, const char *key);
3776              
3777             /**
3778             Removes all key-value pair from the object with given key.
3779             @param obj The object from which the key-value pair is to be removed.
3780             @param key The key, should be a UTF-8 string, null-terminator is not required.
3781             @param key_len The length of the key.
3782             @return The first matched value, or NULL if no matched value.
3783             @warning This function takes a linear search time.
3784             */
3785             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn(
3786             yyjson_mut_val *obj, const char *key, size_t key_len);
3787              
3788             /**
3789             Removes all key-value pairs in this object.
3790             @param obj The object from which all of the values are to be removed.
3791             @return Whether successful.
3792             */
3793             yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj);
3794              
3795             /**
3796             Replaces value from the object with given key.
3797             If the key is not exist, or the value is NULL, it will fail.
3798             @param obj The object to which the value is to be replaced.
3799             @param key The key, should be a string value.
3800             @param val The value to replace into the object.
3801             @return Whether successful.
3802             @warning This function takes a linear search time.
3803             */
3804             yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj,
3805             yyjson_mut_val *key,
3806             yyjson_mut_val *val);
3807              
3808             /**
3809             Rotates key-value pairs in the object for the given number of times.
3810             For example: `{"a":1,"b":2,"c":3,"d":4}` rotate 1 is
3811             `{"b":2,"c":3,"d":4,"a":1}`.
3812             @param obj The object to be rotated.
3813             @param idx Index (or times) to rotate.
3814             @return Whether successful.
3815             @warning This function takes a linear search time.
3816             */
3817             yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj,
3818             size_t idx);
3819              
3820              
3821              
3822             /*==============================================================================
3823             * MARK: - Mutable JSON Object Modification Convenience API
3824             *============================================================================*/
3825              
3826             /** Adds a `null` value at the end of the object.
3827             The `key` should be a null-terminated UTF-8 string.
3828             This function allows duplicated key in one object.
3829              
3830             @warning The key string is not copied, you should keep the string
3831             unmodified for the lifetime of this JSON document. */
3832             yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
3833             yyjson_mut_val *obj,
3834             const char *key);
3835              
3836             /** Adds a `true` value at the end of the object.
3837             The `key` should be a null-terminated UTF-8 string.
3838             This function allows duplicated key in one object.
3839              
3840             @warning The key string is not copied, you should keep the string
3841             unmodified for the lifetime of this JSON document. */
3842             yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
3843             yyjson_mut_val *obj,
3844             const char *key);
3845              
3846             /** Adds a `false` value at the end of the object.
3847             The `key` should be a null-terminated UTF-8 string.
3848             This function allows duplicated key in one object.
3849              
3850             @warning The key string is not copied, you should keep the string
3851             unmodified for the lifetime of this JSON document. */
3852             yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
3853             yyjson_mut_val *obj,
3854             const char *key);
3855              
3856             /** Adds a bool value at the end of the object.
3857             The `key` should be a null-terminated UTF-8 string.
3858             This function allows duplicated key in one object.
3859              
3860             @warning The key string is not copied, you should keep the string
3861             unmodified for the lifetime of this JSON document. */
3862             yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
3863             yyjson_mut_val *obj,
3864             const char *key, bool val);
3865              
3866             /** Adds an unsigned integer value at the end of the object.
3867             The `key` should be a null-terminated UTF-8 string.
3868             This function allows duplicated key in one object.
3869              
3870             @warning The key string is not copied, you should keep the string
3871             unmodified for the lifetime of this JSON document. */
3872             yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
3873             yyjson_mut_val *obj,
3874             const char *key, uint64_t val);
3875              
3876             /** Adds a signed integer value at the end of the object.
3877             The `key` should be a null-terminated UTF-8 string.
3878             This function allows duplicated key in one object.
3879              
3880             @warning The key string is not copied, you should keep the string
3881             unmodified for the lifetime of this JSON document. */
3882             yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
3883             yyjson_mut_val *obj,
3884             const char *key, int64_t val);
3885              
3886             /** Adds an int value at the end of the object.
3887             The `key` should be a null-terminated UTF-8 string.
3888             This function allows duplicated key in one object.
3889              
3890             @warning The key string is not copied, you should keep the string
3891             unmodified for the lifetime of this JSON document. */
3892             yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
3893             yyjson_mut_val *obj,
3894             const char *key, int64_t val);
3895              
3896             /** Adds a float value at the end of the object.
3897             The `key` should be a null-terminated UTF-8 string.
3898             This function allows duplicated key in one object.
3899              
3900             @warning The key string is not copied, you should keep the string
3901             unmodified for the lifetime of this JSON document. */
3902             yyjson_api_inline bool yyjson_mut_obj_add_float(yyjson_mut_doc *doc,
3903             yyjson_mut_val *obj,
3904             const char *key, float val);
3905              
3906             /** Adds a double value at the end of the object.
3907             The `key` should be a null-terminated UTF-8 string.
3908             This function allows duplicated key in one object.
3909              
3910             @warning The key string is not copied, you should keep the string
3911             unmodified for the lifetime of this JSON document. */
3912             yyjson_api_inline bool yyjson_mut_obj_add_double(yyjson_mut_doc *doc,
3913             yyjson_mut_val *obj,
3914             const char *key, double val);
3915              
3916             /** Adds a real value at the end of the object.
3917             The `key` should be a null-terminated UTF-8 string.
3918             This function allows duplicated key in one object.
3919              
3920             @warning The key string is not copied, you should keep the string
3921             unmodified for the lifetime of this JSON document. */
3922             yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
3923             yyjson_mut_val *obj,
3924             const char *key, double val);
3925              
3926             /** Adds a string value at the end of the object.
3927             The `key` and `val` should be null-terminated UTF-8 strings.
3928             This function allows duplicated key in one object.
3929              
3930             @warning The key/value strings are not copied, you should keep these strings
3931             unmodified for the lifetime of this JSON document. */
3932             yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
3933             yyjson_mut_val *obj,
3934             const char *key, const char *val);
3935              
3936             /** Adds a string value at the end of the object.
3937             The `key` should be a null-terminated UTF-8 string.
3938             The `val` should be a UTF-8 string, null-terminator is not required.
3939             The `len` should be the length of the `val`, in bytes.
3940             This function allows duplicated key in one object.
3941              
3942             @warning The key/value strings are not copied, you should keep these strings
3943             unmodified for the lifetime of this JSON document. */
3944             yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
3945             yyjson_mut_val *obj,
3946             const char *key,
3947             const char *val, size_t len);
3948              
3949             /** Adds a string value at the end of the object.
3950             The `key` and `val` should be null-terminated UTF-8 strings.
3951             The value string is copied.
3952             This function allows duplicated key in one object.
3953              
3954             @warning The key string is not copied, you should keep the string
3955             unmodified for the lifetime of this JSON document. */
3956             yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
3957             yyjson_mut_val *obj,
3958             const char *key,
3959             const char *val);
3960              
3961             /** Adds a string value at the end of the object.
3962             The `key` should be a null-terminated UTF-8 string.
3963             The `val` should be a UTF-8 string, null-terminator is not required.
3964             The `len` should be the length of the `val`, in bytes.
3965             This function allows duplicated key in one object.
3966              
3967             @warning The key strings are not copied, you should keep these strings
3968             unmodified for the lifetime of this JSON document. */
3969             yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
3970             yyjson_mut_val *obj,
3971             const char *key,
3972             const char *val, size_t len);
3973              
3974             /**
3975             Creates and adds a new array to the target object.
3976             The `key` should be a null-terminated UTF-8 string.
3977             This function allows duplicated key in one object.
3978              
3979             @warning The key string is not copied, you should keep these strings
3980             unmodified for the lifetime of this JSON document.
3981             @return The new array, or NULL on error.
3982             */
3983             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc,
3984             yyjson_mut_val *obj,
3985             const char *key);
3986              
3987             /**
3988             Creates and adds a new object to the target object.
3989             The `key` should be a null-terminated UTF-8 string.
3990             This function allows duplicated key in one object.
3991              
3992             @warning The key string is not copied, you should keep these strings
3993             unmodified for the lifetime of this JSON document.
3994             @return The new object, or NULL on error.
3995             */
3996             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc,
3997             yyjson_mut_val *obj,
3998             const char *key);
3999              
4000             /** Adds a JSON value at the end of the object.
4001             The `key` should be a null-terminated UTF-8 string.
4002             This function allows duplicated key in one object.
4003              
4004             @warning The key string is not copied, you should keep the string
4005             unmodified for the lifetime of this JSON document. */
4006             yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
4007             yyjson_mut_val *obj,
4008             const char *key,
4009             yyjson_mut_val *val);
4010              
4011             /** Removes all key-value pairs for the given key.
4012             Returns the first value to which the specified key is mapped or NULL if this
4013             object contains no mapping for the key.
4014             The `key` should be a null-terminated UTF-8 string.
4015              
4016             @warning This function takes a linear search time. */
4017             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str(
4018             yyjson_mut_val *obj, const char *key);
4019              
4020             /** Removes all key-value pairs for the given key.
4021             Returns the first value to which the specified key is mapped or NULL if this
4022             object contains no mapping for the key.
4023             The `key` should be a UTF-8 string, null-terminator is not required.
4024             The `len` should be the length of the key, in bytes.
4025              
4026             @warning This function takes a linear search time. */
4027             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn(
4028             yyjson_mut_val *obj, const char *key, size_t len);
4029              
4030             /** Replaces all matching keys with the new key.
4031             Returns true if at least one key was renamed.
4032             The `key` and `new_key` should be a null-terminated UTF-8 string.
4033             The `new_key` is copied and held by doc.
4034              
4035             @warning This function takes a linear search time.
4036             If `new_key` already exists, it will cause duplicate keys.
4037             */
4038             yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc,
4039             yyjson_mut_val *obj,
4040             const char *key,
4041             const char *new_key);
4042              
4043             /** Replaces all matching keys with the new key.
4044             Returns true if at least one key was renamed.
4045             The `key` and `new_key` should be a UTF-8 string,
4046             null-terminator is not required. The `new_key` is copied and held by doc.
4047              
4048             @warning This function takes a linear search time.
4049             If `new_key` already exists, it will cause duplicate keys.
4050             */
4051             yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc,
4052             yyjson_mut_val *obj,
4053             const char *key,
4054             size_t len,
4055             const char *new_key,
4056             size_t new_len);
4057              
4058              
4059              
4060             #if !defined(YYJSON_DISABLE_UTILS) || !YYJSON_DISABLE_UTILS
4061              
4062             /*==============================================================================
4063             * MARK: - JSON Pointer API (RFC 6901)
4064             * https://tools.ietf.org/html/rfc6901
4065             *============================================================================*/
4066              
4067             /** JSON Pointer error code. */
4068             typedef uint32_t yyjson_ptr_code;
4069              
4070             /** No JSON pointer error. */
4071             static const yyjson_ptr_code YYJSON_PTR_ERR_NONE = 0;
4072              
4073             /** Invalid input parameter, such as NULL input. */
4074             static const yyjson_ptr_code YYJSON_PTR_ERR_PARAMETER = 1;
4075              
4076             /** JSON pointer syntax error, such as invalid escape, token no prefix. */
4077             static const yyjson_ptr_code YYJSON_PTR_ERR_SYNTAX = 2;
4078              
4079             /** JSON pointer resolve failed, such as index out of range, key not found. */
4080             static const yyjson_ptr_code YYJSON_PTR_ERR_RESOLVE = 3;
4081              
4082             /** Document's root is NULL, but it is required for the function call. */
4083             static const yyjson_ptr_code YYJSON_PTR_ERR_NULL_ROOT = 4;
4084              
4085             /** Cannot set root as the target is not a document. */
4086             static const yyjson_ptr_code YYJSON_PTR_ERR_SET_ROOT = 5;
4087              
4088             /** The memory allocation failed and a new value could not be created. */
4089             static const yyjson_ptr_code YYJSON_PTR_ERR_MEMORY_ALLOCATION = 6;
4090              
4091             /** Error information for JSON pointer. */
4092             typedef struct yyjson_ptr_err {
4093             /** Error code, see `yyjson_ptr_code` for all possible values. */
4094             yyjson_ptr_code code;
4095             /** Error message, constant, no need to free (NULL if no error). */
4096             const char *msg;
4097             /** Error byte position for input JSON pointer (0 if no error). */
4098             size_t pos;
4099             } yyjson_ptr_err;
4100              
4101             /**
4102             A context for JSON pointer operation.
4103              
4104             This struct stores the context of JSON Pointer operation result. The struct
4105             can be used with three helper functions: `ctx_append()`, `ctx_replace()`, and
4106             `ctx_remove()`, which perform the corresponding operations on the container
4107             without re-parsing the JSON Pointer.
4108              
4109             For example:
4110             @code
4111             // doc before: {"a":[0,1,null]}
4112             // ptr: "/a/2"
4113             val = yyjson_mut_doc_ptr_getx(doc, ptr, strlen(ptr), &ctx, &err);
4114             if (yyjson_is_null(val)) {
4115             yyjson_ptr_ctx_remove(&ctx);
4116             }
4117             // doc after: {"a":[0,1]}
4118             @endcode
4119             */
4120             typedef struct yyjson_ptr_ctx {
4121             /**
4122             The container (parent) of the target value. It can be either an array or
4123             an object. If the target location has no value, but all its parent
4124             containers exist, and the target location can be used to insert a new
4125             value, then `ctn` is the parent container of the target location.
4126             Otherwise, `ctn` is NULL.
4127             */
4128             yyjson_mut_val *ctn;
4129             /**
4130             The previous sibling of the target value. It can be either a value in an
4131             array or a key in an object. As the container is a `circular linked list`
4132             of elements, `pre` is the previous node of the target value. If the
4133             operation is `add` or `set`, then `pre` is the previous node of the new
4134             value, not the original target value. If the target value does not exist,
4135             `pre` is NULL.
4136             */
4137             yyjson_mut_val *pre;
4138             /**
4139             The removed value if the operation is `set`, `replace` or `remove`. It can
4140             be used to restore the original state of the document if needed.
4141             */
4142             yyjson_mut_val *old;
4143             } yyjson_ptr_ctx;
4144              
4145             /**
4146             Get value by a JSON Pointer.
4147             @param doc The JSON document to be queried.
4148             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4149             @return The value referenced by the JSON pointer.
4150             NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4151             */
4152             yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc,
4153             const char *ptr);
4154              
4155             /**
4156             Get value by a JSON Pointer.
4157             @param doc The JSON document to be queried.
4158             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4159             @param len The length of `ptr` in bytes.
4160             @return The value referenced by the JSON pointer.
4161             NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4162             */
4163             yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc,
4164             const char *ptr, size_t len);
4165              
4166             /**
4167             Get value by a JSON Pointer.
4168             @param doc The JSON document to be queried.
4169             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4170             @param len The length of `ptr` in bytes.
4171             @param err A pointer to store the error information, or NULL if not needed.
4172             @return The value referenced by the JSON pointer.
4173             NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4174             */
4175             yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc,
4176             const char *ptr, size_t len,
4177             yyjson_ptr_err *err);
4178              
4179             /**
4180             Get value by a JSON Pointer.
4181             @param val The JSON value to be queried.
4182             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4183             @return The value referenced by the JSON pointer.
4184             NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4185             */
4186             yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val,
4187             const char *ptr);
4188              
4189             /**
4190             Get value by a JSON Pointer.
4191             @param val The JSON value to be queried.
4192             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4193             @param len The length of `ptr` in bytes.
4194             @return The value referenced by the JSON pointer.
4195             NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4196             */
4197             yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val,
4198             const char *ptr, size_t len);
4199              
4200             /**
4201             Get value by a JSON Pointer.
4202             @param val The JSON value to be queried.
4203             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4204             @param len The length of `ptr` in bytes.
4205             @param err A pointer to store the error information, or NULL if not needed.
4206             @return The value referenced by the JSON pointer.
4207             NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4208             */
4209             yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val,
4210             const char *ptr, size_t len,
4211             yyjson_ptr_err *err);
4212              
4213             /**
4214             Get value by a JSON Pointer.
4215             @param doc The JSON document to be queried.
4216             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4217             @return The value referenced by the JSON pointer.
4218             NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4219             */
4220             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc,
4221             const char *ptr);
4222              
4223             /**
4224             Get value by a JSON Pointer.
4225             @param doc The JSON document to be queried.
4226             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4227             @param len The length of `ptr` in bytes.
4228             @return The value referenced by the JSON pointer.
4229             NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4230             */
4231             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc,
4232             const char *ptr,
4233             size_t len);
4234              
4235             /**
4236             Get value by a JSON Pointer.
4237             @param doc The JSON document to be queried.
4238             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4239             @param len The length of `ptr` in bytes.
4240             @param ctx A pointer to store the result context, or NULL if not needed.
4241             @param err A pointer to store the error information, or NULL if not needed.
4242             @return The value referenced by the JSON pointer.
4243             NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4244             */
4245             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc,
4246             const char *ptr,
4247             size_t len,
4248             yyjson_ptr_ctx *ctx,
4249             yyjson_ptr_err *err);
4250              
4251             /**
4252             Get value by a JSON Pointer.
4253             @param val The JSON value to be queried.
4254             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4255             @return The value referenced by the JSON pointer.
4256             NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4257             */
4258             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val,
4259             const char *ptr);
4260              
4261             /**
4262             Get value by a JSON Pointer.
4263             @param val The JSON value to be queried.
4264             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4265             @param len The length of `ptr` in bytes.
4266             @return The value referenced by the JSON pointer.
4267             NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4268             */
4269             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val,
4270             const char *ptr,
4271             size_t len);
4272              
4273             /**
4274             Get value by a JSON Pointer.
4275             @param val The JSON value to be queried.
4276             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4277             @param len The length of `ptr` in bytes.
4278             @param ctx A pointer to store the result context, or NULL if not needed.
4279             @param err A pointer to store the error information, or NULL if not needed.
4280             @return The value referenced by the JSON pointer.
4281             NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
4282             */
4283             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val,
4284             const char *ptr,
4285             size_t len,
4286             yyjson_ptr_ctx *ctx,
4287             yyjson_ptr_err *err);
4288              
4289             /**
4290             Add (insert) value by a JSON pointer.
4291             @param doc The target JSON document.
4292             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4293             @param new_val The value to be added.
4294             @return true if JSON pointer is valid and new value is added, false otherwise.
4295             @note The parent nodes will be created if they do not exist.
4296             */
4297             yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc,
4298             const char *ptr,
4299             yyjson_mut_val *new_val);
4300              
4301             /**
4302             Add (insert) value by a JSON pointer.
4303             @param doc The target JSON document.
4304             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4305             @param len The length of `ptr` in bytes.
4306             @param new_val The value to be added.
4307             @return true if JSON pointer is valid and new value is added, false otherwise.
4308             @note The parent nodes will be created if they do not exist.
4309             */
4310             yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc,
4311             const char *ptr, size_t len,
4312             yyjson_mut_val *new_val);
4313              
4314             /**
4315             Add (insert) value by a JSON pointer.
4316             @param doc The target JSON document.
4317             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4318             @param len The length of `ptr` in bytes.
4319             @param new_val The value to be added.
4320             @param create_parent Whether to create parent nodes if not exist.
4321             @param ctx A pointer to store the result context, or NULL if not needed.
4322             @param err A pointer to store the error information, or NULL if not needed.
4323             @return true if JSON pointer is valid and new value is added, false otherwise.
4324             */
4325             yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc,
4326             const char *ptr, size_t len,
4327             yyjson_mut_val *new_val,
4328             bool create_parent,
4329             yyjson_ptr_ctx *ctx,
4330             yyjson_ptr_err *err);
4331              
4332             /**
4333             Add (insert) value by a JSON pointer.
4334             @param val The target JSON value.
4335             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4336             @param doc Only used to create new values when needed.
4337             @param new_val The value to be added.
4338             @return true if JSON pointer is valid and new value is added, false otherwise.
4339             @note The parent nodes will be created if they do not exist.
4340             */
4341             yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val,
4342             const char *ptr,
4343             yyjson_mut_val *new_val,
4344             yyjson_mut_doc *doc);
4345              
4346             /**
4347             Add (insert) value by a JSON pointer.
4348             @param val The target JSON value.
4349             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4350             @param len The length of `ptr` in bytes.
4351             @param doc Only used to create new values when needed.
4352             @param new_val The value to be added.
4353             @return true if JSON pointer is valid and new value is added, false otherwise.
4354             @note The parent nodes will be created if they do not exist.
4355             */
4356             yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val,
4357             const char *ptr, size_t len,
4358             yyjson_mut_val *new_val,
4359             yyjson_mut_doc *doc);
4360              
4361             /**
4362             Add (insert) value by a JSON pointer.
4363             @param val The target JSON value.
4364             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4365             @param len The length of `ptr` in bytes.
4366             @param doc Only used to create new values when needed.
4367             @param new_val The value to be added.
4368             @param create_parent Whether to create parent nodes if not exist.
4369             @param ctx A pointer to store the result context, or NULL if not needed.
4370             @param err A pointer to store the error information, or NULL if not needed.
4371             @return true if JSON pointer is valid and new value is added, false otherwise.
4372             */
4373             yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val,
4374             const char *ptr, size_t len,
4375             yyjson_mut_val *new_val,
4376             yyjson_mut_doc *doc,
4377             bool create_parent,
4378             yyjson_ptr_ctx *ctx,
4379             yyjson_ptr_err *err);
4380              
4381             /**
4382             Set value by a JSON pointer.
4383             @param doc The target JSON document.
4384             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4385             @param new_val The value to be set, pass NULL to remove.
4386             @return true if JSON pointer is valid and new value is set, false otherwise.
4387             @note The parent nodes will be created if they do not exist.
4388             If the target value already exists, it will be replaced by the new value.
4389             */
4390             yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc,
4391             const char *ptr,
4392             yyjson_mut_val *new_val);
4393              
4394             /**
4395             Set value by a JSON pointer.
4396             @param doc The target JSON document.
4397             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4398             @param len The length of `ptr` in bytes.
4399             @param new_val The value to be set, pass NULL to remove.
4400             @return true if JSON pointer is valid and new value is set, false otherwise.
4401             @note The parent nodes will be created if they do not exist.
4402             If the target value already exists, it will be replaced by the new value.
4403             */
4404             yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc,
4405             const char *ptr, size_t len,
4406             yyjson_mut_val *new_val);
4407              
4408             /**
4409             Set value by a JSON pointer.
4410             @param doc The target JSON document.
4411             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4412             @param len The length of `ptr` in bytes.
4413             @param new_val The value to be set, pass NULL to remove.
4414             @param create_parent Whether to create parent nodes if not exist.
4415             @param ctx A pointer to store the result context, or NULL if not needed.
4416             @param err A pointer to store the error information, or NULL if not needed.
4417             @return true if JSON pointer is valid and new value is set, false otherwise.
4418             @note If the target value already exists, it will be replaced by the new value.
4419             */
4420             yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc,
4421             const char *ptr, size_t len,
4422             yyjson_mut_val *new_val,
4423             bool create_parent,
4424             yyjson_ptr_ctx *ctx,
4425             yyjson_ptr_err *err);
4426              
4427             /**
4428             Set value by a JSON pointer.
4429             @param val The target JSON value.
4430             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4431             @param new_val The value to be set, pass NULL to remove.
4432             @param doc Only used to create new values when needed.
4433             @return true if JSON pointer is valid and new value is set, false otherwise.
4434             @note The parent nodes will be created if they do not exist.
4435             If the target value already exists, it will be replaced by the new value.
4436             */
4437             yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val,
4438             const char *ptr,
4439             yyjson_mut_val *new_val,
4440             yyjson_mut_doc *doc);
4441              
4442             /**
4443             Set value by a JSON pointer.
4444             @param val The target JSON value.
4445             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4446             @param len The length of `ptr` in bytes.
4447             @param new_val The value to be set, pass NULL to remove.
4448             @param doc Only used to create new values when needed.
4449             @return true if JSON pointer is valid and new value is set, false otherwise.
4450             @note The parent nodes will be created if they do not exist.
4451             If the target value already exists, it will be replaced by the new value.
4452             */
4453             yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val,
4454             const char *ptr, size_t len,
4455             yyjson_mut_val *new_val,
4456             yyjson_mut_doc *doc);
4457              
4458             /**
4459             Set value by a JSON pointer.
4460             @param val The target JSON value.
4461             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4462             @param len The length of `ptr` in bytes.
4463             @param new_val The value to be set, pass NULL to remove.
4464             @param doc Only used to create new values when needed.
4465             @param create_parent Whether to create parent nodes if not exist.
4466             @param ctx A pointer to store the result context, or NULL if not needed.
4467             @param err A pointer to store the error information, or NULL if not needed.
4468             @return true if JSON pointer is valid and new value is set, false otherwise.
4469             @note If the target value already exists, it will be replaced by the new value.
4470             */
4471             yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val,
4472             const char *ptr, size_t len,
4473             yyjson_mut_val *new_val,
4474             yyjson_mut_doc *doc,
4475             bool create_parent,
4476             yyjson_ptr_ctx *ctx,
4477             yyjson_ptr_err *err);
4478              
4479             /**
4480             Replace value by a JSON pointer.
4481             @param doc The target JSON document.
4482             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4483             @param new_val The new value to replace the old one.
4484             @return The old value that was replaced, or NULL if not found.
4485             */
4486             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace(
4487             yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val);
4488              
4489             /**
4490             Replace value by a JSON pointer.
4491             @param doc The target JSON document.
4492             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4493             @param len The length of `ptr` in bytes.
4494             @param new_val The new value to replace the old one.
4495             @return The old value that was replaced, or NULL if not found.
4496             */
4497             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen(
4498             yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val);
4499              
4500             /**
4501             Replace value by a JSON pointer.
4502             @param doc The target JSON document.
4503             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4504             @param len The length of `ptr` in bytes.
4505             @param new_val The new value to replace the old one.
4506             @param ctx A pointer to store the result context, or NULL if not needed.
4507             @param err A pointer to store the error information, or NULL if not needed.
4508             @return The old value that was replaced, or NULL if not found.
4509             */
4510             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex(
4511             yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val,
4512             yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
4513              
4514             /**
4515             Replace value by a JSON pointer.
4516             @param val The target JSON value.
4517             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4518             @param new_val The new value to replace the old one.
4519             @return The old value that was replaced, or NULL if not found.
4520             */
4521             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace(
4522             yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val);
4523              
4524             /**
4525             Replace value by a JSON pointer.
4526             @param val The target JSON value.
4527             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4528             @param len The length of `ptr` in bytes.
4529             @param new_val The new value to replace the old one.
4530             @return The old value that was replaced, or NULL if not found.
4531             */
4532             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen(
4533             yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val);
4534              
4535             /**
4536             Replace value by a JSON pointer.
4537             @param val The target JSON value.
4538             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4539             @param len The length of `ptr` in bytes.
4540             @param new_val The new value to replace the old one.
4541             @param ctx A pointer to store the result context, or NULL if not needed.
4542             @param err A pointer to store the error information, or NULL if not needed.
4543             @return The old value that was replaced, or NULL if not found.
4544             */
4545             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex(
4546             yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
4547             yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
4548              
4549             /**
4550             Remove value by a JSON pointer.
4551             @param doc The target JSON document.
4552             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4553             @return The removed value, or NULL on error.
4554             */
4555             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove(
4556             yyjson_mut_doc *doc, const char *ptr);
4557              
4558             /**
4559             Remove value by a JSON pointer.
4560             @param doc The target JSON document.
4561             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4562             @param len The length of `ptr` in bytes.
4563             @return The removed value, or NULL on error.
4564             */
4565             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen(
4566             yyjson_mut_doc *doc, const char *ptr, size_t len);
4567              
4568             /**
4569             Remove value by a JSON pointer.
4570             @param doc The target JSON document.
4571             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4572             @param len The length of `ptr` in bytes.
4573             @param ctx A pointer to store the result context, or NULL if not needed.
4574             @param err A pointer to store the error information, or NULL if not needed.
4575             @return The removed value, or NULL on error.
4576             */
4577             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex(
4578             yyjson_mut_doc *doc, const char *ptr, size_t len,
4579             yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
4580              
4581             /**
4582             Remove value by a JSON pointer.
4583             @param val The target JSON value.
4584             @param ptr The JSON pointer string (UTF-8 with null-terminator).
4585             @return The removed value, or NULL on error.
4586             */
4587             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val,
4588             const char *ptr);
4589              
4590             /**
4591             Remove value by a JSON pointer.
4592             @param val The target JSON value.
4593             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4594             @param len The length of `ptr` in bytes.
4595             @return The removed value, or NULL on error.
4596             */
4597             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val,
4598             const char *ptr,
4599             size_t len);
4600              
4601             /**
4602             Remove value by a JSON pointer.
4603             @param val The target JSON value.
4604             @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
4605             @param len The length of `ptr` in bytes.
4606             @param ctx A pointer to store the result context, or NULL if not needed.
4607             @param err A pointer to store the error information, or NULL if not needed.
4608             @return The removed value, or NULL on error.
4609             */
4610             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val,
4611             const char *ptr,
4612             size_t len,
4613             yyjson_ptr_ctx *ctx,
4614             yyjson_ptr_err *err);
4615              
4616             /**
4617             Append value by JSON pointer context.
4618             @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
4619             @param key New key if `ctx->ctn` is object, or NULL if `ctx->ctn` is array.
4620             @param val New value to be added.
4621             @return true on success or false on fail.
4622             */
4623             yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx,
4624             yyjson_mut_val *key,
4625             yyjson_mut_val *val);
4626              
4627             /**
4628             Replace value by JSON pointer context.
4629             @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
4630             @param val New value to be replaced.
4631             @return true on success or false on fail.
4632             @note If success, the old value will be returned via `ctx->old`.
4633             */
4634             yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx,
4635             yyjson_mut_val *val);
4636              
4637             /**
4638             Remove value by JSON pointer context.
4639             @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
4640             @return true on success or false on fail.
4641             @note If success, the old value will be returned via `ctx->old`.
4642             */
4643             yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx);
4644              
4645              
4646              
4647             /*==============================================================================
4648             * MARK: - JSON Patch API (RFC 6902)
4649             * https://tools.ietf.org/html/rfc6902
4650             *============================================================================*/
4651              
4652             /** Result code for JSON patch. */
4653             typedef uint32_t yyjson_patch_code;
4654              
4655             /** Success, no error. */
4656             static const yyjson_patch_code YYJSON_PATCH_SUCCESS = 0;
4657              
4658             /** Invalid parameter, such as NULL input or non-array patch. */
4659             static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_PARAMETER = 1;
4660              
4661             /** Memory allocation failure occurs. */
4662             static const yyjson_patch_code YYJSON_PATCH_ERROR_MEMORY_ALLOCATION = 2;
4663              
4664             /** JSON patch operation is not object type. */
4665             static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_OPERATION = 3;
4666              
4667             /** JSON patch operation is missing a required key. */
4668             static const yyjson_patch_code YYJSON_PATCH_ERROR_MISSING_KEY = 4;
4669              
4670             /** JSON patch operation member is invalid. */
4671             static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_MEMBER = 5;
4672              
4673             /** JSON patch operation `test` not equal. */
4674             static const yyjson_patch_code YYJSON_PATCH_ERROR_EQUAL = 6;
4675              
4676             /** JSON patch operation failed on JSON pointer. */
4677             static const yyjson_patch_code YYJSON_PATCH_ERROR_POINTER = 7;
4678              
4679             /** Error information for JSON patch. */
4680             typedef struct yyjson_patch_err {
4681             /** Error code, see `yyjson_patch_code` for all possible values. */
4682             yyjson_patch_code code;
4683             /** Index of the error operation (0 if no error). */
4684             size_t idx;
4685             /** Error message, constant, no need to free (NULL if no error). */
4686             const char *msg;
4687             /** JSON pointer error if `code == YYJSON_PATCH_ERROR_POINTER`. */
4688             yyjson_ptr_err ptr;
4689             } yyjson_patch_err;
4690              
4691             /**
4692             Creates and returns a patched JSON value (RFC 6902).
4693             The memory of the returned value is allocated by the `doc`.
4694             The `err` is used to receive error information, pass NULL if not needed.
4695             Returns NULL if the patch could not be applied.
4696             */
4697             yyjson_api yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc,
4698             yyjson_val *orig,
4699             yyjson_val *patch,
4700             yyjson_patch_err *err);
4701              
4702             /**
4703             Creates and returns a patched JSON value (RFC 6902).
4704             The memory of the returned value is allocated by the `doc`.
4705             The `err` is used to receive error information, pass NULL if not needed.
4706             Returns NULL if the patch could not be applied.
4707             */
4708             yyjson_api yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc,
4709             yyjson_mut_val *orig,
4710             yyjson_mut_val *patch,
4711             yyjson_patch_err *err);
4712              
4713              
4714              
4715             /*==============================================================================
4716             * MARK: - JSON Merge-Patch API (RFC 7386)
4717             * https://tools.ietf.org/html/rfc7386
4718             *============================================================================*/
4719              
4720             /**
4721             Creates and returns a merge-patched JSON value (RFC 7386).
4722             The memory of the returned value is allocated by the `doc`.
4723             Returns NULL if the patch could not be applied.
4724              
4725             @warning This function is recursive and may cause a stack overflow if the
4726             object level is too deep.
4727             */
4728             yyjson_api yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc,
4729             yyjson_val *orig,
4730             yyjson_val *patch);
4731              
4732             /**
4733             Creates and returns a merge-patched JSON value (RFC 7386).
4734             The memory of the returned value is allocated by the `doc`.
4735             Returns NULL if the patch could not be applied.
4736              
4737             @warning This function is recursive and may cause a stack overflow if the
4738             object level is too deep.
4739             */
4740             yyjson_api yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc,
4741             yyjson_mut_val *orig,
4742             yyjson_mut_val *patch);
4743              
4744             #endif /* YYJSON_DISABLE_UTILS */
4745              
4746              
4747              
4748             /*==============================================================================
4749             * MARK: - JSON Structure (Implementation)
4750             *============================================================================*/
4751              
4752             /** Payload of a JSON value (8 bytes). */
4753             typedef union yyjson_val_uni {
4754             uint64_t u64;
4755             int64_t i64;
4756             double f64;
4757             const char *str;
4758             void *ptr;
4759             size_t ofs;
4760             } yyjson_val_uni;
4761              
4762             /**
4763             Immutable JSON value, 16 bytes.
4764             */
4765             struct yyjson_val {
4766             uint64_t tag; /**< type, subtype and length */
4767             yyjson_val_uni uni; /**< payload */
4768             };
4769              
4770             struct yyjson_doc {
4771             /** Root value of the document (nonnull). */
4772             yyjson_val *root;
4773             /** Allocator used by document (nonnull). */
4774             yyjson_alc alc;
4775             /** The total number of bytes read when parsing JSON (nonzero). */
4776             size_t dat_read;
4777             /** The total number of value read when parsing JSON (nonzero). */
4778             size_t val_read;
4779             /** The string pool used by JSON values (nullable). */
4780             char *str_pool;
4781             };
4782              
4783              
4784              
4785             /*==============================================================================
4786             * MARK: - Unsafe JSON Value API (Implementation)
4787             *============================================================================*/
4788              
4789             /*
4790             Whether the string does not need to be escaped for serialization.
4791             This function is used to optimize the writing speed of small constant strings.
4792             This function works only if the compiler can evaluate it at compile time.
4793              
4794             Clang supports it since v8.0,
4795             earlier versions do not support constant_p(strlen) and return false.
4796             GCC supports it since at least v4.4,
4797             earlier versions may compile it as run-time instructions.
4798             ICC supports it since at least v16,
4799             earlier versions are uncertain.
4800              
4801             @param str The C string.
4802             @param len The returnd value from strlen(str).
4803             */
4804             yyjson_api_inline bool unsafe_yyjson_is_str_noesc(const char *str, size_t len) {
4805             #if YYJSON_HAS_CONSTANT_P && \
4806             (!YYJSON_IS_REAL_GCC || yyjson_gcc_available(4, 4, 0))
4807             if (yyjson_constant_p(len) && len <= 32) {
4808             /*
4809             Same as the following loop:
4810              
4811             for (size_t i = 0; i < len; i++) {
4812             char c = str[i];
4813             if (c < ' ' || c > '~' || c == '"' || c == '\\') return false;
4814             }
4815              
4816             GCC evaluates it at compile time only if the string length is within 17
4817             and -O3 (which turns on the -fpeel-loops flag) is used.
4818             So the loop is unrolled for GCC.
4819             */
4820             # define yyjson_repeat32_incr(x) \
4821             x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \
4822             x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) \
4823             x(16) x(17) x(18) x(19) x(20) x(21) x(22) x(23) \
4824             x(24) x(25) x(26) x(27) x(28) x(29) x(30) x(31)
4825             # define yyjson_check_char_noesc(i) \
4826             if (i < len) { \
4827             char c = str[i]; \
4828             if (c < ' ' || c > '~' || c == '"' || c == '\\') return false; }
4829             yyjson_repeat32_incr(yyjson_check_char_noesc)
4830             # undef yyjson_repeat32_incr
4831             # undef yyjson_check_char_noesc
4832             return true;
4833             }
4834             #else
4835             (void)str;
4836             (void)len;
4837             #endif
4838             return false;
4839             }
4840              
4841             yyjson_api_inline double unsafe_yyjson_u64_to_f64(uint64_t num) {
4842             #if YYJSON_U64_TO_F64_NO_IMPL
4843             uint64_t msb = ((uint64_t)1) << 63;
4844             if ((num & msb) == 0) {
4845             return (double)(int64_t)num;
4846             } else {
4847             return ((double)(int64_t)((num >> 1) | (num & 1))) * (double)2.0;
4848             }
4849             #else
4850 3           return (double)num;
4851             #endif
4852             }
4853              
4854             yyjson_api_inline yyjson_type unsafe_yyjson_get_type(void *val) {
4855 66047           uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
4856 66047           return (yyjson_type)(tag & YYJSON_TYPE_MASK);
4857             }
4858              
4859             yyjson_api_inline yyjson_subtype unsafe_yyjson_get_subtype(void *val) {
4860 12070           uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
4861 12070           return (yyjson_subtype)(tag & YYJSON_SUBTYPE_MASK);
4862             }
4863              
4864             yyjson_api_inline uint8_t unsafe_yyjson_get_tag(void *val) {
4865 26246           uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
4866 15           return (uint8_t)(tag & YYJSON_TAG_MASK);
4867             }
4868              
4869             yyjson_api_inline bool unsafe_yyjson_is_raw(void *val) {
4870             return unsafe_yyjson_get_type(val) == YYJSON_TYPE_RAW;
4871             }
4872              
4873             yyjson_api_inline bool unsafe_yyjson_is_null(void *val) {
4874 2           return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NULL;
4875             }
4876              
4877             yyjson_api_inline bool unsafe_yyjson_is_bool(void *val) {
4878 19           return unsafe_yyjson_get_type(val) == YYJSON_TYPE_BOOL;
4879             }
4880              
4881             yyjson_api_inline bool unsafe_yyjson_is_num(void *val) {
4882 9           return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NUM;
4883             }
4884              
4885             yyjson_api_inline bool unsafe_yyjson_is_str(void *val) {
4886 19136           return unsafe_yyjson_get_type(val) == YYJSON_TYPE_STR;
4887             }
4888              
4889             yyjson_api_inline bool unsafe_yyjson_is_arr(void *val) {
4890 15441           return unsafe_yyjson_get_type(val) == YYJSON_TYPE_ARR;
4891             }
4892              
4893             yyjson_api_inline bool unsafe_yyjson_is_obj(void *val) {
4894 17165           return unsafe_yyjson_get_type(val) == YYJSON_TYPE_OBJ;
4895             }
4896              
4897             yyjson_api_inline bool unsafe_yyjson_is_ctn(void *val) {
4898 14156           uint8_t mask = YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ;
4899 14156           return (unsafe_yyjson_get_tag(val) & mask) == mask;
4900             }
4901              
4902             yyjson_api_inline bool unsafe_yyjson_is_uint(void *val) {
4903 2           const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
4904 2           return unsafe_yyjson_get_tag(val) == patt;
4905             }
4906              
4907             yyjson_api_inline bool unsafe_yyjson_is_sint(void *val) {
4908 1           const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
4909 1           return unsafe_yyjson_get_tag(val) == patt;
4910             }
4911              
4912             yyjson_api_inline bool unsafe_yyjson_is_int(void *val) {
4913 12069           const uint8_t mask = YYJSON_TAG_MASK & (~YYJSON_SUBTYPE_SINT);
4914 12069           const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
4915 12069           return (unsafe_yyjson_get_tag(val) & mask) == patt;
4916             }
4917              
4918             yyjson_api_inline bool unsafe_yyjson_is_real(void *val) {
4919 3           const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
4920 3           return unsafe_yyjson_get_tag(val) == patt;
4921             }
4922              
4923             yyjson_api_inline bool unsafe_yyjson_is_true(void *val) {
4924             const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE;
4925             return unsafe_yyjson_get_tag(val) == patt;
4926             }
4927              
4928             yyjson_api_inline bool unsafe_yyjson_is_false(void *val) {
4929             const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE;
4930             return unsafe_yyjson_get_tag(val) == patt;
4931             }
4932              
4933             yyjson_api_inline bool unsafe_yyjson_arr_is_flat(yyjson_val *val) {
4934             size_t ofs = val->uni.ofs;
4935             size_t len = (size_t)(val->tag >> YYJSON_TAG_BIT);
4936             return len * sizeof(yyjson_val) + sizeof(yyjson_val) == ofs;
4937             }
4938              
4939             yyjson_api_inline const char *unsafe_yyjson_get_raw(void *val) {
4940             return ((yyjson_val *)val)->uni.str;
4941             }
4942              
4943             yyjson_api_inline bool unsafe_yyjson_get_bool(void *val) {
4944 12           uint8_t tag = unsafe_yyjson_get_tag(val);
4945 12           return (bool)((tag & YYJSON_SUBTYPE_MASK) >> YYJSON_TYPE_BIT);
4946             }
4947              
4948             yyjson_api_inline uint64_t unsafe_yyjson_get_uint(void *val) {
4949 12061           return ((yyjson_val *)val)->uni.u64;
4950             }
4951              
4952             yyjson_api_inline int64_t unsafe_yyjson_get_sint(void *val) {
4953 8           return ((yyjson_val *)val)->uni.i64;
4954             }
4955              
4956             yyjson_api_inline int unsafe_yyjson_get_int(void *val) {
4957             return (int)((yyjson_val *)val)->uni.i64;
4958             }
4959              
4960             yyjson_api_inline double unsafe_yyjson_get_real(void *val) {
4961 1           return ((yyjson_val *)val)->uni.f64;
4962             }
4963              
4964             yyjson_api_inline double unsafe_yyjson_get_num(void *val) {
4965 3           uint8_t tag = unsafe_yyjson_get_tag(val);
4966 3 50         if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL)) {
4967 0           return ((yyjson_val *)val)->uni.f64;
4968 3 50         } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT)) {
4969 0           return (double)((yyjson_val *)val)->uni.i64;
4970 3 50         } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT)) {
4971 6           return unsafe_yyjson_u64_to_f64(((yyjson_val *)val)->uni.u64);
4972             }
4973 0           return 0.0;
4974             }
4975              
4976             yyjson_api_inline const char *unsafe_yyjson_get_str(void *val) {
4977 4094           return ((yyjson_val *)val)->uni.str;
4978             }
4979              
4980             yyjson_api_inline size_t unsafe_yyjson_get_len(void *val) {
4981 36577           return (size_t)(((yyjson_val *)val)->tag >> YYJSON_TAG_BIT);
4982             }
4983              
4984             yyjson_api_inline yyjson_val *unsafe_yyjson_get_first(yyjson_val *ctn) {
4985 1136           return ctn + 1;
4986             }
4987              
4988             yyjson_api_inline yyjson_val *unsafe_yyjson_get_next(yyjson_val *val) {
4989 14156           bool is_ctn = unsafe_yyjson_is_ctn(val);
4990 14156           size_t ctn_ofs = val->uni.ofs;
4991 14156 100         size_t ofs = (is_ctn ? ctn_ofs : sizeof(yyjson_val));
    100          
    100          
    100          
4992 14156           return (yyjson_val *)(void *)((uint8_t *)val + ofs);
4993             }
4994              
4995             yyjson_api_inline bool unsafe_yyjson_equals_strn(void *val, const char *str,
4996             size_t len) {
4997 13 100         return unsafe_yyjson_get_len(val) == len &&
4998 4 100         memcmp(((yyjson_val *)val)->uni.str, str, len) == 0;
4999             }
5000              
5001             yyjson_api_inline bool unsafe_yyjson_equals_str(void *val, const char *str) {
5002             return unsafe_yyjson_equals_strn(val, str, strlen(str));
5003             }
5004              
5005             yyjson_api_inline void unsafe_yyjson_set_type(void *val, yyjson_type type,
5006             yyjson_subtype subtype) {
5007             uint8_t tag = (type | subtype);
5008             uint64_t new_tag = ((yyjson_val *)val)->tag;
5009             new_tag = (new_tag & (~(uint64_t)YYJSON_TAG_MASK)) | (uint64_t)tag;
5010             ((yyjson_val *)val)->tag = new_tag;
5011             }
5012              
5013             yyjson_api_inline void unsafe_yyjson_set_len(void *val, size_t len) {
5014 30024           uint64_t tag = ((yyjson_val *)val)->tag & YYJSON_TAG_MASK;
5015 30024           tag |= (uint64_t)len << YYJSON_TAG_BIT;
5016 30024           ((yyjson_val *)val)->tag = tag;
5017 30024           }
5018              
5019             yyjson_api_inline void unsafe_yyjson_set_tag(void *val, yyjson_type type,
5020             yyjson_subtype subtype,
5021             size_t len) {
5022 45061           uint64_t tag = (uint64_t)len << YYJSON_TAG_BIT;
5023 45061           tag |= (type | subtype);
5024 45061           ((yyjson_val *)val)->tag = tag;
5025 45056           }
5026              
5027             yyjson_api_inline void unsafe_yyjson_inc_len(void *val) {
5028             uint64_t tag = ((yyjson_val *)val)->tag;
5029             tag += (uint64_t)(1 << YYJSON_TAG_BIT);
5030             ((yyjson_val *)val)->tag = tag;
5031             }
5032              
5033             yyjson_api_inline void unsafe_yyjson_set_raw(void *val, const char *raw,
5034             size_t len) {
5035             unsafe_yyjson_set_tag(val, YYJSON_TYPE_RAW, YYJSON_SUBTYPE_NONE, len);
5036             ((yyjson_val *)val)->uni.str = raw;
5037             }
5038              
5039             yyjson_api_inline void unsafe_yyjson_set_null(void *val) {
5040             unsafe_yyjson_set_tag(val, YYJSON_TYPE_NULL, YYJSON_SUBTYPE_NONE, 0);
5041 3           }
5042              
5043             yyjson_api_inline void unsafe_yyjson_set_bool(void *val, bool num) {
5044 5           yyjson_subtype subtype = num ? YYJSON_SUBTYPE_TRUE : YYJSON_SUBTYPE_FALSE;
5045 5           unsafe_yyjson_set_tag(val, YYJSON_TYPE_BOOL, subtype, 0);
5046 5           }
5047              
5048             yyjson_api_inline void unsafe_yyjson_set_uint(void *val, uint64_t num) {
5049             unsafe_yyjson_set_tag(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_UINT, 0);
5050 0           ((yyjson_val *)val)->uni.u64 = num;
5051 0           }
5052              
5053             yyjson_api_inline void unsafe_yyjson_set_sint(void *val, int64_t num) {
5054             unsafe_yyjson_set_tag(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_SINT, 0);
5055 25028           ((yyjson_val *)val)->uni.i64 = num;
5056 25028           }
5057              
5058             yyjson_api_inline void unsafe_yyjson_set_fp_to_fixed(void *val, int prec) {
5059             ((yyjson_val *)val)->tag &= ~((uint64_t)YYJSON_WRITE_FP_TO_FIXED(15) << 32);
5060             ((yyjson_val *)val)->tag |= (uint64_t)YYJSON_WRITE_FP_TO_FIXED(prec) << 32;
5061             }
5062              
5063             yyjson_api_inline void unsafe_yyjson_set_fp_to_float(void *val, bool flt) {
5064             uint64_t flag = (uint64_t)YYJSON_WRITE_FP_TO_FLOAT << 32;
5065             if (flt) ((yyjson_val *)val)->tag |= flag;
5066             else ((yyjson_val *)val)->tag &= ~flag;
5067             }
5068              
5069             yyjson_api_inline void unsafe_yyjson_set_float(void *val, float num) {
5070             unsafe_yyjson_set_tag(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_REAL, 0);
5071             ((yyjson_val *)val)->tag |= (uint64_t)YYJSON_WRITE_FP_TO_FLOAT << 32;
5072             ((yyjson_val *)val)->uni.f64 = (double)num;
5073             }
5074              
5075             yyjson_api_inline void unsafe_yyjson_set_double(void *val, double num) {
5076             unsafe_yyjson_set_tag(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_REAL, 0);
5077             ((yyjson_val *)val)->uni.f64 = num;
5078             }
5079              
5080             yyjson_api_inline void unsafe_yyjson_set_real(void *val, double num) {
5081             unsafe_yyjson_set_tag(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_REAL, 0);
5082 1           ((yyjson_val *)val)->uni.f64 = num;
5083 1           }
5084              
5085             yyjson_api_inline void unsafe_yyjson_set_str_noesc(void *val, bool noesc) {
5086             ((yyjson_val *)val)->tag &= ~(uint64_t)YYJSON_SUBTYPE_MASK;
5087             if (noesc) ((yyjson_val *)val)->tag |= (uint64_t)YYJSON_SUBTYPE_NOESC;
5088             }
5089              
5090             yyjson_api_inline void unsafe_yyjson_set_strn(void *val, const char *str,
5091             size_t len) {
5092             unsafe_yyjson_set_tag(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE, len);
5093 20024           ((yyjson_val *)val)->uni.str = str;
5094 20024           }
5095              
5096             yyjson_api_inline void unsafe_yyjson_set_str(void *val, const char *str) {
5097             size_t len = strlen(str);
5098             bool noesc = unsafe_yyjson_is_str_noesc(str, len);
5099             yyjson_subtype subtype = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
5100             unsafe_yyjson_set_tag(val, YYJSON_TYPE_STR, subtype, len);
5101             ((yyjson_val *)val)->uni.str = str;
5102             }
5103              
5104             yyjson_api_inline void unsafe_yyjson_set_arr(void *val, size_t size) {
5105             unsafe_yyjson_set_tag(val, YYJSON_TYPE_ARR, YYJSON_SUBTYPE_NONE, size);
5106             }
5107              
5108             yyjson_api_inline void unsafe_yyjson_set_obj(void *val, size_t size) {
5109             unsafe_yyjson_set_tag(val, YYJSON_TYPE_OBJ, YYJSON_SUBTYPE_NONE, size);
5110             }
5111              
5112              
5113              
5114             /*==============================================================================
5115             * MARK: - JSON Document API (Implementation)
5116             *============================================================================*/
5117              
5118             yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc) {
5119 40 0         return doc ? doc->root : NULL;
    0          
    50          
    50          
    50          
    50          
5120             }
5121              
5122             yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc) {
5123             return doc ? doc->dat_read : 0;
5124             }
5125              
5126             yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc) {
5127             return doc ? doc->val_read : 0;
5128             }
5129              
5130             yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc) {
5131 10114 0         if (doc) {
    0          
    0          
    50          
5132 10114           yyjson_alc alc = doc->alc;
5133 10114           memset(&doc->alc, 0, sizeof(alc));
5134 10114 0         if (doc->str_pool) alc.free(alc.ctx, doc->str_pool);
    0          
    0          
    50          
    0          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
5135 10114           alc.free(alc.ctx, doc);
5136             }
5137 10114           }
5138              
5139              
5140              
5141             /*==============================================================================
5142             * MARK: - JSON Value Type API (Implementation)
5143             *============================================================================*/
5144              
5145             yyjson_api_inline bool yyjson_is_raw(yyjson_val *val) {
5146             return val ? unsafe_yyjson_is_raw(val) : false;
5147             }
5148              
5149             yyjson_api_inline bool yyjson_is_null(yyjson_val *val) {
5150             return val ? unsafe_yyjson_is_null(val) : false;
5151             }
5152              
5153             yyjson_api_inline bool yyjson_is_true(yyjson_val *val) {
5154             return val ? unsafe_yyjson_is_true(val) : false;
5155             }
5156              
5157             yyjson_api_inline bool yyjson_is_false(yyjson_val *val) {
5158             return val ? unsafe_yyjson_is_false(val) : false;
5159             }
5160              
5161             yyjson_api_inline bool yyjson_is_bool(yyjson_val *val) {
5162 24 50         return val ? unsafe_yyjson_is_bool(val) : false;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5163             }
5164              
5165             yyjson_api_inline bool yyjson_is_uint(yyjson_val *val) {
5166             return val ? unsafe_yyjson_is_uint(val) : false;
5167             }
5168              
5169             yyjson_api_inline bool yyjson_is_sint(yyjson_val *val) {
5170             return val ? unsafe_yyjson_is_sint(val) : false;
5171             }
5172              
5173             yyjson_api_inline bool yyjson_is_int(yyjson_val *val) {
5174 24138 50         return val ? unsafe_yyjson_is_int(val) : false;
    50          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5175             }
5176              
5177             yyjson_api_inline bool yyjson_is_real(yyjson_val *val) {
5178 2 0         return val ? unsafe_yyjson_is_real(val) : false;
    0          
    0          
    0          
    50          
    50          
5179             }
5180              
5181             yyjson_api_inline bool yyjson_is_num(yyjson_val *val) {
5182             return val ? unsafe_yyjson_is_num(val) : false;
5183             }
5184              
5185             yyjson_api_inline bool yyjson_is_str(yyjson_val *val) {
5186 8188 50         return val ? unsafe_yyjson_is_str(val) : false;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5187             }
5188              
5189             yyjson_api_inline bool yyjson_is_arr(yyjson_val *val) {
5190 666 50         return val ? unsafe_yyjson_is_arr(val) : false;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5191             }
5192              
5193             yyjson_api_inline bool yyjson_is_obj(yyjson_val *val) {
5194 4104 50         return val ? unsafe_yyjson_is_obj(val) : false;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5195             }
5196              
5197             yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val) {
5198             return val ? unsafe_yyjson_is_ctn(val) : false;
5199             }
5200              
5201              
5202              
5203             /*==============================================================================
5204             * MARK: - JSON Value Content API (Implementation)
5205             *============================================================================*/
5206              
5207             yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val) {
5208 28550 0         return val ? unsafe_yyjson_get_type(val) : YYJSON_TYPE_NONE;
    50          
    50          
    50          
    50          
    50          
    50          
5209             }
5210              
5211             yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val) {
5212 24140 50         return val ? unsafe_yyjson_get_subtype(val) : YYJSON_SUBTYPE_NONE;
    50          
    50          
5213             }
5214              
5215             yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val) {
5216             return val ? unsafe_yyjson_get_tag(val) : 0;
5217             }
5218              
5219             yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val) {
5220             switch (yyjson_get_tag(val)) {
5221             case YYJSON_TYPE_RAW | YYJSON_SUBTYPE_NONE: return "raw";
5222             case YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE: return "null";
5223             case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return "string";
5224             case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: return "string";
5225             case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: return "array";
5226             case YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE: return "object";
5227             case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE: return "true";
5228             case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE: return "false";
5229             case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT: return "uint";
5230             case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT: return "sint";
5231             case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL: return "real";
5232             default: return "unknown";
5233             }
5234             }
5235              
5236             yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val) {
5237             return yyjson_is_raw(val) ? unsafe_yyjson_get_raw(val) : NULL;
5238             }
5239              
5240             yyjson_api_inline bool yyjson_get_bool(yyjson_val *val) {
5241 24 50         return yyjson_is_bool(val) ? unsafe_yyjson_get_bool(val) : false;
    100          
    50          
    100          
    50          
    100          
    50          
    100          
5242             }
5243              
5244             yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val) {
5245 24122 50         return yyjson_is_int(val) ? unsafe_yyjson_get_uint(val) : 0;
    50          
    50          
5246             }
5247              
5248             yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val) {
5249 16 0         return yyjson_is_int(val) ? unsafe_yyjson_get_sint(val) : 0;
    50          
    50          
5250             }
5251              
5252             yyjson_api_inline int yyjson_get_int(yyjson_val *val) {
5253             return yyjson_is_int(val) ? unsafe_yyjson_get_int(val) : 0;
5254             }
5255              
5256             yyjson_api_inline double yyjson_get_real(yyjson_val *val) {
5257 2 0         return yyjson_is_real(val) ? unsafe_yyjson_get_real(val) : 0.0;
    0          
    50          
5258             }
5259              
5260             yyjson_api_inline double yyjson_get_num(yyjson_val *val) {
5261 6 50         return val ? unsafe_yyjson_get_num(val) : 0.0;
5262             }
5263              
5264             yyjson_api_inline const char *yyjson_get_str(yyjson_val *val) {
5265 8188 50         return yyjson_is_str(val) ? unsafe_yyjson_get_str(val) : NULL;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5266             }
5267              
5268             yyjson_api_inline size_t yyjson_get_len(yyjson_val *val) {
5269 8190 50         return val ? unsafe_yyjson_get_len(val) : 0;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5270             }
5271              
5272             yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str) {
5273             if (yyjson_likely(val && str)) {
5274             return unsafe_yyjson_is_str(val) &&
5275             unsafe_yyjson_equals_str(val, str);
5276             }
5277             return false;
5278             }
5279              
5280             yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str,
5281             size_t len) {
5282 9 50         if (yyjson_likely(val && str)) {
    50          
5283 18 50         return unsafe_yyjson_is_str(val) &&
5284 9 100         unsafe_yyjson_equals_strn(val, str, len);
5285             }
5286 0           return false;
5287             }
5288              
5289             yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs);
5290              
5291             yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) {
5292             if (yyjson_unlikely(!lhs || !rhs)) return false;
5293             return unsafe_yyjson_equals(lhs, rhs);
5294             }
5295              
5296             yyjson_api_inline bool yyjson_set_raw(yyjson_val *val,
5297             const char *raw, size_t len) {
5298             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5299             unsafe_yyjson_set_raw(val, raw, len);
5300             return true;
5301             }
5302              
5303             yyjson_api_inline bool yyjson_set_null(yyjson_val *val) {
5304             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5305             unsafe_yyjson_set_null(val);
5306             return true;
5307             }
5308              
5309             yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num) {
5310             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5311             unsafe_yyjson_set_bool(val, num);
5312             return true;
5313             }
5314              
5315             yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num) {
5316             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5317             unsafe_yyjson_set_uint(val, num);
5318             return true;
5319             }
5320              
5321             yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num) {
5322             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5323             unsafe_yyjson_set_sint(val, num);
5324             return true;
5325             }
5326              
5327             yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num) {
5328             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5329             unsafe_yyjson_set_sint(val, (int64_t)num);
5330             return true;
5331             }
5332              
5333             yyjson_api_inline bool yyjson_set_float(yyjson_val *val, float num) {
5334             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5335             unsafe_yyjson_set_float(val, num);
5336             return true;
5337             }
5338              
5339             yyjson_api_inline bool yyjson_set_double(yyjson_val *val, double num) {
5340             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5341             unsafe_yyjson_set_double(val, num);
5342             return true;
5343             }
5344              
5345             yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num) {
5346             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5347             unsafe_yyjson_set_real(val, num);
5348             return true;
5349             }
5350              
5351             yyjson_api_inline bool yyjson_set_fp_to_fixed(yyjson_val *val, int prec) {
5352             if (yyjson_unlikely(!yyjson_is_real(val))) return false;
5353             unsafe_yyjson_set_fp_to_fixed(val, prec);
5354             return true;
5355             }
5356              
5357             yyjson_api_inline bool yyjson_set_fp_to_float(yyjson_val *val, bool flt) {
5358             if (yyjson_unlikely(!yyjson_is_real(val))) return false;
5359             unsafe_yyjson_set_fp_to_float(val, flt);
5360             return true;
5361             }
5362              
5363             yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str) {
5364             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5365             if (yyjson_unlikely(!str)) return false;
5366             unsafe_yyjson_set_str(val, str);
5367             return true;
5368             }
5369              
5370             yyjson_api_inline bool yyjson_set_strn(yyjson_val *val,
5371             const char *str, size_t len) {
5372             if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
5373             if (yyjson_unlikely(!str)) return false;
5374             unsafe_yyjson_set_strn(val, str, len);
5375             return true;
5376             }
5377              
5378             yyjson_api_inline bool yyjson_set_str_noesc(yyjson_val *val, bool noesc) {
5379             if (yyjson_unlikely(!yyjson_is_str(val))) return false;
5380             unsafe_yyjson_set_str_noesc(val, noesc);
5381             return true;
5382             }
5383              
5384              
5385              
5386             /*==============================================================================
5387             * MARK: - JSON Array API (Implementation)
5388             *============================================================================*/
5389              
5390             yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr) {
5391 444 50         return yyjson_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0;
    50          
    50          
    50          
5392             }
5393              
5394             yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx) {
5395             if (yyjson_likely(yyjson_is_arr(arr))) {
5396             if (yyjson_likely(unsafe_yyjson_get_len(arr) > idx)) {
5397             yyjson_val *val = unsafe_yyjson_get_first(arr);
5398             if (unsafe_yyjson_arr_is_flat(arr)) {
5399             return val + idx;
5400             } else {
5401             while (idx-- > 0) val = unsafe_yyjson_get_next(val);
5402             return val;
5403             }
5404             }
5405             }
5406             return NULL;
5407             }
5408              
5409             yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr) {
5410 111 50         if (yyjson_likely(yyjson_is_arr(arr))) {
    50          
5411 111 50         if (yyjson_likely(unsafe_yyjson_get_len(arr) > 0)) {
    100          
5412 110           return unsafe_yyjson_get_first(arr);
5413             }
5414             }
5415 1           return NULL;
5416             }
5417              
5418             yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr) {
5419             if (yyjson_likely(yyjson_is_arr(arr))) {
5420             size_t len = unsafe_yyjson_get_len(arr);
5421             if (yyjson_likely(len > 0)) {
5422             yyjson_val *val = unsafe_yyjson_get_first(arr);
5423             if (unsafe_yyjson_arr_is_flat(arr)) {
5424             return val + (len - 1);
5425             } else {
5426             while (len-- > 1) val = unsafe_yyjson_get_next(val);
5427             return val;
5428             }
5429             }
5430             }
5431             return NULL;
5432             }
5433              
5434              
5435              
5436             /*==============================================================================
5437             * MARK: - JSON Array Iterator API (Implementation)
5438             *============================================================================*/
5439              
5440             yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr,
5441             yyjson_arr_iter *iter) {
5442             if (yyjson_likely(yyjson_is_arr(arr) && iter)) {
5443             iter->idx = 0;
5444             iter->max = unsafe_yyjson_get_len(arr);
5445             iter->cur = unsafe_yyjson_get_first(arr);
5446             return true;
5447             }
5448             if (iter) memset(iter, 0, sizeof(yyjson_arr_iter));
5449             return false;
5450             }
5451              
5452             yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr) {
5453             yyjson_arr_iter iter;
5454             yyjson_arr_iter_init(arr, &iter);
5455             return iter;
5456             }
5457              
5458             yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter) {
5459             return iter ? iter->idx < iter->max : false;
5460             }
5461              
5462             yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter) {
5463             yyjson_val *val;
5464             if (iter && iter->idx < iter->max) {
5465             val = iter->cur;
5466             iter->cur = unsafe_yyjson_get_next(val);
5467             iter->idx++;
5468             return val;
5469             }
5470             return NULL;
5471             }
5472              
5473              
5474              
5475             /*==============================================================================
5476             * MARK: - JSON Object API (Implementation)
5477             *============================================================================*/
5478              
5479             yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj) {
5480 4104 50         return yyjson_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0;
    50          
    50          
    50          
5481             }
5482              
5483             yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj,
5484             const char *key) {
5485             return yyjson_obj_getn(obj, key, key ? strlen(key) : 0);
5486             }
5487              
5488             yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj,
5489             const char *_key,
5490             size_t key_len) {
5491             if (yyjson_likely(yyjson_is_obj(obj) && _key)) {
5492             size_t len = unsafe_yyjson_get_len(obj);
5493             yyjson_val *key = unsafe_yyjson_get_first(obj);
5494             while (len-- > 0) {
5495             if (unsafe_yyjson_equals_strn(key, _key, key_len)) return key + 1;
5496             key = unsafe_yyjson_get_next(key + 1);
5497             }
5498             }
5499             return NULL;
5500             }
5501              
5502              
5503              
5504             /*==============================================================================
5505             * MARK: - JSON Object Iterator API (Implementation)
5506             *============================================================================*/
5507              
5508             yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj,
5509             yyjson_obj_iter *iter) {
5510             if (yyjson_likely(yyjson_is_obj(obj) && iter)) {
5511             iter->idx = 0;
5512             iter->max = unsafe_yyjson_get_len(obj);
5513             iter->cur = unsafe_yyjson_get_first(obj);
5514             iter->obj = obj;
5515             return true;
5516             }
5517             if (iter) memset(iter, 0, sizeof(yyjson_obj_iter));
5518             return false;
5519             }
5520              
5521             yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj) {
5522             yyjson_obj_iter iter;
5523             yyjson_obj_iter_init(obj, &iter);
5524             return iter;
5525             }
5526              
5527             yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter) {
5528             return iter ? iter->idx < iter->max : false;
5529             }
5530              
5531             yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter) {
5532             if (iter && iter->idx < iter->max) {
5533             yyjson_val *key = iter->cur;
5534             iter->idx++;
5535             iter->cur = unsafe_yyjson_get_next(key + 1);
5536             return key;
5537             }
5538             return NULL;
5539             }
5540              
5541             yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key) {
5542             return key ? key + 1 : NULL;
5543             }
5544              
5545             yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter,
5546             const char *key) {
5547             return yyjson_obj_iter_getn(iter, key, key ? strlen(key) : 0);
5548             }
5549              
5550             yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter,
5551             const char *key,
5552             size_t key_len) {
5553             if (iter && key) {
5554             size_t idx = iter->idx;
5555             size_t max = iter->max;
5556             yyjson_val *cur = iter->cur;
5557             if (yyjson_unlikely(idx == max)) {
5558             idx = 0;
5559             cur = unsafe_yyjson_get_first(iter->obj);
5560             }
5561             while (idx++ < max) {
5562             yyjson_val *next = unsafe_yyjson_get_next(cur + 1);
5563             if (unsafe_yyjson_equals_strn(cur, key, key_len)) {
5564             iter->idx = idx;
5565             iter->cur = next;
5566             return cur + 1;
5567             }
5568             cur = next;
5569             if (idx == iter->max && iter->idx < iter->max) {
5570             idx = 0;
5571             max = iter->idx;
5572             cur = unsafe_yyjson_get_first(iter->obj);
5573             }
5574             }
5575             }
5576             return NULL;
5577             }
5578              
5579              
5580              
5581             /*==============================================================================
5582             * MARK: - Mutable JSON Structure (Implementation)
5583             *============================================================================*/
5584              
5585             /**
5586             Mutable JSON value, 24 bytes.
5587             The 'tag' and 'uni' field is same as immutable value.
5588             The 'next' field links all elements inside the container to be a cycle.
5589             */
5590             struct yyjson_mut_val {
5591             uint64_t tag; /**< type, subtype and length */
5592             yyjson_val_uni uni; /**< payload */
5593             yyjson_mut_val *next; /**< the next value in circular linked list */
5594             };
5595              
5596             /**
5597             A memory chunk in string memory pool.
5598             */
5599             typedef struct yyjson_str_chunk {
5600             struct yyjson_str_chunk *next; /* next chunk linked list */
5601             size_t chunk_size; /* chunk size in bytes */
5602             /* char str[]; flexible array member */
5603             } yyjson_str_chunk;
5604              
5605             /**
5606             A memory pool to hold all strings in a mutable document.
5607             */
5608             typedef struct yyjson_str_pool {
5609             char *cur; /* cursor inside current chunk */
5610             char *end; /* the end of current chunk */
5611             size_t chunk_size; /* chunk size in bytes while creating new chunk */
5612             size_t chunk_size_max; /* maximum chunk size in bytes */
5613             yyjson_str_chunk *chunks; /* a linked list of chunks, nullable */
5614             } yyjson_str_pool;
5615              
5616             /**
5617             A memory chunk in value memory pool.
5618             `sizeof(yyjson_val_chunk)` should not larger than `sizeof(yyjson_mut_val)`.
5619             */
5620             typedef struct yyjson_val_chunk {
5621             struct yyjson_val_chunk *next; /* next chunk linked list */
5622             size_t chunk_size; /* chunk size in bytes */
5623             /* char pad[sizeof(yyjson_mut_val) - sizeof(yyjson_val_chunk)]; padding */
5624             /* yyjson_mut_val vals[]; flexible array member */
5625             } yyjson_val_chunk;
5626              
5627             /**
5628             A memory pool to hold all values in a mutable document.
5629             */
5630             typedef struct yyjson_val_pool {
5631             yyjson_mut_val *cur; /* cursor inside current chunk */
5632             yyjson_mut_val *end; /* the end of current chunk */
5633             size_t chunk_size; /* chunk size in bytes while creating new chunk */
5634             size_t chunk_size_max; /* maximum chunk size in bytes */
5635             yyjson_val_chunk *chunks; /* a linked list of chunks, nullable */
5636             } yyjson_val_pool;
5637              
5638             struct yyjson_mut_doc {
5639             yyjson_mut_val *root; /**< root value of the JSON document, nullable */
5640             yyjson_alc alc; /**< a valid allocator, nonnull */
5641             yyjson_str_pool str_pool; /**< string memory pool */
5642             yyjson_val_pool val_pool; /**< value memory pool */
5643             };
5644              
5645             /* Ensures the capacity to at least equal to the specified byte length. */
5646             yyjson_api bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool,
5647             const yyjson_alc *alc,
5648             size_t len);
5649              
5650             /* Ensures the capacity to at least equal to the specified value count. */
5651             yyjson_api bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool,
5652             const yyjson_alc *alc,
5653             size_t count);
5654              
5655             /* Allocate memory for string. */
5656             yyjson_api_inline char *unsafe_yyjson_mut_str_alc(yyjson_mut_doc *doc,
5657             size_t len) {
5658             char *mem;
5659 20024           const yyjson_alc *alc = &doc->alc;
5660 20024           yyjson_str_pool *pool = &doc->str_pool;
5661 20024 100         if (yyjson_unlikely((size_t)(pool->end - pool->cur) <= len)) {
    100          
    50          
5662 5013 50         if (yyjson_unlikely(!unsafe_yyjson_str_pool_grow(pool, alc, len + 1))) {
    50          
    50          
5663 0           return NULL;
5664             }
5665             }
5666 20024           mem = pool->cur;
5667 20024           pool->cur = mem + len + 1;
5668 20024           return mem;
5669             }
5670              
5671             yyjson_api_inline char *unsafe_yyjson_mut_strncpy(yyjson_mut_doc *doc,
5672             const char *str, size_t len) {
5673 20024           char *mem = unsafe_yyjson_mut_str_alc(doc, len);
5674 20024 50         if (yyjson_unlikely(!mem)) return NULL;
    50          
    50          
5675 20024           memcpy((void *)mem, (const void *)str, len);
5676 20024           mem[len] = '\0';
5677 20024           return mem;
5678             }
5679              
5680             yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_val(yyjson_mut_doc *doc,
5681             size_t count) {
5682             yyjson_mut_val *val;
5683 60080           yyjson_alc *alc = &doc->alc;
5684 60080           yyjson_val_pool *pool = &doc->val_pool;
5685 60080 50         if (yyjson_unlikely((size_t)(pool->end - pool->cur) < count)) {
    0          
    50          
    0          
    100          
    100          
    50          
    0          
    0          
    100          
    0          
    100          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    0          
    0          
5686 5028 0         if (yyjson_unlikely(!unsafe_yyjson_val_pool_grow(pool, alc, count))) {
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    50          
    0          
    50          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    0          
    0          
5687 0           return NULL;
5688             }
5689             }
5690 60080           val = pool->cur;
5691 60080           pool->cur += count;
5692 60080           return val;
5693             }
5694              
5695              
5696              
5697             /*==============================================================================
5698             * MARK: - Mutable JSON Document API (Implementation)
5699             *============================================================================*/
5700              
5701             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc) {
5702 10074 50         return doc ? doc->root : NULL;
    50          
    50          
5703             }
5704              
5705             yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc,
5706             yyjson_mut_val *root) {
5707 10043 50         if (doc) doc->root = root;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
5708 10043           }
5709              
5710              
5711              
5712             /*==============================================================================
5713             * MARK: - Mutable JSON Value Type API (Implementation)
5714             *============================================================================*/
5715              
5716             yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val) {
5717             return val ? unsafe_yyjson_is_raw(val) : false;
5718             }
5719              
5720             yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val) {
5721 4 50         return val ? unsafe_yyjson_is_null(val) : false;
    100          
5722             }
5723              
5724             yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val) {
5725             return val ? unsafe_yyjson_is_true(val) : false;
5726             }
5727              
5728             yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val) {
5729             return val ? unsafe_yyjson_is_false(val) : false;
5730             }
5731              
5732             yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val) {
5733 14 50         return val ? unsafe_yyjson_is_bool(val) : false;
    50          
    50          
    100          
5734             }
5735              
5736             yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val) {
5737 4 50         return val ? unsafe_yyjson_is_uint(val) : false;
    100          
5738             }
5739              
5740             yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val) {
5741 2 50         return val ? unsafe_yyjson_is_sint(val) : false;
    50          
5742             }
5743              
5744             yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val) {
5745             return val ? unsafe_yyjson_is_int(val) : false;
5746             }
5747              
5748             yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val) {
5749 4 50         return val ? unsafe_yyjson_is_real(val) : false;
    100          
5750             }
5751              
5752             yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val) {
5753 18 50         return val ? unsafe_yyjson_is_num(val) : false;
    100          
    50          
    100          
5754             }
5755              
5756             yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val) {
5757 30066 50         return val ? unsafe_yyjson_is_str(val) : false;
    50          
    50          
    100          
    50          
    100          
    50          
    50          
5758             }
5759              
5760             yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val) {
5761 30216 50         return val ? unsafe_yyjson_is_arr(val) : false;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
5762             }
5763              
5764             yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val) {
5765 30226 50         return val ? unsafe_yyjson_is_obj(val) : false;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    50          
    100          
    50          
    50          
5766             }
5767              
5768             yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val) {
5769             return val ? unsafe_yyjson_is_ctn(val) : false;
5770             }
5771              
5772              
5773              
5774             /*==============================================================================
5775             * MARK: - Mutable JSON Value Content API (Implementation)
5776             *============================================================================*/
5777              
5778             yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val) {
5779 73           return yyjson_get_type((yyjson_val *)val);
5780             }
5781              
5782             yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val) {
5783 41           return yyjson_get_subtype((yyjson_val *)val);
5784             }
5785              
5786             yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val) {
5787             return yyjson_get_tag((yyjson_val *)val);
5788             }
5789              
5790             yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val) {
5791             return yyjson_get_type_desc((yyjson_val *)val);
5792             }
5793              
5794             yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val) {
5795             return yyjson_get_raw((yyjson_val *)val);
5796             }
5797              
5798             yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val) {
5799 5           return yyjson_get_bool((yyjson_val *)val);
5800             }
5801              
5802             yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val) {
5803 34           return yyjson_get_uint((yyjson_val *)val);
5804             }
5805              
5806             yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val) {
5807 7           return yyjson_get_sint((yyjson_val *)val);
5808             }
5809              
5810             yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val) {
5811             return yyjson_get_int((yyjson_val *)val);
5812             }
5813              
5814             yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val) {
5815 0           return yyjson_get_real((yyjson_val *)val);
5816             }
5817              
5818             yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val) {
5819 3           return yyjson_get_num((yyjson_val *)val);
5820             }
5821              
5822             yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val) {
5823 42           return yyjson_get_str((yyjson_val *)val);
5824             }
5825              
5826             yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val) {
5827 43           return yyjson_get_len((yyjson_val *)val);
5828             }
5829              
5830             yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val,
5831             const char *str) {
5832             return yyjson_equals_str((yyjson_val *)val, str);
5833             }
5834              
5835             yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val,
5836             const char *str, size_t len) {
5837 9           return yyjson_equals_strn((yyjson_val *)val, str, len);
5838             }
5839              
5840             yyjson_api bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs,
5841             yyjson_mut_val *rhs);
5842              
5843             yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs,
5844             yyjson_mut_val *rhs) {
5845 5 50         if (yyjson_unlikely(!lhs || !rhs)) return false;
    50          
    50          
    50          
5846 5           return unsafe_yyjson_mut_equals(lhs, rhs);
5847             }
5848              
5849             yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val,
5850             const char *raw, size_t len) {
5851             if (yyjson_unlikely(!val || !raw)) return false;
5852             unsafe_yyjson_set_raw(val, raw, len);
5853             return true;
5854             }
5855              
5856             yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val) {
5857             if (yyjson_unlikely(!val)) return false;
5858             unsafe_yyjson_set_null(val);
5859             return true;
5860             }
5861              
5862             yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num) {
5863             if (yyjson_unlikely(!val)) return false;
5864             unsafe_yyjson_set_bool(val, num);
5865             return true;
5866             }
5867              
5868             yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num) {
5869             if (yyjson_unlikely(!val)) return false;
5870             unsafe_yyjson_set_uint(val, num);
5871             return true;
5872             }
5873              
5874             yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num) {
5875             if (yyjson_unlikely(!val)) return false;
5876             unsafe_yyjson_set_sint(val, num);
5877             return true;
5878             }
5879              
5880             yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num) {
5881             if (yyjson_unlikely(!val)) return false;
5882             unsafe_yyjson_set_sint(val, (int64_t)num);
5883             return true;
5884             }
5885              
5886             yyjson_api_inline bool yyjson_mut_set_float(yyjson_mut_val *val, float num) {
5887             if (yyjson_unlikely(!val)) return false;
5888             unsafe_yyjson_set_float(val, num);
5889             return true;
5890             }
5891              
5892             yyjson_api_inline bool yyjson_mut_set_double(yyjson_mut_val *val, double num) {
5893             if (yyjson_unlikely(!val)) return false;
5894             unsafe_yyjson_set_double(val, num);
5895             return true;
5896             }
5897              
5898             yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num) {
5899             if (yyjson_unlikely(!val)) return false;
5900             unsafe_yyjson_set_real(val, num);
5901             return true;
5902             }
5903              
5904             yyjson_api_inline bool yyjson_mut_set_fp_to_fixed(yyjson_mut_val *val,
5905             int prec) {
5906             if (yyjson_unlikely(!yyjson_mut_is_real(val))) return false;
5907             unsafe_yyjson_set_fp_to_fixed(val, prec);
5908             return true;
5909             }
5910              
5911             yyjson_api_inline bool yyjson_mut_set_fp_to_float(yyjson_mut_val *val,
5912             bool flt) {
5913             if (yyjson_unlikely(!yyjson_mut_is_real(val))) return false;
5914             unsafe_yyjson_set_fp_to_float(val, flt);
5915             return true;
5916             }
5917              
5918             yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val,
5919             const char *str) {
5920             if (yyjson_unlikely(!val || !str)) return false;
5921             unsafe_yyjson_set_str(val, str);
5922             return true;
5923             }
5924              
5925             yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val,
5926             const char *str, size_t len) {
5927             if (yyjson_unlikely(!val || !str)) return false;
5928             unsafe_yyjson_set_strn(val, str, len);
5929             return true;
5930             }
5931              
5932             yyjson_api_inline bool yyjson_mut_set_str_noesc(yyjson_mut_val *val,
5933             bool noesc) {
5934             if (yyjson_unlikely(!yyjson_mut_is_str(val))) return false;
5935             unsafe_yyjson_set_str_noesc(val, noesc);
5936             return true;
5937             }
5938              
5939             yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val) {
5940             if (yyjson_unlikely(!val)) return false;
5941             unsafe_yyjson_set_arr(val, 0);
5942             return true;
5943             }
5944              
5945             yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val) {
5946             if (yyjson_unlikely(!val)) return false;
5947             unsafe_yyjson_set_obj(val, 0);
5948             return true;
5949             }
5950              
5951              
5952              
5953             /*==============================================================================
5954             * MARK: - Mutable JSON Value Creation API (Implementation)
5955             *============================================================================*/
5956              
5957             #define yyjson_mut_val_one(func) \
5958             if (yyjson_likely(doc)) { \
5959             yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); \
5960             if (yyjson_likely(val)) { \
5961             func \
5962             return val; \
5963             } \
5964             } \
5965             return NULL
5966              
5967             #define yyjson_mut_val_one_str(func) \
5968             if (yyjson_likely(doc && str)) { \
5969             yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); \
5970             if (yyjson_likely(val)) { \
5971             func \
5972             return val; \
5973             } \
5974             } \
5975             return NULL
5976              
5977             yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc,
5978             const char *str) {
5979             yyjson_mut_val_one_str({ unsafe_yyjson_set_raw(val, str, strlen(str)); });
5980             }
5981              
5982             yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc,
5983             const char *str,
5984             size_t len) {
5985             yyjson_mut_val_one_str({ unsafe_yyjson_set_raw(val, str, len); });
5986             }
5987              
5988             yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc,
5989             const char *str) {
5990             yyjson_mut_val_one_str({
5991             size_t len = strlen(str);
5992             char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
5993             if (yyjson_unlikely(!new_str)) return NULL;
5994             unsafe_yyjson_set_raw(val, new_str, len);
5995             });
5996             }
5997              
5998             yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc,
5999             const char *str,
6000             size_t len) {
6001             yyjson_mut_val_one_str({
6002             char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
6003             if (yyjson_unlikely(!new_str)) return NULL;
6004             unsafe_yyjson_set_raw(val, new_str, len);
6005             });
6006             }
6007              
6008             yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc) {
6009 9 50         yyjson_mut_val_one({ unsafe_yyjson_set_null(val); });
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
6010             }
6011              
6012             yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc) {
6013             yyjson_mut_val_one({ unsafe_yyjson_set_bool(val, true); });
6014             }
6015              
6016             yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc) {
6017             yyjson_mut_val_one({ unsafe_yyjson_set_bool(val, false); });
6018             }
6019              
6020             yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc,
6021             bool _val) {
6022 15 50         yyjson_mut_val_one({ unsafe_yyjson_set_bool(val, _val); });
    50          
    50          
    0          
    0          
    0          
    50          
    50          
    100          
6023             }
6024              
6025             yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc,
6026             uint64_t num) {
6027 0 0         yyjson_mut_val_one({ unsafe_yyjson_set_uint(val, num); });
    0          
    0          
    0          
6028             }
6029              
6030             yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc,
6031             int64_t num) {
6032 75084 50         yyjson_mut_val_one({ unsafe_yyjson_set_sint(val, num); });
    50          
    50          
    50          
6033             }
6034              
6035             yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc,
6036             int64_t num) {
6037             yyjson_mut_val_one({ unsafe_yyjson_set_sint(val, num); });
6038             }
6039              
6040             yyjson_api_inline yyjson_mut_val *yyjson_mut_float(yyjson_mut_doc *doc,
6041             float num) {
6042             yyjson_mut_val_one({ unsafe_yyjson_set_float(val, num); });
6043             }
6044              
6045             yyjson_api_inline yyjson_mut_val *yyjson_mut_double(yyjson_mut_doc *doc,
6046             double num) {
6047             yyjson_mut_val_one({ unsafe_yyjson_set_double(val, num); });
6048             }
6049              
6050             yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc,
6051             double num) {
6052 3 0         yyjson_mut_val_one({ unsafe_yyjson_set_real(val, num); });
    0          
    50          
    50          
6053             }
6054              
6055             yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc,
6056             const char *str) {
6057             yyjson_mut_val_one_str({ unsafe_yyjson_set_str(val, str); });
6058             }
6059              
6060             yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc,
6061             const char *str,
6062             size_t len) {
6063             yyjson_mut_val_one_str({ unsafe_yyjson_set_strn(val, str, len); });
6064             }
6065              
6066             yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc,
6067             const char *str) {
6068             yyjson_mut_val_one_str({
6069             size_t len = strlen(str);
6070             bool noesc = unsafe_yyjson_is_str_noesc(str, len);
6071             yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
6072             char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
6073             if (yyjson_unlikely(!new_str)) return NULL;
6074             unsafe_yyjson_set_tag(val, YYJSON_TYPE_STR, sub, len);
6075             val->uni.str = new_str;
6076             });
6077             }
6078              
6079             yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc,
6080             const char *str,
6081             size_t len) {
6082 80096 50         yyjson_mut_val_one_str({
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
6083             char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
6084             if (yyjson_unlikely(!new_str)) return NULL;
6085             unsafe_yyjson_set_strn(val, new_str, len);
6086             });
6087             }
6088              
6089             #undef yyjson_mut_val_one
6090             #undef yyjson_mut_val_one_str
6091              
6092              
6093              
6094             /*==============================================================================
6095             * MARK: - Mutable JSON Array API (Implementation)
6096             *============================================================================*/
6097              
6098             yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr) {
6099 78 50         return yyjson_mut_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0;
    50          
    50          
    50          
    50          
    50          
    50          
    50          
6100             }
6101              
6102             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr,
6103             size_t idx) {
6104             if (yyjson_likely(idx < yyjson_mut_arr_size(arr))) {
6105             yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr;
6106             while (idx-- > 0) val = val->next;
6107             return val->next;
6108             }
6109             return NULL;
6110             }
6111              
6112             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first(
6113             yyjson_mut_val *arr) {
6114 15 50         if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) {
    50          
    100          
6115 13           return ((yyjson_mut_val *)arr->uni.ptr)->next;
6116             }
6117 2           return NULL;
6118             }
6119              
6120             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(
6121             yyjson_mut_val *arr) {
6122             if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) {
6123             return ((yyjson_mut_val *)arr->uni.ptr);
6124             }
6125             return NULL;
6126             }
6127              
6128              
6129              
6130             /*==============================================================================
6131             * MARK: - Mutable JSON Array Iterator API (Implementation)
6132             *============================================================================*/
6133              
6134             yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr,
6135             yyjson_mut_arr_iter *iter) {
6136 9 50         if (yyjson_likely(yyjson_mut_is_arr(arr) && iter)) {
    50          
6137 9           iter->idx = 0;
6138 9           iter->max = unsafe_yyjson_get_len(arr);
6139 9 100         iter->cur = iter->max ? (yyjson_mut_val *)arr->uni.ptr : NULL;
6140 9           iter->pre = NULL;
6141 9           iter->arr = arr;
6142 9           return true;
6143             }
6144 0 0         if (iter) memset(iter, 0, sizeof(yyjson_mut_arr_iter));
6145 0           return false;
6146             }
6147              
6148             yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with(
6149             yyjson_mut_val *arr) {
6150             yyjson_mut_arr_iter iter;
6151             yyjson_mut_arr_iter_init(arr, &iter);
6152             return iter;
6153             }
6154              
6155             yyjson_api_inline bool yyjson_mut_arr_iter_has_next(yyjson_mut_arr_iter *iter) {
6156 1021 50         return iter ? iter->idx < iter->max : false;
    100          
6157             }
6158              
6159             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next(
6160             yyjson_mut_arr_iter *iter) {
6161 1014 50         if (iter && iter->idx < iter->max) {
    50          
6162 1014           yyjson_mut_val *val = iter->cur;
6163 1014           iter->pre = val;
6164 1014           iter->cur = val->next;
6165 1014           iter->idx++;
6166 1014           return iter->cur;
6167             }
6168 0           return NULL;
6169             }
6170              
6171             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove(
6172             yyjson_mut_arr_iter *iter) {
6173             if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) {
6174             yyjson_mut_val *prev = iter->pre;
6175             yyjson_mut_val *cur = iter->cur;
6176             yyjson_mut_val *next = cur->next;
6177             if (yyjson_unlikely(iter->idx == iter->max)) iter->arr->uni.ptr = prev;
6178             iter->idx--;
6179             iter->max--;
6180             unsafe_yyjson_set_len(iter->arr, iter->max);
6181             prev->next = next;
6182             iter->cur = prev;
6183             return cur;
6184             }
6185             return NULL;
6186             }
6187              
6188              
6189              
6190             /*==============================================================================
6191             * MARK: - Mutable JSON Array Creation API (Implementation)
6192             *============================================================================*/
6193              
6194             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc) {
6195 5006           if (yyjson_likely(doc)) {
6196 5006           yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
6197 5006 50         if (yyjson_likely(val)) {
    50          
6198 5006           val->tag = YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE;
6199 5006           return val;
6200             }
6201             }
6202 0           return NULL;
6203             }
6204              
6205             #define yyjson_mut_arr_with_func(func) \
6206             if (yyjson_likely(doc && ((0 < count && count < \
6207             (~(size_t)0) / sizeof(yyjson_mut_val) && vals) || count == 0))) { \
6208             yyjson_mut_val *arr = unsafe_yyjson_mut_val(doc, 1 + count); \
6209             if (yyjson_likely(arr)) { \
6210             arr->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; \
6211             if (count > 0) { \
6212             size_t i; \
6213             for (i = 0; i < count; i++) { \
6214             yyjson_mut_val *val = arr + i + 1; \
6215             func \
6216             val->next = val + 1; \
6217             } \
6218             arr[count].next = arr + 1; \
6219             arr->uni.ptr = arr + count; \
6220             } \
6221             return arr; \
6222             } \
6223             } \
6224             return NULL
6225              
6226             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool(
6227             yyjson_mut_doc *doc, const bool *vals, size_t count) {
6228             yyjson_mut_arr_with_func({
6229             unsafe_yyjson_set_bool(val, vals[i]);
6230             });
6231             }
6232              
6233             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint(
6234             yyjson_mut_doc *doc, const int64_t *vals, size_t count) {
6235             return yyjson_mut_arr_with_sint64(doc, vals, count);
6236             }
6237              
6238             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint(
6239             yyjson_mut_doc *doc, const uint64_t *vals, size_t count) {
6240             return yyjson_mut_arr_with_uint64(doc, vals, count);
6241             }
6242              
6243             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real(
6244             yyjson_mut_doc *doc, const double *vals, size_t count) {
6245             yyjson_mut_arr_with_func({
6246             unsafe_yyjson_set_real(val, vals[i]);
6247             });
6248             }
6249              
6250             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8(
6251             yyjson_mut_doc *doc, const int8_t *vals, size_t count) {
6252             yyjson_mut_arr_with_func({
6253             unsafe_yyjson_set_sint(val, vals[i]);
6254             });
6255             }
6256              
6257             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16(
6258             yyjson_mut_doc *doc, const int16_t *vals, size_t count) {
6259             yyjson_mut_arr_with_func({
6260             unsafe_yyjson_set_sint(val, vals[i]);
6261             });
6262             }
6263              
6264             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32(
6265             yyjson_mut_doc *doc, const int32_t *vals, size_t count) {
6266             yyjson_mut_arr_with_func({
6267             unsafe_yyjson_set_sint(val, vals[i]);
6268             });
6269             }
6270              
6271             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64(
6272             yyjson_mut_doc *doc, const int64_t *vals, size_t count) {
6273             yyjson_mut_arr_with_func({
6274             unsafe_yyjson_set_sint(val, vals[i]);
6275             });
6276             }
6277              
6278             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8(
6279             yyjson_mut_doc *doc, const uint8_t *vals, size_t count) {
6280             yyjson_mut_arr_with_func({
6281             unsafe_yyjson_set_uint(val, vals[i]);
6282             });
6283             }
6284              
6285             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16(
6286             yyjson_mut_doc *doc, const uint16_t *vals, size_t count) {
6287             yyjson_mut_arr_with_func({
6288             unsafe_yyjson_set_uint(val, vals[i]);
6289             });
6290             }
6291              
6292             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32(
6293             yyjson_mut_doc *doc, const uint32_t *vals, size_t count) {
6294             yyjson_mut_arr_with_func({
6295             unsafe_yyjson_set_uint(val, vals[i]);
6296             });
6297             }
6298              
6299             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64(
6300             yyjson_mut_doc *doc, const uint64_t *vals, size_t count) {
6301             yyjson_mut_arr_with_func({
6302             unsafe_yyjson_set_uint(val, vals[i]);
6303             });
6304             }
6305              
6306             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float(
6307             yyjson_mut_doc *doc, const float *vals, size_t count) {
6308             yyjson_mut_arr_with_func({
6309             unsafe_yyjson_set_float(val, vals[i]);
6310             });
6311             }
6312              
6313             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double(
6314             yyjson_mut_doc *doc, const double *vals, size_t count) {
6315             yyjson_mut_arr_with_func({
6316             unsafe_yyjson_set_double(val, vals[i]);
6317             });
6318             }
6319              
6320             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str(
6321             yyjson_mut_doc *doc, const char **vals, size_t count) {
6322             yyjson_mut_arr_with_func({
6323             if (yyjson_unlikely(!vals[i])) return NULL;
6324             unsafe_yyjson_set_str(val, vals[i]);
6325             });
6326             }
6327              
6328             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn(
6329             yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) {
6330             if (yyjson_unlikely(count > 0 && !lens)) return NULL;
6331             yyjson_mut_arr_with_func({
6332             if (yyjson_unlikely(!vals[i])) return NULL;
6333             unsafe_yyjson_set_strn(val, vals[i], lens[i]);
6334             });
6335             }
6336              
6337             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy(
6338             yyjson_mut_doc *doc, const char **vals, size_t count) {
6339             size_t len;
6340             const char *str, *new_str;
6341             yyjson_mut_arr_with_func({
6342             str = vals[i];
6343             if (yyjson_unlikely(!str)) return NULL;
6344             len = strlen(str);
6345             new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
6346             if (yyjson_unlikely(!new_str)) return NULL;
6347             unsafe_yyjson_set_strn(val, new_str, len);
6348             });
6349             }
6350              
6351             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy(
6352             yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) {
6353             size_t len;
6354             const char *str, *new_str;
6355             if (yyjson_unlikely(count > 0 && !lens)) return NULL;
6356             yyjson_mut_arr_with_func({
6357             str = vals[i];
6358             if (yyjson_unlikely(!str)) return NULL;
6359             len = lens[i];
6360             new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
6361             if (yyjson_unlikely(!new_str)) return NULL;
6362             unsafe_yyjson_set_strn(val, new_str, len);
6363             });
6364             }
6365              
6366             #undef yyjson_mut_arr_with_func
6367              
6368              
6369              
6370             /*==============================================================================
6371             * MARK: - Mutable JSON Array Modification API (Implementation)
6372             *============================================================================*/
6373              
6374             yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr,
6375             yyjson_mut_val *val, size_t idx) {
6376             if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
6377             size_t len = unsafe_yyjson_get_len(arr);
6378             if (yyjson_likely(idx <= len)) {
6379             unsafe_yyjson_set_len(arr, len + 1);
6380             if (len == 0) {
6381             val->next = val;
6382             arr->uni.ptr = val;
6383             } else {
6384             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6385             yyjson_mut_val *next = prev->next;
6386             if (idx == len) {
6387             prev->next = val;
6388             val->next = next;
6389             arr->uni.ptr = val;
6390             } else {
6391             while (idx-- > 0) {
6392             prev = next;
6393             next = next->next;
6394             }
6395             prev->next = val;
6396             val->next = next;
6397             }
6398             }
6399             return true;
6400             }
6401             }
6402             return false;
6403             }
6404              
6405             yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr,
6406             yyjson_mut_val *val) {
6407 15009 50         if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
    50          
6408 15009           size_t len = unsafe_yyjson_get_len(arr);
6409 15009           unsafe_yyjson_set_len(arr, len + 1);
6410 15009 100         if (len == 0) {
6411 5003           val->next = val;
6412             } else {
6413 10006           yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6414 10006           yyjson_mut_val *next = prev->next;
6415 10006           prev->next = val;
6416 10006           val->next = next;
6417             }
6418 15009           arr->uni.ptr = val;
6419 15009           return true;
6420             }
6421 0           return false;
6422             }
6423              
6424             yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr,
6425             yyjson_mut_val *val) {
6426             if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
6427             size_t len = unsafe_yyjson_get_len(arr);
6428             unsafe_yyjson_set_len(arr, len + 1);
6429             if (len == 0) {
6430             val->next = val;
6431             arr->uni.ptr = val;
6432             } else {
6433             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6434             yyjson_mut_val *next = prev->next;
6435             prev->next = val;
6436             val->next = next;
6437             }
6438             return true;
6439             }
6440             return false;
6441             }
6442              
6443             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr,
6444             size_t idx,
6445             yyjson_mut_val *val) {
6446             if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
6447             size_t len = unsafe_yyjson_get_len(arr);
6448             if (yyjson_likely(idx < len)) {
6449             if (yyjson_likely(len > 1)) {
6450             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6451             yyjson_mut_val *next = prev->next;
6452             while (idx-- > 0) {
6453             prev = next;
6454             next = next->next;
6455             }
6456             prev->next = val;
6457             val->next = next->next;
6458             if ((void *)next == arr->uni.ptr) arr->uni.ptr = val;
6459             return next;
6460             } else {
6461             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6462             val->next = val;
6463             arr->uni.ptr = val;
6464             return prev;
6465             }
6466             }
6467             }
6468             return NULL;
6469             }
6470              
6471             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr,
6472             size_t idx) {
6473             if (yyjson_likely(yyjson_mut_is_arr(arr))) {
6474             size_t len = unsafe_yyjson_get_len(arr);
6475             if (yyjson_likely(idx < len)) {
6476             unsafe_yyjson_set_len(arr, len - 1);
6477             if (yyjson_likely(len > 1)) {
6478             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6479             yyjson_mut_val *next = prev->next;
6480             while (idx-- > 0) {
6481             prev = next;
6482             next = next->next;
6483             }
6484             prev->next = next->next;
6485             if ((void *)next == arr->uni.ptr) arr->uni.ptr = prev;
6486             return next;
6487             } else {
6488             return ((yyjson_mut_val *)arr->uni.ptr);
6489             }
6490             }
6491             }
6492             return NULL;
6493             }
6494              
6495             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first(
6496             yyjson_mut_val *arr) {
6497             if (yyjson_likely(yyjson_mut_is_arr(arr))) {
6498             size_t len = unsafe_yyjson_get_len(arr);
6499             if (len > 1) {
6500             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6501             yyjson_mut_val *next = prev->next;
6502             prev->next = next->next;
6503             unsafe_yyjson_set_len(arr, len - 1);
6504             return next;
6505             } else if (len == 1) {
6506             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6507             unsafe_yyjson_set_len(arr, 0);
6508             return prev;
6509             }
6510             }
6511             return NULL;
6512             }
6513              
6514             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last(
6515             yyjson_mut_val *arr) {
6516             if (yyjson_likely(yyjson_mut_is_arr(arr))) {
6517             size_t len = unsafe_yyjson_get_len(arr);
6518             if (yyjson_likely(len > 1)) {
6519             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6520             yyjson_mut_val *next = prev->next;
6521             unsafe_yyjson_set_len(arr, len - 1);
6522             while (--len > 0) prev = prev->next;
6523             prev->next = next;
6524             next = (yyjson_mut_val *)arr->uni.ptr;
6525             arr->uni.ptr = prev;
6526             return next;
6527             } else if (len == 1) {
6528             yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
6529             unsafe_yyjson_set_len(arr, 0);
6530             return prev;
6531             }
6532             }
6533             return NULL;
6534             }
6535              
6536             yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr,
6537             size_t _idx, size_t _len) {
6538             if (yyjson_likely(yyjson_mut_is_arr(arr))) {
6539             yyjson_mut_val *prev, *next;
6540             bool tail_removed;
6541             size_t len = unsafe_yyjson_get_len(arr);
6542             if (yyjson_unlikely(_idx + _len > len)) return false;
6543             if (yyjson_unlikely(_len == 0)) return true;
6544             unsafe_yyjson_set_len(arr, len - _len);
6545             if (yyjson_unlikely(len == _len)) return true;
6546             tail_removed = (_idx + _len == len);
6547             prev = ((yyjson_mut_val *)arr->uni.ptr);
6548             while (_idx-- > 0) prev = prev->next;
6549             next = prev->next;
6550             while (_len-- > 0) next = next->next;
6551             prev->next = next;
6552             if (yyjson_unlikely(tail_removed)) arr->uni.ptr = prev;
6553             return true;
6554             }
6555             return false;
6556             }
6557              
6558             yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr) {
6559             if (yyjson_likely(yyjson_mut_is_arr(arr))) {
6560             unsafe_yyjson_set_len(arr, 0);
6561             return true;
6562             }
6563             return false;
6564             }
6565              
6566             yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr,
6567             size_t idx) {
6568             if (yyjson_likely(yyjson_mut_is_arr(arr) &&
6569             unsafe_yyjson_get_len(arr) > idx)) {
6570             yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr;
6571             while (idx-- > 0) val = val->next;
6572             arr->uni.ptr = (void *)val;
6573             return true;
6574             }
6575             return false;
6576             }
6577              
6578              
6579              
6580             /*==============================================================================
6581             * MARK: - Mutable JSON Array Modification Convenience API (Implementation)
6582             *============================================================================*/
6583              
6584             yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr,
6585             yyjson_mut_val *val) {
6586             return yyjson_mut_arr_append(arr, val);
6587             }
6588              
6589             yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc,
6590             yyjson_mut_val *arr) {
6591             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6592             yyjson_mut_val *val = yyjson_mut_null(doc);
6593             return yyjson_mut_arr_append(arr, val);
6594             }
6595             return false;
6596             }
6597              
6598             yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc,
6599             yyjson_mut_val *arr) {
6600             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6601             yyjson_mut_val *val = yyjson_mut_true(doc);
6602             return yyjson_mut_arr_append(arr, val);
6603             }
6604             return false;
6605             }
6606              
6607             yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc,
6608             yyjson_mut_val *arr) {
6609             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6610             yyjson_mut_val *val = yyjson_mut_false(doc);
6611             return yyjson_mut_arr_append(arr, val);
6612             }
6613             return false;
6614             }
6615              
6616             yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc,
6617             yyjson_mut_val *arr,
6618             bool _val) {
6619             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6620             yyjson_mut_val *val = yyjson_mut_bool(doc, _val);
6621             return yyjson_mut_arr_append(arr, val);
6622             }
6623             return false;
6624             }
6625              
6626             yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc,
6627             yyjson_mut_val *arr,
6628             uint64_t num) {
6629             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6630             yyjson_mut_val *val = yyjson_mut_uint(doc, num);
6631             return yyjson_mut_arr_append(arr, val);
6632             }
6633             return false;
6634             }
6635              
6636             yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc,
6637             yyjson_mut_val *arr,
6638             int64_t num) {
6639             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6640             yyjson_mut_val *val = yyjson_mut_sint(doc, num);
6641             return yyjson_mut_arr_append(arr, val);
6642             }
6643             return false;
6644             }
6645              
6646             yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc,
6647             yyjson_mut_val *arr,
6648             int64_t num) {
6649             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6650             yyjson_mut_val *val = yyjson_mut_sint(doc, num);
6651             return yyjson_mut_arr_append(arr, val);
6652             }
6653             return false;
6654             }
6655              
6656             yyjson_api_inline bool yyjson_mut_arr_add_float(yyjson_mut_doc *doc,
6657             yyjson_mut_val *arr,
6658             float num) {
6659             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6660             yyjson_mut_val *val = yyjson_mut_float(doc, num);
6661             return yyjson_mut_arr_append(arr, val);
6662             }
6663             return false;
6664             }
6665              
6666             yyjson_api_inline bool yyjson_mut_arr_add_double(yyjson_mut_doc *doc,
6667             yyjson_mut_val *arr,
6668             double num) {
6669             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6670             yyjson_mut_val *val = yyjson_mut_double(doc, num);
6671             return yyjson_mut_arr_append(arr, val);
6672             }
6673             return false;
6674             }
6675              
6676             yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc,
6677             yyjson_mut_val *arr,
6678             double num) {
6679             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6680             yyjson_mut_val *val = yyjson_mut_real(doc, num);
6681             return yyjson_mut_arr_append(arr, val);
6682             }
6683             return false;
6684             }
6685              
6686             yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc,
6687             yyjson_mut_val *arr,
6688             const char *str) {
6689             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6690             yyjson_mut_val *val = yyjson_mut_str(doc, str);
6691             return yyjson_mut_arr_append(arr, val);
6692             }
6693             return false;
6694             }
6695              
6696             yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc,
6697             yyjson_mut_val *arr,
6698             const char *str, size_t len) {
6699             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6700             yyjson_mut_val *val = yyjson_mut_strn(doc, str, len);
6701             return yyjson_mut_arr_append(arr, val);
6702             }
6703             return false;
6704             }
6705              
6706             yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc,
6707             yyjson_mut_val *arr,
6708             const char *str) {
6709             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6710             yyjson_mut_val *val = yyjson_mut_strcpy(doc, str);
6711             return yyjson_mut_arr_append(arr, val);
6712             }
6713             return false;
6714             }
6715              
6716             yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc,
6717             yyjson_mut_val *arr,
6718             const char *str, size_t len) {
6719             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6720             yyjson_mut_val *val = yyjson_mut_strncpy(doc, str, len);
6721             return yyjson_mut_arr_append(arr, val);
6722             }
6723             return false;
6724             }
6725              
6726             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc,
6727             yyjson_mut_val *arr) {
6728             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6729             yyjson_mut_val *val = yyjson_mut_arr(doc);
6730             return yyjson_mut_arr_append(arr, val) ? val : NULL;
6731             }
6732             return NULL;
6733             }
6734              
6735             yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc,
6736             yyjson_mut_val *arr) {
6737             if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
6738             yyjson_mut_val *val = yyjson_mut_obj(doc);
6739             return yyjson_mut_arr_append(arr, val) ? val : NULL;
6740             }
6741             return NULL;
6742             }
6743              
6744              
6745              
6746             /*==============================================================================
6747             * MARK: - Mutable JSON Object API (Implementation)
6748             *============================================================================*/
6749              
6750             yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj) {
6751 50 50         return yyjson_mut_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0;
    50          
    50          
    50          
    50          
    0          
    50          
    50          
    50          
    0          
    50          
    50          
6752             }
6753              
6754             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj,
6755             const char *key) {
6756             return yyjson_mut_obj_getn(obj, key, key ? strlen(key) : 0);
6757             }
6758              
6759             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj,
6760             const char *_key,
6761             size_t key_len) {
6762             size_t len = yyjson_mut_obj_size(obj);
6763             if (yyjson_likely(len && _key)) {
6764             yyjson_mut_val *key = ((yyjson_mut_val *)obj->uni.ptr)->next->next;
6765             while (len-- > 0) {
6766             if (unsafe_yyjson_equals_strn(key, _key, key_len)) return key->next;
6767             key = key->next->next;
6768             }
6769             }
6770             return NULL;
6771             }
6772              
6773              
6774              
6775             /*==============================================================================
6776             * MARK: - Mutable JSON Object Iterator API (Implementation)
6777             *============================================================================*/
6778              
6779             yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj,
6780             yyjson_mut_obj_iter *iter) {
6781 2 50         if (yyjson_likely(yyjson_mut_is_obj(obj) && iter)) {
    50          
6782 2           iter->idx = 0;
6783 2           iter->max = unsafe_yyjson_get_len(obj);
6784 2 100         iter->cur = iter->max ? (yyjson_mut_val *)obj->uni.ptr : NULL;
6785 2           iter->pre = NULL;
6786 2           iter->obj = obj;
6787 2           return true;
6788             }
6789 0 0         if (iter) memset(iter, 0, sizeof(yyjson_mut_obj_iter));
6790 0           return false;
6791             }
6792              
6793             yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with(
6794             yyjson_mut_val *obj) {
6795             yyjson_mut_obj_iter iter;
6796             yyjson_mut_obj_iter_init(obj, &iter);
6797             return iter;
6798             }
6799              
6800             yyjson_api_inline bool yyjson_mut_obj_iter_has_next(yyjson_mut_obj_iter *iter) {
6801 5 50         return iter ? iter->idx < iter->max : false;
    100          
6802             }
6803              
6804             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next(
6805             yyjson_mut_obj_iter *iter) {
6806 3 50         if (iter && iter->idx < iter->max) {
    50          
6807 3           yyjson_mut_val *key = iter->cur;
6808 3           iter->pre = key;
6809 3           iter->cur = key->next->next;
6810 3           iter->idx++;
6811 3           return iter->cur;
6812             }
6813 0           return NULL;
6814             }
6815              
6816             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val(
6817             yyjson_mut_val *key) {
6818 3 50         return key ? key->next : NULL;
6819             }
6820              
6821             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove(
6822             yyjson_mut_obj_iter *iter) {
6823             if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) {
6824             yyjson_mut_val *prev = iter->pre;
6825             yyjson_mut_val *cur = iter->cur;
6826             yyjson_mut_val *next = cur->next->next;
6827             if (yyjson_unlikely(iter->idx == iter->max)) iter->obj->uni.ptr = prev;
6828             iter->idx--;
6829             iter->max--;
6830             unsafe_yyjson_set_len(iter->obj, iter->max);
6831             prev->next->next = next;
6832             iter->cur = prev;
6833             return cur->next;
6834             }
6835             return NULL;
6836             }
6837              
6838             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get(
6839             yyjson_mut_obj_iter *iter, const char *key) {
6840             return yyjson_mut_obj_iter_getn(iter, key, key ? strlen(key) : 0);
6841             }
6842              
6843             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn(
6844             yyjson_mut_obj_iter *iter, const char *key, size_t key_len) {
6845             if (iter && key) {
6846             size_t idx = 0;
6847             size_t max = iter->max;
6848             yyjson_mut_val *pre, *cur = iter->cur;
6849             while (idx++ < max) {
6850             pre = cur;
6851             cur = cur->next->next;
6852             if (unsafe_yyjson_equals_strn(cur, key, key_len)) {
6853             iter->idx += idx;
6854             if (iter->idx > max) iter->idx -= max + 1;
6855             iter->pre = pre;
6856             iter->cur = cur;
6857             return cur->next;
6858             }
6859             }
6860             }
6861             return NULL;
6862             }
6863              
6864              
6865              
6866             /*==============================================================================
6867             * MARK: - Mutable JSON Object Creation API (Implementation)
6868             *============================================================================*/
6869              
6870             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc) {
6871 10013 50         if (yyjson_likely(doc)) {
    0          
    0          
    0          
6872 10013           yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
6873 10013 50         if (yyjson_likely(val)) {
    0          
    0          
    50          
    0          
    0          
6874 10013           val->tag = YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE;
6875 10013           return val;
6876             }
6877             }
6878 0           return NULL;
6879             }
6880              
6881             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc,
6882             const char **keys,
6883             const char **vals,
6884             size_t count) {
6885             if (yyjson_likely(doc && ((count > 0 && keys && vals) || (count == 0)))) {
6886             yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2);
6887             if (yyjson_likely(obj)) {
6888             obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ;
6889             if (count > 0) {
6890             size_t i;
6891             for (i = 0; i < count; i++) {
6892             yyjson_mut_val *key = obj + (i * 2 + 1);
6893             yyjson_mut_val *val = obj + (i * 2 + 2);
6894             uint64_t key_len = (uint64_t)strlen(keys[i]);
6895             uint64_t val_len = (uint64_t)strlen(vals[i]);
6896             key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
6897             val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
6898             key->uni.str = keys[i];
6899             val->uni.str = vals[i];
6900             key->next = val;
6901             val->next = val + 1;
6902             }
6903             obj[count * 2].next = obj + 1;
6904             obj->uni.ptr = obj + (count * 2 - 1);
6905             }
6906             return obj;
6907             }
6908             }
6909             return NULL;
6910             }
6911              
6912             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc,
6913             const char **pairs,
6914             size_t count) {
6915             if (yyjson_likely(doc && ((count > 0 && pairs) || (count == 0)))) {
6916             yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2);
6917             if (yyjson_likely(obj)) {
6918             obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ;
6919             if (count > 0) {
6920             size_t i;
6921             for (i = 0; i < count; i++) {
6922             yyjson_mut_val *key = obj + (i * 2 + 1);
6923             yyjson_mut_val *val = obj + (i * 2 + 2);
6924             const char *key_str = pairs[i * 2 + 0];
6925             const char *val_str = pairs[i * 2 + 1];
6926             uint64_t key_len = (uint64_t)strlen(key_str);
6927             uint64_t val_len = (uint64_t)strlen(val_str);
6928             key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
6929             val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
6930             key->uni.str = key_str;
6931             val->uni.str = val_str;
6932             key->next = val;
6933             val->next = val + 1;
6934             }
6935             obj[count * 2].next = obj + 1;
6936             obj->uni.ptr = obj + (count * 2 - 1);
6937             }
6938             return obj;
6939             }
6940             }
6941             return NULL;
6942             }
6943              
6944              
6945              
6946             /*==============================================================================
6947             * MARK: - Mutable JSON Object Modification API (Implementation)
6948             *============================================================================*/
6949              
6950             yyjson_api_inline void unsafe_yyjson_mut_obj_add(yyjson_mut_val *obj,
6951             yyjson_mut_val *key,
6952             yyjson_mut_val *val,
6953             size_t len) {
6954 15015           if (yyjson_likely(len)) {
6955 5004           yyjson_mut_val *prev_val = ((yyjson_mut_val *)obj->uni.ptr)->next;
6956 5004           yyjson_mut_val *next_key = prev_val->next;
6957 5004           prev_val->next = key;
6958 5004           val->next = next_key;
6959             } else {
6960 10011           val->next = key;
6961             }
6962 15015           key->next = val;
6963 15015           obj->uni.ptr = (void *)key;
6964 15015           unsafe_yyjson_set_len(obj, len + 1);
6965 15015           }
6966              
6967             yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_obj_remove(
6968             yyjson_mut_val *obj, const char *key, size_t key_len) {
6969             size_t obj_len = unsafe_yyjson_get_len(obj);
6970             if (obj_len) {
6971             yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr;
6972             yyjson_mut_val *cur_key = pre_key->next->next;
6973             yyjson_mut_val *removed_item = NULL;
6974             size_t i;
6975             for (i = 0; i < obj_len; i++) {
6976             if (unsafe_yyjson_equals_strn(cur_key, key, key_len)) {
6977             if (!removed_item) removed_item = cur_key->next;
6978             cur_key = cur_key->next->next;
6979             pre_key->next->next = cur_key;
6980             if (i + 1 == obj_len) obj->uni.ptr = pre_key;
6981             i--;
6982             obj_len--;
6983             } else {
6984             pre_key = cur_key;
6985             cur_key = cur_key->next->next;
6986             }
6987             }
6988             unsafe_yyjson_set_len(obj, obj_len);
6989             return removed_item;
6990             } else {
6991             return NULL;
6992             }
6993             }
6994              
6995             yyjson_api_inline bool unsafe_yyjson_mut_obj_replace(yyjson_mut_val *obj,
6996             yyjson_mut_val *key,
6997             yyjson_mut_val *val) {
6998             size_t key_len = unsafe_yyjson_get_len(key);
6999             size_t obj_len = unsafe_yyjson_get_len(obj);
7000             if (obj_len) {
7001             yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr;
7002             yyjson_mut_val *cur_key = pre_key->next->next;
7003             size_t i;
7004             for (i = 0; i < obj_len; i++) {
7005             if (unsafe_yyjson_equals_strn(cur_key, key->uni.str, key_len)) {
7006             cur_key->next->tag = val->tag;
7007             cur_key->next->uni.u64 = val->uni.u64;
7008             return true;
7009             } else {
7010             cur_key = cur_key->next->next;
7011             }
7012             }
7013             }
7014             return false;
7015             }
7016              
7017             yyjson_api_inline void unsafe_yyjson_mut_obj_rotate(yyjson_mut_val *obj,
7018             size_t idx) {
7019             yyjson_mut_val *key = (yyjson_mut_val *)obj->uni.ptr;
7020             while (idx-- > 0) key = key->next->next;
7021             obj->uni.ptr = (void *)key;
7022             }
7023              
7024             yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj,
7025             yyjson_mut_val *key,
7026             yyjson_mut_val *val) {
7027 30030 50         if (yyjson_likely(yyjson_mut_is_obj(obj) &&
    50          
    50          
    50          
7028             yyjson_mut_is_str(key) && val)) {
7029 15015 100         unsafe_yyjson_mut_obj_add(obj, key, val, unsafe_yyjson_get_len(obj));
7030 15015           return true;
7031             }
7032 0           return false;
7033             }
7034              
7035             yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj,
7036             yyjson_mut_val *key,
7037             yyjson_mut_val *val) {
7038             bool replaced = false;
7039             size_t key_len;
7040             yyjson_mut_obj_iter iter;
7041             yyjson_mut_val *cur_key;
7042             if (yyjson_unlikely(!yyjson_mut_is_obj(obj) ||
7043             !yyjson_mut_is_str(key))) return false;
7044             key_len = unsafe_yyjson_get_len(key);
7045             yyjson_mut_obj_iter_init(obj, &iter);
7046             while ((cur_key = yyjson_mut_obj_iter_next(&iter)) != 0) {
7047             if (unsafe_yyjson_equals_strn(cur_key, key->uni.str, key_len)) {
7048             if (!replaced && val) {
7049             replaced = true;
7050             val->next = cur_key->next->next;
7051             cur_key->next = val;
7052             } else {
7053             yyjson_mut_obj_iter_remove(&iter);
7054             }
7055             }
7056             }
7057             if (!replaced && val) unsafe_yyjson_mut_obj_add(obj, key, val, iter.max);
7058             return true;
7059             }
7060              
7061             yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj,
7062             yyjson_mut_val *key,
7063             yyjson_mut_val *val,
7064             size_t idx) {
7065             if (yyjson_likely(yyjson_mut_is_obj(obj) &&
7066             yyjson_mut_is_str(key) && val)) {
7067             size_t len = unsafe_yyjson_get_len(obj);
7068             if (yyjson_likely(len >= idx)) {
7069             if (len > idx) {
7070             void *ptr = obj->uni.ptr;
7071             unsafe_yyjson_mut_obj_rotate(obj, idx);
7072             unsafe_yyjson_mut_obj_add(obj, key, val, len);
7073             obj->uni.ptr = ptr;
7074             } else {
7075             unsafe_yyjson_mut_obj_add(obj, key, val, len);
7076             }
7077             return true;
7078             }
7079             }
7080             return false;
7081             }
7082              
7083             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj,
7084             yyjson_mut_val *key) {
7085             if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key))) {
7086             return unsafe_yyjson_mut_obj_remove(obj, key->uni.str,
7087             unsafe_yyjson_get_len(key));
7088             }
7089             return NULL;
7090             }
7091              
7092             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key(
7093             yyjson_mut_val *obj, const char *key) {
7094             if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) {
7095             size_t key_len = strlen(key);
7096             return unsafe_yyjson_mut_obj_remove(obj, key, key_len);
7097             }
7098             return NULL;
7099             }
7100              
7101             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn(
7102             yyjson_mut_val *obj, const char *key, size_t key_len) {
7103             if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) {
7104             return unsafe_yyjson_mut_obj_remove(obj, key, key_len);
7105             }
7106             return NULL;
7107             }
7108              
7109             yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj) {
7110             if (yyjson_likely(yyjson_mut_is_obj(obj))) {
7111             unsafe_yyjson_set_len(obj, 0);
7112             return true;
7113             }
7114             return false;
7115             }
7116              
7117             yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj,
7118             yyjson_mut_val *key,
7119             yyjson_mut_val *val) {
7120             if (yyjson_likely(yyjson_mut_is_obj(obj) &&
7121             yyjson_mut_is_str(key) && val)) {
7122             return unsafe_yyjson_mut_obj_replace(obj, key, val);
7123             }
7124             return false;
7125             }
7126              
7127             yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj,
7128             size_t idx) {
7129             if (yyjson_likely(yyjson_mut_is_obj(obj) &&
7130             unsafe_yyjson_get_len(obj) > idx)) {
7131             unsafe_yyjson_mut_obj_rotate(obj, idx);
7132             return true;
7133             }
7134             return false;
7135             }
7136              
7137              
7138              
7139             /*==============================================================================
7140             * MARK: - Mutable JSON Object Modification Convenience API (Implementation)
7141             *============================================================================*/
7142              
7143             #define yyjson_mut_obj_add_func(func) \
7144             if (yyjson_likely(doc && yyjson_mut_is_obj(obj) && _key)) { \
7145             yyjson_mut_val *key = unsafe_yyjson_mut_val(doc, 2); \
7146             if (yyjson_likely(key)) { \
7147             size_t len = unsafe_yyjson_get_len(obj); \
7148             yyjson_mut_val *val = key + 1; \
7149             size_t key_len = strlen(_key); \
7150             bool noesc = unsafe_yyjson_is_str_noesc(_key, key_len); \
7151             key->tag = YYJSON_TYPE_STR; \
7152             key->tag |= noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE; \
7153             key->tag |= (uint64_t)strlen(_key) << YYJSON_TAG_BIT; \
7154             key->uni.str = _key; \
7155             func \
7156             unsafe_yyjson_mut_obj_add(obj, key, val, len); \
7157             return true; \
7158             } \
7159             } \
7160             return false
7161              
7162             yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
7163             yyjson_mut_val *obj,
7164             const char *_key) {
7165             yyjson_mut_obj_add_func({ unsafe_yyjson_set_null(val); });
7166             }
7167              
7168             yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
7169             yyjson_mut_val *obj,
7170             const char *_key) {
7171             yyjson_mut_obj_add_func({ unsafe_yyjson_set_bool(val, true); });
7172             }
7173              
7174             yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
7175             yyjson_mut_val *obj,
7176             const char *_key) {
7177             yyjson_mut_obj_add_func({ unsafe_yyjson_set_bool(val, false); });
7178             }
7179              
7180             yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
7181             yyjson_mut_val *obj,
7182             const char *_key,
7183             bool _val) {
7184             yyjson_mut_obj_add_func({ unsafe_yyjson_set_bool(val, _val); });
7185             }
7186              
7187             yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
7188             yyjson_mut_val *obj,
7189             const char *_key,
7190             uint64_t _val) {
7191             yyjson_mut_obj_add_func({ unsafe_yyjson_set_uint(val, _val); });
7192             }
7193              
7194             yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
7195             yyjson_mut_val *obj,
7196             const char *_key,
7197             int64_t _val) {
7198             yyjson_mut_obj_add_func({ unsafe_yyjson_set_sint(val, _val); });
7199             }
7200              
7201             yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
7202             yyjson_mut_val *obj,
7203             const char *_key,
7204             int64_t _val) {
7205             yyjson_mut_obj_add_func({ unsafe_yyjson_set_sint(val, _val); });
7206             }
7207              
7208             yyjson_api_inline bool yyjson_mut_obj_add_float(yyjson_mut_doc *doc,
7209             yyjson_mut_val *obj,
7210             const char *_key,
7211             float _val) {
7212             yyjson_mut_obj_add_func({ unsafe_yyjson_set_float(val, _val); });
7213             }
7214              
7215             yyjson_api_inline bool yyjson_mut_obj_add_double(yyjson_mut_doc *doc,
7216             yyjson_mut_val *obj,
7217             const char *_key,
7218             double _val) {
7219             yyjson_mut_obj_add_func({ unsafe_yyjson_set_double(val, _val); });
7220             }
7221              
7222             yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
7223             yyjson_mut_val *obj,
7224             const char *_key,
7225             double _val) {
7226             yyjson_mut_obj_add_func({ unsafe_yyjson_set_real(val, _val); });
7227             }
7228              
7229             yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
7230             yyjson_mut_val *obj,
7231             const char *_key,
7232             const char *_val) {
7233             if (yyjson_unlikely(!_val)) return false;
7234             yyjson_mut_obj_add_func({
7235             size_t val_len = strlen(_val);
7236             bool val_noesc = unsafe_yyjson_is_str_noesc(_val, val_len);
7237             val->tag = ((uint64_t)strlen(_val) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
7238             val->tag |= val_noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
7239             val->uni.str = _val;
7240             });
7241             }
7242              
7243             yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
7244             yyjson_mut_val *obj,
7245             const char *_key,
7246             const char *_val,
7247             size_t _len) {
7248             if (yyjson_unlikely(!_val)) return false;
7249             yyjson_mut_obj_add_func({
7250             val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
7251             val->uni.str = _val;
7252             });
7253             }
7254              
7255             yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
7256             yyjson_mut_val *obj,
7257             const char *_key,
7258             const char *_val) {
7259             if (yyjson_unlikely(!_val)) return false;
7260             yyjson_mut_obj_add_func({
7261             size_t _len = strlen(_val);
7262             val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len);
7263             if (yyjson_unlikely(!val->uni.str)) return false;
7264             val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
7265             });
7266             }
7267              
7268             yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
7269             yyjson_mut_val *obj,
7270             const char *_key,
7271             const char *_val,
7272             size_t _len) {
7273             if (yyjson_unlikely(!_val)) return false;
7274             yyjson_mut_obj_add_func({
7275             val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len);
7276             if (yyjson_unlikely(!val->uni.str)) return false;
7277             val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
7278             });
7279             }
7280              
7281             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc,
7282             yyjson_mut_val *obj,
7283             const char *_key) {
7284             yyjson_mut_val *key = yyjson_mut_str(doc, _key);
7285             yyjson_mut_val *val = yyjson_mut_arr(doc);
7286             return yyjson_mut_obj_add(obj, key, val) ? val : NULL;
7287             }
7288              
7289             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc,
7290             yyjson_mut_val *obj,
7291             const char *_key) {
7292             yyjson_mut_val *key = yyjson_mut_str(doc, _key);
7293             yyjson_mut_val *val = yyjson_mut_obj(doc);
7294             return yyjson_mut_obj_add(obj, key, val) ? val : NULL;
7295             }
7296              
7297             yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
7298             yyjson_mut_val *obj,
7299             const char *_key,
7300             yyjson_mut_val *_val) {
7301             if (yyjson_unlikely(!_val)) return false;
7302             yyjson_mut_obj_add_func({
7303             val = _val;
7304             });
7305             }
7306              
7307             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str(yyjson_mut_val *obj,
7308             const char *key) {
7309             return yyjson_mut_obj_remove_strn(obj, key, key ? strlen(key) : 0);
7310             }
7311              
7312             yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn(
7313             yyjson_mut_val *obj, const char *_key, size_t _len) {
7314             if (yyjson_likely(yyjson_mut_is_obj(obj) && _key)) {
7315             yyjson_mut_val *key;
7316             yyjson_mut_obj_iter iter;
7317             yyjson_mut_val *val_removed = NULL;
7318             yyjson_mut_obj_iter_init(obj, &iter);
7319             while ((key = yyjson_mut_obj_iter_next(&iter)) != NULL) {
7320             if (unsafe_yyjson_equals_strn(key, _key, _len)) {
7321             if (!val_removed) val_removed = key->next;
7322             yyjson_mut_obj_iter_remove(&iter);
7323             }
7324             }
7325             return val_removed;
7326             }
7327             return NULL;
7328             }
7329              
7330             yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc,
7331             yyjson_mut_val *obj,
7332             const char *key,
7333             const char *new_key) {
7334             if (!key || !new_key) return false;
7335             return yyjson_mut_obj_rename_keyn(doc, obj, key, strlen(key),
7336             new_key, strlen(new_key));
7337             }
7338              
7339             yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc,
7340             yyjson_mut_val *obj,
7341             const char *key,
7342             size_t len,
7343             const char *new_key,
7344             size_t new_len) {
7345             char *cpy_key = NULL;
7346             yyjson_mut_val *old_key;
7347             yyjson_mut_obj_iter iter;
7348             if (!doc || !obj || !key || !new_key) return false;
7349             yyjson_mut_obj_iter_init(obj, &iter);
7350             while ((old_key = yyjson_mut_obj_iter_next(&iter))) {
7351             if (unsafe_yyjson_equals_strn((void *)old_key, key, len)) {
7352             if (!cpy_key) {
7353             cpy_key = unsafe_yyjson_mut_strncpy(doc, new_key, new_len);
7354             if (!cpy_key) return false;
7355             }
7356             yyjson_mut_set_strn(old_key, cpy_key, new_len);
7357             }
7358             }
7359             return cpy_key != NULL;
7360             }
7361              
7362              
7363              
7364             #if !defined(YYJSON_DISABLE_UTILS) || !YYJSON_DISABLE_UTILS
7365              
7366             /*==============================================================================
7367             * MARK: - JSON Pointer API (Implementation)
7368             *============================================================================*/
7369              
7370             #define yyjson_ptr_set_err(_code, _msg) do { \
7371             if (err) { \
7372             err->code = YYJSON_PTR_ERR_##_code; \
7373             err->msg = _msg; \
7374             err->pos = 0; \
7375             } \
7376             } while(false)
7377              
7378             /* require: val != NULL, *ptr == '/', len > 0 */
7379             yyjson_api yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val,
7380             const char *ptr, size_t len,
7381             yyjson_ptr_err *err);
7382              
7383             /* require: val != NULL, *ptr == '/', len > 0 */
7384             yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val,
7385             const char *ptr,
7386             size_t len,
7387             yyjson_ptr_ctx *ctx,
7388             yyjson_ptr_err *err);
7389              
7390             /* require: val/new_val/doc != NULL, *ptr == '/', len > 0 */
7391             yyjson_api bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val,
7392             const char *ptr, size_t len,
7393             yyjson_mut_val *new_val,
7394             yyjson_mut_doc *doc,
7395             bool create_parent, bool insert_new,
7396             yyjson_ptr_ctx *ctx,
7397             yyjson_ptr_err *err);
7398              
7399             /* require: val/err != NULL, *ptr == '/', len > 0 */
7400             yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex(
7401             yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
7402             yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
7403              
7404             /* require: val/err != NULL, *ptr == '/', len > 0 */
7405             yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val,
7406             const char *ptr,
7407             size_t len,
7408             yyjson_ptr_ctx *ctx,
7409             yyjson_ptr_err *err);
7410              
7411             yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc,
7412             const char *ptr) {
7413             if (yyjson_unlikely(!ptr)) return NULL;
7414             return yyjson_doc_ptr_getn(doc, ptr, strlen(ptr));
7415             }
7416              
7417             yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc,
7418             const char *ptr, size_t len) {
7419             return yyjson_doc_ptr_getx(doc, ptr, len, NULL);
7420             }
7421              
7422             yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc,
7423             const char *ptr, size_t len,
7424             yyjson_ptr_err *err) {
7425             yyjson_ptr_set_err(NONE, NULL);
7426             if (yyjson_unlikely(!doc || !ptr)) {
7427             yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7428             return NULL;
7429             }
7430             if (yyjson_unlikely(!doc->root)) {
7431             yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
7432             return NULL;
7433             }
7434             if (yyjson_unlikely(len == 0)) {
7435             return doc->root;
7436             }
7437             if (yyjson_unlikely(*ptr != '/')) {
7438             yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7439             return NULL;
7440             }
7441             return unsafe_yyjson_ptr_getx(doc->root, ptr, len, err);
7442             }
7443              
7444             yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val,
7445             const char *ptr) {
7446             if (yyjson_unlikely(!ptr)) return NULL;
7447             return yyjson_ptr_getn(val, ptr, strlen(ptr));
7448             }
7449              
7450             yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val,
7451             const char *ptr, size_t len) {
7452             return yyjson_ptr_getx(val, ptr, len, NULL);
7453             }
7454              
7455             yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val,
7456             const char *ptr, size_t len,
7457             yyjson_ptr_err *err) {
7458             yyjson_ptr_set_err(NONE, NULL);
7459             if (yyjson_unlikely(!val || !ptr)) {
7460             yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7461             return NULL;
7462             }
7463             if (yyjson_unlikely(len == 0)) {
7464             return val;
7465             }
7466             if (yyjson_unlikely(*ptr != '/')) {
7467             yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7468             return NULL;
7469             }
7470             return unsafe_yyjson_ptr_getx(val, ptr, len, err);
7471             }
7472              
7473             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc,
7474             const char *ptr) {
7475             if (!ptr) return NULL;
7476             return yyjson_mut_doc_ptr_getn(doc, ptr, strlen(ptr));
7477             }
7478              
7479             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc,
7480             const char *ptr,
7481             size_t len) {
7482             return yyjson_mut_doc_ptr_getx(doc, ptr, len, NULL, NULL);
7483             }
7484              
7485             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc,
7486             const char *ptr,
7487             size_t len,
7488             yyjson_ptr_ctx *ctx,
7489             yyjson_ptr_err *err) {
7490             yyjson_ptr_set_err(NONE, NULL);
7491             if (ctx) memset(ctx, 0, sizeof(*ctx));
7492              
7493             if (yyjson_unlikely(!doc || !ptr)) {
7494             yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7495             return NULL;
7496             }
7497             if (yyjson_unlikely(!doc->root)) {
7498             yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
7499             return NULL;
7500             }
7501             if (yyjson_unlikely(len == 0)) {
7502             return doc->root;
7503             }
7504             if (yyjson_unlikely(*ptr != '/')) {
7505             yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7506             return NULL;
7507             }
7508             return unsafe_yyjson_mut_ptr_getx(doc->root, ptr, len, ctx, err);
7509             }
7510              
7511             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val,
7512             const char *ptr) {
7513             if (!ptr) return NULL;
7514             return yyjson_mut_ptr_getn(val, ptr, strlen(ptr));
7515             }
7516              
7517             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val,
7518             const char *ptr,
7519             size_t len) {
7520 5117           return yyjson_mut_ptr_getx(val, ptr, len, NULL, NULL);
7521             }
7522              
7523             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val,
7524             const char *ptr,
7525             size_t len,
7526             yyjson_ptr_ctx *ctx,
7527             yyjson_ptr_err *err) {
7528 5117 50         yyjson_ptr_set_err(NONE, NULL);
    50          
7529 5117 50         if (ctx) memset(ctx, 0, sizeof(*ctx));
    50          
7530              
7531 5117 50         if (yyjson_unlikely(!val || !ptr)) {
    50          
    50          
    50          
7532 0 0         yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
    0          
7533 0           return NULL;
7534             }
7535 5117 50         if (yyjson_unlikely(len == 0)) {
    50          
7536 0           return val;
7537             }
7538 5117 50         if (yyjson_unlikely(*ptr != '/')) {
    50          
7539 0 0         yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
    0          
7540 0           return NULL;
7541             }
7542 5117           return unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err);
7543             }
7544              
7545             yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc,
7546             const char *ptr,
7547             yyjson_mut_val *new_val) {
7548             if (yyjson_unlikely(!ptr)) return false;
7549             return yyjson_mut_doc_ptr_addn(doc, ptr, strlen(ptr), new_val);
7550             }
7551              
7552             yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc,
7553             const char *ptr,
7554             size_t len,
7555             yyjson_mut_val *new_val) {
7556             return yyjson_mut_doc_ptr_addx(doc, ptr, len, new_val, true, NULL, NULL);
7557             }
7558              
7559             yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc,
7560             const char *ptr, size_t len,
7561             yyjson_mut_val *new_val,
7562             bool create_parent,
7563             yyjson_ptr_ctx *ctx,
7564             yyjson_ptr_err *err) {
7565 5 50         yyjson_ptr_set_err(NONE, NULL);
    50          
7566 5 50         if (ctx) memset(ctx, 0, sizeof(*ctx));
    50          
7567              
7568 5 50         if (yyjson_unlikely(!doc || !ptr || !new_val)) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
7569 0 0         yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
    0          
7570 0           return false;
7571             }
7572 5 50         if (yyjson_unlikely(len == 0)) {
    50          
7573 0 0         if (doc->root) {
    0          
7574 0 0         yyjson_ptr_set_err(SET_ROOT, "cannot set document's root");
    0          
7575 0           return false;
7576             } else {
7577 0           doc->root = new_val;
7578 0           return true;
7579             }
7580             }
7581 5 50         if (yyjson_unlikely(*ptr != '/')) {
    50          
7582 0 0         yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
    0          
7583 0           return false;
7584             }
7585 5 50         if (yyjson_unlikely(!doc->root && !create_parent)) {
    0          
    50          
    0          
7586 0 0         yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
    0          
7587 0           return false;
7588             }
7589 5 50         if (yyjson_unlikely(!doc->root)) {
    50          
7590 0           yyjson_mut_val *root = yyjson_mut_obj(doc);
7591 0 0         if (yyjson_unlikely(!root)) {
    0          
7592 0 0         yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value");
    0          
7593 0           return false;
7594             }
7595 0 0         if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc,
    0          
7596             create_parent, true, ctx, err)) {
7597 0           doc->root = root;
7598 0           return true;
7599             }
7600 0           return false;
7601             }
7602 5           return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc,
7603             create_parent, true, ctx, err);
7604             }
7605              
7606             yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val,
7607             const char *ptr,
7608             yyjson_mut_val *new_val,
7609             yyjson_mut_doc *doc) {
7610             if (yyjson_unlikely(!ptr)) return false;
7611             return yyjson_mut_ptr_addn(val, ptr, strlen(ptr), new_val, doc);
7612             }
7613              
7614             yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val,
7615             const char *ptr, size_t len,
7616             yyjson_mut_val *new_val,
7617             yyjson_mut_doc *doc) {
7618             return yyjson_mut_ptr_addx(val, ptr, len, new_val, doc, true, NULL, NULL);
7619             }
7620              
7621             yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val,
7622             const char *ptr, size_t len,
7623             yyjson_mut_val *new_val,
7624             yyjson_mut_doc *doc,
7625             bool create_parent,
7626             yyjson_ptr_ctx *ctx,
7627             yyjson_ptr_err *err) {
7628             yyjson_ptr_set_err(NONE, NULL);
7629             if (ctx) memset(ctx, 0, sizeof(*ctx));
7630              
7631             if (yyjson_unlikely(!val || !ptr || !new_val || !doc)) {
7632             yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7633             return false;
7634             }
7635             if (yyjson_unlikely(len == 0)) {
7636             yyjson_ptr_set_err(SET_ROOT, "cannot set root");
7637             return false;
7638             }
7639             if (yyjson_unlikely(*ptr != '/')) {
7640             yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7641             return false;
7642             }
7643             return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val,
7644             doc, create_parent, true, ctx, err);
7645             }
7646              
7647             yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc,
7648             const char *ptr,
7649             yyjson_mut_val *new_val) {
7650             if (yyjson_unlikely(!ptr)) return false;
7651             return yyjson_mut_doc_ptr_setn(doc, ptr, strlen(ptr), new_val);
7652             }
7653              
7654             yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc,
7655             const char *ptr, size_t len,
7656             yyjson_mut_val *new_val) {
7657             return yyjson_mut_doc_ptr_setx(doc, ptr, len, new_val, true, NULL, NULL);
7658             }
7659              
7660             yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc,
7661             const char *ptr, size_t len,
7662             yyjson_mut_val *new_val,
7663             bool create_parent,
7664             yyjson_ptr_ctx *ctx,
7665             yyjson_ptr_err *err) {
7666 10023 50         yyjson_ptr_set_err(NONE, NULL);
    50          
7667 10023 50         if (ctx) memset(ctx, 0, sizeof(*ctx));
    50          
7668              
7669 10023 50         if (yyjson_unlikely(!doc || !ptr)) {
    50          
    50          
    50          
7670 0 0         yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
    0          
7671 0           return false;
7672             }
7673 10023 50         if (yyjson_unlikely(len == 0)) {
    50          
7674 0 0         if (ctx) ctx->old = doc->root;
    0          
7675 0           doc->root = new_val;
7676 0           return true;
7677             }
7678 10023 50         if (yyjson_unlikely(*ptr != '/')) {
    50          
7679 0 0         yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
    0          
7680 0           return false;
7681             }
7682 10023 50         if (!new_val) {
    50          
7683 0 0         if (!doc->root) {
    0          
7684 0 0         yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved");
    0          
7685 0           return false;
7686             }
7687 0           return !!unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err);
7688             }
7689 10023 50         if (yyjson_unlikely(!doc->root && !create_parent)) {
    0          
    50          
    0          
7690 0 0         yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
    0          
7691 0           return false;
7692             }
7693 10023 50         if (yyjson_unlikely(!doc->root)) {
    50          
7694 0           yyjson_mut_val *root = yyjson_mut_obj(doc);
7695 0 0         if (yyjson_unlikely(!root)) {
    0          
7696 0 0         yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value");
    0          
7697 0           return false;
7698             }
7699 0 0         if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc,
    0          
7700             create_parent, false, ctx, err)) {
7701 0           doc->root = root;
7702 0           return true;
7703             }
7704 0           return false;
7705             }
7706 10023           return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc,
7707             create_parent, false, ctx, err);
7708             }
7709              
7710             yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val,
7711             const char *ptr,
7712             yyjson_mut_val *new_val,
7713             yyjson_mut_doc *doc) {
7714             if (yyjson_unlikely(!ptr)) return false;
7715             return yyjson_mut_ptr_setn(val, ptr, strlen(ptr), new_val, doc);
7716             }
7717              
7718             yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val,
7719             const char *ptr, size_t len,
7720             yyjson_mut_val *new_val,
7721             yyjson_mut_doc *doc) {
7722             return yyjson_mut_ptr_setx(val, ptr, len, new_val, doc, true, NULL, NULL);
7723             }
7724              
7725             yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val,
7726             const char *ptr, size_t len,
7727             yyjson_mut_val *new_val,
7728             yyjson_mut_doc *doc,
7729             bool create_parent,
7730             yyjson_ptr_ctx *ctx,
7731             yyjson_ptr_err *err) {
7732             yyjson_ptr_set_err(NONE, NULL);
7733             if (ctx) memset(ctx, 0, sizeof(*ctx));
7734              
7735             if (yyjson_unlikely(!val || !ptr || !doc)) {
7736             yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7737             return false;
7738             }
7739             if (yyjson_unlikely(len == 0)) {
7740             yyjson_ptr_set_err(SET_ROOT, "cannot set root");
7741             return false;
7742             }
7743             if (yyjson_unlikely(*ptr != '/')) {
7744             yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7745             return false;
7746             }
7747             if (!new_val) {
7748             return !!unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err);
7749             }
7750             return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, doc,
7751             create_parent, false, ctx, err);
7752             }
7753              
7754             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace(
7755             yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) {
7756             if (!ptr) return NULL;
7757             return yyjson_mut_doc_ptr_replacen(doc, ptr, strlen(ptr), new_val);
7758             }
7759              
7760             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen(
7761             yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) {
7762             return yyjson_mut_doc_ptr_replacex(doc, ptr, len, new_val, NULL, NULL);
7763             }
7764              
7765             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex(
7766             yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val,
7767             yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
7768              
7769             yyjson_ptr_set_err(NONE, NULL);
7770             if (ctx) memset(ctx, 0, sizeof(*ctx));
7771              
7772             if (yyjson_unlikely(!doc || !ptr || !new_val)) {
7773             yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7774             return NULL;
7775             }
7776             if (yyjson_unlikely(len == 0)) {
7777             yyjson_mut_val *root = doc->root;
7778             if (yyjson_unlikely(!root)) {
7779             yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved");
7780             return NULL;
7781             }
7782             if (ctx) ctx->old = root;
7783             doc->root = new_val;
7784             return root;
7785             }
7786             if (yyjson_unlikely(!doc->root)) {
7787             yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
7788             return NULL;
7789             }
7790             if (yyjson_unlikely(*ptr != '/')) {
7791             yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7792             return NULL;
7793             }
7794             return unsafe_yyjson_mut_ptr_replacex(doc->root, ptr, len, new_val,
7795             ctx, err);
7796             }
7797              
7798             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace(
7799             yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val) {
7800             if (!ptr) return NULL;
7801             return yyjson_mut_ptr_replacen(val, ptr, strlen(ptr), new_val);
7802             }
7803              
7804             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen(
7805             yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val) {
7806             return yyjson_mut_ptr_replacex(val, ptr, len, new_val, NULL, NULL);
7807             }
7808              
7809             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex(
7810             yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
7811             yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
7812              
7813             yyjson_ptr_set_err(NONE, NULL);
7814             if (ctx) memset(ctx, 0, sizeof(*ctx));
7815              
7816             if (yyjson_unlikely(!val || !ptr || !new_val)) {
7817             yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7818             return NULL;
7819             }
7820             if (yyjson_unlikely(len == 0)) {
7821             yyjson_ptr_set_err(SET_ROOT, "cannot set root");
7822             return NULL;
7823             }
7824             if (yyjson_unlikely(*ptr != '/')) {
7825             yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7826             return NULL;
7827             }
7828             return unsafe_yyjson_mut_ptr_replacex(val, ptr, len, new_val, ctx, err);
7829             }
7830              
7831             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove(
7832             yyjson_mut_doc *doc, const char *ptr) {
7833             if (!ptr) return NULL;
7834             return yyjson_mut_doc_ptr_removen(doc, ptr, strlen(ptr));
7835             }
7836              
7837             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen(
7838             yyjson_mut_doc *doc, const char *ptr, size_t len) {
7839             return yyjson_mut_doc_ptr_removex(doc, ptr, len, NULL, NULL);
7840             }
7841              
7842             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex(
7843             yyjson_mut_doc *doc, const char *ptr, size_t len,
7844             yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
7845              
7846 4 50         yyjson_ptr_set_err(NONE, NULL);
7847 4 50         if (ctx) memset(ctx, 0, sizeof(*ctx));
7848              
7849 4 50         if (yyjson_unlikely(!doc || !ptr)) {
    50          
7850 0 0         yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7851 0           return NULL;
7852             }
7853 4 50         if (yyjson_unlikely(!doc->root)) {
7854 0 0         yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
7855 0           return NULL;
7856             }
7857 4 50         if (yyjson_unlikely(len == 0)) {
7858 0           yyjson_mut_val *root = doc->root;
7859 0 0         if (ctx) ctx->old = root;
7860 0           doc->root = NULL;
7861 0           return root;
7862             }
7863 4 50         if (yyjson_unlikely(*ptr != '/')) {
7864 0 0         yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7865 0           return NULL;
7866             }
7867 4           return unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err);
7868             }
7869              
7870             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val,
7871             const char *ptr) {
7872             if (!ptr) return NULL;
7873             return yyjson_mut_ptr_removen(val, ptr, strlen(ptr));
7874             }
7875              
7876             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val,
7877             const char *ptr,
7878             size_t len) {
7879             return yyjson_mut_ptr_removex(val, ptr, len, NULL, NULL);
7880             }
7881              
7882             yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val,
7883             const char *ptr,
7884             size_t len,
7885             yyjson_ptr_ctx *ctx,
7886             yyjson_ptr_err *err) {
7887             yyjson_ptr_set_err(NONE, NULL);
7888             if (ctx) memset(ctx, 0, sizeof(*ctx));
7889              
7890             if (yyjson_unlikely(!val || !ptr)) {
7891             yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
7892             return NULL;
7893             }
7894             if (yyjson_unlikely(len == 0)) {
7895             yyjson_ptr_set_err(SET_ROOT, "cannot set root");
7896             return NULL;
7897             }
7898             if (yyjson_unlikely(*ptr != '/')) {
7899             yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
7900             return NULL;
7901             }
7902             return unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err);
7903             }
7904              
7905             yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx,
7906             yyjson_mut_val *key,
7907             yyjson_mut_val *val) {
7908             yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val;
7909             if (!ctx || !ctx->ctn || !val) return false;
7910             ctn = ctx->ctn;
7911              
7912             if (yyjson_mut_is_obj(ctn)) {
7913             if (!key) return false;
7914             key->next = val;
7915             pre_key = ctx->pre;
7916             if (unsafe_yyjson_get_len(ctn) == 0) {
7917             val->next = key;
7918             ctn->uni.ptr = key;
7919             ctx->pre = key;
7920             } else if (!pre_key) {
7921             pre_key = (yyjson_mut_val *)ctn->uni.ptr;
7922             pre_val = pre_key->next;
7923             val->next = pre_val->next;
7924             pre_val->next = key;
7925             ctn->uni.ptr = key;
7926             ctx->pre = pre_key;
7927             } else {
7928             cur_key = pre_key->next->next;
7929             cur_val = cur_key->next;
7930             val->next = cur_val->next;
7931             cur_val->next = key;
7932             if (ctn->uni.ptr == cur_key) ctn->uni.ptr = key;
7933             ctx->pre = cur_key;
7934             }
7935             } else {
7936             pre_val = ctx->pre;
7937             if (unsafe_yyjson_get_len(ctn) == 0) {
7938             val->next = val;
7939             ctn->uni.ptr = val;
7940             ctx->pre = val;
7941             } else if (!pre_val) {
7942             pre_val = (yyjson_mut_val *)ctn->uni.ptr;
7943             val->next = pre_val->next;
7944             pre_val->next = val;
7945             ctn->uni.ptr = val;
7946             ctx->pre = pre_val;
7947             } else {
7948             cur_val = pre_val->next;
7949             val->next = cur_val->next;
7950             cur_val->next = val;
7951             if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val;
7952             ctx->pre = cur_val;
7953             }
7954             }
7955             unsafe_yyjson_inc_len(ctn);
7956             return true;
7957             }
7958              
7959             yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx,
7960             yyjson_mut_val *val) {
7961             yyjson_mut_val *ctn, *pre_key, *cur_key, *pre_val, *cur_val;
7962             if (!ctx || !ctx->ctn || !ctx->pre || !val) return false;
7963             ctn = ctx->ctn;
7964             if (yyjson_mut_is_obj(ctn)) {
7965             pre_key = ctx->pre;
7966             pre_val = pre_key->next;
7967             cur_key = pre_val->next;
7968             cur_val = cur_key->next;
7969             /* replace current value */
7970             cur_key->next = val;
7971             val->next = cur_val->next;
7972             ctx->old = cur_val;
7973             } else {
7974             pre_val = ctx->pre;
7975             cur_val = pre_val->next;
7976             /* replace current value */
7977             if (pre_val != cur_val) {
7978             val->next = cur_val->next;
7979             pre_val->next = val;
7980             if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val;
7981             } else {
7982             val->next = val;
7983             ctn->uni.ptr = val;
7984             ctx->pre = val;
7985             }
7986             ctx->old = cur_val;
7987             }
7988             return true;
7989             }
7990              
7991             yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx) {
7992             yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val;
7993             size_t len;
7994             if (!ctx || !ctx->ctn || !ctx->pre) return false;
7995             ctn = ctx->ctn;
7996             if (yyjson_mut_is_obj(ctn)) {
7997             pre_key = ctx->pre;
7998             pre_val = pre_key->next;
7999             cur_key = pre_val->next;
8000             cur_val = cur_key->next;
8001             /* remove current key-value */
8002             pre_val->next = cur_val->next;
8003             if (ctn->uni.ptr == cur_key) ctn->uni.ptr = pre_key;
8004             ctx->pre = NULL;
8005             ctx->old = cur_val;
8006             } else {
8007             pre_val = ctx->pre;
8008             cur_val = pre_val->next;
8009             /* remove current key-value */
8010             pre_val->next = cur_val->next;
8011             if (ctn->uni.ptr == cur_val) ctn->uni.ptr = pre_val;
8012             ctx->pre = NULL;
8013             ctx->old = cur_val;
8014             }
8015             len = unsafe_yyjson_get_len(ctn) - 1;
8016             if (len == 0) ctn->uni.ptr = NULL;
8017             unsafe_yyjson_set_len(ctn, len);
8018             return true;
8019             }
8020              
8021             #undef yyjson_ptr_set_err
8022              
8023              
8024              
8025             /*==============================================================================
8026             * MARK: - JSON Value at Pointer API (Implementation)
8027             *============================================================================*/
8028              
8029             /**
8030             Set provided `value` if the JSON Pointer (RFC 6901) exists and is type bool.
8031             Returns true if value at `ptr` exists and is the correct type, otherwise false.
8032             */
8033             yyjson_api_inline bool yyjson_ptr_get_bool(
8034             yyjson_val *root, const char *ptr, bool *value) {
8035             yyjson_val *val = yyjson_ptr_get(root, ptr);
8036             if (value && yyjson_is_bool(val)) {
8037             *value = unsafe_yyjson_get_bool(val);
8038             return true;
8039             } else {
8040             return false;
8041             }
8042             }
8043              
8044             /**
8045             Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
8046             that fits in `uint64_t`. Returns true if successful, otherwise false.
8047             */
8048             yyjson_api_inline bool yyjson_ptr_get_uint(
8049             yyjson_val *root, const char *ptr, uint64_t *value) {
8050             yyjson_val *val = yyjson_ptr_get(root, ptr);
8051             if (value && val) {
8052             uint64_t ret = val->uni.u64;
8053             if (unsafe_yyjson_is_uint(val) ||
8054             (unsafe_yyjson_is_sint(val) && !(ret >> 63))) {
8055             *value = ret;
8056             return true;
8057             }
8058             }
8059             return false;
8060             }
8061              
8062             /**
8063             Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
8064             that fits in `int64_t`. Returns true if successful, otherwise false.
8065             */
8066             yyjson_api_inline bool yyjson_ptr_get_sint(
8067             yyjson_val *root, const char *ptr, int64_t *value) {
8068             yyjson_val *val = yyjson_ptr_get(root, ptr);
8069             if (value && val) {
8070             int64_t ret = val->uni.i64;
8071             if (unsafe_yyjson_is_sint(val) ||
8072             (unsafe_yyjson_is_uint(val) && ret >= 0)) {
8073             *value = ret;
8074             return true;
8075             }
8076             }
8077             return false;
8078             }
8079              
8080             /**
8081             Set provided `value` if the JSON Pointer (RFC 6901) exists and is type real.
8082             Returns true if value at `ptr` exists and is the correct type, otherwise false.
8083             */
8084             yyjson_api_inline bool yyjson_ptr_get_real(
8085             yyjson_val *root, const char *ptr, double *value) {
8086             yyjson_val *val = yyjson_ptr_get(root, ptr);
8087             if (value && yyjson_is_real(val)) {
8088             *value = unsafe_yyjson_get_real(val);
8089             return true;
8090             } else {
8091             return false;
8092             }
8093             }
8094              
8095             /**
8096             Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint,
8097             uint or real.
8098             Returns true if value at `ptr` exists and is the correct type, otherwise false.
8099             */
8100             yyjson_api_inline bool yyjson_ptr_get_num(
8101             yyjson_val *root, const char *ptr, double *value) {
8102             yyjson_val *val = yyjson_ptr_get(root, ptr);
8103             if (value && yyjson_is_num(val)) {
8104             *value = unsafe_yyjson_get_num(val);
8105             return true;
8106             } else {
8107             return false;
8108             }
8109             }
8110              
8111             /**
8112             Set provided `value` if the JSON Pointer (RFC 6901) exists and is type string.
8113             Returns true if value at `ptr` exists and is the correct type, otherwise false.
8114             */
8115             yyjson_api_inline bool yyjson_ptr_get_str(
8116             yyjson_val *root, const char *ptr, const char **value) {
8117             yyjson_val *val = yyjson_ptr_get(root, ptr);
8118             if (value && yyjson_is_str(val)) {
8119             *value = unsafe_yyjson_get_str(val);
8120             return true;
8121             } else {
8122             return false;
8123             }
8124             }
8125              
8126              
8127              
8128             /*==============================================================================
8129             * MARK: - Deprecated
8130             *============================================================================*/
8131              
8132             /** @deprecated renamed to `yyjson_doc_ptr_get` */
8133             yyjson_deprecated("renamed to yyjson_doc_ptr_get")
8134             yyjson_api_inline yyjson_val *yyjson_doc_get_pointer(yyjson_doc *doc,
8135             const char *ptr) {
8136             return yyjson_doc_ptr_get(doc, ptr);
8137             }
8138              
8139             /** @deprecated renamed to `yyjson_doc_ptr_getn` */
8140             yyjson_deprecated("renamed to yyjson_doc_ptr_getn")
8141             yyjson_api_inline yyjson_val *yyjson_doc_get_pointern(yyjson_doc *doc,
8142             const char *ptr,
8143             size_t len) {
8144             return yyjson_doc_ptr_getn(doc, ptr, len);
8145             }
8146              
8147             /** @deprecated renamed to `yyjson_mut_doc_ptr_get` */
8148             yyjson_deprecated("renamed to yyjson_mut_doc_ptr_get")
8149             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer(
8150             yyjson_mut_doc *doc, const char *ptr) {
8151             return yyjson_mut_doc_ptr_get(doc, ptr);
8152             }
8153              
8154             /** @deprecated renamed to `yyjson_mut_doc_ptr_getn` */
8155             yyjson_deprecated("renamed to yyjson_mut_doc_ptr_getn")
8156             yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointern(
8157             yyjson_mut_doc *doc, const char *ptr, size_t len) {
8158             return yyjson_mut_doc_ptr_getn(doc, ptr, len);
8159             }
8160              
8161             /** @deprecated renamed to `yyjson_ptr_get` */
8162             yyjson_deprecated("renamed to yyjson_ptr_get")
8163             yyjson_api_inline yyjson_val *yyjson_get_pointer(yyjson_val *val,
8164             const char *ptr) {
8165             return yyjson_ptr_get(val, ptr);
8166             }
8167              
8168             /** @deprecated renamed to `yyjson_ptr_getn` */
8169             yyjson_deprecated("renamed to yyjson_ptr_getn")
8170             yyjson_api_inline yyjson_val *yyjson_get_pointern(yyjson_val *val,
8171             const char *ptr,
8172             size_t len) {
8173             return yyjson_ptr_getn(val, ptr, len);
8174             }
8175              
8176             /** @deprecated renamed to `yyjson_mut_ptr_get` */
8177             yyjson_deprecated("renamed to yyjson_mut_ptr_get")
8178             yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointer(yyjson_mut_val *val,
8179             const char *ptr) {
8180             return yyjson_mut_ptr_get(val, ptr);
8181             }
8182              
8183             /** @deprecated renamed to `yyjson_mut_ptr_getn` */
8184             yyjson_deprecated("renamed to yyjson_mut_ptr_getn")
8185             yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointern(yyjson_mut_val *val,
8186             const char *ptr,
8187             size_t len) {
8188             return yyjson_mut_ptr_getn(val, ptr, len);
8189             }
8190              
8191             /** @deprecated renamed to `yyjson_mut_ptr_getn` */
8192             yyjson_deprecated("renamed to unsafe_yyjson_ptr_getn")
8193             yyjson_api_inline yyjson_val *unsafe_yyjson_get_pointer(yyjson_val *val,
8194             const char *ptr,
8195             size_t len) {
8196             yyjson_ptr_err err;
8197             return unsafe_yyjson_ptr_getx(val, ptr, len, &err);
8198             }
8199              
8200             /** @deprecated renamed to `unsafe_yyjson_mut_ptr_getx` */
8201             yyjson_deprecated("renamed to unsafe_yyjson_mut_ptr_getx")
8202             yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_get_pointer(
8203             yyjson_mut_val *val, const char *ptr, size_t len) {
8204             yyjson_ptr_err err;
8205             return unsafe_yyjson_mut_ptr_getx(val, ptr, len, NULL, &err);
8206             }
8207              
8208             #endif /* YYJSON_DISABLE_UTILS */
8209              
8210              
8211              
8212             /*==============================================================================
8213             * MARK: - Compiler Hint End
8214             *============================================================================*/
8215              
8216             #if defined(__clang__)
8217             # pragma clang diagnostic pop
8218             #elif defined(__GNUC__)
8219             # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
8220             # pragma GCC diagnostic pop
8221             # endif
8222             #elif defined(_MSC_VER)
8223             # pragma warning(pop)
8224             #endif /* warning suppress end */
8225              
8226             #ifdef __cplusplus
8227             }
8228             #endif /* extern "C" end */
8229              
8230             #endif /* YYJSON_H */