File Coverage

include/yyjson.h
Criterion Covered Total %
statement 7 7 100.0
branch 3 6 50.0
condition n/a
subroutine n/a
pod n/a
total 10 13 76.9


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