summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2025-02-13 01:35:02 +0000
committerSadie Powell <sadie@witchery.services>2025-02-13 01:45:13 +0000
commiteaa00c7c9e38f7f5633544a767876f2f6d57185d (patch)
treec5123ad26ef498dc0781366d5f488cf249d458f1
parent2d48d9ef0d1d24e3f976b2c8815f5cda44833a86 (diff)
Vendor yyjson.
-rw-r--r--vendor/README.md10
-rw-r--r--vendor/update.toml7
-rw-r--r--vendor/yyjson/LICENSE21
-rw-r--r--vendor/yyjson/yyjson.c9568
-rw-r--r--vendor/yyjson/yyjson.h7942
5 files changed, 17548 insertions, 0 deletions
diff --git a/vendor/README.md b/vendor/README.md
index 66a335c36..fb4210c35 100644
--- a/vendor/README.md
+++ b/vendor/README.md
@@ -31,3 +31,13 @@ This directory contains vendored dependencies that are shipped with Anope to avo
**Version** &mdash; 2007-02-02
**Website** &mdash; [http://www.ouah.org/ogay/sha2/](http://www.ouah.org/ogay/sha2/)
+
+## yyjson
+
+**Author** &mdash; Yaoyuan Guo
+
+**License** &mdash; MIT License
+
+**Version** &mdash; 0.10.0
+
+**Website** &mdash; [https://github.com/ibireme/yyjson](https://github.com/ibireme/yyjson)
diff --git a/vendor/update.toml b/vendor/update.toml
index 5b8936686..cee9fbd9e 100644
--- a/vendor/update.toml
+++ b/vendor/update.toml
@@ -25,3 +25,10 @@ license = "3-clause BSD License"
tarball = "http://www.ouah.org/ogay/sha2/sha2.tar.gz"
version = "2007-02-02"
website = "http://www.ouah.org/ogay/sha2/"
+
+[yyjson]
+author = "Yaoyuan Guo"
+depth = 1
+git = "https://github.com/ibireme/yyjson"
+files = "{LICENSE,src/yyjson.[ch]}"
+license = "MIT License"
diff --git a/vendor/yyjson/LICENSE b/vendor/yyjson/LICENSE
new file mode 100644
index 000000000..a09bff355
--- /dev/null
+++ b/vendor/yyjson/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 YaoYuan <ibireme@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/yyjson/yyjson.c b/vendor/yyjson/yyjson.c
new file mode 100644
index 000000000..16ecbacf5
--- /dev/null
+++ b/vendor/yyjson/yyjson.c
@@ -0,0 +1,9568 @@
+/*==============================================================================
+ Copyright (c) 2020 YaoYuan <ibireme@gmail.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ *============================================================================*/
+
+#include "yyjson.h"
+#include <math.h>
+
+
+
+/*==============================================================================
+ * Warning Suppress
+ *============================================================================*/
+
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wunused-function"
+# pragma clang diagnostic ignored "-Wunused-parameter"
+# pragma clang diagnostic ignored "-Wunused-label"
+# pragma clang diagnostic ignored "-Wunused-macros"
+# pragma clang diagnostic ignored "-Wunused-variable"
+#elif defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Wunused-function"
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+# pragma GCC diagnostic ignored "-Wunused-label"
+# pragma GCC diagnostic ignored "-Wunused-macros"
+# pragma GCC diagnostic ignored "-Wunused-variable"
+#elif defined(_MSC_VER)
+# pragma warning(disable:4100) /* unreferenced formal parameter */
+# pragma warning(disable:4101) /* unreferenced variable */
+# pragma warning(disable:4102) /* unreferenced label */
+# pragma warning(disable:4127) /* conditional expression is constant */
+# pragma warning(disable:4706) /* assignment within conditional expression */
+#endif
+
+
+
+/*==============================================================================
+ * Version
+ *============================================================================*/
+
+uint32_t yyjson_version(void) {
+ return YYJSON_VERSION_HEX;
+}
+
+
+
+/*==============================================================================
+ * Flags
+ *============================================================================*/
+
+/* msvc intrinsic */
+#if YYJSON_MSC_VER >= 1400
+# include <intrin.h>
+# if defined(_M_AMD64) || defined(_M_ARM64)
+# define MSC_HAS_BIT_SCAN_64 1
+# pragma intrinsic(_BitScanForward64)
+# pragma intrinsic(_BitScanReverse64)
+# else
+# define MSC_HAS_BIT_SCAN_64 0
+# endif
+# if defined(_M_AMD64) || defined(_M_ARM64) || \
+ defined(_M_IX86) || defined(_M_ARM)
+# define MSC_HAS_BIT_SCAN 1
+# pragma intrinsic(_BitScanForward)
+# pragma intrinsic(_BitScanReverse)
+# else
+# define MSC_HAS_BIT_SCAN 0
+# endif
+# if defined(_M_AMD64)
+# define MSC_HAS_UMUL128 1
+# pragma intrinsic(_umul128)
+# else
+# define MSC_HAS_UMUL128 0
+# endif
+#else
+# define MSC_HAS_BIT_SCAN_64 0
+# define MSC_HAS_BIT_SCAN 0
+# define MSC_HAS_UMUL128 0
+#endif
+
+/* gcc builtin */
+#if yyjson_has_builtin(__builtin_clzll) || yyjson_gcc_available(3, 4, 0)
+# define GCC_HAS_CLZLL 1
+#else
+# define GCC_HAS_CLZLL 0
+#endif
+
+#if yyjson_has_builtin(__builtin_ctzll) || yyjson_gcc_available(3, 4, 0)
+# define GCC_HAS_CTZLL 1
+#else
+# define GCC_HAS_CTZLL 0
+#endif
+
+/* int128 type */
+#if defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16) && \
+ (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER))
+# define YYJSON_HAS_INT128 1
+#else
+# define YYJSON_HAS_INT128 0
+#endif
+
+/* IEEE 754 floating-point binary representation */
+#if defined(__STDC_IEC_559__) || defined(__STDC_IEC_60559_BFP__)
+# define YYJSON_HAS_IEEE_754 1
+#elif (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_DIG == 15) && \
+ (DBL_MIN_EXP == -1021) && (DBL_MAX_EXP == 1024) && \
+ (DBL_MIN_10_EXP == -307) && (DBL_MAX_10_EXP == 308)
+# define YYJSON_HAS_IEEE_754 1
+#else
+# define YYJSON_HAS_IEEE_754 0
+#endif
+
+/*
+ Correct rounding in double number computations.
+
+ On the x86 architecture, some compilers may use x87 FPU instructions for
+ floating-point arithmetic. The x87 FPU loads all floating point number as
+ 80-bit double-extended precision internally, then rounds the result to original
+ precision, which may produce inaccurate results. For a more detailed
+ explanation, see the paper: https://arxiv.org/abs/cs/0701192
+
+ Here are some examples of double precision calculation error:
+
+ 2877.0 / 1e6 == 0.002877, but x87 returns 0.0028770000000000002
+ 43683.0 * 1e21 == 4.3683e25, but x87 returns 4.3683000000000004e25
+
+ Here are some examples of compiler flags to generate x87 instructions on x86:
+
+ clang -m32 -mno-sse
+ gcc/icc -m32 -mfpmath=387
+ msvc /arch:SSE or /arch:IA32
+
+ If we are sure that there's no similar error described above, we can define the
+ YYJSON_DOUBLE_MATH_CORRECT as 1 to enable the fast path calculation. This is
+ not an accurate detection, it's just try to avoid the error at compile-time.
+ An accurate detection can be done at run-time:
+
+ bool is_double_math_correct(void) {
+ volatile double r = 43683.0;
+ r *= 1e21;
+ return r == 4.3683e25;
+ }
+
+ See also: utils.h in https://github.com/google/double-conversion/
+ */
+#if !defined(FLT_EVAL_METHOD) && defined(__FLT_EVAL_METHOD__)
+# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#endif
+
+#if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1
+# define YYJSON_DOUBLE_MATH_CORRECT 0
+#elif defined(i386) || defined(__i386) || defined(__i386__) || \
+ defined(_X86_) || defined(__X86__) || defined(_M_IX86) || \
+ defined(__I86__) || defined(__IA32__) || defined(__THW_INTEL)
+# if (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 2) || \
+ (defined(__SSE2_MATH__) && __SSE2_MATH__)
+# define YYJSON_DOUBLE_MATH_CORRECT 1
+# else
+# define YYJSON_DOUBLE_MATH_CORRECT 0
+# endif
+#elif defined(__mc68000__) || defined(__pnacl__) || defined(__native_client__)
+# define YYJSON_DOUBLE_MATH_CORRECT 0
+#else
+# define YYJSON_DOUBLE_MATH_CORRECT 1
+#endif
+
+/* endian */
+#if yyjson_has_include(<sys/types.h>)
+# include <sys/types.h> /* POSIX */
+#endif
+#if yyjson_has_include(<endian.h>)
+# include <endian.h> /* Linux */
+#elif yyjson_has_include(<sys/endian.h>)
+# include <sys/endian.h> /* BSD, Android */
+#elif yyjson_has_include(<machine/endian.h>)
+# include <machine/endian.h> /* BSD, Darwin */
+#endif
+
+#define YYJSON_BIG_ENDIAN 4321
+#define YYJSON_LITTLE_ENDIAN 1234
+
+#if defined(BYTE_ORDER) && BYTE_ORDER
+# if defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN)
+# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN
+# elif defined(LITTLE_ENDIAN) && (BYTE_ORDER == LITTLE_ENDIAN)
+# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN
+# endif
+
+#elif defined(__BYTE_ORDER) && __BYTE_ORDER
+# if defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN)
+# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN
+# elif defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN
+# endif
+
+#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__
+# if defined(__ORDER_BIG_ENDIAN__) && \
+ (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN
+# elif defined(__ORDER_LITTLE_ENDIAN__) && \
+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN
+# endif
+
+#elif (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \
+ defined(__i386) || defined(__i386__) || \
+ defined(_X86_) || defined(__X86__) || \
+ defined(_M_IX86) || defined(__THW_INTEL__) || \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(__amd64) || defined(__amd64__) || \
+ defined(_M_AMD64) || defined(_M_X64) || \
+ defined(_M_ARM) || defined(_M_ARM64) || \
+ defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
+ defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
+ defined(__EMSCRIPTEN__) || defined(__wasm__) || \
+ defined(__loongarch__)
+# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN
+
+#elif (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \
+ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
+ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \
+ defined(__or1k__) || defined(__OR1K__)
+# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN
+
+#else
+# define YYJSON_ENDIAN 0 /* unknown endian, detect at run-time */
+#endif
+
+/*
+ This macro controls how yyjson handles unaligned memory accesses.
+
+ By default, yyjson uses `memcpy()` for memory copying. This takes advantage of
+ the compiler's automatic optimizations to generate unaligned memory access
+ instructions when the target architecture supports it.
+
+ However, for some older compilers or architectures where `memcpy()` isn't
+ optimized well and may generate unnecessary function calls, consider defining
+ this macro as 1. In such cases, yyjson switches to manual byte-by-byte access,
+ potentially improving performance. An example of the generated assembly code on
+ the ARM platform can be found here: https://godbolt.org/z/334jjhxPT
+
+ As this flag has already been enabled for some common architectures in the
+ following code, users typically don't need to manually specify it. If users are
+ unsure about it, please review the generated assembly code or perform actual
+ benchmark to make an informed decision.
+ */
+#ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS
+# if defined(__ia64) || defined(_IA64) || defined(__IA64__) || \
+ defined(__ia64__) || defined(_M_IA64) || defined(__itanium__)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* Itanium */
+# elif (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) && \
+ (defined(__GNUC__) || defined(__clang__)) && \
+ (!defined(__ARM_FEATURE_UNALIGNED) || !__ARM_FEATURE_UNALIGNED)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* ARM */
+# elif defined(__sparc) || defined(__sparc__)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* SPARC */
+# elif defined(__mips) || defined(__mips__) || defined(__MIPS__)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* MIPS */
+# elif defined(__m68k__) || defined(M68000)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* M68K */
+# else
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0
+# endif
+#endif
+
+/*
+ Estimated initial ratio of the JSON data (data_size / value_count).
+ For example:
+
+ data: {"id":12345678,"name":"Harry"}
+ data_size: 30
+ value_count: 5
+ ratio: 6
+
+ yyjson uses dynamic memory with a growth factor of 1.5 when reading and writing
+ JSON, the ratios below are used to determine the initial memory size.
+
+ A too large ratio will waste memory, and a too small ratio will cause multiple
+ memory growths and degrade performance. Currently, these ratios are generated
+ with some commonly used JSON datasets.
+ */
+#define YYJSON_READER_ESTIMATED_PRETTY_RATIO 16
+#define YYJSON_READER_ESTIMATED_MINIFY_RATIO 6
+#define YYJSON_WRITER_ESTIMATED_PRETTY_RATIO 32
+#define YYJSON_WRITER_ESTIMATED_MINIFY_RATIO 18
+
+/* The initial and maximum size of the memory pool's chunk in yyjson_mut_doc. */
+#define YYJSON_MUT_DOC_STR_POOL_INIT_SIZE 0x100
+#define YYJSON_MUT_DOC_STR_POOL_MAX_SIZE 0x10000000
+#define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val))
+#define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val))
+
+/* The minimum size of the dynamic allocator's chunk. */
+#define YYJSON_ALC_DYN_MIN_SIZE 0x1000
+
+/* Default value for compile-time options. */
+#ifndef YYJSON_DISABLE_READER
+#define YYJSON_DISABLE_READER 0
+#endif
+#ifndef YYJSON_DISABLE_WRITER
+#define YYJSON_DISABLE_WRITER 0
+#endif
+#ifndef YYJSON_DISABLE_UTILS
+#define YYJSON_DISABLE_UTILS 0
+#endif
+#ifndef YYJSON_DISABLE_FAST_FP_CONV
+#define YYJSON_DISABLE_FAST_FP_CONV 0
+#endif
+#ifndef YYJSON_DISABLE_NON_STANDARD
+#define YYJSON_DISABLE_NON_STANDARD 0
+#endif
+#ifndef YYJSON_DISABLE_UTF8_VALIDATION
+#define YYJSON_DISABLE_UTF8_VALIDATION 0
+#endif
+
+
+
+/*==============================================================================
+ * Macros
+ *============================================================================*/
+
+/* Macros used for loop unrolling and other purpose. */
+#define repeat2(x) { x x }
+#define repeat3(x) { x x x }
+#define repeat4(x) { x x x x }
+#define repeat8(x) { x x x x x x x x }
+#define repeat16(x) { x x x x x x x x x x x x x x x x }
+
+#define repeat2_incr(x) { x(0) x(1) }
+#define repeat4_incr(x) { x(0) x(1) x(2) x(3) }
+#define repeat8_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) }
+#define repeat16_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \
+ x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) }
+
+#define repeat_in_1_18(x) { x(1) x(2) x(3) x(4) x(5) x(6) x(7) x(8) \
+ x(9) x(10) x(11) x(12) x(13) x(14) x(15) x(16) \
+ x(17) x(18) }
+
+/* Macros used to provide branch prediction information for compiler. */
+#undef likely
+#define likely(x) yyjson_likely(x)
+#undef unlikely
+#define unlikely(x) yyjson_unlikely(x)
+
+/* Macros used to provide inline information for compiler. */
+#undef static_inline
+#define static_inline static yyjson_inline
+#undef static_noinline
+#define static_noinline static yyjson_noinline
+
+/* Macros for min and max. */
+#undef yyjson_min
+#define yyjson_min(x, y) ((x) < (y) ? (x) : (y))
+#undef yyjson_max
+#define yyjson_max(x, y) ((x) > (y) ? (x) : (y))
+
+/* Used to write u64 literal for C89 which doesn't support "ULL" suffix. */
+#undef U64
+#define U64(hi, lo) ((((u64)hi##UL) << 32U) + lo##UL)
+
+/* Used to cast away (remove) const qualifier. */
+#define constcast(type) (type)(void *)(size_t)(const void *)
+
+/* flag test */
+#define has_read_flag(_flag) unlikely(read_flag_eq(flg, YYJSON_READ_##_flag))
+#define has_write_flag(_flag) unlikely(write_flag_eq(flg, YYJSON_WRITE_##_flag))
+
+static_inline bool read_flag_eq(yyjson_read_flag flg, yyjson_read_flag chk) {
+#if YYJSON_DISABLE_NON_STANDARD
+ if (chk == YYJSON_READ_ALLOW_INF_AND_NAN ||
+ chk == YYJSON_READ_ALLOW_COMMENTS ||
+ chk == YYJSON_READ_ALLOW_TRAILING_COMMAS ||
+ chk == YYJSON_READ_ALLOW_INVALID_UNICODE)
+ return false; /* this should be evaluated at compile-time */
+#endif
+ return (flg & chk) != 0;
+}
+
+static_inline bool write_flag_eq(yyjson_write_flag flg, yyjson_write_flag chk) {
+#if YYJSON_DISABLE_NON_STANDARD
+ if (chk == YYJSON_WRITE_ALLOW_INF_AND_NAN ||
+ chk == YYJSON_WRITE_ALLOW_INVALID_UNICODE)
+ return false; /* this should be evaluated at compile-time */
+#endif
+ return (flg & chk) != 0;
+}
+
+
+
+/*==============================================================================
+ * Integer Constants
+ *============================================================================*/
+
+/* U64 constant values */
+#undef U64_MAX
+#define U64_MAX U64(0xFFFFFFFF, 0xFFFFFFFF)
+#undef I64_MAX
+#define I64_MAX U64(0x7FFFFFFF, 0xFFFFFFFF)
+#undef USIZE_MAX
+#define USIZE_MAX ((usize)(~(usize)0))
+
+/* Maximum number of digits for reading u32/u64/usize safety (not overflow). */
+#undef U32_SAFE_DIG
+#define U32_SAFE_DIG 9 /* u32 max is 4294967295, 10 digits */
+#undef U64_SAFE_DIG
+#define U64_SAFE_DIG 19 /* u64 max is 18446744073709551615, 20 digits */
+#undef USIZE_SAFE_DIG
+#define USIZE_SAFE_DIG (sizeof(usize) == 8 ? U64_SAFE_DIG : U32_SAFE_DIG)
+
+
+
+/*==============================================================================
+ * IEEE-754 Double Number Constants
+ *============================================================================*/
+
+/* Inf raw value (positive) */
+#define F64_RAW_INF U64(0x7FF00000, 0x00000000)
+
+/* NaN raw value (quiet NaN, no payload, no sign) */
+#if defined(__hppa__) || (defined(__mips__) && !defined(__mips_nan2008))
+#define F64_RAW_NAN U64(0x7FF7FFFF, 0xFFFFFFFF)
+#else
+#define F64_RAW_NAN U64(0x7FF80000, 0x00000000)
+#endif
+
+/* double number bits */
+#define F64_BITS 64
+
+/* double number exponent part bits */
+#define F64_EXP_BITS 11
+
+/* double number significand part bits */
+#define F64_SIG_BITS 52
+
+/* double number significand part bits (with 1 hidden bit) */
+#define F64_SIG_FULL_BITS 53
+
+/* double number significand bit mask */
+#define F64_SIG_MASK U64(0x000FFFFF, 0xFFFFFFFF)
+
+/* double number exponent bit mask */
+#define F64_EXP_MASK U64(0x7FF00000, 0x00000000)
+
+/* double number exponent bias */
+#define F64_EXP_BIAS 1023
+
+/* double number significant digits count in decimal */
+#define F64_DEC_DIG 17
+
+/* max significant digits count in decimal when reading double number */
+#define F64_MAX_DEC_DIG 768
+
+/* maximum decimal power of double number (1.7976931348623157e308) */
+#define F64_MAX_DEC_EXP 308
+
+/* minimum decimal power of double number (4.9406564584124654e-324) */
+#define F64_MIN_DEC_EXP (-324)
+
+/* maximum binary power of double number */
+#define F64_MAX_BIN_EXP 1024
+
+/* minimum binary power of double number */
+#define F64_MIN_BIN_EXP (-1021)
+
+
+
+/*==============================================================================
+ * Types
+ *============================================================================*/
+
+/** Type define for primitive types. */
+typedef float f32;
+typedef double f64;
+typedef int8_t i8;
+typedef uint8_t u8;
+typedef int16_t i16;
+typedef uint16_t u16;
+typedef int32_t i32;
+typedef uint32_t u32;
+typedef int64_t i64;
+typedef uint64_t u64;
+typedef size_t usize;
+
+/** 128-bit integer, used by floating-point number reader and writer. */
+#if YYJSON_HAS_INT128
+__extension__ typedef __int128 i128;
+__extension__ typedef unsigned __int128 u128;
+#endif
+
+/** 16/32/64-bit vector */
+typedef struct v16 { char c[2]; } v16;
+typedef struct v32 { char c[4]; } v32;
+typedef struct v64 { char c[8]; } v64;
+
+/** 16/32/64-bit vector union */
+typedef union v16_uni { v16 v; u16 u; } v16_uni;
+typedef union v32_uni { v32 v; u32 u; } v32_uni;
+typedef union v64_uni { v64 v; u64 u; } v64_uni;
+
+
+
+/*==============================================================================
+ * Load/Store Utils
+ *============================================================================*/
+
+#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS
+
+#define byte_move_idx(x) ((char *)dst)[x] = ((const char *)src)[x];
+
+static_inline void byte_copy_2(void *dst, const void *src) {
+ repeat2_incr(byte_move_idx)
+}
+
+static_inline void byte_copy_4(void *dst, const void *src) {
+ repeat4_incr(byte_move_idx)
+}
+
+static_inline void byte_copy_8(void *dst, const void *src) {
+ repeat8_incr(byte_move_idx)
+}
+
+static_inline void byte_copy_16(void *dst, const void *src) {
+ repeat16_incr(byte_move_idx)
+}
+
+static_inline void byte_move_2(void *dst, const void *src) {
+ repeat2_incr(byte_move_idx)
+}
+
+static_inline void byte_move_4(void *dst, const void *src) {
+ repeat4_incr(byte_move_idx)
+}
+
+static_inline void byte_move_8(void *dst, const void *src) {
+ repeat8_incr(byte_move_idx)
+}
+
+static_inline void byte_move_16(void *dst, const void *src) {
+ repeat16_incr(byte_move_idx)
+}
+
+static_inline bool byte_match_2(void *buf, const char *pat) {
+ return
+ ((char *)buf)[0] == ((const char *)pat)[0] &&
+ ((char *)buf)[1] == ((const char *)pat)[1];
+}
+
+static_inline bool byte_match_4(void *buf, const char *pat) {
+ return
+ ((char *)buf)[0] == ((const char *)pat)[0] &&
+ ((char *)buf)[1] == ((const char *)pat)[1] &&
+ ((char *)buf)[2] == ((const char *)pat)[2] &&
+ ((char *)buf)[3] == ((const char *)pat)[3];
+}
+
+static_inline u16 byte_load_2(const void *src) {
+ v16_uni uni;
+ uni.v.c[0] = ((const char *)src)[0];
+ uni.v.c[1] = ((const char *)src)[1];
+ return uni.u;
+}
+
+static_inline u32 byte_load_3(const void *src) {
+ v32_uni uni;
+ uni.v.c[0] = ((const char *)src)[0];
+ uni.v.c[1] = ((const char *)src)[1];
+ uni.v.c[2] = ((const char *)src)[2];
+ uni.v.c[3] = 0;
+ return uni.u;
+}
+
+static_inline u32 byte_load_4(const void *src) {
+ v32_uni uni;
+ uni.v.c[0] = ((const char *)src)[0];
+ uni.v.c[1] = ((const char *)src)[1];
+ uni.v.c[2] = ((const char *)src)[2];
+ uni.v.c[3] = ((const char *)src)[3];
+ return uni.u;
+}
+
+#undef byte_move_expr
+
+#else
+
+static_inline void byte_copy_2(void *dst, const void *src) {
+ memcpy(dst, src, 2);
+}
+
+static_inline void byte_copy_4(void *dst, const void *src) {
+ memcpy(dst, src, 4);
+}
+
+static_inline void byte_copy_8(void *dst, const void *src) {
+ memcpy(dst, src, 8);
+}
+
+static_inline void byte_copy_16(void *dst, const void *src) {
+ memcpy(dst, src, 16);
+}
+
+static_inline void byte_move_2(void *dst, const void *src) {
+ u16 tmp;
+ memcpy(&tmp, src, 2);
+ memcpy(dst, &tmp, 2);
+}
+
+static_inline void byte_move_4(void *dst, const void *src) {
+ u32 tmp;
+ memcpy(&tmp, src, 4);
+ memcpy(dst, &tmp, 4);
+}
+
+static_inline void byte_move_8(void *dst, const void *src) {
+ u64 tmp;
+ memcpy(&tmp, src, 8);
+ memcpy(dst, &tmp, 8);
+}
+
+static_inline void byte_move_16(void *dst, const void *src) {
+ char *pdst = (char *)dst;
+ const char *psrc = (const char *)src;
+ u64 tmp1, tmp2;
+ memcpy(&tmp1, psrc, 8);
+ memcpy(&tmp2, psrc + 8, 8);
+ memcpy(pdst, &tmp1, 8);
+ memcpy(pdst + 8, &tmp2, 8);
+}
+
+static_inline bool byte_match_2(void *buf, const char *pat) {
+ v16_uni u1, u2;
+ memcpy(&u1, buf, 2);
+ memcpy(&u2, pat, 2);
+ return u1.u == u2.u;
+}
+
+static_inline bool byte_match_4(void *buf, const char *pat) {
+ v32_uni u1, u2;
+ memcpy(&u1, buf, 4);
+ memcpy(&u2, pat, 4);
+ return u1.u == u2.u;
+}
+
+static_inline u16 byte_load_2(const void *src) {
+ v16_uni uni;
+ memcpy(&uni, src, 2);
+ return uni.u;
+}
+
+static_inline u32 byte_load_3(const void *src) {
+ v32_uni uni;
+ memcpy(&uni, src, 2);
+ uni.v.c[2] = ((const char *)src)[2];
+ uni.v.c[3] = 0;
+ return uni.u;
+}
+
+static_inline u32 byte_load_4(const void *src) {
+ v32_uni uni;
+ memcpy(&uni, src, 4);
+ return uni.u;
+}
+
+#endif
+
+
+
+/*==============================================================================
+ * Number Utils
+ * These functions are used to detect and convert NaN and Inf numbers.
+ *============================================================================*/
+
+/** Convert raw binary to double. */
+static_inline f64 f64_from_raw(u64 u) {
+ /* use memcpy to avoid violating the strict aliasing rule */
+ f64 f;
+ memcpy(&f, &u, 8);
+ return f;
+}
+
+/** Convert double to raw binary. */
+static_inline u64 f64_to_raw(f64 f) {
+ /* use memcpy to avoid violating the strict aliasing rule */
+ u64 u;
+ memcpy(&u, &f, 8);
+ return u;
+}
+
+/** Get raw 'infinity' with sign. */
+static_inline u64 f64_raw_get_inf(bool sign) {
+#if YYJSON_HAS_IEEE_754
+ return F64_RAW_INF | ((u64)sign << 63);
+#elif defined(INFINITY)
+ return f64_to_raw(sign ? -INFINITY : INFINITY);
+#else
+ return f64_to_raw(sign ? -HUGE_VAL : HUGE_VAL);
+#endif
+}
+
+/** Get raw 'nan' with sign. */
+static_inline u64 f64_raw_get_nan(bool sign) {
+#if YYJSON_HAS_IEEE_754
+ return F64_RAW_NAN | ((u64)sign << 63);
+#elif defined(NAN)
+ return f64_to_raw(sign ? (f64)-NAN : (f64)NAN);
+#else
+ return f64_to_raw((sign ? -0.0 : 0.0) / 0.0);
+#endif
+}
+
+/**
+ Convert normalized u64 (highest bit is 1) to f64.
+
+ Some compiler (such as Microsoft Visual C++ 6.0) do not support converting
+ number from u64 to f64. This function will first convert u64 to i64 and then
+ to f64, with `to nearest` rounding mode.
+ */
+static_inline f64 normalized_u64_to_f64(u64 val) {
+#if YYJSON_U64_TO_F64_NO_IMPL
+ i64 sig = (i64)((val >> 1) | (val & 1));
+ return ((f64)sig) * (f64)2.0;
+#else
+ return (f64)val;
+#endif
+}
+
+
+
+/*==============================================================================
+ * Size Utils
+ * These functions are used for memory allocation.
+ *============================================================================*/
+
+/** Returns whether the size is overflow after increment. */
+static_inline bool size_add_is_overflow(usize size, usize add) {
+ return size > (size + add);
+}
+
+/** Returns whether the size is power of 2 (size should not be 0). */
+static_inline bool size_is_pow2(usize size) {
+ return (size & (size - 1)) == 0;
+}
+
+/** Align size upwards (may overflow). */
+static_inline usize size_align_up(usize size, usize align) {
+ if (size_is_pow2(align)) {
+ return (size + (align - 1)) & ~(align - 1);
+ } else {
+ return size + align - (size + align - 1) % align - 1;
+ }
+}
+
+/** Align size downwards. */
+static_inline usize size_align_down(usize size, usize align) {
+ if (size_is_pow2(align)) {
+ return size & ~(align - 1);
+ } else {
+ return size - (size % align);
+ }
+}
+
+/** Align address upwards (may overflow). */
+static_inline void *mem_align_up(void *mem, usize align) {
+ usize size;
+ memcpy(&size, &mem, sizeof(usize));
+ size = size_align_up(size, align);
+ memcpy(&mem, &size, sizeof(usize));
+ return mem;
+}
+
+
+
+/*==============================================================================
+ * Bits Utils
+ * These functions are used by the floating-point number reader and writer.
+ *============================================================================*/
+
+/** Returns the number of leading 0-bits in value (input should not be 0). */
+static_inline u32 u64_lz_bits(u64 v) {
+#if GCC_HAS_CLZLL
+ return (u32)__builtin_clzll(v);
+#elif MSC_HAS_BIT_SCAN_64
+ unsigned long r;
+ _BitScanReverse64(&r, v);
+ return (u32)63 - (u32)r;
+#elif MSC_HAS_BIT_SCAN
+ unsigned long hi, lo;
+ bool hi_set = _BitScanReverse(&hi, (u32)(v >> 32)) != 0;
+ _BitScanReverse(&lo, (u32)v);
+ hi |= 32;
+ return (u32)63 - (u32)(hi_set ? hi : lo);
+#else
+ /*
+ branchless, use de Bruijn sequences
+ see: https://www.chessprogramming.org/BitScan
+ */
+ const u8 table[64] = {
+ 63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2,
+ 9, 5, 28, 11, 13, 21, 42, 19, 25, 31, 34, 40, 46, 52, 59, 1,
+ 17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41, 53, 18,
+ 38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0
+ };
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v |= v >> 32;
+ return table[(v * U64(0x03F79D71, 0xB4CB0A89)) >> 58];
+#endif
+}
+
+/** Returns the number of trailing 0-bits in value (input should not be 0). */
+static_inline u32 u64_tz_bits(u64 v) {
+#if GCC_HAS_CTZLL
+ return (u32)__builtin_ctzll(v);
+#elif MSC_HAS_BIT_SCAN_64
+ unsigned long r;
+ _BitScanForward64(&r, v);
+ return (u32)r;
+#elif MSC_HAS_BIT_SCAN
+ unsigned long lo, hi;
+ bool lo_set = _BitScanForward(&lo, (u32)(v)) != 0;
+ _BitScanForward(&hi, (u32)(v >> 32));
+ hi += 32;
+ return lo_set ? lo : hi;
+#else
+ /*
+ branchless, use de Bruijn sequences
+ see: https://www.chessprogramming.org/BitScan
+ */
+ const u8 table[64] = {
+ 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
+ 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
+ 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
+ 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
+ };
+ return table[((v & (~v + 1)) * U64(0x022FDD63, 0xCC95386D)) >> 58];
+#endif
+}
+
+
+
+/*==============================================================================
+ * 128-bit Integer Utils
+ * These functions are used by the floating-point number reader and writer.
+ *============================================================================*/
+
+/** Multiplies two 64-bit unsigned integers (a * b),
+ returns the 128-bit result as 'hi' and 'lo'. */
+static_inline void u128_mul(u64 a, u64 b, u64 *hi, u64 *lo) {
+#if YYJSON_HAS_INT128
+ u128 m = (u128)a * b;
+ *hi = (u64)(m >> 64);
+ *lo = (u64)(m);
+#elif MSC_HAS_UMUL128
+ *lo = _umul128(a, b, hi);
+#else
+ u32 a0 = (u32)(a), a1 = (u32)(a >> 32);
+ u32 b0 = (u32)(b), b1 = (u32)(b >> 32);
+ u64 p00 = (u64)a0 * b0, p01 = (u64)a0 * b1;
+ u64 p10 = (u64)a1 * b0, p11 = (u64)a1 * b1;
+ u64 m0 = p01 + (p00 >> 32);
+ u32 m00 = (u32)(m0), m01 = (u32)(m0 >> 32);
+ u64 m1 = p10 + m00;
+ u32 m10 = (u32)(m1), m11 = (u32)(m1 >> 32);
+ *hi = p11 + m01 + m11;
+ *lo = ((u64)m10 << 32) | (u32)p00;
+#endif
+}
+
+/** Multiplies two 64-bit unsigned integers and add a value (a * b + c),
+ returns the 128-bit result as 'hi' and 'lo'. */
+static_inline void u128_mul_add(u64 a, u64 b, u64 c, u64 *hi, u64 *lo) {
+#if YYJSON_HAS_INT128
+ u128 m = (u128)a * b + c;
+ *hi = (u64)(m >> 64);
+ *lo = (u64)(m);
+#else
+ u64 h, l, t;
+ u128_mul(a, b, &h, &l);
+ t = l + c;
+ h += (u64)(((t < l) | (t < c)));
+ *hi = h;
+ *lo = t;
+#endif
+}
+
+
+
+/*==============================================================================
+ * File Utils
+ * These functions are used to read and write JSON files.
+ *============================================================================*/
+
+#define YYJSON_FOPEN_EXT
+#if !defined(_MSC_VER) && defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+# if __GLIBC_PREREQ(2, 7)
+# undef YYJSON_FOPEN_EXT
+# define YYJSON_FOPEN_EXT "e" /* glibc extension to enable O_CLOEXEC */
+# endif
+#endif
+
+static_inline FILE *fopen_safe(const char *path, const char *mode) {
+#if YYJSON_MSC_VER >= 1400
+ FILE *file = NULL;
+ if (fopen_s(&file, path, mode) != 0) return NULL;
+ return file;
+#else
+ return fopen(path, mode);
+#endif
+}
+
+static_inline FILE *fopen_readonly(const char *path) {
+ return fopen_safe(path, "rb" YYJSON_FOPEN_EXT);
+}
+
+static_inline FILE *fopen_writeonly(const char *path) {
+ return fopen_safe(path, "wb" YYJSON_FOPEN_EXT);
+}
+
+static_inline usize fread_safe(void *buf, usize size, FILE *file) {
+#if YYJSON_MSC_VER >= 1400
+ return fread_s(buf, size, 1, size, file);
+#else
+ return fread(buf, 1, size, file);
+#endif
+}
+
+
+
+/*==============================================================================
+ * Default Memory Allocator
+ * This is a simple libc memory allocator wrapper.
+ *============================================================================*/
+
+static void *default_malloc(void *ctx, usize size) {
+ return malloc(size);
+}
+
+static void *default_realloc(void *ctx, void *ptr, usize old_size, usize size) {
+ return realloc(ptr, size);
+}
+