| 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
|
|
|
|
|
|
|
#include "yyjson.h" |
|
24
|
|
|
|
|
|
|
#include /* for `HUGE_VAL/INFINIY/NAN` macros, no libm required */ |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
/*============================================================================== |
|
29
|
|
|
|
|
|
|
* MARK: - Warning Suppress (Private) |
|
30
|
|
|
|
|
|
|
*============================================================================*/ |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
#if defined(__clang__) |
|
33
|
|
|
|
|
|
|
# pragma clang diagnostic ignored "-Wunused-function" |
|
34
|
|
|
|
|
|
|
# pragma clang diagnostic ignored "-Wunused-parameter" |
|
35
|
|
|
|
|
|
|
# pragma clang diagnostic ignored "-Wunused-label" |
|
36
|
|
|
|
|
|
|
# pragma clang diagnostic ignored "-Wunused-macros" |
|
37
|
|
|
|
|
|
|
# pragma clang diagnostic ignored "-Wunused-variable" |
|
38
|
|
|
|
|
|
|
#elif defined(__GNUC__) |
|
39
|
|
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wunused-function" |
|
40
|
|
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wunused-parameter" |
|
41
|
|
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wunused-label" |
|
42
|
|
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wunused-macros" |
|
43
|
|
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wunused-variable" |
|
44
|
|
|
|
|
|
|
#elif defined(_MSC_VER) |
|
45
|
|
|
|
|
|
|
# pragma warning(disable:4100) /* unreferenced formal parameter */ |
|
46
|
|
|
|
|
|
|
# pragma warning(disable:4101) /* unreferenced variable */ |
|
47
|
|
|
|
|
|
|
# pragma warning(disable:4102) /* unreferenced label */ |
|
48
|
|
|
|
|
|
|
# pragma warning(disable:4127) /* conditional expression is constant */ |
|
49
|
|
|
|
|
|
|
# pragma warning(disable:4706) /* assignment within conditional expression */ |
|
50
|
|
|
|
|
|
|
#endif |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
/*============================================================================== |
|
55
|
|
|
|
|
|
|
* MARK: - Version (Public) |
|
56
|
|
|
|
|
|
|
*============================================================================*/ |
|
57
|
|
|
|
|
|
|
|
|
58
|
0
|
|
|
|
|
|
uint32_t yyjson_version(void) { |
|
59
|
0
|
|
|
|
|
|
return YYJSON_VERSION_HEX; |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
/*============================================================================== |
|
65
|
|
|
|
|
|
|
* MARK: - Flags (Private) |
|
66
|
|
|
|
|
|
|
*============================================================================*/ |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
/* msvc intrinsic */ |
|
69
|
|
|
|
|
|
|
#if YYJSON_MSC_VER >= 1400 |
|
70
|
|
|
|
|
|
|
# include |
|
71
|
|
|
|
|
|
|
# if defined(_M_AMD64) || defined(_M_ARM64) |
|
72
|
|
|
|
|
|
|
# define MSC_HAS_BIT_SCAN_64 1 |
|
73
|
|
|
|
|
|
|
# pragma intrinsic(_BitScanForward64) |
|
74
|
|
|
|
|
|
|
# pragma intrinsic(_BitScanReverse64) |
|
75
|
|
|
|
|
|
|
# else |
|
76
|
|
|
|
|
|
|
# define MSC_HAS_BIT_SCAN_64 0 |
|
77
|
|
|
|
|
|
|
# endif |
|
78
|
|
|
|
|
|
|
# if defined(_M_AMD64) || defined(_M_ARM64) || \ |
|
79
|
|
|
|
|
|
|
defined(_M_IX86) || defined(_M_ARM) |
|
80
|
|
|
|
|
|
|
# define MSC_HAS_BIT_SCAN 1 |
|
81
|
|
|
|
|
|
|
# pragma intrinsic(_BitScanForward) |
|
82
|
|
|
|
|
|
|
# pragma intrinsic(_BitScanReverse) |
|
83
|
|
|
|
|
|
|
# else |
|
84
|
|
|
|
|
|
|
# define MSC_HAS_BIT_SCAN 0 |
|
85
|
|
|
|
|
|
|
# endif |
|
86
|
|
|
|
|
|
|
# if defined(_M_AMD64) |
|
87
|
|
|
|
|
|
|
# define MSC_HAS_UMUL128 1 |
|
88
|
|
|
|
|
|
|
# pragma intrinsic(_umul128) |
|
89
|
|
|
|
|
|
|
# else |
|
90
|
|
|
|
|
|
|
# define MSC_HAS_UMUL128 0 |
|
91
|
|
|
|
|
|
|
# endif |
|
92
|
|
|
|
|
|
|
#else |
|
93
|
|
|
|
|
|
|
# define MSC_HAS_BIT_SCAN_64 0 |
|
94
|
|
|
|
|
|
|
# define MSC_HAS_BIT_SCAN 0 |
|
95
|
|
|
|
|
|
|
# define MSC_HAS_UMUL128 0 |
|
96
|
|
|
|
|
|
|
#endif |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
/* gcc builtin */ |
|
99
|
|
|
|
|
|
|
#if yyjson_has_builtin(__builtin_clzll) || yyjson_gcc_available(3, 4, 0) |
|
100
|
|
|
|
|
|
|
# define GCC_HAS_CLZLL 1 |
|
101
|
|
|
|
|
|
|
#else |
|
102
|
|
|
|
|
|
|
# define GCC_HAS_CLZLL 0 |
|
103
|
|
|
|
|
|
|
#endif |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
#if yyjson_has_builtin(__builtin_ctzll) || yyjson_gcc_available(3, 4, 0) |
|
106
|
|
|
|
|
|
|
# define GCC_HAS_CTZLL 1 |
|
107
|
|
|
|
|
|
|
#else |
|
108
|
|
|
|
|
|
|
# define GCC_HAS_CTZLL 0 |
|
109
|
|
|
|
|
|
|
#endif |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
/* int128 type */ |
|
112
|
|
|
|
|
|
|
#if defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16) && \ |
|
113
|
|
|
|
|
|
|
(defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)) |
|
114
|
|
|
|
|
|
|
# define YYJSON_HAS_INT128 1 |
|
115
|
|
|
|
|
|
|
#else |
|
116
|
|
|
|
|
|
|
# define YYJSON_HAS_INT128 0 |
|
117
|
|
|
|
|
|
|
#endif |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
/* IEEE 754 floating-point binary representation */ |
|
120
|
|
|
|
|
|
|
#if defined(__STDC_IEC_559__) || defined(__STDC_IEC_60559_BFP__) |
|
121
|
|
|
|
|
|
|
# define YYJSON_HAS_IEEE_754 1 |
|
122
|
|
|
|
|
|
|
#elif FLT_RADIX == 2 && \ |
|
123
|
|
|
|
|
|
|
FLT_MANT_DIG == 24 && FLT_DIG == 6 && \ |
|
124
|
|
|
|
|
|
|
FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128 && \ |
|
125
|
|
|
|
|
|
|
FLT_MIN_10_EXP == -37 && FLT_MAX_10_EXP == 38 && \ |
|
126
|
|
|
|
|
|
|
DBL_MANT_DIG == 53 && DBL_DIG == 15 && \ |
|
127
|
|
|
|
|
|
|
DBL_MIN_EXP == -1021 && DBL_MAX_EXP == 1024 && \ |
|
128
|
|
|
|
|
|
|
DBL_MIN_10_EXP == -307 && DBL_MAX_10_EXP == 308 |
|
129
|
|
|
|
|
|
|
# define YYJSON_HAS_IEEE_754 1 |
|
130
|
|
|
|
|
|
|
#else |
|
131
|
|
|
|
|
|
|
# define YYJSON_HAS_IEEE_754 0 |
|
132
|
|
|
|
|
|
|
# undef YYJSON_DISABLE_FAST_FP_CONV |
|
133
|
|
|
|
|
|
|
# define YYJSON_DISABLE_FAST_FP_CONV 1 |
|
134
|
|
|
|
|
|
|
#endif |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
/* |
|
137
|
|
|
|
|
|
|
Correct rounding in double number computations. |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
On the x86 architecture, some compilers may use x87 FPU instructions for |
|
140
|
|
|
|
|
|
|
floating-point arithmetic. The x87 FPU loads all floating point number as |
|
141
|
|
|
|
|
|
|
80-bit double-extended precision internally, then rounds the result to original |
|
142
|
|
|
|
|
|
|
precision, which may produce inaccurate results. For a more detailed |
|
143
|
|
|
|
|
|
|
explanation, see the paper: https://arxiv.org/abs/cs/0701192 |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
Here are some examples of double precision calculation error: |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
2877.0 / 1e6 == 0.002877, but x87 returns 0.0028770000000000002 |
|
148
|
|
|
|
|
|
|
43683.0 * 1e21 == 4.3683e25, but x87 returns 4.3683000000000004e25 |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
Here are some examples of compiler flags to generate x87 instructions on x86: |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
clang -m32 -mno-sse |
|
153
|
|
|
|
|
|
|
gcc/icc -m32 -mfpmath=387 |
|
154
|
|
|
|
|
|
|
msvc /arch:SSE or /arch:IA32 |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
If we are sure that there's no similar error described above, we can define the |
|
157
|
|
|
|
|
|
|
YYJSON_DOUBLE_MATH_CORRECT as 1 to enable the fast path calculation. This is |
|
158
|
|
|
|
|
|
|
not an accurate detection, it's just try to avoid the error at compile-time. |
|
159
|
|
|
|
|
|
|
An accurate detection can be done at run-time: |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
bool is_double_math_correct(void) { |
|
162
|
|
|
|
|
|
|
volatile double r = 43683.0; |
|
163
|
|
|
|
|
|
|
r *= 1e21; |
|
164
|
|
|
|
|
|
|
return r == 4.3683e25; |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
See also: utils.h in https://github.com/google/double-conversion/ |
|
168
|
|
|
|
|
|
|
*/ |
|
169
|
|
|
|
|
|
|
#if !defined(FLT_EVAL_METHOD) && defined(__FLT_EVAL_METHOD__) |
|
170
|
|
|
|
|
|
|
# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ |
|
171
|
|
|
|
|
|
|
#endif |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
#if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1 |
|
174
|
|
|
|
|
|
|
# define YYJSON_DOUBLE_MATH_CORRECT 0 |
|
175
|
|
|
|
|
|
|
#elif defined(i386) || defined(__i386) || defined(__i386__) || \ |
|
176
|
|
|
|
|
|
|
defined(_X86_) || defined(__X86__) || defined(_M_IX86) || \ |
|
177
|
|
|
|
|
|
|
defined(__I86__) || defined(__IA32__) || defined(__THW_INTEL) |
|
178
|
|
|
|
|
|
|
# if (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 2) || \ |
|
179
|
|
|
|
|
|
|
(defined(__SSE2_MATH__) && __SSE2_MATH__) |
|
180
|
|
|
|
|
|
|
# define YYJSON_DOUBLE_MATH_CORRECT 1 |
|
181
|
|
|
|
|
|
|
# else |
|
182
|
|
|
|
|
|
|
# define YYJSON_DOUBLE_MATH_CORRECT 0 |
|
183
|
|
|
|
|
|
|
# endif |
|
184
|
|
|
|
|
|
|
#elif defined(__mc68000__) || defined(__pnacl__) || defined(__native_client__) |
|
185
|
|
|
|
|
|
|
# define YYJSON_DOUBLE_MATH_CORRECT 0 |
|
186
|
|
|
|
|
|
|
#else |
|
187
|
|
|
|
|
|
|
# define YYJSON_DOUBLE_MATH_CORRECT 1 |
|
188
|
|
|
|
|
|
|
#endif |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
/* |
|
191
|
|
|
|
|
|
|
Detect the endianness at compile-time. |
|
192
|
|
|
|
|
|
|
YYJSON_ENDIAN == YYJSON_BIG_ENDIAN |
|
193
|
|
|
|
|
|
|
YYJSON_ENDIAN == YYJSON_LITTLE_ENDIAN |
|
194
|
|
|
|
|
|
|
*/ |
|
195
|
|
|
|
|
|
|
#define YYJSON_BIG_ENDIAN 4321 |
|
196
|
|
|
|
|
|
|
#define YYJSON_LITTLE_ENDIAN 1234 |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
#if yyjson_has_include() |
|
199
|
|
|
|
|
|
|
# include /* POSIX */ |
|
200
|
|
|
|
|
|
|
#endif |
|
201
|
|
|
|
|
|
|
#if yyjson_has_include() |
|
202
|
|
|
|
|
|
|
# include /* Linux */ |
|
203
|
|
|
|
|
|
|
#elif yyjson_has_include() |
|
204
|
|
|
|
|
|
|
# include /* BSD, Android */ |
|
205
|
|
|
|
|
|
|
#elif yyjson_has_include() |
|
206
|
|
|
|
|
|
|
# include /* BSD, Darwin */ |
|
207
|
|
|
|
|
|
|
#endif |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
#if defined(BYTE_ORDER) && BYTE_ORDER |
|
210
|
|
|
|
|
|
|
# if defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN) |
|
211
|
|
|
|
|
|
|
# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN |
|
212
|
|
|
|
|
|
|
# elif defined(LITTLE_ENDIAN) && (BYTE_ORDER == LITTLE_ENDIAN) |
|
213
|
|
|
|
|
|
|
# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN |
|
214
|
|
|
|
|
|
|
# endif |
|
215
|
|
|
|
|
|
|
#elif defined(__BYTE_ORDER) && __BYTE_ORDER |
|
216
|
|
|
|
|
|
|
# if defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) |
|
217
|
|
|
|
|
|
|
# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN |
|
218
|
|
|
|
|
|
|
# elif defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) |
|
219
|
|
|
|
|
|
|
# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN |
|
220
|
|
|
|
|
|
|
# endif |
|
221
|
|
|
|
|
|
|
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ |
|
222
|
|
|
|
|
|
|
# if defined(__ORDER_BIG_ENDIAN__) && \ |
|
223
|
|
|
|
|
|
|
(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) |
|
224
|
|
|
|
|
|
|
# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN |
|
225
|
|
|
|
|
|
|
# elif defined(__ORDER_LITTLE_ENDIAN__) && \ |
|
226
|
|
|
|
|
|
|
(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) |
|
227
|
|
|
|
|
|
|
# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN |
|
228
|
|
|
|
|
|
|
# endif |
|
229
|
|
|
|
|
|
|
#elif (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \ |
|
230
|
|
|
|
|
|
|
defined(__i386) || defined(__i386__) || \ |
|
231
|
|
|
|
|
|
|
defined(_X86_) || defined(__X86__) || \ |
|
232
|
|
|
|
|
|
|
defined(_M_IX86) || defined(__THW_INTEL__) || \ |
|
233
|
|
|
|
|
|
|
defined(__x86_64) || defined(__x86_64__) || \ |
|
234
|
|
|
|
|
|
|
defined(__amd64) || defined(__amd64__) || \ |
|
235
|
|
|
|
|
|
|
defined(_M_AMD64) || defined(_M_X64) || \ |
|
236
|
|
|
|
|
|
|
defined(_M_ARM) || defined(_M_ARM64) || \ |
|
237
|
|
|
|
|
|
|
defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ |
|
238
|
|
|
|
|
|
|
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \ |
|
239
|
|
|
|
|
|
|
defined(__EMSCRIPTEN__) || defined(__wasm__) || \ |
|
240
|
|
|
|
|
|
|
defined(__loongarch__) |
|
241
|
|
|
|
|
|
|
# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN |
|
242
|
|
|
|
|
|
|
#elif (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \ |
|
243
|
|
|
|
|
|
|
defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ |
|
244
|
|
|
|
|
|
|
defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ |
|
245
|
|
|
|
|
|
|
defined(__or1k__) || defined(__OR1K__) |
|
246
|
|
|
|
|
|
|
# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN |
|
247
|
|
|
|
|
|
|
#else |
|
248
|
|
|
|
|
|
|
# define YYJSON_ENDIAN 0 /* unknown endian, detect at run-time */ |
|
249
|
|
|
|
|
|
|
#endif |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
/* |
|
252
|
|
|
|
|
|
|
This macro controls how yyjson handles unaligned memory accesses. |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
By default, yyjson uses `memcpy()` for memory copying. This allows the compiler |
|
255
|
|
|
|
|
|
|
to optimize the code and emit unaligned memory access instructions when |
|
256
|
|
|
|
|
|
|
supported by the target architecture. |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
However, on some older compilers or architectures where `memcpy()` is not |
|
259
|
|
|
|
|
|
|
well-optimized and may result in unnecessary function calls, defining this |
|
260
|
|
|
|
|
|
|
macro as 1 may help. In such cases, yyjson switches to manual byte-by-byte |
|
261
|
|
|
|
|
|
|
access, which can potentially improve performance. |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
An example of the generated assembly code for ARM can be found here: |
|
264
|
|
|
|
|
|
|
https://godbolt.org/z/334jjhxPT |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
This flag is already enabled for common architectures in the following code, |
|
267
|
|
|
|
|
|
|
so manual configuration is usually unnecessary. If unsure, you can check the |
|
268
|
|
|
|
|
|
|
generated assembly or run benchmarks to make an informed decision. |
|
269
|
|
|
|
|
|
|
*/ |
|
270
|
|
|
|
|
|
|
#ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
271
|
|
|
|
|
|
|
# if defined(__ia64) || defined(_IA64) || defined(__IA64__) || \ |
|
272
|
|
|
|
|
|
|
defined(__ia64__) || defined(_M_IA64) || defined(__itanium__) |
|
273
|
|
|
|
|
|
|
# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* Itanium */ |
|
274
|
|
|
|
|
|
|
# elif (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) && \ |
|
275
|
|
|
|
|
|
|
(defined(__GNUC__) || defined(__clang__)) && \ |
|
276
|
|
|
|
|
|
|
(!defined(__ARM_FEATURE_UNALIGNED) || !__ARM_FEATURE_UNALIGNED) |
|
277
|
|
|
|
|
|
|
# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* ARM */ |
|
278
|
|
|
|
|
|
|
# elif defined(__sparc) || defined(__sparc__) |
|
279
|
|
|
|
|
|
|
# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* SPARC */ |
|
280
|
|
|
|
|
|
|
# elif defined(__mips) || defined(__mips__) || defined(__MIPS__) |
|
281
|
|
|
|
|
|
|
# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* MIPS */ |
|
282
|
|
|
|
|
|
|
# elif defined(__m68k__) || defined(M68000) |
|
283
|
|
|
|
|
|
|
# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* M68K */ |
|
284
|
|
|
|
|
|
|
# else |
|
285
|
|
|
|
|
|
|
# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 |
|
286
|
|
|
|
|
|
|
# endif |
|
287
|
|
|
|
|
|
|
#endif |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
/* |
|
290
|
|
|
|
|
|
|
Estimated initial ratio of the JSON data (data_size / value_count). |
|
291
|
|
|
|
|
|
|
For example: |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
data: {"id":12345678,"name":"Harry"} |
|
294
|
|
|
|
|
|
|
data_size: 30 |
|
295
|
|
|
|
|
|
|
value_count: 5 |
|
296
|
|
|
|
|
|
|
ratio: 6 |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
yyjson uses dynamic memory with a growth factor of 1.5 when reading and writing |
|
299
|
|
|
|
|
|
|
JSON, the ratios below are used to determine the initial memory size. |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
A too large ratio will waste memory, and a too small ratio will cause multiple |
|
302
|
|
|
|
|
|
|
memory growths and degrade performance. Currently, these ratios are generated |
|
303
|
|
|
|
|
|
|
with some commonly used JSON datasets. |
|
304
|
|
|
|
|
|
|
*/ |
|
305
|
|
|
|
|
|
|
#define YYJSON_READER_ESTIMATED_PRETTY_RATIO 16 |
|
306
|
|
|
|
|
|
|
#define YYJSON_READER_ESTIMATED_MINIFY_RATIO 6 |
|
307
|
|
|
|
|
|
|
#define YYJSON_WRITER_ESTIMATED_PRETTY_RATIO 32 |
|
308
|
|
|
|
|
|
|
#define YYJSON_WRITER_ESTIMATED_MINIFY_RATIO 18 |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
/* The initial and maximum size of the memory pool's chunk in yyjson_mut_doc. */ |
|
311
|
|
|
|
|
|
|
#define YYJSON_MUT_DOC_STR_POOL_INIT_SIZE 0x100 |
|
312
|
|
|
|
|
|
|
#define YYJSON_MUT_DOC_STR_POOL_MAX_SIZE 0x10000000 |
|
313
|
|
|
|
|
|
|
#define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val)) |
|
314
|
|
|
|
|
|
|
#define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val)) |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
/* The minimum size of the dynamic allocator's chunk. */ |
|
317
|
|
|
|
|
|
|
#define YYJSON_ALC_DYN_MIN_SIZE 0x1000 |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
/* Default value for compile-time options. */ |
|
320
|
|
|
|
|
|
|
#ifndef YYJSON_DISABLE_READER |
|
321
|
|
|
|
|
|
|
#define YYJSON_DISABLE_READER 0 |
|
322
|
|
|
|
|
|
|
#endif |
|
323
|
|
|
|
|
|
|
#ifndef YYJSON_DISABLE_WRITER |
|
324
|
|
|
|
|
|
|
#define YYJSON_DISABLE_WRITER 0 |
|
325
|
|
|
|
|
|
|
#endif |
|
326
|
|
|
|
|
|
|
#ifndef YYJSON_DISABLE_INCR_READER |
|
327
|
|
|
|
|
|
|
#define YYJSON_DISABLE_INCR_READER 0 |
|
328
|
|
|
|
|
|
|
#endif |
|
329
|
|
|
|
|
|
|
#ifndef YYJSON_DISABLE_UTILS |
|
330
|
|
|
|
|
|
|
#define YYJSON_DISABLE_UTILS 0 |
|
331
|
|
|
|
|
|
|
#endif |
|
332
|
|
|
|
|
|
|
#ifndef YYJSON_DISABLE_FAST_FP_CONV |
|
333
|
|
|
|
|
|
|
#define YYJSON_DISABLE_FAST_FP_CONV 0 |
|
334
|
|
|
|
|
|
|
#endif |
|
335
|
|
|
|
|
|
|
#ifndef YYJSON_DISABLE_NON_STANDARD |
|
336
|
|
|
|
|
|
|
#define YYJSON_DISABLE_NON_STANDARD 0 |
|
337
|
|
|
|
|
|
|
#endif |
|
338
|
|
|
|
|
|
|
#ifndef YYJSON_DISABLE_UTF8_VALIDATION |
|
339
|
|
|
|
|
|
|
#define YYJSON_DISABLE_UTF8_VALIDATION 0 |
|
340
|
|
|
|
|
|
|
#endif |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
/*============================================================================== |
|
345
|
|
|
|
|
|
|
* MARK: - Macros (Private) |
|
346
|
|
|
|
|
|
|
*============================================================================*/ |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
/* Macros used for loop unrolling and other purpose. */ |
|
349
|
|
|
|
|
|
|
#define repeat2(x) { x x } |
|
350
|
|
|
|
|
|
|
#define repeat4(x) { x x x x } |
|
351
|
|
|
|
|
|
|
#define repeat8(x) { x x x x x x x x } |
|
352
|
|
|
|
|
|
|
#define repeat16(x) { x x x x x x x x x x x x x x x x } |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
#define repeat2_incr(x) { x(0) x(1) } |
|
355
|
|
|
|
|
|
|
#define repeat4_incr(x) { x(0) x(1) x(2) x(3) } |
|
356
|
|
|
|
|
|
|
#define repeat8_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) } |
|
357
|
|
|
|
|
|
|
#define repeat16_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ |
|
358
|
|
|
|
|
|
|
x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) } |
|
359
|
|
|
|
|
|
|
#define repeat_in_1_18(x) { x(1) x(2) x(3) x(4) x(5) x(6) x(7) x(8) \ |
|
360
|
|
|
|
|
|
|
x(9) x(10) x(11) x(12) x(13) x(14) x(15) x(16) \ |
|
361
|
|
|
|
|
|
|
x(17) x(18) } |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
/* Macros used to provide branch prediction information for compiler. */ |
|
364
|
|
|
|
|
|
|
#undef likely |
|
365
|
|
|
|
|
|
|
#define likely(x) yyjson_likely(x) |
|
366
|
|
|
|
|
|
|
#undef unlikely |
|
367
|
|
|
|
|
|
|
#define unlikely(x) yyjson_unlikely(x) |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
/* Macros used to provide inline information for compiler. */ |
|
370
|
|
|
|
|
|
|
#undef static_inline |
|
371
|
|
|
|
|
|
|
#define static_inline static yyjson_inline |
|
372
|
|
|
|
|
|
|
#undef static_noinline |
|
373
|
|
|
|
|
|
|
#define static_noinline static yyjson_noinline |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
/* Macros for min and max. */ |
|
376
|
|
|
|
|
|
|
#undef yyjson_min |
|
377
|
|
|
|
|
|
|
#define yyjson_min(x, y) ((x) < (y) ? (x) : (y)) |
|
378
|
|
|
|
|
|
|
#undef yyjson_max |
|
379
|
|
|
|
|
|
|
#define yyjson_max(x, y) ((x) > (y) ? (x) : (y)) |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
/* Used to write u64 literal for C89 which doesn't support "ULL" suffix. */ |
|
382
|
|
|
|
|
|
|
#undef U64 |
|
383
|
|
|
|
|
|
|
#define U64(hi, lo) ((((u64)hi##UL) << 32U) + lo##UL) |
|
384
|
|
|
|
|
|
|
#undef U32 |
|
385
|
|
|
|
|
|
|
#define U32(hi) ((u32)(hi##UL)) |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
/* Used to cast away (remove) const qualifier. */ |
|
388
|
|
|
|
|
|
|
#define constcast(type) (type)(void *)(size_t)(const void *) |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
/* |
|
391
|
|
|
|
|
|
|
Compiler barriers for single variables. |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
These macros inform GCC that a read or write access to the given memory |
|
394
|
|
|
|
|
|
|
location will occur, preventing certain compiler optimizations or reordering |
|
395
|
|
|
|
|
|
|
around the access to 'val'. They do not emit any actual instructions. |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
This is useful when GCC's default optimization strategies are suboptimal and |
|
398
|
|
|
|
|
|
|
precise control over memory access patterns is required. |
|
399
|
|
|
|
|
|
|
These barriers are not needed when using Clang or MSVC. |
|
400
|
|
|
|
|
|
|
*/ |
|
401
|
|
|
|
|
|
|
#if YYJSON_IS_REAL_GCC |
|
402
|
|
|
|
|
|
|
# define gcc_load_barrier(val) __asm__ volatile(""::"m"(val)) |
|
403
|
|
|
|
|
|
|
# define gcc_store_barrier(val) __asm__ volatile("":"=m"(val)) |
|
404
|
|
|
|
|
|
|
# define gcc_full_barrier(val) __asm__ volatile("":"=m"(val):"m"(val)) |
|
405
|
|
|
|
|
|
|
#else |
|
406
|
|
|
|
|
|
|
# define gcc_load_barrier(val) |
|
407
|
|
|
|
|
|
|
# define gcc_store_barrier(val) |
|
408
|
|
|
|
|
|
|
# define gcc_full_barrier(val) |
|
409
|
|
|
|
|
|
|
#endif |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
/*============================================================================== |
|
414
|
|
|
|
|
|
|
* MARK: - Constants (Private) |
|
415
|
|
|
|
|
|
|
*============================================================================*/ |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
/* Common error messages. */ |
|
418
|
|
|
|
|
|
|
#define MSG_FOPEN "failed to open file" |
|
419
|
|
|
|
|
|
|
#define MSG_FREAD "failed to read file" |
|
420
|
|
|
|
|
|
|
#define MSG_FWRITE "failed to write file" |
|
421
|
|
|
|
|
|
|
#define MSG_FCLOSE "failed to close file" |
|
422
|
|
|
|
|
|
|
#define MSG_MALLOC "failed to allocate memory" |
|
423
|
|
|
|
|
|
|
#define MSG_CHAR_T "invalid literal, expected 'true'" |
|
424
|
|
|
|
|
|
|
#define MSG_CHAR_F "invalid literal, expected 'false'" |
|
425
|
|
|
|
|
|
|
#define MSG_CHAR_N "invalid literal, expected 'null'" |
|
426
|
|
|
|
|
|
|
#define MSG_CHAR "unexpected character, expected a JSON value" |
|
427
|
|
|
|
|
|
|
#define MSG_ARR_END "unexpected character, expected ',' or ']'" |
|
428
|
|
|
|
|
|
|
#define MSG_OBJ_KEY "unexpected character, expected a string key" |
|
429
|
|
|
|
|
|
|
#define MSG_OBJ_SEP "unexpected character, expected ':' after key" |
|
430
|
|
|
|
|
|
|
#define MSG_OBJ_END "unexpected character, expected ',' or '}'" |
|
431
|
|
|
|
|
|
|
#define MSG_GARBAGE "unexpected content after document" |
|
432
|
|
|
|
|
|
|
#define MSG_NOT_END "unexpected end of data" |
|
433
|
|
|
|
|
|
|
#define MSG_COMMENT "unclosed multiline comment" |
|
434
|
|
|
|
|
|
|
#define MSG_COMMA "trailing comma is not allowed" |
|
435
|
|
|
|
|
|
|
#define MSG_NAN_INF "nan or inf number is not allowed" |
|
436
|
|
|
|
|
|
|
#define MSG_ERR_TYPE "invalid JSON value type" |
|
437
|
|
|
|
|
|
|
#define MSG_ERR_BOM "UTF-8 byte order mark (BOM) is not supported" |
|
438
|
|
|
|
|
|
|
#define MSG_ERR_UTF8 "invalid utf-8 encoding in string" |
|
439
|
|
|
|
|
|
|
#define MSG_ERR_UTF16 "UTF-16 encoding is not supported" |
|
440
|
|
|
|
|
|
|
#define MSG_ERR_UTF32 "UTF-32 encoding is not supported" |
|
441
|
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
/* U64 constant values */ |
|
443
|
|
|
|
|
|
|
#undef U64_MAX |
|
444
|
|
|
|
|
|
|
#define U64_MAX U64(0xFFFFFFFF, 0xFFFFFFFF) |
|
445
|
|
|
|
|
|
|
#undef I64_MAX |
|
446
|
|
|
|
|
|
|
#define I64_MAX U64(0x7FFFFFFF, 0xFFFFFFFF) |
|
447
|
|
|
|
|
|
|
#undef USIZE_MAX |
|
448
|
|
|
|
|
|
|
#define USIZE_MAX ((usize)(~(usize)0)) |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
/* Maximum number of digits for reading u32/u64/usize safety (not overflow). */ |
|
451
|
|
|
|
|
|
|
#undef U32_SAFE_DIG |
|
452
|
|
|
|
|
|
|
#define U32_SAFE_DIG 9 /* u32 max is 4294967295, 10 digits */ |
|
453
|
|
|
|
|
|
|
#undef U64_SAFE_DIG |
|
454
|
|
|
|
|
|
|
#define U64_SAFE_DIG 19 /* u64 max is 18446744073709551615, 20 digits */ |
|
455
|
|
|
|
|
|
|
#undef USIZE_SAFE_DIG |
|
456
|
|
|
|
|
|
|
#define USIZE_SAFE_DIG (sizeof(usize) == 8 ? U64_SAFE_DIG : U32_SAFE_DIG) |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
/* Inf bits (positive) */ |
|
459
|
|
|
|
|
|
|
#define F64_BITS_INF U64(0x7FF00000, 0x00000000) |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
/* NaN bits (quiet NaN, no payload, no sign) */ |
|
462
|
|
|
|
|
|
|
#if defined(__hppa__) || (defined(__mips__) && !defined(__mips_nan2008)) |
|
463
|
|
|
|
|
|
|
#define F64_BITS_NAN U64(0x7FF7FFFF, 0xFFFFFFFF) |
|
464
|
|
|
|
|
|
|
#else |
|
465
|
|
|
|
|
|
|
#define F64_BITS_NAN U64(0x7FF80000, 0x00000000) |
|
466
|
|
|
|
|
|
|
#endif |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
/* maximum significant digits count in decimal when reading double number */ |
|
469
|
|
|
|
|
|
|
#define F64_MAX_DEC_DIG 768 |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
/* maximum decimal power of double number (1.7976931348623157e308) */ |
|
472
|
|
|
|
|
|
|
#define F64_MAX_DEC_EXP 308 |
|
473
|
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
/* minimum decimal power of double number (4.9406564584124654e-324) */ |
|
475
|
|
|
|
|
|
|
#define F64_MIN_DEC_EXP (-324) |
|
476
|
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
/* maximum binary power of double number */ |
|
478
|
|
|
|
|
|
|
#define F64_MAX_BIN_EXP 1024 |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
/* minimum binary power of double number */ |
|
481
|
|
|
|
|
|
|
#define F64_MIN_BIN_EXP (-1021) |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
/* float/double number bits */ |
|
484
|
|
|
|
|
|
|
#define F32_BITS 32 |
|
485
|
|
|
|
|
|
|
#define F64_BITS 64 |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
/* float/double number exponent part bits */ |
|
488
|
|
|
|
|
|
|
#define F32_EXP_BITS 8 |
|
489
|
|
|
|
|
|
|
#define F64_EXP_BITS 11 |
|
490
|
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
/* float/double number significand part bits */ |
|
492
|
|
|
|
|
|
|
#define F32_SIG_BITS 23 |
|
493
|
|
|
|
|
|
|
#define F64_SIG_BITS 52 |
|
494
|
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
/* float/double number significand part bits (with 1 hidden bit) */ |
|
496
|
|
|
|
|
|
|
#define F32_SIG_FULL_BITS 24 |
|
497
|
|
|
|
|
|
|
#define F64_SIG_FULL_BITS 53 |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
/* float/double number significand bit mask */ |
|
500
|
|
|
|
|
|
|
#define F32_SIG_MASK U32(0x007FFFFF) |
|
501
|
|
|
|
|
|
|
#define F64_SIG_MASK U64(0x000FFFFF, 0xFFFFFFFF) |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
/* float/double number exponent bit mask */ |
|
504
|
|
|
|
|
|
|
#define F32_EXP_MASK U32(0x7F800000) |
|
505
|
|
|
|
|
|
|
#define F64_EXP_MASK U64(0x7FF00000, 0x00000000) |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
/* float/double number exponent bias */ |
|
508
|
|
|
|
|
|
|
#define F32_EXP_BIAS 127 |
|
509
|
|
|
|
|
|
|
#define F64_EXP_BIAS 1023 |
|
510
|
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
/* float/double number significant digits count in decimal */ |
|
512
|
|
|
|
|
|
|
#define F32_DEC_DIG 9 |
|
513
|
|
|
|
|
|
|
#define F64_DEC_DIG 17 |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
/* buffer length required for float/double number writer */ |
|
516
|
|
|
|
|
|
|
#define FP_BUF_LEN 40 |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
/* maximum length of a number in incremental parsing */ |
|
519
|
|
|
|
|
|
|
#define INCR_NUM_MAX_LEN 1024 |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
/*============================================================================== |
|
524
|
|
|
|
|
|
|
* MARK: - Types (Private) |
|
525
|
|
|
|
|
|
|
*============================================================================*/ |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
/** Type define for primitive types. */ |
|
528
|
|
|
|
|
|
|
typedef float f32; |
|
529
|
|
|
|
|
|
|
typedef double f64; |
|
530
|
|
|
|
|
|
|
typedef int8_t i8; |
|
531
|
|
|
|
|
|
|
typedef uint8_t u8; |
|
532
|
|
|
|
|
|
|
typedef int16_t i16; |
|
533
|
|
|
|
|
|
|
typedef uint16_t u16; |
|
534
|
|
|
|
|
|
|
typedef int32_t i32; |
|
535
|
|
|
|
|
|
|
typedef uint32_t u32; |
|
536
|
|
|
|
|
|
|
typedef int64_t i64; |
|
537
|
|
|
|
|
|
|
typedef uint64_t u64; |
|
538
|
|
|
|
|
|
|
typedef size_t usize; |
|
539
|
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
/** 128-bit integer, used by floating-point number reader and writer. */ |
|
541
|
|
|
|
|
|
|
#if YYJSON_HAS_INT128 |
|
542
|
|
|
|
|
|
|
__extension__ typedef __int128 i128; |
|
543
|
|
|
|
|
|
|
__extension__ typedef unsigned __int128 u128; |
|
544
|
|
|
|
|
|
|
#endif |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
/** 16/32/64-bit vector */ |
|
547
|
|
|
|
|
|
|
typedef struct v16 { char c[2]; } v16; |
|
548
|
|
|
|
|
|
|
typedef struct v32 { char c[4]; } v32; |
|
549
|
|
|
|
|
|
|
typedef struct v64 { char c[8]; } v64; |
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
/** 16/32/64-bit vector union */ |
|
552
|
|
|
|
|
|
|
typedef union v16_uni { v16 v; u16 u; } v16_uni; |
|
553
|
|
|
|
|
|
|
typedef union v32_uni { v32 v; u32 u; } v32_uni; |
|
554
|
|
|
|
|
|
|
typedef union v64_uni { v64 v; u64 u; } v64_uni; |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
/*============================================================================== |
|
559
|
|
|
|
|
|
|
* MARK: - Load/Store Utils (Private) |
|
560
|
|
|
|
|
|
|
*============================================================================*/ |
|
561
|
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
#define byte_move_idx(x) ((char *)dst)[x] = ((const char *)src)[x]; |
|
563
|
|
|
|
|
|
|
#define byte_move_src(x) ((char *)tmp)[x] = ((const char *)src)[x]; |
|
564
|
|
|
|
|
|
|
#define byte_move_dst(x) ((char *)dst)[x] = ((const char *)tmp)[x]; |
|
565
|
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
/** Same as `memcpy(dst, src, 2)`, no overlap. */ |
|
567
|
|
|
|
|
|
|
static_inline void byte_copy_2(void *dst, const void *src) { |
|
568
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
569
|
35057
|
|
|
|
|
|
memcpy(dst, src, 2); |
|
570
|
|
|
|
|
|
|
#else |
|
571
|
|
|
|
|
|
|
repeat2_incr(byte_move_idx) |
|
572
|
|
|
|
|
|
|
#endif |
|
573
|
0
|
|
|
|
|
|
} |
|
574
|
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
/** Same as `memcpy(dst, src, 4)`, no overlap. */ |
|
576
|
|
|
|
|
|
|
static_inline void byte_copy_4(void *dst, const void *src) { |
|
577
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
578
|
24
|
|
|
|
|
|
memcpy(dst, src, 4); |
|
579
|
|
|
|
|
|
|
#else |
|
580
|
|
|
|
|
|
|
repeat4_incr(byte_move_idx) |
|
581
|
|
|
|
|
|
|
#endif |
|
582
|
24
|
|
|
|
|
|
} |
|
583
|
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
/** Same as `memcpy(dst, src, 8)`, no overlap. */ |
|
585
|
|
|
|
|
|
|
static_inline void byte_copy_8(void *dst, const void *src) { |
|
586
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
587
|
9
|
|
|
|
|
|
memcpy(dst, src, 8); |
|
588
|
|
|
|
|
|
|
#else |
|
589
|
|
|
|
|
|
|
repeat8_incr(byte_move_idx) |
|
590
|
|
|
|
|
|
|
#endif |
|
591
|
6
|
|
|
|
|
|
} |
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
/** Same as `memcpy(dst, src, 16)`, no overlap. */ |
|
594
|
|
|
|
|
|
|
static_inline void byte_copy_16(void *dst, const void *src) { |
|
595
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
596
|
0
|
|
|
|
|
|
memcpy(dst, src, 16); |
|
597
|
|
|
|
|
|
|
#else |
|
598
|
|
|
|
|
|
|
repeat16_incr(byte_move_idx) |
|
599
|
|
|
|
|
|
|
#endif |
|
600
|
0
|
|
|
|
|
|
} |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
/** Same as `memmove(dst, src, 2)`, allows overlap. */ |
|
603
|
|
|
|
|
|
|
static_inline void byte_move_2(void *dst, const void *src) { |
|
604
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
605
|
|
|
|
|
|
|
u16 tmp; |
|
606
|
3
|
|
|
|
|
|
memcpy(&tmp, src, 2); |
|
607
|
3
|
|
|
|
|
|
memcpy(dst, &tmp, 2); |
|
608
|
|
|
|
|
|
|
#else |
|
609
|
|
|
|
|
|
|
char tmp[2]; |
|
610
|
|
|
|
|
|
|
repeat2_incr(byte_move_src) |
|
611
|
|
|
|
|
|
|
repeat2_incr(byte_move_dst) |
|
612
|
|
|
|
|
|
|
#endif |
|
613
|
3
|
|
|
|
|
|
} |
|
614
|
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
/** Same as `memmove(dst, src, 4)`, allows overlap. */ |
|
616
|
|
|
|
|
|
|
static_inline void byte_move_4(void *dst, const void *src) { |
|
617
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
618
|
|
|
|
|
|
|
u32 tmp; |
|
619
|
1
|
|
|
|
|
|
memcpy(&tmp, src, 4); |
|
620
|
1
|
|
|
|
|
|
memcpy(dst, &tmp, 4); |
|
621
|
|
|
|
|
|
|
#else |
|
622
|
|
|
|
|
|
|
char tmp[4]; |
|
623
|
|
|
|
|
|
|
repeat4_incr(byte_move_src) |
|
624
|
|
|
|
|
|
|
repeat4_incr(byte_move_dst) |
|
625
|
|
|
|
|
|
|
#endif |
|
626
|
1
|
|
|
|
|
|
} |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
/** Same as `memmove(dst, src, 8)`, allows overlap. */ |
|
629
|
|
|
|
|
|
|
static_inline void byte_move_8(void *dst, const void *src) { |
|
630
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
631
|
|
|
|
|
|
|
u64 tmp; |
|
632
|
0
|
|
|
|
|
|
memcpy(&tmp, src, 8); |
|
633
|
0
|
|
|
|
|
|
memcpy(dst, &tmp, 8); |
|
634
|
|
|
|
|
|
|
#else |
|
635
|
|
|
|
|
|
|
char tmp[8]; |
|
636
|
|
|
|
|
|
|
repeat8_incr(byte_move_src) |
|
637
|
|
|
|
|
|
|
repeat8_incr(byte_move_dst) |
|
638
|
|
|
|
|
|
|
#endif |
|
639
|
0
|
|
|
|
|
|
} |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
/** Same as `memmove(dst, src, 16)`, allows overlap. */ |
|
642
|
|
|
|
|
|
|
static_inline void byte_move_16(void *dst, const void *src) { |
|
643
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
644
|
1
|
|
|
|
|
|
char *pdst = (char *)dst; |
|
645
|
1
|
|
|
|
|
|
const char *psrc = (const char *)src; |
|
646
|
|
|
|
|
|
|
u64 tmp1, tmp2; |
|
647
|
1
|
|
|
|
|
|
memcpy(&tmp1, psrc, 8); |
|
648
|
1
|
|
|
|
|
|
memcpy(&tmp2, psrc + 8, 8); |
|
649
|
1
|
|
|
|
|
|
memcpy(pdst, &tmp1, 8); |
|
650
|
1
|
|
|
|
|
|
memcpy(pdst + 8, &tmp2, 8); |
|
651
|
|
|
|
|
|
|
#else |
|
652
|
|
|
|
|
|
|
char tmp[16]; |
|
653
|
|
|
|
|
|
|
repeat16_incr(byte_move_src) |
|
654
|
|
|
|
|
|
|
repeat16_incr(byte_move_dst) |
|
655
|
|
|
|
|
|
|
#endif |
|
656
|
0
|
|
|
|
|
|
} |
|
657
|
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
/** Same as `memmove(dst, src, n)`, but only `dst <= src` and `n <= 16`. */ |
|
659
|
|
|
|
|
|
|
static_inline void byte_move_forward(void *dst, void *src, usize n) { |
|
660
|
9
|
|
|
|
|
|
char *d = (char *)dst, *s = (char *)src; |
|
661
|
9
|
|
|
|
|
|
n += (n % 2); /* round up to even */ |
|
662
|
0
|
|
|
|
|
|
if (n == 16) { byte_move_16(d, s); return; } |
|
663
|
9
|
0
|
|
|
|
|
if (n >= 8) { byte_move_8(d, s); n -= 8; d += 8; s += 8; } |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
664
|
10
|
0
|
|
|
|
|
if (n >= 4) { byte_move_4(d, s); n -= 4; d += 4; s += 4; } |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
665
|
9
|
0
|
|
|
|
|
if (n >= 2) { byte_move_2(d, s); } |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
} |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
/** Same as `memcmp(buf, pat, 2) == 0`. */ |
|
669
|
|
|
|
|
|
|
static_inline bool byte_match_2(void *buf, const char *pat) { |
|
670
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
671
|
|
|
|
|
|
|
v16_uni u1, u2; |
|
672
|
73
|
|
|
|
|
|
memcpy(&u1, buf, 2); |
|
673
|
73
|
|
|
|
|
|
memcpy(&u2, pat, 2); |
|
674
|
1
|
|
|
|
|
|
return u1.u == u2.u; |
|
675
|
|
|
|
|
|
|
#else |
|
676
|
|
|
|
|
|
|
return ((char *)buf)[0] == ((const char *)pat)[0] && |
|
677
|
|
|
|
|
|
|
((char *)buf)[1] == ((const char *)pat)[1]; |
|
678
|
|
|
|
|
|
|
#endif |
|
679
|
|
|
|
|
|
|
} |
|
680
|
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
/** Same as `memcmp(buf, pat, 4) == 0`. */ |
|
682
|
|
|
|
|
|
|
static_inline bool byte_match_4(void *buf, const char *pat) { |
|
683
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
684
|
|
|
|
|
|
|
v32_uni u1, u2; |
|
685
|
28
|
|
|
|
|
|
memcpy(&u1, buf, 4); |
|
686
|
28
|
|
|
|
|
|
memcpy(&u2, pat, 4); |
|
687
|
28
|
|
|
|
|
|
return u1.u == u2.u; |
|
688
|
|
|
|
|
|
|
#else |
|
689
|
|
|
|
|
|
|
return ((char *)buf)[0] == ((const char *)pat)[0] && |
|
690
|
|
|
|
|
|
|
((char *)buf)[1] == ((const char *)pat)[1] && |
|
691
|
|
|
|
|
|
|
((char *)buf)[2] == ((const char *)pat)[2] && |
|
692
|
|
|
|
|
|
|
((char *)buf)[3] == ((const char *)pat)[3]; |
|
693
|
|
|
|
|
|
|
#endif |
|
694
|
|
|
|
|
|
|
} |
|
695
|
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
/** Loads 2 bytes from `src` as a u16 (native-endian). */ |
|
697
|
|
|
|
|
|
|
static_inline u16 byte_load_2(const void *src) { |
|
698
|
|
|
|
|
|
|
v16_uni uni; |
|
699
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
700
|
12
|
|
|
|
|
|
memcpy(&uni, src, 2); |
|
701
|
|
|
|
|
|
|
#else |
|
702
|
|
|
|
|
|
|
uni.v.c[0] = ((const char *)src)[0]; |
|
703
|
|
|
|
|
|
|
uni.v.c[1] = ((const char *)src)[1]; |
|
704
|
|
|
|
|
|
|
#endif |
|
705
|
6
|
|
|
|
|
|
return uni.u; |
|
706
|
|
|
|
|
|
|
} |
|
707
|
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
/** Loads 3 bytes from `src` as a u32 (native-endian). */ |
|
709
|
|
|
|
|
|
|
static_inline u32 byte_load_3(const void *src) { |
|
710
|
|
|
|
|
|
|
v32_uni uni; |
|
711
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
712
|
8
|
|
|
|
|
|
memcpy(&uni, src, 2); |
|
713
|
8
|
|
|
|
|
|
uni.v.c[2] = ((const char *)src)[2]; |
|
714
|
8
|
|
|
|
|
|
uni.v.c[3] = 0; |
|
715
|
|
|
|
|
|
|
#else |
|
716
|
|
|
|
|
|
|
uni.v.c[0] = ((const char *)src)[0]; |
|
717
|
|
|
|
|
|
|
uni.v.c[1] = ((const char *)src)[1]; |
|
718
|
|
|
|
|
|
|
uni.v.c[2] = ((const char *)src)[2]; |
|
719
|
|
|
|
|
|
|
uni.v.c[3] = 0; |
|
720
|
|
|
|
|
|
|
#endif |
|
721
|
4
|
|
|
|
|
|
return uni.u; |
|
722
|
|
|
|
|
|
|
} |
|
723
|
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
/** Loads 4 bytes from `src` as a u32 (native-endian). */ |
|
725
|
|
|
|
|
|
|
static_inline u32 byte_load_4(const void *src) { |
|
726
|
|
|
|
|
|
|
v32_uni uni; |
|
727
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS |
|
728
|
18
|
|
|
|
|
|
memcpy(&uni, src, 4); |
|
729
|
|
|
|
|
|
|
#else |
|
730
|
|
|
|
|
|
|
uni.v.c[0] = ((const char *)src)[0]; |
|
731
|
|
|
|
|
|
|
uni.v.c[1] = ((const char *)src)[1]; |
|
732
|
|
|
|
|
|
|
uni.v.c[2] = ((const char *)src)[2]; |
|
733
|
|
|
|
|
|
|
uni.v.c[3] = ((const char *)src)[3]; |
|
734
|
|
|
|
|
|
|
#endif |
|
735
|
6
|
|
|
|
|
|
return uni.u; |
|
736
|
|
|
|
|
|
|
} |
|
737
|
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
/*============================================================================== |
|
741
|
|
|
|
|
|
|
* MARK: - Character Utils (Private) |
|
742
|
|
|
|
|
|
|
* These lookup tables were generated by `misc/make_tables.c`. |
|
743
|
|
|
|
|
|
|
*============================================================================*/ |
|
744
|
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
/* char_table1 */ |
|
746
|
|
|
|
|
|
|
#define CHAR_TYPE_ASCII (1 << 0) /* Except: ["\], [0x00-0x1F, 0x80-0xFF] */ |
|
747
|
|
|
|
|
|
|
#define CHAR_TYPE_ASCII_SQ (1 << 1) /* Except: ['\], [0x00-0x1F, 0x80-0xFF] */ |
|
748
|
|
|
|
|
|
|
#define CHAR_TYPE_SPACE (1 << 2) /* Whitespace: [ \t\n\r] */ |
|
749
|
|
|
|
|
|
|
#define CHAR_TYPE_SPACE_EXT (1 << 3) /* Whitespace: [ \t\n\r\v\f], JSON5 */ |
|
750
|
|
|
|
|
|
|
#define CHAR_TYPE_NUM (1 << 4) /* Number: [.-+0-9] */ |
|
751
|
|
|
|
|
|
|
#define CHAR_TYPE_COMMENT (1 << 5) /* Comment: [/] */ |
|
752
|
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
/* char_table2 */ |
|
754
|
|
|
|
|
|
|
#define CHAR_TYPE_EOL (1 << 0) /* End of line: [\r\n] */ |
|
755
|
|
|
|
|
|
|
#define CHAR_TYPE_EOL_EXT (1 << 1) /* End of line: [\r\n], JSON5 */ |
|
756
|
|
|
|
|
|
|
#define CHAR_TYPE_ID_START (1 << 2) /* ID start: [_$A-Za-z\], U+0080+ */ |
|
757
|
|
|
|
|
|
|
#define CHAR_TYPE_ID_NEXT (1 << 3) /* ID next: [_$A-Za-z0-9\], U+0080+ */ |
|
758
|
|
|
|
|
|
|
#define CHAR_TYPE_ID_ASCII (1 << 4) /* ID next ASCII: [_$A-Za-z0-9] */ |
|
759
|
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
/* char_table3 */ |
|
761
|
|
|
|
|
|
|
#define CHAR_TYPE_SIGN (1 << 0) /* [-+] */ |
|
762
|
|
|
|
|
|
|
#define CHAR_TYPE_DIGIT (1 << 1) /* [0-9] */ |
|
763
|
|
|
|
|
|
|
#define CHAR_TYPE_NONZERO (1 << 2) /* [1-9] */ |
|
764
|
|
|
|
|
|
|
#define CHAR_TYPE_EXP (1 << 3) /* [eE] */ |
|
765
|
|
|
|
|
|
|
#define CHAR_TYPE_DOT (1 << 4) /* [.] */ |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
static const u8 char_table1[256] = { |
|
768
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
769
|
|
|
|
|
|
|
0x00, 0x0C, 0x0C, 0x08, 0x08, 0x0C, 0x00, 0x00, |
|
770
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
771
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
772
|
|
|
|
|
|
|
0x0F, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x01, |
|
773
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x13, 0x03, 0x13, 0x13, 0x23, |
|
774
|
|
|
|
|
|
|
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, |
|
775
|
|
|
|
|
|
|
0x13, 0x13, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
|
776
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
|
777
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
|
778
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
|
779
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, |
|
780
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
|
781
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
|
782
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
|
783
|
|
|
|
|
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
|
784
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
785
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
786
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
787
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
788
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
789
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
790
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
791
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
792
|
|
|
|
|
|
|
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
793
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
794
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
795
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
796
|
|
|
|
|
|
|
0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, |
|
797
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, |
|
798
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
799
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
|
800
|
|
|
|
|
|
|
}; |
|
801
|
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
static const u8 char_table2[256] = { |
|
803
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
804
|
|
|
|
|
|
|
0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, |
|
805
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
806
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
807
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, |
|
808
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
809
|
|
|
|
|
|
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, |
|
810
|
|
|
|
|
|
|
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
811
|
|
|
|
|
|
|
0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, |
|
812
|
|
|
|
|
|
|
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, |
|
813
|
|
|
|
|
|
|
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, |
|
814
|
|
|
|
|
|
|
0x1C, 0x1C, 0x1C, 0x00, 0x0C, 0x00, 0x00, 0x1C, |
|
815
|
|
|
|
|
|
|
0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, |
|
816
|
|
|
|
|
|
|
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, |
|
817
|
|
|
|
|
|
|
0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, |
|
818
|
|
|
|
|
|
|
0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
819
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
820
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
821
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
822
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
823
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
824
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
825
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
826
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
827
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
828
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
829
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
830
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
831
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
832
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
833
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, |
|
834
|
|
|
|
|
|
|
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C |
|
835
|
|
|
|
|
|
|
}; |
|
836
|
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
static const u8 char_table3[256] = { |
|
838
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
839
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
840
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
841
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
842
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
843
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, |
|
844
|
|
|
|
|
|
|
0x02, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
|
845
|
|
|
|
|
|
|
0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
846
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, |
|
847
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
848
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
849
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
850
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, |
|
851
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
852
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
853
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
854
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
855
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
856
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
857
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
858
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
859
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
860
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
861
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
862
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
863
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
864
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
865
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
866
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
867
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
868
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
869
|
|
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
|
870
|
|
|
|
|
|
|
}; |
|
871
|
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
/** Match a whitespace: [ \t\n\r]. */ |
|
873
|
|
|
|
|
|
|
static_inline bool char_is_space(u8 c) { |
|
874
|
10134
|
|
|
|
|
|
return !!(char_table1[c] & CHAR_TYPE_SPACE); |
|
875
|
|
|
|
|
|
|
} |
|
876
|
|
|
|
|
|
|
|
|
877
|
|
|
|
|
|
|
/** Match an extended whitespace: [ \t\n\r\\v\\f], JSON5 whitespace. */ |
|
878
|
|
|
|
|
|
|
static_inline bool char_is_space_ext(u8 c) { |
|
879
|
0
|
|
|
|
|
|
return !!(char_table1[c] & CHAR_TYPE_SPACE_EXT); |
|
880
|
|
|
|
|
|
|
} |
|
881
|
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
/** Match a JSON number: [.-+0-9]. */ |
|
883
|
|
|
|
|
|
|
static_inline bool char_is_num(u8 c) { |
|
884
|
34235
|
|
|
|
|
|
return !!(char_table1[c] & CHAR_TYPE_NUM); |
|
885
|
|
|
|
|
|
|
} |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
/** Match an ASCII character in string: ["\], [0x00-0x1F, 0x80-0xFF]. */ |
|
888
|
|
|
|
|
|
|
static_inline bool char_is_ascii_skip(u8 c) { |
|
889
|
241577
|
|
|
|
|
|
return !!(char_table1[c] & CHAR_TYPE_ASCII); |
|
890
|
|
|
|
|
|
|
} |
|
891
|
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
/** Match an ASCII character single-quoted: ['\], [0x00-0x1F, 0x80-0xFF]. */ |
|
893
|
|
|
|
|
|
|
static_inline bool char_is_ascii_skip_sq(u8 c) { |
|
894
|
0
|
|
|
|
|
|
return !!(char_table1[c] & CHAR_TYPE_ASCII_SQ); |
|
895
|
|
|
|
|
|
|
} |
|
896
|
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
/** Match a trivia character: extended whitespace or comment. */ |
|
898
|
|
|
|
|
|
|
static_inline bool char_is_trivia(u8 c) { |
|
899
|
0
|
|
|
|
|
|
return !!(char_table1[c] & (CHAR_TYPE_SPACE_EXT | CHAR_TYPE_COMMENT)); |
|
900
|
|
|
|
|
|
|
} |
|
901
|
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
/** Match a line end character: [\r\n]. */ |
|
903
|
|
|
|
|
|
|
static_inline bool char_is_eol(u8 c) { |
|
904
|
0
|
|
|
|
|
|
return !!(char_table2[c] & CHAR_TYPE_EOL); |
|
905
|
|
|
|
|
|
|
} |
|
906
|
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
/** Match an extended line end character: [\r\n], JSON5 line terminator. */ |
|
908
|
|
|
|
|
|
|
static_inline bool char_is_eol_ext(u8 c) { |
|
909
|
0
|
|
|
|
|
|
return !!(char_table2[c] & CHAR_TYPE_EOL_EXT); |
|
910
|
|
|
|
|
|
|
} |
|
911
|
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
/** Match an identifier name start: [_$A-Za-z\], U+0080+. */ |
|
913
|
|
|
|
|
|
|
static_inline bool char_is_id_start(u8 c) { |
|
914
|
0
|
|
|
|
|
|
return !!(char_table2[c] & CHAR_TYPE_ID_START); |
|
915
|
|
|
|
|
|
|
} |
|
916
|
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
/** Match an identifier name next: [_$A-Za-z0-9\], U+0080+. */ |
|
918
|
|
|
|
|
|
|
static_inline bool char_is_id_next(u8 c) { |
|
919
|
0
|
|
|
|
|
|
return !!(char_table2[c] & CHAR_TYPE_ID_NEXT); |
|
920
|
|
|
|
|
|
|
} |
|
921
|
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
/** Match an identifier name ASCII: [_$A-Za-z0-9]. */ |
|
923
|
|
|
|
|
|
|
static_inline bool char_is_id_ascii(u8 c) { |
|
924
|
0
|
|
|
|
|
|
return !!(char_table2[c] & CHAR_TYPE_ID_ASCII); |
|
925
|
|
|
|
|
|
|
} |
|
926
|
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
/** Match a sign: [+-] */ |
|
928
|
|
|
|
|
|
|
static_inline bool char_is_sign(u8 d) { |
|
929
|
0
|
|
|
|
|
|
return !!(char_table3[d] & CHAR_TYPE_SIGN); |
|
930
|
|
|
|
|
|
|
} |
|
931
|
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
/** Match a none-zero digit: [1-9] */ |
|
933
|
|
|
|
|
|
|
static_inline bool char_is_nonzero(u8 d) { |
|
934
|
34148
|
|
|
|
|
|
return !!(char_table3[d] & CHAR_TYPE_NONZERO); |
|
935
|
|
|
|
|
|
|
} |
|
936
|
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
/** Match a digit: [0-9] */ |
|
938
|
|
|
|
|
|
|
static_inline bool char_is_digit(u8 d) { |
|
939
|
0
|
|
|
|
|
|
return !!(char_table3[d] & CHAR_TYPE_DIGIT); |
|
940
|
|
|
|
|
|
|
} |
|
941
|
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
/** Match an exponent sign: [eE]. */ |
|
943
|
|
|
|
|
|
|
static_inline bool char_is_exp(u8 d) { |
|
944
|
2
|
|
|
|
|
|
return !!(char_table3[d] & CHAR_TYPE_EXP); |
|
945
|
|
|
|
|
|
|
} |
|
946
|
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
/** Match a floating point indicator: [.eE]. */ |
|
948
|
|
|
|
|
|
|
static_inline bool char_is_fp(u8 d) { |
|
949
|
34148
|
|
|
|
|
|
return !!(char_table3[d] & (CHAR_TYPE_DOT | CHAR_TYPE_EXP)); |
|
950
|
|
|
|
|
|
|
} |
|
951
|
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
/** Match a digit or floating point indicator: [0-9.eE]. */ |
|
953
|
|
|
|
|
|
|
static_inline bool char_is_digit_or_fp(u8 d) { |
|
954
|
0
|
|
|
|
|
|
return !!(char_table3[d] & (CHAR_TYPE_DIGIT | CHAR_TYPE_DOT | |
|
955
|
|
|
|
|
|
|
CHAR_TYPE_EXP)); |
|
956
|
|
|
|
|
|
|
} |
|
957
|
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
/** Match a JSON container: `{` or `[`. */ |
|
959
|
|
|
|
|
|
|
static_inline bool char_is_ctn(u8 c) { |
|
960
|
20250
|
|
|
|
|
|
return (c & 0xDF) == 0x5B; /* '[': 0x5B, '{': 0x7B */ |
|
961
|
|
|
|
|
|
|
} |
|
962
|
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
/** Convert ASCII letter to lowercase; valid only for [A-Za-z]. */ |
|
964
|
|
|
|
|
|
|
static_inline u8 char_to_lower(u8 c) { |
|
965
|
0
|
|
|
|
|
|
return c | 0x20; |
|
966
|
|
|
|
|
|
|
} |
|
967
|
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
/** Match UTF-8 byte order mask. */ |
|
969
|
|
|
|
|
|
|
static_inline bool is_utf8_bom(const u8 *cur) { |
|
970
|
8
|
|
|
|
|
|
return byte_load_3(cur) == byte_load_3("\xEF\xBB\xBF"); |
|
971
|
|
|
|
|
|
|
} |
|
972
|
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
/** Match UTF-16 byte order mask. */ |
|
974
|
|
|
|
|
|
|
static_inline bool is_utf16_bom(const u8 *cur) { |
|
975
|
9
|
0
|
|
|
|
|
return byte_load_2(cur) == byte_load_2("\xFE\xFF") || |
|
|
|
50
|
|
|
|
|
|
|
976
|
6
|
0
|
|
|
|
|
byte_load_2(cur) == byte_load_2("\xFF\xFE"); |
|
|
|
50
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
} |
|
978
|
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
/** Match UTF-32 byte order mask, need length check to avoid zero padding. */ |
|
980
|
|
|
|
|
|
|
static_inline bool is_utf32_bom(const u8 *cur) { |
|
981
|
9
|
0
|
|
|
|
|
return byte_load_4(cur) == byte_load_4("\x00\x00\xFE\xFF") || |
|
|
|
50
|
|
|
|
|
|
|
982
|
6
|
0
|
|
|
|
|
byte_load_4(cur) == byte_load_4("\xFF\xFE\x00\x00"); |
|
|
|
50
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
} |
|
984
|
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
/** Get the extended line end length. Used with `char_is_eol_ext`. */ |
|
986
|
|
|
|
|
|
|
static_inline usize ext_eol_len(const u8 *cur) { |
|
987
|
0
|
0
|
|
|
|
|
if (cur[0] < 0x80) return 1; |
|
988
|
0
|
0
|
|
|
|
|
if (cur[1] == 0x80 && (cur[2] == 0xA8 || cur[2] == 0xA9)) return 3; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
989
|
0
|
|
|
|
|
|
return 0; |
|
990
|
|
|
|
|
|
|
} |
|
991
|
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
/** Get the extended whitespace length. Used with `char_is_space_ext`. */ |
|
993
|
|
|
|
|
|
|
static_inline usize ext_space_len(const u8 *cur) { |
|
994
|
0
|
0
|
|
|
|
|
if (cur[0] < 0x80) { |
|
995
|
0
|
|
|
|
|
|
return 1; |
|
996
|
0
|
0
|
|
|
|
|
} else if (byte_load_2(cur) == byte_load_2("\xC2\xA0")) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
997
|
0
|
|
|
|
|
|
return 2; |
|
998
|
0
|
0
|
|
|
|
|
} else if (byte_load_2(cur) == byte_load_2("\xE2\x80")) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
999
|
0
|
0
|
|
|
|
|
if (cur[2] >= 0x80 && cur[2] <= 0x8A) return 3; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1000
|
0
|
0
|
|
|
|
|
if (cur[2] == 0xA8 || cur[2] == 0xA9 || cur[2] == 0xAF) return 3; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
} else { |
|
1002
|
0
|
|
|
|
|
|
u32 uni = byte_load_3(cur); |
|
1003
|
0
|
0
|
|
|
|
|
if (uni == byte_load_3("\xE1\x9A\x80") || |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1004
|
0
|
0
|
|
|
|
|
uni == byte_load_3("\xE2\x81\x9F") || |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1005
|
0
|
0
|
|
|
|
|
uni == byte_load_3("\xE3\x80\x80") || |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1006
|
0
|
0
|
|
|
|
|
uni == byte_load_3("\xEF\xBB\xBF")) return 3; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
} |
|
1008
|
0
|
|
|
|
|
|
return 0; |
|
1009
|
|
|
|
|
|
|
} |
|
1010
|
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
/*============================================================================== |
|
1014
|
|
|
|
|
|
|
* MARK: - Hex Character Reader (Private) |
|
1015
|
|
|
|
|
|
|
* This function is used by JSON reader to read escaped characters. |
|
1016
|
|
|
|
|
|
|
*============================================================================*/ |
|
1017
|
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
/** |
|
1019
|
|
|
|
|
|
|
This table is used to convert 4 hex character sequence to a number. |
|
1020
|
|
|
|
|
|
|
A valid hex character [0-9A-Fa-f] will mapped to it's raw number [0x00, 0x0F], |
|
1021
|
|
|
|
|
|
|
an invalid hex character will mapped to [0xF0]. |
|
1022
|
|
|
|
|
|
|
(generate with misc/make_tables.c) |
|
1023
|
|
|
|
|
|
|
*/ |
|
1024
|
|
|
|
|
|
|
static const u8 hex_conv_table[256] = { |
|
1025
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1026
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1027
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1028
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1029
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1030
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1031
|
|
|
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
|
1032
|
|
|
|
|
|
|
0x08, 0x09, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1033
|
|
|
|
|
|
|
0xF0, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xF0, |
|
1034
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1035
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1036
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1037
|
|
|
|
|
|
|
0xF0, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xF0, |
|
1038
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1039
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1040
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1041
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1042
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1043
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1044
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1045
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1046
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1047
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1048
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1049
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1050
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1051
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1052
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1053
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1054
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1055
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, |
|
1056
|
|
|
|
|
|
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0 |
|
1057
|
|
|
|
|
|
|
}; |
|
1058
|
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
/** Load 4 hex characters to `u16`, return true on valid input. */ |
|
1060
|
|
|
|
|
|
|
static_inline bool hex_load_4(const u8 *src, u16 *dst) { |
|
1061
|
10
|
|
|
|
|
|
u16 c0 = hex_conv_table[src[0]]; |
|
1062
|
10
|
|
|
|
|
|
u16 c1 = hex_conv_table[src[1]]; |
|
1063
|
10
|
|
|
|
|
|
u16 c2 = hex_conv_table[src[2]]; |
|
1064
|
10
|
|
|
|
|
|
u16 c3 = hex_conv_table[src[3]]; |
|
1065
|
10
|
|
|
|
|
|
u16 t0 = (u16)((c0 << 8) | c2); |
|
1066
|
10
|
|
|
|
|
|
u16 t1 = (u16)((c1 << 8) | c3); |
|
1067
|
10
|
|
|
|
|
|
*dst = (u16)((t0 << 4) | t1); |
|
1068
|
10
|
|
|
|
|
|
return ((t0 | t1) & (u16)0xF0F0) == 0; |
|
1069
|
|
|
|
|
|
|
} |
|
1070
|
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
/** Load 2 hex characters to `u8`, return true on valid input. */ |
|
1072
|
|
|
|
|
|
|
static_inline bool hex_load_2(const u8 *src, u8 *dst) { |
|
1073
|
0
|
|
|
|
|
|
u8 c0 = hex_conv_table[src[0]]; |
|
1074
|
0
|
|
|
|
|
|
u8 c1 = hex_conv_table[src[1]]; |
|
1075
|
0
|
|
|
|
|
|
*dst = (u8)((c0 << 4) | c1); |
|
1076
|
0
|
|
|
|
|
|
return ((c0 | c1) & 0xF0) == 0; |
|
1077
|
|
|
|
|
|
|
} |
|
1078
|
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
/** Match a hexadecimal numeric character: [0-9a-fA-F]. */ |
|
1080
|
|
|
|
|
|
|
static_inline bool char_is_hex(u8 c) { |
|
1081
|
0
|
|
|
|
|
|
return hex_conv_table[c] != 0xF0; |
|
1082
|
|
|
|
|
|
|
} |
|
1083
|
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
/*============================================================================== |
|
1087
|
|
|
|
|
|
|
* MARK: - UTF8 Validation (Private) |
|
1088
|
|
|
|
|
|
|
* Each Unicode code point is encoded using 1 to 4 bytes in UTF-8. |
|
1089
|
|
|
|
|
|
|
* Validation is performed using a 4-byte mask and pattern-based approach, |
|
1090
|
|
|
|
|
|
|
* which requires the input data to be padded with four zero bytes at the end. |
|
1091
|
|
|
|
|
|
|
*============================================================================*/ |
|
1092
|
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
/* Macro for concatenating four u8 into a u32 and keeping the byte order. */ |
|
1094
|
|
|
|
|
|
|
#if YYJSON_ENDIAN == YYJSON_LITTLE_ENDIAN |
|
1095
|
|
|
|
|
|
|
# define utf8_seq_def(name, a, b, c, d) \ |
|
1096
|
|
|
|
|
|
|
static const u32 utf8_seq_##name = 0x##d##c##b##a##UL; |
|
1097
|
|
|
|
|
|
|
# define utf8_seq(name) utf8_seq_##name |
|
1098
|
|
|
|
|
|
|
#elif YYJSON_ENDIAN == YYJSON_BIG_ENDIAN |
|
1099
|
|
|
|
|
|
|
# define utf8_seq_def(name, a, b, c, d) \ |
|
1100
|
|
|
|
|
|
|
static const u32 utf8_seq_##name = 0x##a##b##c##d##UL; |
|
1101
|
|
|
|
|
|
|
# define utf8_seq(name) utf8_seq_##name |
|
1102
|
|
|
|
|
|
|
#else |
|
1103
|
|
|
|
|
|
|
# define utf8_seq_def(name, a, b, c, d) \ |
|
1104
|
|
|
|
|
|
|
static const v32_uni utf8_uni_##name = {{ 0x##a, 0x##b, 0x##c, 0x##d }}; |
|
1105
|
|
|
|
|
|
|
# define utf8_seq(name) utf8_uni_##name.u |
|
1106
|
|
|
|
|
|
|
#endif |
|
1107
|
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
/* |
|
1109
|
|
|
|
|
|
|
1-byte sequence (U+0000 to U+007F) |
|
1110
|
|
|
|
|
|
|
bit min [.......0] (U+0000) |
|
1111
|
|
|
|
|
|
|
bit max [.1111111] (U+007F) |
|
1112
|
|
|
|
|
|
|
bit mask [x.......] (80) |
|
1113
|
|
|
|
|
|
|
bit pattern [0.......] (00) |
|
1114
|
|
|
|
|
|
|
*/ |
|
1115
|
|
|
|
|
|
|
utf8_seq_def(b1_mask, 80, 00, 00, 00) |
|
1116
|
|
|
|
|
|
|
utf8_seq_def(b1_patt, 00, 00, 00, 00) |
|
1117
|
|
|
|
|
|
|
#define is_utf8_seq1(uni) ( \ |
|
1118
|
|
|
|
|
|
|
((uni & utf8_seq(b1_mask)) == utf8_seq(b1_patt)) ) |
|
1119
|
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
/* |
|
1121
|
|
|
|
|
|
|
2-byte sequence (U+0080 to U+07FF) |
|
1122
|
|
|
|
|
|
|
bit min [......10 ..000000] (U+0080) |
|
1123
|
|
|
|
|
|
|
bit max [...11111 ..111111] (U+07FF) |
|
1124
|
|
|
|
|
|
|
bit mask [xxx..... xx......] (E0 C0) |
|
1125
|
|
|
|
|
|
|
bit pattern [110..... 10......] (C0 80) |
|
1126
|
|
|
|
|
|
|
bit require [...xxxx. ........] (1E 00) |
|
1127
|
|
|
|
|
|
|
*/ |
|
1128
|
|
|
|
|
|
|
utf8_seq_def(b2_mask, E0, C0, 00, 00) |
|
1129
|
|
|
|
|
|
|
utf8_seq_def(b2_patt, C0, 80, 00, 00) |
|
1130
|
|
|
|
|
|
|
utf8_seq_def(b2_requ, 1E, 00, 00, 00) |
|
1131
|
|
|
|
|
|
|
#define is_utf8_seq2(uni) ( \ |
|
1132
|
|
|
|
|
|
|
((uni & utf8_seq(b2_mask)) == utf8_seq(b2_patt)) && \ |
|
1133
|
|
|
|
|
|
|
((uni & utf8_seq(b2_requ))) ) |
|
1134
|
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
/* |
|
1136
|
|
|
|
|
|
|
3-byte sequence (U+0800 to U+FFFF) |
|
1137
|
|
|
|
|
|
|
bit min [........ ..100000 ..000000] (U+0800) |
|
1138
|
|
|
|
|
|
|
bit max [....1111 ..111111 ..111111] (U+FFFF) |
|
1139
|
|
|
|
|
|
|
bit mask [xxxx.... xx...... xx......] (F0 C0 C0) |
|
1140
|
|
|
|
|
|
|
bit pattern [1110.... 10...... 10......] (E0 80 80) |
|
1141
|
|
|
|
|
|
|
bit require [....xxxx ..x..... ........] (0F 20 00) |
|
1142
|
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
3-byte invalid sequence, reserved for surrogate halves (U+D800 to U+DFFF) |
|
1144
|
|
|
|
|
|
|
bit min [....1101 ..100000 ..000000] (U+D800) |
|
1145
|
|
|
|
|
|
|
bit max [....1101 ..111111 ..111111] (U+DFFF) |
|
1146
|
|
|
|
|
|
|
bit mask [....xxxx ..x..... ........] (0F 20 00) |
|
1147
|
|
|
|
|
|
|
bit pattern [....1101 ..1..... ........] (0D 20 00) |
|
1148
|
|
|
|
|
|
|
*/ |
|
1149
|
|
|
|
|
|
|
utf8_seq_def(b3_mask, F0, C0, C0, 00) |
|
1150
|
|
|
|
|
|
|
utf8_seq_def(b3_patt, E0, 80, 80, 00) |
|
1151
|
|
|
|
|
|
|
utf8_seq_def(b3_requ, 0F, 20, 00, 00) |
|
1152
|
|
|
|
|
|
|
utf8_seq_def(b3_erro, 0D, 20, 00, 00) |
|
1153
|
|
|
|
|
|
|
#define is_utf8_seq3(uni) ( \ |
|
1154
|
|
|
|
|
|
|
((uni & utf8_seq(b3_mask)) == utf8_seq(b3_patt)) && \ |
|
1155
|
|
|
|
|
|
|
((tmp = (uni & utf8_seq(b3_requ)))) && \ |
|
1156
|
|
|
|
|
|
|
((tmp != utf8_seq(b3_erro))) ) |
|
1157
|
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
/* |
|
1159
|
|
|
|
|
|
|
4-byte sequence (U+10000 to U+10FFFF) |
|
1160
|
|
|
|
|
|
|
bit min [........ ...10000 ..000000 ..000000] (U+10000) |
|
1161
|
|
|
|
|
|
|
bit max [.....100 ..001111 ..111111 ..111111] (U+10FFFF) |
|
1162
|
|
|
|
|
|
|
bit mask [xxxxx... xx...... xx...... xx......] (F8 C0 C0 C0) |
|
1163
|
|
|
|
|
|
|
bit pattern [11110... 10...... 10...... 10......] (F0 80 80 80) |
|
1164
|
|
|
|
|
|
|
bit require [.....xxx ..xx.... ........ ........] (07 30 00 00) |
|
1165
|
|
|
|
|
|
|
bit require 1 [.....x.. ........ ........ ........] (04 00 00 00) |
|
1166
|
|
|
|
|
|
|
bit require 2 [......xx ..xx.... ........ ........] (03 30 00 00) |
|
1167
|
|
|
|
|
|
|
*/ |
|
1168
|
|
|
|
|
|
|
utf8_seq_def(b4_mask, F8, C0, C0, C0) |
|
1169
|
|
|
|
|
|
|
utf8_seq_def(b4_patt, F0, 80, 80, 80) |
|
1170
|
|
|
|
|
|
|
utf8_seq_def(b4_requ, 07, 30, 00, 00) |
|
1171
|
|
|
|
|
|
|
utf8_seq_def(b4_req1, 04, 00, 00, 00) |
|
1172
|
|
|
|
|
|
|
utf8_seq_def(b4_req2, 03, 30, 00, 00) |
|
1173
|
|
|
|
|
|
|
#define is_utf8_seq4(uni) ( \ |
|
1174
|
|
|
|
|
|
|
((uni & utf8_seq(b4_mask)) == utf8_seq(b4_patt)) && \ |
|
1175
|
|
|
|
|
|
|
((tmp = (uni & utf8_seq(b4_requ)))) && \ |
|
1176
|
|
|
|
|
|
|
((tmp & utf8_seq(b4_req1)) == 0 || (tmp & utf8_seq(b4_req2)) == 0) ) |
|
1177
|
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
/*============================================================================== |
|
1181
|
|
|
|
|
|
|
* MARK: - Power10 Lookup Table (Private) |
|
1182
|
|
|
|
|
|
|
* These data are used by the floating-point number reader and writer. |
|
1183
|
|
|
|
|
|
|
*============================================================================*/ |
|
1184
|
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_FAST_FP_CONV |
|
1186
|
|
|
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
/** Maximum pow10 exponent that can be represented exactly as a float64. */ |
|
1188
|
|
|
|
|
|
|
#define F64_POW10_MAX_EXACT_EXP 22 |
|
1189
|
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
/** Cached pow10 table. */ |
|
1191
|
|
|
|
|
|
|
static const f64 f64_pow10_table[F64_POW10_MAX_EXACT_EXP + 1] = { |
|
1192
|
|
|
|
|
|
|
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, |
|
1193
|
|
|
|
|
|
|
1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 |
|
1194
|
|
|
|
|
|
|
}; |
|
1195
|
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
/** Maximum pow10 exponent that can be represented exactly as a uint64. */ |
|
1197
|
|
|
|
|
|
|
#define U64_POW10_MAX_EXACT_EXP 19 |
|
1198
|
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
/** Table: [ 10^0, ..., 10^19 ] (generate with misc/make_tables.c) */ |
|
1200
|
|
|
|
|
|
|
static const u64 u64_pow10_table[U64_POW10_MAX_EXACT_EXP + 1] = { |
|
1201
|
|
|
|
|
|
|
U64(0x00000000, 0x00000001), U64(0x00000000, 0x0000000A), |
|
1202
|
|
|
|
|
|
|
U64(0x00000000, 0x00000064), U64(0x00000000, 0x000003E8), |
|
1203
|
|
|
|
|
|
|
U64(0x00000000, 0x00002710), U64(0x00000000, 0x000186A0), |
|
1204
|
|
|
|
|
|
|
U64(0x00000000, 0x000F4240), U64(0x00000000, 0x00989680), |
|
1205
|
|
|
|
|
|
|
U64(0x00000000, 0x05F5E100), U64(0x00000000, 0x3B9ACA00), |
|
1206
|
|
|
|
|
|
|
U64(0x00000002, 0x540BE400), U64(0x00000017, 0x4876E800), |
|
1207
|
|
|
|
|
|
|
U64(0x000000E8, 0xD4A51000), U64(0x00000918, 0x4E72A000), |
|
1208
|
|
|
|
|
|
|
U64(0x00005AF3, 0x107A4000), U64(0x00038D7E, 0xA4C68000), |
|
1209
|
|
|
|
|
|
|
U64(0x002386F2, 0x6FC10000), U64(0x01634578, 0x5D8A0000), |
|
1210
|
|
|
|
|
|
|
U64(0x0DE0B6B3, 0xA7640000), U64(0x8AC72304, 0x89E80000) |
|
1211
|
|
|
|
|
|
|
}; |
|
1212
|
|
|
|
|
|
|
|
|
1213
|
|
|
|
|
|
|
/** Minimum decimal exponent in pow10_sig_table. */ |
|
1214
|
|
|
|
|
|
|
#define POW10_SIG_TABLE_MIN_EXP -343 |
|
1215
|
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
/** Maximum decimal exponent in pow10_sig_table. */ |
|
1217
|
|
|
|
|
|
|
#define POW10_SIG_TABLE_MAX_EXP 324 |
|
1218
|
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
/** Minimum exact decimal exponent in pow10_sig_table */ |
|
1220
|
|
|
|
|
|
|
#define POW10_SIG_TABLE_MIN_EXACT_EXP 0 |
|
1221
|
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
/** Maximum exact decimal exponent in pow10_sig_table */ |
|
1223
|
|
|
|
|
|
|
#define POW10_SIG_TABLE_MAX_EXACT_EXP 55 |
|
1224
|
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
/** Normalized significant 128 bits of pow10, no rounded up (size: 10.4KB). |
|
1226
|
|
|
|
|
|
|
This lookup table is used by both the double number reader and writer. |
|
1227
|
|
|
|
|
|
|
(generate with misc/make_tables.c) */ |
|
1228
|
|
|
|
|
|
|
static const u64 pow10_sig_table[] = { |
|
1229
|
|
|
|
|
|
|
U64(0xBF29DCAB, 0xA82FDEAE), U64(0x7432EE87, 0x3880FC33), /* ~= 10^-343 */ |
|
1230
|
|
|
|
|
|
|
U64(0xEEF453D6, 0x923BD65A), U64(0x113FAA29, 0x06A13B3F), /* ~= 10^-342 */ |
|
1231
|
|
|
|
|
|
|
U64(0x9558B466, 0x1B6565F8), U64(0x4AC7CA59, 0xA424C507), /* ~= 10^-341 */ |
|
1232
|
|
|
|
|
|
|
U64(0xBAAEE17F, 0xA23EBF76), U64(0x5D79BCF0, 0x0D2DF649), /* ~= 10^-340 */ |
|
1233
|
|
|
|
|
|
|
U64(0xE95A99DF, 0x8ACE6F53), U64(0xF4D82C2C, 0x107973DC), /* ~= 10^-339 */ |
|
1234
|
|
|
|
|
|
|
U64(0x91D8A02B, 0xB6C10594), U64(0x79071B9B, 0x8A4BE869), /* ~= 10^-338 */ |
|
1235
|
|
|
|
|
|
|
U64(0xB64EC836, 0xA47146F9), U64(0x9748E282, 0x6CDEE284), /* ~= 10^-337 */ |
|
1236
|
|
|
|
|
|
|
U64(0xE3E27A44, 0x4D8D98B7), U64(0xFD1B1B23, 0x08169B25), /* ~= 10^-336 */ |
|
1237
|
|
|
|
|
|
|
U64(0x8E6D8C6A, 0xB0787F72), U64(0xFE30F0F5, 0xE50E20F7), /* ~= 10^-335 */ |
|
1238
|
|
|
|
|
|
|
U64(0xB208EF85, 0x5C969F4F), U64(0xBDBD2D33, 0x5E51A935), /* ~= 10^-334 */ |
|
1239
|
|
|
|
|
|
|
U64(0xDE8B2B66, 0xB3BC4723), U64(0xAD2C7880, 0x35E61382), /* ~= 10^-333 */ |
|
1240
|
|
|
|
|
|
|
U64(0x8B16FB20, 0x3055AC76), U64(0x4C3BCB50, 0x21AFCC31), /* ~= 10^-332 */ |
|
1241
|
|
|
|
|
|
|
U64(0xADDCB9E8, 0x3C6B1793), U64(0xDF4ABE24, 0x2A1BBF3D), /* ~= 10^-331 */ |
|
1242
|
|
|
|
|
|
|
U64(0xD953E862, 0x4B85DD78), U64(0xD71D6DAD, 0x34A2AF0D), /* ~= 10^-330 */ |
|
1243
|
|
|
|
|
|
|
U64(0x87D4713D, 0x6F33AA6B), U64(0x8672648C, 0x40E5AD68), /* ~= 10^-329 */ |
|
1244
|
|
|
|
|
|
|
U64(0xA9C98D8C, 0xCB009506), U64(0x680EFDAF, 0x511F18C2), /* ~= 10^-328 */ |
|
1245
|
|
|
|
|
|
|
U64(0xD43BF0EF, 0xFDC0BA48), U64(0x0212BD1B, 0x2566DEF2), /* ~= 10^-327 */ |
|
1246
|
|
|
|
|
|
|
U64(0x84A57695, 0xFE98746D), U64(0x014BB630, 0xF7604B57), /* ~= 10^-326 */ |
|
1247
|
|
|
|
|
|
|
U64(0xA5CED43B, 0x7E3E9188), U64(0x419EA3BD, 0x35385E2D), /* ~= 10^-325 */ |
|
1248
|
|
|
|
|
|
|
U64(0xCF42894A, 0x5DCE35EA), U64(0x52064CAC, 0x828675B9), /* ~= 10^-324 */ |
|
1249
|
|
|
|
|
|
|
U64(0x818995CE, 0x7AA0E1B2), U64(0x7343EFEB, 0xD1940993), /* ~= 10^-323 */ |
|
1250
|
|
|
|
|
|
|
U64(0xA1EBFB42, 0x19491A1F), U64(0x1014EBE6, 0xC5F90BF8), /* ~= 10^-322 */ |
|
1251
|
|
|
|
|
|
|
U64(0xCA66FA12, 0x9F9B60A6), U64(0xD41A26E0, 0x77774EF6), /* ~= 10^-321 */ |
|
1252
|
|
|
|
|
|
|
U64(0xFD00B897, 0x478238D0), U64(0x8920B098, 0x955522B4), /* ~= 10^-320 */ |
|
1253
|
|
|
|
|
|
|
U64(0x9E20735E, 0x8CB16382), U64(0x55B46E5F, 0x5D5535B0), /* ~= 10^-319 */ |
|
1254
|
|
|
|
|
|
|
U64(0xC5A89036, 0x2FDDBC62), U64(0xEB2189F7, 0x34AA831D), /* ~= 10^-318 */ |
|
1255
|
|
|
|
|
|
|
U64(0xF712B443, 0xBBD52B7B), U64(0xA5E9EC75, 0x01D523E4), /* ~= 10^-317 */ |
|
1256
|
|
|
|
|
|
|
U64(0x9A6BB0AA, 0x55653B2D), U64(0x47B233C9, 0x2125366E), /* ~= 10^-316 */ |
|
1257
|
|
|
|
|
|
|
U64(0xC1069CD4, 0xEABE89F8), U64(0x999EC0BB, 0x696E840A), /* ~= 10^-315 */ |
|
1258
|
|
|
|
|
|
|
U64(0xF148440A, 0x256E2C76), U64(0xC00670EA, 0x43CA250D), /* ~= 10^-314 */ |
|
1259
|
|
|
|
|
|
|
U64(0x96CD2A86, 0x5764DBCA), U64(0x38040692, 0x6A5E5728), /* ~= 10^-313 */ |
|
1260
|
|
|
|
|
|
|
U64(0xBC807527, 0xED3E12BC), U64(0xC6050837, 0x04F5ECF2), /* ~= 10^-312 */ |
|
1261
|
|
|
|
|
|
|
U64(0xEBA09271, 0xE88D976B), U64(0xF7864A44, 0xC633682E), /* ~= 10^-311 */ |
|
1262
|
|
|
|
|
|
|
U64(0x93445B87, 0x31587EA3), U64(0x7AB3EE6A, 0xFBE0211D), /* ~= 10^-310 */ |
|
1263
|
|
|
|
|
|
|
U64(0xB8157268, 0xFDAE9E4C), U64(0x5960EA05, 0xBAD82964), /* ~= 10^-309 */ |
|
1264
|
|
|
|
|
|
|
U64(0xE61ACF03, 0x3D1A45DF), U64(0x6FB92487, 0x298E33BD), /* ~= 10^-308 */ |
|
1265
|
|
|
|
|
|
|
U64(0x8FD0C162, 0x06306BAB), U64(0xA5D3B6D4, 0x79F8E056), /* ~= 10^-307 */ |
|
1266
|
|
|
|
|
|
|
U64(0xB3C4F1BA, 0x87BC8696), U64(0x8F48A489, 0x9877186C), /* ~= 10^-306 */ |
|
1267
|
|
|
|
|
|
|
U64(0xE0B62E29, 0x29ABA83C), U64(0x331ACDAB, 0xFE94DE87), /* ~= 10^-305 */ |
|
1268
|
|
|
|
|
|
|
U64(0x8C71DCD9, 0xBA0B4925), U64(0x9FF0C08B, 0x7F1D0B14), /* ~= 10^-304 */ |
|
1269
|
|
|
|
|
|
|
U64(0xAF8E5410, 0x288E1B6F), U64(0x07ECF0AE, 0x5EE44DD9), /* ~= 10^-303 */ |
|
1270
|
|
|
|
|
|
|
U64(0xDB71E914, 0x32B1A24A), U64(0xC9E82CD9, 0xF69D6150), /* ~= 10^-302 */ |
|
1271
|
|
|
|
|
|
|
U64(0x892731AC, 0x9FAF056E), U64(0xBE311C08, 0x3A225CD2), /* ~= 10^-301 */ |
|
1272
|
|
|
|
|
|
|
U64(0xAB70FE17, 0xC79AC6CA), U64(0x6DBD630A, 0x48AAF406), /* ~= 10^-300 */ |
|
1273
|
|
|
|
|
|
|
U64(0xD64D3D9D, 0xB981787D), U64(0x092CBBCC, 0xDAD5B108), /* ~= 10^-299 */ |
|
1274
|
|
|
|
|
|
|
U64(0x85F04682, 0x93F0EB4E), U64(0x25BBF560, 0x08C58EA5), /* ~= 10^-298 */ |
|
1275
|
|
|
|
|
|
|
U64(0xA76C5823, 0x38ED2621), U64(0xAF2AF2B8, 0x0AF6F24E), /* ~= 10^-297 */ |
|
1276
|
|
|
|
|
|
|
U64(0xD1476E2C, 0x07286FAA), U64(0x1AF5AF66, 0x0DB4AEE1), /* ~= 10^-296 */ |
|
1277
|
|
|
|
|
|
|
U64(0x82CCA4DB, 0x847945CA), U64(0x50D98D9F, 0xC890ED4D), /* ~= 10^-295 */ |
|
1278
|
|
|
|
|
|
|
U64(0xA37FCE12, 0x6597973C), U64(0xE50FF107, 0xBAB528A0), /* ~= 10^-294 */ |
|
1279
|
|
|
|
|
|
|
U64(0xCC5FC196, 0xFEFD7D0C), U64(0x1E53ED49, 0xA96272C8), /* ~= 10^-293 */ |
|
1280
|
|
|
|
|
|
|
U64(0xFF77B1FC, 0xBEBCDC4F), U64(0x25E8E89C, 0x13BB0F7A), /* ~= 10^-292 */ |
|
1281
|
|
|
|
|
|
|
U64(0x9FAACF3D, 0xF73609B1), U64(0x77B19161, 0x8C54E9AC), /* ~= 10^-291 */ |
|
1282
|
|
|
|
|
|
|
U64(0xC795830D, 0x75038C1D), U64(0xD59DF5B9, 0xEF6A2417), /* ~= 10^-290 */ |
|
1283
|
|
|
|
|
|
|
U64(0xF97AE3D0, 0xD2446F25), U64(0x4B057328, 0x6B44AD1D), /* ~= 10^-289 */ |
|
1284
|
|
|
|
|
|
|
U64(0x9BECCE62, 0x836AC577), U64(0x4EE367F9, 0x430AEC32), /* ~= 10^-288 */ |
|
1285
|
|
|
|
|
|
|
U64(0xC2E801FB, 0x244576D5), U64(0x229C41F7, 0x93CDA73F), /* ~= 10^-287 */ |
|
1286
|
|
|
|
|
|
|
U64(0xF3A20279, 0xED56D48A), U64(0x6B435275, 0x78C1110F), /* ~= 10^-286 */ |
|
1287
|
|
|
|
|
|
|
U64(0x9845418C, 0x345644D6), U64(0x830A1389, 0x6B78AAA9), /* ~= 10^-285 */ |
|
1288
|
|
|
|
|
|
|
U64(0xBE5691EF, 0x416BD60C), U64(0x23CC986B, 0xC656D553), /* ~= 10^-284 */ |
|
1289
|
|
|
|
|
|
|
U64(0xEDEC366B, 0x11C6CB8F), U64(0x2CBFBE86, 0xB7EC8AA8), /* ~= 10^-283 */ |
|
1290
|
|
|
|
|
|
|
U64(0x94B3A202, 0xEB1C3F39), U64(0x7BF7D714, 0x32F3D6A9), /* ~= 10^-282 */ |
|
1291
|
|
|
|
|
|
|
U64(0xB9E08A83, 0xA5E34F07), U64(0xDAF5CCD9, 0x3FB0CC53), /* ~= 10^-281 */ |
|
1292
|
|
|
|
|
|
|
U64(0xE858AD24, 0x8F5C22C9), U64(0xD1B3400F, 0x8F9CFF68), /* ~= 10^-280 */ |
|
1293
|
|
|
|
|
|
|
U64(0x91376C36, 0xD99995BE), U64(0x23100809, 0xB9C21FA1), /* ~= 10^-279 */ |
|
1294
|
|
|
|
|
|
|
U64(0xB5854744, 0x8FFFFB2D), U64(0xABD40A0C, 0x2832A78A), /* ~= 10^-278 */ |
|
1295
|
|
|
|
|
|
|
U64(0xE2E69915, 0xB3FFF9F9), U64(0x16C90C8F, 0x323F516C), /* ~= 10^-277 */ |
|
1296
|
|
|
|
|
|
|
U64(0x8DD01FAD, 0x907FFC3B), U64(0xAE3DA7D9, 0x7F6792E3), /* ~= 10^-276 */ |
|
1297
|
|
|
|
|
|
|
U64(0xB1442798, 0xF49FFB4A), U64(0x99CD11CF, 0xDF41779C), /* ~= 10^-275 */ |
|
1298
|
|
|
|
|
|
|
U64(0xDD95317F, 0x31C7FA1D), U64(0x40405643, 0xD711D583), /* ~= 10^-274 */ |
|
1299
|
|
|
|
|
|
|
U64(0x8A7D3EEF, 0x7F1CFC52), U64(0x482835EA, 0x666B2572), /* ~= 10^-273 */ |
|
1300
|
|
|
|
|
|
|
U64(0xAD1C8EAB, 0x5EE43B66), U64(0xDA324365, 0x0005EECF), /* ~= 10^-272 */ |
|
1301
|
|
|
|
|
|
|
U64(0xD863B256, 0x369D4A40), U64(0x90BED43E, 0x40076A82), /* ~= 10^-271 */ |
|
1302
|
|
|
|
|
|
|
U64(0x873E4F75, 0xE2224E68), U64(0x5A7744A6, 0xE804A291), /* ~= 10^-270 */ |
|
1303
|
|
|
|
|
|
|
U64(0xA90DE353, 0x5AAAE202), U64(0x711515D0, 0xA205CB36), /* ~= 10^-269 */ |
|
1304
|
|
|
|
|
|
|
U64(0xD3515C28, 0x31559A83), U64(0x0D5A5B44, 0xCA873E03), /* ~= 10^-268 */ |
|
1305
|
|
|
|
|
|
|
U64(0x8412D999, 0x1ED58091), U64(0xE858790A, 0xFE9486C2), /* ~= 10^-267 */ |
|
1306
|
|
|
|
|
|
|
U64(0xA5178FFF, 0x668AE0B6), U64(0x626E974D, 0xBE39A872), /* ~= 10^-266 */ |
|
1307
|
|
|
|
|
|
|
U64(0xCE5D73FF, 0x402D98E3), U64(0xFB0A3D21, 0x2DC8128F), /* ~= 10^-265 */ |
|
1308
|
|
|
|
|
|
|
U64(0x80FA687F, 0x881C7F8E), U64(0x7CE66634, 0xBC9D0B99), /* ~= 10^-264 */ |
|
1309
|
|
|
|
|
|
|
U64(0xA139029F, 0x6A239F72), U64(0x1C1FFFC1, 0xEBC44E80), /* ~= 10^-263 */ |
|
1310
|
|
|
|
|
|
|
U64(0xC9874347, 0x44AC874E), U64(0xA327FFB2, 0x66B56220), /* ~= 10^-262 */ |
|
1311
|
|
|
|
|
|
|
U64(0xFBE91419, 0x15D7A922), U64(0x4BF1FF9F, 0x0062BAA8), /* ~= 10^-261 */ |
|
1312
|
|
|
|
|
|
|
U64(0x9D71AC8F, 0xADA6C9B5), U64(0x6F773FC3, 0x603DB4A9), /* ~= 10^-260 */ |
|
1313
|
|
|
|
|
|
|
U64(0xC4CE17B3, 0x99107C22), U64(0xCB550FB4, 0x384D21D3), /* ~= 10^-259 */ |
|
1314
|
|
|
|
|
|
|
U64(0xF6019DA0, 0x7F549B2B), U64(0x7E2A53A1, 0x46606A48), /* ~= 10^-258 */ |
|
1315
|
|
|
|
|
|
|
U64(0x99C10284, 0x4F94E0FB), U64(0x2EDA7444, 0xCBFC426D), /* ~= 10^-257 */ |
|
1316
|
|
|
|
|
|
|
U64(0xC0314325, 0x637A1939), U64(0xFA911155, 0xFEFB5308), /* ~= 10^-256 */ |
|
1317
|
|
|
|
|
|
|
U64(0xF03D93EE, 0xBC589F88), U64(0x793555AB, 0x7EBA27CA), /* ~= 10^-255 */ |
|
1318
|
|
|
|
|
|
|
U64(0x96267C75, 0x35B763B5), U64(0x4BC1558B, 0x2F3458DE), /* ~= 10^-254 */ |
|
1319
|
|
|
|
|
|
|
U64(0xBBB01B92, 0x83253CA2), U64(0x9EB1AAED, 0xFB016F16), /* ~= 10^-253 */ |
|
1320
|
|
|
|
|
|
|
U64(0xEA9C2277, 0x23EE8BCB), U64(0x465E15A9, 0x79C1CADC), /* ~= 10^-252 */ |
|
1321
|
|
|
|
|
|
|
U64(0x92A1958A, 0x7675175F), U64(0x0BFACD89, 0xEC191EC9), /* ~= 10^-251 */ |
|
1322
|
|
|
|
|
|
|
U64(0xB749FAED, 0x14125D36), U64(0xCEF980EC, 0x671F667B), /* ~= 10^-250 */ |
|
1323
|
|
|
|
|
|
|
U64(0xE51C79A8, 0x5916F484), U64(0x82B7E127, 0x80E7401A), /* ~= 10^-249 */ |
|
1324
|
|
|
|
|
|
|
U64(0x8F31CC09, 0x37AE58D2), U64(0xD1B2ECB8, 0xB0908810), /* ~= 10^-248 */ |
|
1325
|
|
|
|
|
|
|
U64(0xB2FE3F0B, 0x8599EF07), U64(0x861FA7E6, 0xDCB4AA15), /* ~= 10^-247 */ |
|
1326
|
|
|
|
|
|
|
U64(0xDFBDCECE, 0x67006AC9), U64(0x67A791E0, 0x93E1D49A), /* ~= 10^-246 */ |
|
1327
|
|
|
|
|
|
|
U64(0x8BD6A141, 0x006042BD), U64(0xE0C8BB2C, 0x5C6D24E0), /* ~= 10^-245 */ |
|
1328
|
|
|
|
|
|
|
U64(0xAECC4991, 0x4078536D), U64(0x58FAE9F7, 0x73886E18), /* ~= 10^-244 */ |
|
1329
|
|
|
|
|
|
|
U64(0xDA7F5BF5, 0x90966848), U64(0xAF39A475, 0x506A899E), /* ~= 10^-243 */ |
|
1330
|
|
|
|
|
|
|
U64(0x888F9979, 0x7A5E012D), U64(0x6D8406C9, 0x52429603), /* ~= 10^-242 */ |
|
1331
|
|
|
|
|
|
|
U64(0xAAB37FD7, 0xD8F58178), U64(0xC8E5087B, 0xA6D33B83), /* ~= 10^-241 */ |
|
1332
|
|
|
|
|
|
|
U64(0xD5605FCD, 0xCF32E1D6), U64(0xFB1E4A9A, 0x90880A64), /* ~= 10^-240 */ |
|
1333
|
|
|
|
|
|
|
U64(0x855C3BE0, 0xA17FCD26), U64(0x5CF2EEA0, 0x9A55067F), /* ~= 10^-239 */ |
|
1334
|
|
|
|
|
|
|
U64(0xA6B34AD8, 0xC9DFC06F), U64(0xF42FAA48, 0xC0EA481E), /* ~= 10^-238 */ |
|
1335
|
|
|
|
|
|
|
U64(0xD0601D8E, 0xFC57B08B), U64(0xF13B94DA, 0xF124DA26), /* ~= 10^-237 */ |
|
1336
|
|
|
|
|
|
|
U64(0x823C1279, 0x5DB6CE57), U64(0x76C53D08, 0xD6B70858), /* ~= 10^-236 */ |
|
1337
|
|
|
|
|
|
|
U64(0xA2CB1717, 0xB52481ED), U64(0x54768C4B, 0x0C64CA6E), /* ~= 10^-235 */ |
|
1338
|
|
|
|
|
|
|
U64(0xCB7DDCDD, 0xA26DA268), U64(0xA9942F5D, 0xCF7DFD09), /* ~= 10^-234 */ |
|
1339
|
|
|
|
|
|
|
U64(0xFE5D5415, 0x0B090B02), U64(0xD3F93B35, 0x435D7C4C), /* ~= 10^-233 */ |
|
1340
|
|
|
|
|
|
|
U64(0x9EFA548D, 0x26E5A6E1), U64(0xC47BC501, 0x4A1A6DAF), /* ~= 10^-232 */ |
|
1341
|
|
|
|
|
|
|
U64(0xC6B8E9B0, 0x709F109A), U64(0x359AB641, 0x9CA1091B), /* ~= 10^-231 */ |
|
1342
|
|
|
|
|
|
|
U64(0xF867241C, 0x8CC6D4C0), U64(0xC30163D2, 0x03C94B62), /* ~= 10^-230 */ |
|
1343
|
|
|
|
|
|
|
U64(0x9B407691, 0xD7FC44F8), U64(0x79E0DE63, 0x425DCF1D), /* ~= 10^-229 */ |
|
1344
|
|
|
|
|
|
|
U64(0xC2109436, 0x4DFB5636), U64(0x985915FC, 0x12F542E4), /* ~= 10^-228 */ |
|
1345
|
|
|
|
|
|
|
U64(0xF294B943, 0xE17A2BC4), U64(0x3E6F5B7B, 0x17B2939D), /* ~= 10^-227 */ |
|
1346
|
|
|
|
|
|
|
U64(0x979CF3CA, 0x6CEC5B5A), U64(0xA705992C, 0xEECF9C42), /* ~= 10^-226 */ |
|
1347
|
|
|
|
|
|
|
U64(0xBD8430BD, 0x08277231), U64(0x50C6FF78, 0x2A838353), /* ~= 10^-225 */ |
|
1348
|
|
|
|
|
|
|
U64(0xECE53CEC, 0x4A314EBD), U64(0xA4F8BF56, 0x35246428), /* ~= 10^-224 */ |
|
1349
|
|
|
|
|
|
|
U64(0x940F4613, 0xAE5ED136), U64(0x871B7795, 0xE136BE99), /* ~= 10^-223 */ |
|
1350
|
|
|
|
|
|
|
U64(0xB9131798, 0x99F68584), U64(0x28E2557B, 0x59846E3F), /* ~= 10^-222 */ |
|
1351
|
|
|
|
|
|
|
U64(0xE757DD7E, 0xC07426E5), U64(0x331AEADA, 0x2FE589CF), /* ~= 10^-221 */ |
|
1352
|
|
|
|
|
|
|
U64(0x9096EA6F, 0x3848984F), U64(0x3FF0D2C8, 0x5DEF7621), /* ~= 10^-220 */ |
|
1353
|
|
|
|
|
|
|
U64(0xB4BCA50B, 0x065ABE63), U64(0x0FED077A, 0x756B53A9), /* ~= 10^-219 */ |
|
1354
|
|
|
|
|
|
|
U64(0xE1EBCE4D, 0xC7F16DFB), U64(0xD3E84959, 0x12C62894), /* ~= 10^-218 */ |
|
1355
|
|
|
|
|
|
|
U64(0x8D3360F0, 0x9CF6E4BD), U64(0x64712DD7, 0xABBBD95C), /* ~= 10^-217 */ |
|
1356
|
|
|
|
|
|
|
U64(0xB080392C, 0xC4349DEC), U64(0xBD8D794D, 0x96AACFB3), /* ~= 10^-216 */ |
|
1357
|
|
|
|
|
|
|
U64(0xDCA04777, 0xF541C567), U64(0xECF0D7A0, 0xFC5583A0), /* ~= 10^-215 */ |
|
1358
|
|
|
|
|
|
|
U64(0x89E42CAA, 0xF9491B60), U64(0xF41686C4, 0x9DB57244), /* ~= 10^-214 */ |
|
1359
|
|
|
|
|
|
|
U64(0xAC5D37D5, 0xB79B6239), U64(0x311C2875, 0xC522CED5), /* ~= 10^-213 */ |
|
1360
|
|
|
|
|
|
|
U64(0xD77485CB, 0x25823AC7), U64(0x7D633293, 0x366B828B), /* ~= 10^-212 */ |
|
1361
|
|
|
|
|
|
|
U64(0x86A8D39E, 0xF77164BC), U64(0xAE5DFF9C, 0x02033197), /* ~= 10^-211 */ |
|
1362
|
|
|
|
|
|
|
U64(0xA8530886, 0xB54DBDEB), U64(0xD9F57F83, 0x0283FDFC), /* ~= 10^-210 */ |
|
1363
|
|
|
|
|
|
|
U64(0xD267CAA8, 0x62A12D66), U64(0xD072DF63, 0xC324FD7B), /* ~= 10^-209 */ |
|
1364
|
|
|
|
|
|
|
U64(0x8380DEA9, 0x3DA4BC60), U64(0x4247CB9E, 0x59F71E6D), /* ~= 10^-208 */ |
|
1365
|
|
|
|
|
|
|
U64(0xA4611653, 0x8D0DEB78), U64(0x52D9BE85, 0xF074E608), /* ~= 10^-207 */ |
|
1366
|
|
|
|
|
|
|
U64(0xCD795BE8, 0x70516656), U64(0x67902E27, 0x6C921F8B), /* ~= 10^-206 */ |
|
1367
|
|
|
|
|
|
|
U64(0x806BD971, 0x4632DFF6), U64(0x00BA1CD8, 0xA3DB53B6), /* ~= 10^-205 */ |
|
1368
|
|
|
|
|
|
|
U64(0xA086CFCD, 0x97BF97F3), U64(0x80E8A40E, 0xCCD228A4), /* ~= 10^-204 */ |
|
1369
|
|
|
|
|
|
|
U64(0xC8A883C0, 0xFDAF7DF0), U64(0x6122CD12, 0x8006B2CD), /* ~= 10^-203 */ |
|
1370
|
|
|
|
|
|
|
U64(0xFAD2A4B1, 0x3D1B5D6C), U64(0x796B8057, 0x20085F81), /* ~= 10^-202 */ |
|
1371
|
|
|
|
|
|
|
U64(0x9CC3A6EE, 0xC6311A63), U64(0xCBE33036, 0x74053BB0), /* ~= 10^-201 */ |
|
1372
|
|
|
|
|
|
|
U64(0xC3F490AA, 0x77BD60FC), U64(0xBEDBFC44, 0x11068A9C), /* ~= 10^-200 */ |
|
1373
|
|
|
|
|
|
|
U64(0xF4F1B4D5, 0x15ACB93B), U64(0xEE92FB55, 0x15482D44), /* ~= 10^-199 */ |
|
1374
|
|
|
|
|
|
|
U64(0x99171105, 0x2D8BF3C5), U64(0x751BDD15, 0x2D4D1C4A), /* ~= 10^-198 */ |
|
1375
|
|
|
|
|
|
|
U64(0xBF5CD546, 0x78EEF0B6), U64(0xD262D45A, 0x78A0635D), /* ~= 10^-197 */ |
|
1376
|
|
|
|
|
|
|
U64(0xEF340A98, 0x172AACE4), U64(0x86FB8971, 0x16C87C34), /* ~= 10^-196 */ |
|
1377
|
|
|
|
|
|
|
U64(0x9580869F, 0x0E7AAC0E), U64(0xD45D35E6, 0xAE3D4DA0), /* ~= 10^-195 */ |
|
1378
|
|
|
|
|
|
|
U64(0xBAE0A846, 0xD2195712), U64(0x89748360, 0x59CCA109), /* ~= 10^-194 */ |
|
1379
|
|
|
|
|
|
|
U64(0xE998D258, 0x869FACD7), U64(0x2BD1A438, 0x703FC94B), /* ~= 10^-193 */ |
|
1380
|
|
|
|
|
|
|
U64(0x91FF8377, 0x5423CC06), U64(0x7B6306A3, 0x4627DDCF), /* ~= 10^-192 */ |
|
1381
|
|
|
|
|
|
|
U64(0xB67F6455, 0x292CBF08), U64(0x1A3BC84C, 0x17B1D542), /* ~= 10^-191 */ |
|
1382
|
|
|
|
|
|
|
U64(0xE41F3D6A, 0x7377EECA), U64(0x20CABA5F, 0x1D9E4A93), /* ~= 10^-190 */ |
|
1383
|
|
|
|
|
|
|
U64(0x8E938662, 0x882AF53E), U64(0x547EB47B, 0x7282EE9C), /* ~= 10^-189 */ |
|
1384
|
|
|
|
|
|
|
U64(0xB23867FB, 0x2A35B28D), U64(0xE99E619A, 0x4F23AA43), /* ~= 10^-188 */ |
|
1385
|
|
|
|
|
|
|
U64(0xDEC681F9, 0xF4C31F31), U64(0x6405FA00, 0xE2EC94D4), /* ~= 10^-187 */ |
|
1386
|
|
|
|
|
|
|
U64(0x8B3C113C, 0x38F9F37E), U64(0xDE83BC40, 0x8DD3DD04), /* ~= 10^-186 */ |
|
1387
|
|
|
|
|
|
|
U64(0xAE0B158B, 0x4738705E), U64(0x9624AB50, 0xB148D445), /* ~= 10^-185 */ |
|
1388
|
|
|
|
|
|
|
U64(0xD98DDAEE, 0x19068C76), U64(0x3BADD624, 0xDD9B0957), /* ~= 10^-184 */ |
|
1389
|
|
|
|
|
|
|
U64(0x87F8A8D4, 0xCFA417C9), U64(0xE54CA5D7, 0x0A80E5D6), /* ~= 10^-183 */ |
|
1390
|
|
|
|
|
|
|
U64(0xA9F6D30A, 0x038D1DBC), U64(0x5E9FCF4C, 0xCD211F4C), /* ~= 10^-182 */ |
|
1391
|
|
|
|
|
|
|
U64(0xD47487CC, 0x8470652B), U64(0x7647C320, 0x0069671F), /* ~= 10^-181 */ |
|
1392
|
|
|
|
|
|
|
U64(0x84C8D4DF, 0xD2C63F3B), U64(0x29ECD9F4, 0x0041E073), /* ~= 10^-180 */ |
|
1393
|
|
|
|
|
|
|
U64(0xA5FB0A17, 0xC777CF09), U64(0xF4681071, 0x00525890), /* ~= 10^-179 */ |
|
1394
|
|
|
|
|
|
|
U64(0xCF79CC9D, 0xB955C2CC), U64(0x7182148D, 0x4066EEB4), /* ~= 10^-178 */ |
|
1395
|
|
|
|
|
|
|
U64(0x81AC1FE2, 0x93D599BF), U64(0xC6F14CD8, 0x48405530), /* ~= 10^-177 */ |
|
1396
|
|
|
|
|
|
|
U64(0xA21727DB, 0x38CB002F), U64(0xB8ADA00E, 0x5A506A7C), /* ~= 10^-176 */ |
|
1397
|
|
|
|
|
|
|
U64(0xCA9CF1D2, 0x06FDC03B), U64(0xA6D90811, 0xF0E4851C), /* ~= 10^-175 */ |
|
1398
|
|
|
|
|
|
|
U64(0xFD442E46, 0x88BD304A), U64(0x908F4A16, 0x6D1DA663), /* ~= 10^-174 */ |
|
1399
|
|
|
|
|
|
|
U64(0x9E4A9CEC, 0x15763E2E), U64(0x9A598E4E, 0x043287FE), /* ~= 10^-173 */ |
|
1400
|
|
|
|
|
|
|
U64(0xC5DD4427, 0x1AD3CDBA), U64(0x40EFF1E1, 0x853F29FD), /* ~= 10^-172 */ |
|
1401
|
|
|
|
|
|
|
U64(0xF7549530, 0xE188C128), U64(0xD12BEE59, 0xE68EF47C), /* ~= 10^-171 */ |
|
1402
|
|
|
|
|
|
|
U64(0x9A94DD3E, 0x8CF578B9), U64(0x82BB74F8, 0x301958CE), /* ~= 10^-170 */ |
|
1403
|
|
|
|
|
|
|
U64(0xC13A148E, 0x3032D6E7), U64(0xE36A5236, 0x3C1FAF01), /* ~= 10^-169 */ |
|
1404
|
|
|
|
|
|
|
U64(0xF18899B1, 0xBC3F8CA1), U64(0xDC44E6C3, 0xCB279AC1), /* ~= 10^-168 */ |
|
1405
|
|
|
|
|
|
|
U64(0x96F5600F, 0x15A7B7E5), U64(0x29AB103A, 0x5EF8C0B9), /* ~= 10^-167 */ |
|
1406
|
|
|
|
|
|
|
U64(0xBCB2B812, 0xDB11A5DE), U64(0x7415D448, 0xF6B6F0E7), /* ~= 10^-166 */ |
|
1407
|
|
|
|
|
|
|
U64(0xEBDF6617, 0x91D60F56), U64(0x111B495B, 0x3464AD21), /* ~= 10^-165 */ |
|
1408
|
|
|
|
|
|
|
U64(0x936B9FCE, 0xBB25C995), U64(0xCAB10DD9, 0x00BEEC34), /* ~= 10^-164 */ |
|
1409
|
|
|
|
|
|
|
U64(0xB84687C2, 0x69EF3BFB), U64(0x3D5D514F, 0x40EEA742), /* ~= 10^-163 */ |
|
1410
|
|
|
|
|
|
|
U64(0xE65829B3, 0x046B0AFA), U64(0x0CB4A5A3, 0x112A5112), /* ~= 10^-162 */ |
|
1411
|
|
|
|
|
|
|
U64(0x8FF71A0F, 0xE2C2E6DC), U64(0x47F0E785, 0xEABA72AB), /* ~= 10^-161 */ |
|
1412
|
|
|
|
|
|
|
U64(0xB3F4E093, 0xDB73A093), U64(0x59ED2167, 0x65690F56), /* ~= 10^-160 */ |
|
1413
|
|
|
|
|
|
|
U64(0xE0F218B8, 0xD25088B8), U64(0x306869C1, 0x3EC3532C), /* ~= 10^-159 */ |
|
1414
|
|
|
|
|
|
|
U64(0x8C974F73, 0x83725573), U64(0x1E414218, 0xC73A13FB), /* ~= 10^-158 */ |
|
1415
|
|
|
|
|
|
|
U64(0xAFBD2350, 0x644EEACF), U64(0xE5D1929E, 0xF90898FA), /* ~= 10^-157 */ |
|
1416
|
|
|
|
|
|
|
U64(0xDBAC6C24, 0x7D62A583), U64(0xDF45F746, 0xB74ABF39), /* ~= 10^-156 */ |
|
1417
|
|
|
|
|
|
|
U64(0x894BC396, 0xCE5DA772), U64(0x6B8BBA8C, 0x328EB783), /* ~= 10^-155 */ |
|
1418
|
|
|
|
|
|
|
U64(0xAB9EB47C, 0x81F5114F), U64(0x066EA92F, 0x3F326564), /* ~= 10^-154 */ |
|
1419
|
|
|
|
|
|
|
U64(0xD686619B, 0xA27255A2), U64(0xC80A537B, 0x0EFEFEBD), /* ~= 10^-153 */ |
|
1420
|
|
|
|
|
|
|
U64(0x8613FD01, 0x45877585), U64(0xBD06742C, 0xE95F5F36), /* ~= 10^-152 */ |
|
1421
|
|
|
|
|
|
|
U64(0xA798FC41, 0x96E952E7), U64(0x2C481138, 0x23B73704), /* ~= 10^-151 */ |
|
1422
|
|
|
|
|
|
|
U64(0xD17F3B51, 0xFCA3A7A0), U64(0xF75A1586, 0x2CA504C5), /* ~= 10^-150 */ |
|
1423
|
|
|
|
|
|
|
U64(0x82EF8513, 0x3DE648C4), U64(0x9A984D73, 0xDBE722FB), /* ~= 10^-149 */ |
|
1424
|
|
|
|
|
|
|
U64(0xA3AB6658, 0x0D5FDAF5), U64(0xC13E60D0, 0xD2E0EBBA), /* ~= 10^-148 */ |
|
1425
|
|
|
|
|
|
|
U64(0xCC963FEE, 0x10B7D1B3), U64(0x318DF905, 0x079926A8), /* ~= 10^-147 */ |
|
1426
|
|
|
|
|
|
|
U64(0xFFBBCFE9, 0x94E5C61F), U64(0xFDF17746, 0x497F7052), /* ~= 10^-146 */ |
|
1427
|
|
|
|
|
|
|
U64(0x9FD561F1, 0xFD0F9BD3), U64(0xFEB6EA8B, 0xEDEFA633), /* ~= 10^-145 */ |
|
1428
|
|
|
|
|
|
|
U64(0xC7CABA6E, 0x7C5382C8), U64(0xFE64A52E, 0xE96B8FC0), /* ~= 10^-144 */ |
|
1429
|
|
|
|
|
|
|
U64(0xF9BD690A, 0x1B68637B), U64(0x3DFDCE7A, 0xA3C673B0), /* ~= 10^-143 */ |
|
1430
|
|
|
|
|
|
|
U64(0x9C1661A6, 0x51213E2D), U64(0x06BEA10C, 0xA65C084E), /* ~= 10^-142 */ |
|
1431
|
|
|
|
|
|
|
U64(0xC31BFA0F, 0xE5698DB8), U64(0x486E494F, 0xCFF30A62), /* ~= 10^-141 */ |
|
1432
|
|
|
|
|
|
|
U64(0xF3E2F893, 0xDEC3F126), U64(0x5A89DBA3, 0xC3EFCCFA), /* ~= 10^-140 */ |
|
1433
|
|
|
|
|
|
|
U64(0x986DDB5C, 0x6B3A76B7), U64(0xF8962946, 0x5A75E01C), /* ~= 10^-139 */ |
|
1434
|
|
|
|
|
|
|
U64(0xBE895233, 0x86091465), U64(0xF6BBB397, 0xF1135823), /* ~= 10^-138 */ |
|
1435
|
|
|
|
|
|
|
U64(0xEE2BA6C0, 0x678B597F), U64(0x746AA07D, 0xED582E2C), /* ~= 10^-137 */ |
|
1436
|
|
|
|
|
|
|
U64(0x94DB4838, 0x40B717EF), U64(0xA8C2A44E, 0xB4571CDC), /* ~= 10^-136 */ |
|
1437
|
|
|
|
|
|
|
U64(0xBA121A46, 0x50E4DDEB), U64(0x92F34D62, 0x616CE413), /* ~= 10^-135 */ |
|
1438
|
|
|
|
|
|
|
U64(0xE896A0D7, 0xE51E1566), U64(0x77B020BA, 0xF9C81D17), /* ~= 10^-134 */ |
|
1439
|
|
|
|
|
|
|
U64(0x915E2486, 0xEF32CD60), U64(0x0ACE1474, 0xDC1D122E), /* ~= 10^-133 */ |
|
1440
|
|
|
|
|
|
|
U64(0xB5B5ADA8, 0xAAFF80B8), U64(0x0D819992, 0x132456BA), /* ~= 10^-132 */ |
|
1441
|
|
|
|
|
|
|
U64(0xE3231912, 0xD5BF60E6), U64(0x10E1FFF6, 0x97ED6C69), /* ~= 10^-131 */ |
|
1442
|
|
|
|
|
|
|
U64(0x8DF5EFAB, 0xC5979C8F), U64(0xCA8D3FFA, 0x1EF463C1), /* ~= 10^-130 */ |
|
1443
|
|
|
|
|
|
|
U64(0xB1736B96, 0xB6FD83B3), U64(0xBD308FF8, 0xA6B17CB2), /* ~= 10^-129 */ |
|
1444
|
|
|
|
|
|
|
U64(0xDDD0467C, 0x64BCE4A0), U64(0xAC7CB3F6, 0xD05DDBDE), /* ~= 10^-128 */ |
|
1445
|
|
|
|
|
|
|
U64(0x8AA22C0D, 0xBEF60EE4), U64(0x6BCDF07A, 0x423AA96B), /* ~= 10^-127 */ |
|
1446
|
|
|
|
|
|
|
U64(0xAD4AB711, 0x2EB3929D), U64(0x86C16C98, 0xD2C953C6), /* ~= 10^-126 */ |
|
1447
|
|
|
|
|
|
|
U64(0xD89D64D5, 0x7A607744), U64(0xE871C7BF, 0x077BA8B7), /* ~= 10^-125 */ |
|
1448
|
|
|
|
|
|
|
U64(0x87625F05, 0x6C7C4A8B), U64(0x11471CD7, 0x64AD4972), /* ~= 10^-124 */ |
|
1449
|
|
|
|
|
|
|
U64(0xA93AF6C6, 0xC79B5D2D), U64(0xD598E40D, 0x3DD89BCF), /* ~= 10^-123 */ |
|
1450
|
|
|
|
|
|
|
U64(0xD389B478, 0x79823479), U64(0x4AFF1D10, 0x8D4EC2C3), /* ~= 10^-122 */ |
|
1451
|
|
|
|
|
|
|
U64(0x843610CB, 0x4BF160CB), U64(0xCEDF722A, 0x585139BA), /* ~= 10^-121 */ |
|
1452
|
|
|
|
|
|
|
U64(0xA54394FE, 0x1EEDB8FE), U64(0xC2974EB4, 0xEE658828), /* ~= 10^-120 */ |
|
1453
|
|
|
|
|
|
|
U64(0xCE947A3D, 0xA6A9273E), U64(0x733D2262, 0x29FEEA32), /* ~= 10^-119 */ |
|
1454
|
|
|
|
|
|
|
U64(0x811CCC66, 0x8829B887), U64(0x0806357D, 0x5A3F525F), /* ~= 10^-118 */ |
|
1455
|
|
|
|
|
|
|
U64(0xA163FF80, 0x2A3426A8), U64(0xCA07C2DC, 0xB0CF26F7), /* ~= 10^-117 */ |
|
1456
|
|
|
|
|
|
|
U64(0xC9BCFF60, 0x34C13052), U64(0xFC89B393, 0xDD02F0B5), /* ~= 10^-116 */ |
|
1457
|
|
|
|
|
|
|
U64(0xFC2C3F38, 0x41F17C67), U64(0xBBAC2078, 0xD443ACE2), /* ~= 10^-115 */ |
|
1458
|
|
|
|
|
|
|
U64(0x9D9BA783, 0x2936EDC0), U64(0xD54B944B, 0x84AA4C0D), /* ~= 10^-114 */ |
|
1459
|
|
|
|
|
|
|
U64(0xC5029163, 0xF384A931), U64(0x0A9E795E, 0x65D4DF11), /* ~= 10^-113 */ |
|
1460
|
|
|
|
|
|
|
U64(0xF64335BC, 0xF065D37D), U64(0x4D4617B5, 0xFF4A16D5), /* ~= 10^-112 */ |
|
1461
|
|
|
|
|
|
|
U64(0x99EA0196, 0x163FA42E), U64(0x504BCED1, 0xBF8E4E45), /* ~= 10^-111 */ |
|
1462
|
|
|
|
|
|
|
U64(0xC06481FB, 0x9BCF8D39), U64(0xE45EC286, 0x2F71E1D6), /* ~= 10^-110 */ |
|
1463
|
|
|
|
|
|
|
U64(0xF07DA27A, 0x82C37088), U64(0x5D767327, 0xBB4E5A4C), /* ~= 10^-109 */ |
|
1464
|
|
|
|
|
|
|
U64(0x964E858C, 0x91BA2655), U64(0x3A6A07F8, 0xD510F86F), /* ~= 10^-108 */ |
|
1465
|
|
|
|
|
|
|
U64(0xBBE226EF, 0xB628AFEA), U64(0x890489F7, 0x0A55368B), /* ~= 10^-107 */ |
|
1466
|
|
|
|
|
|
|
U64(0xEADAB0AB, 0xA3B2DBE5), U64(0x2B45AC74, 0xCCEA842E), /* ~= 10^-106 */ |
|
1467
|
|
|
|
|
|
|
U64(0x92C8AE6B, 0x464FC96F), U64(0x3B0B8BC9, 0x0012929D), /* ~= 10^-105 */ |
|
1468
|
|
|
|
|
|
|
U64(0xB77ADA06, 0x17E3BBCB), U64(0x09CE6EBB, 0x40173744), /* ~= 10^-104 */ |
|
1469
|
|
|
|
|
|
|
U64(0xE5599087, 0x9DDCAABD), U64(0xCC420A6A, 0x101D0515), /* ~= 10^-103 */ |
|
1470
|
|
|
|
|
|
|
U64(0x8F57FA54, 0xC2A9EAB6), U64(0x9FA94682, 0x4A12232D), /* ~= 10^-102 */ |
|
1471
|
|
|
|
|
|
|
U64(0xB32DF8E9, 0xF3546564), U64(0x47939822, 0xDC96ABF9), /* ~= 10^-101 */ |
|
1472
|
|
|
|
|
|
|
U64(0xDFF97724, 0x70297EBD), U64(0x59787E2B, 0x93BC56F7), /* ~= 10^-100 */ |
|
1473
|
|
|
|
|
|
|
U64(0x8BFBEA76, 0xC619EF36), U64(0x57EB4EDB, 0x3C55B65A), /* ~= 10^-99 */ |
|
1474
|
|
|
|
|
|
|
U64(0xAEFAE514, 0x77A06B03), U64(0xEDE62292, 0x0B6B23F1), /* ~= 10^-98 */ |
|
1475
|
|
|
|
|
|
|
U64(0xDAB99E59, 0x958885C4), U64(0xE95FAB36, 0x8E45ECED), /* ~= 10^-97 */ |
|
1476
|
|
|
|
|
|
|
U64(0x88B402F7, 0xFD75539B), U64(0x11DBCB02, 0x18EBB414), /* ~= 10^-96 */ |
|
1477
|
|
|
|
|
|
|
U64(0xAAE103B5, 0xFCD2A881), U64(0xD652BDC2, 0x9F26A119), /* ~= 10^-95 */ |
|
1478
|
|
|
|
|
|
|
U64(0xD59944A3, 0x7C0752A2), U64(0x4BE76D33, 0x46F0495F), /* ~= 10^-94 */ |
|
1479
|
|
|
|
|
|
|
U64(0x857FCAE6, 0x2D8493A5), U64(0x6F70A440, 0x0C562DDB), /* ~= 10^-93 */ |
|
1480
|
|
|
|
|
|
|
U64(0xA6DFBD9F, 0xB8E5B88E), U64(0xCB4CCD50, 0x0F6BB952), /* ~= 10^-92 */ |
|
1481
|
|
|
|
|
|
|
U64(0xD097AD07, 0xA71F26B2), U64(0x7E2000A4, 0x1346A7A7), /* ~= 10^-91 */ |
|
1482
|
|
|
|
|
|
|
U64(0x825ECC24, 0xC873782F), U64(0x8ED40066, 0x8C0C28C8), /* ~= 10^-90 */ |
|
1483
|
|
|
|
|
|
|
U64(0xA2F67F2D, 0xFA90563B), U64(0x72890080, 0x2F0F32FA), /* ~= 10^-89 */ |
|
1484
|
|
|
|
|
|
|
U64(0xCBB41EF9, 0x79346BCA), U64(0x4F2B40A0, 0x3AD2FFB9), /* ~= 10^-88 */ |
|
1485
|
|
|
|
|
|
|
U64(0xFEA126B7, 0xD78186BC), U64(0xE2F610C8, 0x4987BFA8), /* ~= 10^-87 */ |
|
1486
|
|
|
|
|
|
|
U64(0x9F24B832, 0xE6B0F436), U64(0x0DD9CA7D, 0x2DF4D7C9), /* ~= 10^-86 */ |
|
1487
|
|
|
|
|
|
|
U64(0xC6EDE63F, 0xA05D3143), U64(0x91503D1C, 0x79720DBB), /* ~= 10^-85 */ |
|
1488
|
|
|
|
|
|
|
U64(0xF8A95FCF, 0x88747D94), U64(0x75A44C63, 0x97CE912A), /* ~= 10^-84 */ |
|
1489
|
|
|
|
|
|
|
U64(0x9B69DBE1, 0xB548CE7C), U64(0xC986AFBE, 0x3EE11ABA), /* ~= 10^-83 */ |
|
1490
|
|
|
|
|
|
|
U64(0xC24452DA, 0x229B021B), U64(0xFBE85BAD, 0xCE996168), /* ~= 10^-82 */ |
|
1491
|
|
|
|
|
|
|
U64(0xF2D56790, 0xAB41C2A2), U64(0xFAE27299, 0x423FB9C3), /* ~= 10^-81 */ |
|
1492
|
|
|
|
|
|
|
U64(0x97C560BA, 0x6B0919A5), U64(0xDCCD879F, 0xC967D41A), /* ~= 10^-80 */ |
|
1493
|
|
|
|
|
|
|
U64(0xBDB6B8E9, 0x05CB600F), U64(0x5400E987, 0xBBC1C920), /* ~= 10^-79 */ |
|
1494
|
|
|
|
|
|
|
U64(0xED246723, 0x473E3813), U64(0x290123E9, 0xAAB23B68), /* ~= 10^-78 */ |
|
1495
|
|
|
|
|
|
|
U64(0x9436C076, 0x0C86E30B), U64(0xF9A0B672, 0x0AAF6521), /* ~= 10^-77 */ |
|
1496
|
|
|
|
|
|
|
U64(0xB9447093, 0x8FA89BCE), U64(0xF808E40E, 0x8D5B3E69), /* ~= 10^-76 */ |
|
1497
|
|
|
|
|
|
|
U64(0xE7958CB8, 0x7392C2C2), U64(0xB60B1D12, 0x30B20E04), /* ~= 10^-75 */ |
|
1498
|
|
|
|
|
|
|
U64(0x90BD77F3, 0x483BB9B9), U64(0xB1C6F22B, 0x5E6F48C2), /* ~= 10^-74 */ |
|
1499
|
|
|
|
|
|
|
U64(0xB4ECD5F0, 0x1A4AA828), U64(0x1E38AEB6, 0x360B1AF3), /* ~= 10^-73 */ |
|
1500
|
|
|
|
|
|
|
U64(0xE2280B6C, 0x20DD5232), U64(0x25C6DA63, 0xC38DE1B0), /* ~= 10^-72 */ |
|
1501
|
|
|
|
|
|
|
U64(0x8D590723, 0x948A535F), U64(0x579C487E, 0x5A38AD0E), /* ~= 10^-71 */ |
|
1502
|
|
|
|
|
|
|
U64(0xB0AF48EC, 0x79ACE837), U64(0x2D835A9D, 0xF0C6D851), /* ~= 10^-70 */ |
|
1503
|
|
|
|
|
|
|
U64(0xDCDB1B27, 0x98182244), U64(0xF8E43145, 0x6CF88E65), /* ~= 10^-69 */ |
|
1504
|
|
|
|
|
|
|
U64(0x8A08F0F8, 0xBF0F156B), U64(0x1B8E9ECB, 0x641B58FF), /* ~= 10^-68 */ |
|
1505
|
|
|
|
|
|
|
U64(0xAC8B2D36, 0xEED2DAC5), U64(0xE272467E, 0x3D222F3F), /* ~= 10^-67 */ |
|
1506
|
|
|
|
|
|
|
U64(0xD7ADF884, 0xAA879177), U64(0x5B0ED81D, 0xCC6ABB0F), /* ~= 10^-66 */ |
|
1507
|
|
|
|
|
|
|
U64(0x86CCBB52, 0xEA94BAEA), U64(0x98E94712, 0x9FC2B4E9), /* ~= 10^-65 */ |
|
1508
|
|
|
|
|
|
|
U64(0xA87FEA27, 0xA539E9A5), U64(0x3F2398D7, 0x47B36224), /* ~= 10^-64 */ |
|
1509
|
|
|
|
|
|
|
U64(0xD29FE4B1, 0x8E88640E), U64(0x8EEC7F0D, 0x19A03AAD), /* ~= 10^-63 */ |
|
1510
|
|
|
|
|
|
|
U64(0x83A3EEEE, 0xF9153E89), U64(0x1953CF68, 0x300424AC), /* ~= 10^-62 */ |
|
1511
|
|
|
|
|
|
|
U64(0xA48CEAAA, 0xB75A8E2B), U64(0x5FA8C342, 0x3C052DD7), /* ~= 10^-61 */ |
|
1512
|
|
|
|
|
|
|
U64(0xCDB02555, 0x653131B6), U64(0x3792F412, 0xCB06794D), /* ~= 10^-60 */ |
|
1513
|
|
|
|
|
|
|
U64(0x808E1755, 0x5F3EBF11), U64(0xE2BBD88B, 0xBEE40BD0), /* ~= 10^-59 */ |
|
1514
|
|
|
|
|
|
|
U64(0xA0B19D2A, 0xB70E6ED6), U64(0x5B6ACEAE, 0xAE9D0EC4), /* ~= 10^-58 */ |
|
1515
|
|
|
|
|
|
|
U64(0xC8DE0475, 0x64D20A8B), U64(0xF245825A, 0x5A445275), /* ~= 10^-57 */ |
|
1516
|
|
|
|
|
|
|
U64(0xFB158592, 0xBE068D2E), U64(0xEED6E2F0, 0xF0D56712), /* ~= 10^-56 */ |
|
1517
|
|
|
|
|
|
|
U64(0x9CED737B, 0xB6C4183D), U64(0x55464DD6, 0x9685606B), /* ~= 10^-55 */ |
|
1518
|
|
|
|
|
|
|
U64(0xC428D05A, 0xA4751E4C), U64(0xAA97E14C, 0x3C26B886), /* ~= 10^-54 */ |
|
1519
|
|
|
|
|
|
|
U64(0xF5330471, 0x4D9265DF), U64(0xD53DD99F, 0x4B3066A8), /* ~= 10^-53 */ |
|
1520
|
|
|
|
|
|
|
U64(0x993FE2C6, 0xD07B7FAB), U64(0xE546A803, 0x8EFE4029), /* ~= 10^-52 */ |
|
1521
|
|
|
|
|
|
|
U64(0xBF8FDB78, 0x849A5F96), U64(0xDE985204, 0x72BDD033), /* ~= 10^-51 */ |
|
1522
|
|
|
|
|
|
|
U64(0xEF73D256, 0xA5C0F77C), U64(0x963E6685, 0x8F6D4440), /* ~= 10^-50 */ |
|
1523
|
|
|
|
|
|
|
U64(0x95A86376, 0x27989AAD), U64(0xDDE70013, 0x79A44AA8), /* ~= 10^-49 */ |
|
1524
|
|
|
|
|
|
|
U64(0xBB127C53, 0xB17EC159), U64(0x5560C018, 0x580D5D52), /* ~= 10^-48 */ |
|
1525
|
|
|
|
|
|
|
U64(0xE9D71B68, 0x9DDE71AF), U64(0xAAB8F01E, 0x6E10B4A6), /* ~= 10^-47 */ |
|
1526
|
|
|
|
|
|
|
U64(0x92267121, 0x62AB070D), U64(0xCAB39613, 0x04CA70E8), /* ~= 10^-46 */ |
|
1527
|
|
|
|
|
|
|
U64(0xB6B00D69, 0xBB55C8D1), U64(0x3D607B97, 0xC5FD0D22), /* ~= 10^-45 */ |
|
1528
|
|
|
|
|
|
|
U64(0xE45C10C4, 0x2A2B3B05), U64(0x8CB89A7D, 0xB77C506A), /* ~= 10^-44 */ |
|
1529
|
|
|
|
|
|
|
U64(0x8EB98A7A, 0x9A5B04E3), U64(0x77F3608E, 0x92ADB242), /* ~= 10^-43 */ |
|
1530
|
|
|
|
|
|
|
U64(0xB267ED19, 0x40F1C61C), U64(0x55F038B2, 0x37591ED3), /* ~= 10^-42 */ |
|
1531
|
|
|
|
|
|
|
U64(0xDF01E85F, 0x912E37A3), U64(0x6B6C46DE, 0xC52F6688), /* ~= 10^-41 */ |
|
1532
|
|
|
|
|
|
|
U64(0x8B61313B, 0xBABCE2C6), U64(0x2323AC4B, 0x3B3DA015), /* ~= 10^-40 */ |
|
1533
|
|
|
|
|
|
|
U64(0xAE397D8A, 0xA96C1B77), U64(0xABEC975E, 0x0A0D081A), /* ~= 10^-39 */ |
|
1534
|
|
|
|
|
|
|
U64(0xD9C7DCED, 0x53C72255), U64(0x96E7BD35, 0x8C904A21), /* ~= 10^-38 */ |
|
1535
|
|
|
|
|
|
|
U64(0x881CEA14, 0x545C7575), U64(0x7E50D641, 0x77DA2E54), /* ~= 10^-37 */ |
|
1536
|
|
|
|
|
|
|
U64(0xAA242499, 0x697392D2), U64(0xDDE50BD1, 0xD5D0B9E9), /* ~= 10^-36 */ |
|
1537
|
|
|
|
|
|
|
U64(0xD4AD2DBF, 0xC3D07787), U64(0x955E4EC6, 0x4B44E864), /* ~= 10^-35 */ |
|
1538
|
|
|
|
|
|
|
U64(0x84EC3C97, 0xDA624AB4), U64(0xBD5AF13B, 0xEF0B113E), /* ~= 10^-34 */ |
|
1539
|
|
|
|
|
|
|
U64(0xA6274BBD, 0xD0FADD61), U64(0xECB1AD8A, 0xEACDD58E), /* ~= 10^-33 */ |
|
1540
|
|
|
|
|
|
|
U64(0xCFB11EAD, 0x453994BA), U64(0x67DE18ED, 0xA5814AF2), /* ~= 10^-32 */ |
|
1541
|
|
|
|
|
|
|
U64(0x81CEB32C, 0x4B43FCF4), U64(0x80EACF94, 0x8770CED7), /* ~= 10^-31 */ |
|
1542
|
|
|
|
|
|
|
U64(0xA2425FF7, 0x5E14FC31), U64(0xA1258379, 0xA94D028D), /* ~= 10^-30 */ |
|
1543
|
|
|
|
|
|
|
U64(0xCAD2F7F5, 0x359A3B3E), U64(0x096EE458, 0x13A04330), /* ~= 10^-29 */ |
|
1544
|
|
|
|
|
|
|
U64(0xFD87B5F2, 0x8300CA0D), U64(0x8BCA9D6E, 0x188853FC), /* ~= 10^-28 */ |
|
1545
|
|
|
|
|
|
|
U64(0x9E74D1B7, 0x91E07E48), U64(0x775EA264, 0xCF55347D), /* ~= 10^-27 */ |
|
1546
|
|
|
|
|
|
|
U64(0xC6120625, 0x76589DDA), U64(0x95364AFE, 0x032A819D), /* ~= 10^-26 */ |
|
1547
|
|
|
|
|
|
|
U64(0xF79687AE, 0xD3EEC551), U64(0x3A83DDBD, 0x83F52204), /* ~= 10^-25 */ |
|
1548
|
|
|
|
|
|
|
U64(0x9ABE14CD, 0x44753B52), U64(0xC4926A96, 0x72793542), /* ~= 10^-24 */ |
|
1549
|
|
|
|
|
|
|
U64(0xC16D9A00, 0x95928A27), U64(0x75B7053C, 0x0F178293), /* ~= 10^-23 */ |
|
1550
|
|
|
|
|
|
|
U64(0xF1C90080, 0xBAF72CB1), U64(0x5324C68B, 0x12DD6338), /* ~= 10^-22 */ |
|
1551
|
|
|
|
|
|
|
U64(0x971DA050, 0x74DA7BEE), U64(0xD3F6FC16, 0xEBCA5E03), /* ~= 10^-21 */ |
|
1552
|
|
|
|
|
|
|
U64(0xBCE50864, 0x92111AEA), U64(0x88F4BB1C, 0xA6BCF584), /* ~= 10^-20 */ |
|
1553
|
|
|
|
|
|
|
U64(0xEC1E4A7D, 0xB69561A5), U64(0x2B31E9E3, 0xD06C32E5), /* ~= 10^-19 */ |
|
1554
|
|
|
|
|
|
|
U64(0x9392EE8E, 0x921D5D07), U64(0x3AFF322E, 0x62439FCF), /* ~= 10^-18 */ |
|
1555
|
|
|
|
|
|
|
U64(0xB877AA32, 0x36A4B449), U64(0x09BEFEB9, 0xFAD487C2), /* ~= 10^-17 */ |
|
1556
|
|
|
|
|
|
|
U64(0xE69594BE, 0xC44DE15B), U64(0x4C2EBE68, 0x7989A9B3), /* ~= 10^-16 */ |
|
1557
|
|
|
|
|
|
|
U64(0x901D7CF7, 0x3AB0ACD9), U64(0x0F9D3701, 0x4BF60A10), /* ~= 10^-15 */ |
|
1558
|
|
|
|
|
|
|
U64(0xB424DC35, 0x095CD80F), U64(0x538484C1, 0x9EF38C94), /* ~= 10^-14 */ |
|
1559
|
|
|
|
|
|
|
U64(0xE12E1342, 0x4BB40E13), U64(0x2865A5F2, 0x06B06FB9), /* ~= 10^-13 */ |
|
1560
|
|
|
|
|
|
|
U64(0x8CBCCC09, 0x6F5088CB), U64(0xF93F87B7, 0x442E45D3), /* ~= 10^-12 */ |
|
1561
|
|
|
|
|
|
|
U64(0xAFEBFF0B, 0xCB24AAFE), U64(0xF78F69A5, 0x1539D748), /* ~= 10^-11 */ |
|
1562
|
|
|
|
|
|
|
U64(0xDBE6FECE, 0xBDEDD5BE), U64(0xB573440E, 0x5A884D1B), /* ~= 10^-10 */ |
|
1563
|
|
|
|
|
|
|
U64(0x89705F41, 0x36B4A597), U64(0x31680A88, 0xF8953030), /* ~= 10^-9 */ |
|
1564
|
|
|
|
|
|
|
U64(0xABCC7711, 0x8461CEFC), U64(0xFDC20D2B, 0x36BA7C3D), /* ~= 10^-8 */ |
|
1565
|
|
|
|
|
|
|
U64(0xD6BF94D5, 0xE57A42BC), U64(0x3D329076, 0x04691B4C), /* ~= 10^-7 */ |
|
1566
|
|
|
|
|
|
|
U64(0x8637BD05, 0xAF6C69B5), U64(0xA63F9A49, 0xC2C1B10F), /* ~= 10^-6 */ |
|
1567
|
|
|
|
|
|
|
U64(0xA7C5AC47, 0x1B478423), U64(0x0FCF80DC, 0x33721D53), /* ~= 10^-5 */ |
|
1568
|
|
|
|
|
|
|
U64(0xD1B71758, 0xE219652B), U64(0xD3C36113, 0x404EA4A8), /* ~= 10^-4 */ |
|
1569
|
|
|
|
|
|
|
U64(0x83126E97, 0x8D4FDF3B), U64(0x645A1CAC, 0x083126E9), /* ~= 10^-3 */ |
|
1570
|
|
|
|
|
|
|
U64(0xA3D70A3D, 0x70A3D70A), U64(0x3D70A3D7, 0x0A3D70A3), /* ~= 10^-2 */ |
|
1571
|
|
|
|
|
|
|
U64(0xCCCCCCCC, 0xCCCCCCCC), U64(0xCCCCCCCC, 0xCCCCCCCC), /* ~= 10^-1 */ |
|
1572
|
|
|
|
|
|
|
U64(0x80000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^0 */ |
|
1573
|
|
|
|
|
|
|
U64(0xA0000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^1 */ |
|
1574
|
|
|
|
|
|
|
U64(0xC8000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^2 */ |
|
1575
|
|
|
|
|
|
|
U64(0xFA000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^3 */ |
|
1576
|
|
|
|
|
|
|
U64(0x9C400000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^4 */ |
|
1577
|
|
|
|
|
|
|
U64(0xC3500000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^5 */ |
|
1578
|
|
|
|
|
|
|
U64(0xF4240000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^6 */ |
|
1579
|
|
|
|
|
|
|
U64(0x98968000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^7 */ |
|
1580
|
|
|
|
|
|
|
U64(0xBEBC2000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^8 */ |
|
1581
|
|
|
|
|
|
|
U64(0xEE6B2800, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^9 */ |
|
1582
|
|
|
|
|
|
|
U64(0x9502F900, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^10 */ |
|
1583
|
|
|
|
|
|
|
U64(0xBA43B740, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^11 */ |
|
1584
|
|
|
|
|
|
|
U64(0xE8D4A510, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^12 */ |
|
1585
|
|
|
|
|
|
|
U64(0x9184E72A, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^13 */ |
|
1586
|
|
|
|
|
|
|
U64(0xB5E620F4, 0x80000000), U64(0x00000000, 0x00000000), /* == 10^14 */ |
|
1587
|
|
|
|
|
|
|
U64(0xE35FA931, 0xA0000000), U64(0x00000000, 0x00000000), /* == 10^15 */ |
|
1588
|
|
|
|
|
|
|
U64(0x8E1BC9BF, 0x04000000), U64(0x00000000, 0x00000000), /* == 10^16 */ |
|
1589
|
|
|
|
|
|
|
U64(0xB1A2BC2E, 0xC5000000), U64(0x00000000, 0x00000000), /* == 10^17 */ |
|
1590
|
|
|
|
|
|
|
U64(0xDE0B6B3A, 0x76400000), U64(0x00000000, 0x00000000), /* == 10^18 */ |
|
1591
|
|
|
|
|
|
|
U64(0x8AC72304, 0x89E80000), U64(0x00000000, 0x00000000), /* == 10^19 */ |
|
1592
|
|
|
|
|
|
|
U64(0xAD78EBC5, 0xAC620000), U64(0x00000000, 0x00000000), /* == 10^20 */ |
|
1593
|
|
|
|
|
|
|
U64(0xD8D726B7, 0x177A8000), U64(0x00000000, 0x00000000), /* == 10^21 */ |
|
1594
|
|
|
|
|
|
|
U64(0x87867832, 0x6EAC9000), U64(0x00000000, 0x00000000), /* == 10^22 */ |
|
1595
|
|
|
|
|
|
|
U64(0xA968163F, 0x0A57B400), U64(0x00000000, 0x00000000), /* == 10^23 */ |
|
1596
|
|
|
|
|
|
|
U64(0xD3C21BCE, 0xCCEDA100), U64(0x00000000, 0x00000000), /* == 10^24 */ |
|
1597
|
|
|
|
|
|
|
U64(0x84595161, 0x401484A0), U64(0x00000000, 0x00000000), /* == 10^25 */ |
|
1598
|
|
|
|
|
|
|
U64(0xA56FA5B9, 0x9019A5C8), U64(0x00000000, 0x00000000), /* == 10^26 */ |
|
1599
|
|
|
|
|
|
|
U64(0xCECB8F27, 0xF4200F3A), U64(0x00000000, 0x00000000), /* == 10^27 */ |
|
1600
|
|
|
|
|
|
|
U64(0x813F3978, 0xF8940984), U64(0x40000000, 0x00000000), /* == 10^28 */ |
|
1601
|
|
|
|
|
|
|
U64(0xA18F07D7, 0x36B90BE5), U64(0x50000000, 0x00000000), /* == 10^29 */ |
|
1602
|
|
|
|
|
|
|
U64(0xC9F2C9CD, 0x04674EDE), U64(0xA4000000, 0x00000000), /* == 10^30 */ |
|
1603
|
|
|
|
|
|
|
U64(0xFC6F7C40, 0x45812296), U64(0x4D000000, 0x00000000), /* == 10^31 */ |
|
1604
|
|
|
|
|
|
|
U64(0x9DC5ADA8, 0x2B70B59D), U64(0xF0200000, 0x00000000), /* == 10^32 */ |
|
1605
|
|
|
|
|
|
|
U64(0xC5371912, 0x364CE305), U64(0x6C280000, 0x00000000), /* == 10^33 */ |
|
1606
|
|
|
|
|
|
|
U64(0xF684DF56, 0xC3E01BC6), U64(0xC7320000, 0x00000000), /* == 10^34 */ |
|
1607
|
|
|
|
|
|
|
U64(0x9A130B96, 0x3A6C115C), U64(0x3C7F4000, 0x00000000), /* == 10^35 */ |
|
1608
|
|
|
|
|
|
|
U64(0xC097CE7B, 0xC90715B3), U64(0x4B9F1000, 0x00000000), /* == 10^36 */ |
|
1609
|
|
|
|
|
|
|
U64(0xF0BDC21A, 0xBB48DB20), U64(0x1E86D400, 0x00000000), /* == 10^37 */ |
|
1610
|
|
|
|
|
|
|
U64(0x96769950, 0xB50D88F4), U64(0x13144480, 0x00000000), /* == 10^38 */ |
|
1611
|
|
|
|
|
|
|
U64(0xBC143FA4, 0xE250EB31), U64(0x17D955A0, 0x00000000), /* == 10^39 */ |
|
1612
|
|
|
|
|
|
|
U64(0xEB194F8E, 0x1AE525FD), U64(0x5DCFAB08, 0x00000000), /* == 10^40 */ |
|
1613
|
|
|
|
|
|
|
U64(0x92EFD1B8, 0xD0CF37BE), U64(0x5AA1CAE5, 0x00000000), /* == 10^41 */ |
|
1614
|
|
|
|
|
|
|
U64(0xB7ABC627, 0x050305AD), U64(0xF14A3D9E, 0x40000000), /* == 10^42 */ |
|
1615
|
|
|
|
|
|
|
U64(0xE596B7B0, 0xC643C719), U64(0x6D9CCD05, 0xD0000000), /* == 10^43 */ |
|
1616
|
|
|
|
|
|
|
U64(0x8F7E32CE, 0x7BEA5C6F), U64(0xE4820023, 0xA2000000), /* == 10^44 */ |
|
1617
|
|
|
|
|
|
|
U64(0xB35DBF82, 0x1AE4F38B), U64(0xDDA2802C, 0x8A800000), /* == 10^45 */ |
|
1618
|
|
|
|
|
|
|
U64(0xE0352F62, 0xA19E306E), U64(0xD50B2037, 0xAD200000), /* == 10^46 */ |
|
1619
|
|
|
|
|
|
|
U64(0x8C213D9D, 0xA502DE45), U64(0x4526F422, 0xCC340000), /* == 10^47 */ |
|
1620
|
|
|
|
|
|
|
U64(0xAF298D05, 0x0E4395D6), U64(0x9670B12B, 0x7F410000), /* == 10^48 */ |
|
1621
|
|
|
|
|
|
|
U64(0xDAF3F046, 0x51D47B4C), U64(0x3C0CDD76, 0x5F114000), /* == 10^49 */ |
|
1622
|
|
|
|
|
|
|
U64(0x88D8762B, 0xF324CD0F), U64(0xA5880A69, 0xFB6AC800), /* == 10^50 */ |
|
1623
|
|
|
|
|
|
|
U64(0xAB0E93B6, 0xEFEE0053), U64(0x8EEA0D04, 0x7A457A00), /* == 10^51 */ |
|
1624
|
|
|
|
|
|
|
U64(0xD5D238A4, 0xABE98068), U64(0x72A49045, 0x98D6D880), /* == 10^52 */ |
|
1625
|
|
|
|
|
|
|
U64(0x85A36366, 0xEB71F041), U64(0x47A6DA2B, 0x7F864750), /* == 10^53 */ |
|
1626
|
|
|
|
|
|
|
U64(0xA70C3C40, 0xA64E6C51), U64(0x999090B6, 0x5F67D924), /* == 10^54 */ |
|
1627
|
|
|
|
|
|
|
U64(0xD0CF4B50, 0xCFE20765), U64(0xFFF4B4E3, 0xF741CF6D), /* == 10^55 */ |
|
1628
|
|
|
|
|
|
|
U64(0x82818F12, 0x81ED449F), U64(0xBFF8F10E, 0x7A8921A4), /* ~= 10^56 */ |
|
1629
|
|
|
|
|
|
|
U64(0xA321F2D7, 0x226895C7), U64(0xAFF72D52, 0x192B6A0D), /* ~= 10^57 */ |
|
1630
|
|
|
|
|
|
|
U64(0xCBEA6F8C, 0xEB02BB39), U64(0x9BF4F8A6, 0x9F764490), /* ~= 10^58 */ |
|
1631
|
|
|
|
|
|
|
U64(0xFEE50B70, 0x25C36A08), U64(0x02F236D0, 0x4753D5B4), /* ~= 10^59 */ |
|
1632
|
|
|
|
|
|
|
U64(0x9F4F2726, 0x179A2245), U64(0x01D76242, 0x2C946590), /* ~= 10^60 */ |
|
1633
|
|
|
|
|
|
|
U64(0xC722F0EF, 0x9D80AAD6), U64(0x424D3AD2, 0xB7B97EF5), /* ~= 10^61 */ |
|
1634
|
|
|
|
|
|
|
U64(0xF8EBAD2B, 0x84E0D58B), U64(0xD2E08987, 0x65A7DEB2), /* ~= 10^62 */ |
|
1635
|
|
|
|
|
|
|
U64(0x9B934C3B, 0x330C8577), U64(0x63CC55F4, 0x9F88EB2F), /* ~= 10^63 */ |
|
1636
|
|
|
|
|
|
|
U64(0xC2781F49, 0xFFCFA6D5), U64(0x3CBF6B71, 0xC76B25FB), /* ~= 10^64 */ |
|
1637
|
|
|
|
|
|
|
U64(0xF316271C, 0x7FC3908A), U64(0x8BEF464E, 0x3945EF7A), /* ~= 10^65 */ |
|
1638
|
|
|
|
|
|
|
U64(0x97EDD871, 0xCFDA3A56), U64(0x97758BF0, 0xE3CBB5AC), /* ~= 10^66 */ |
|
1639
|
|
|
|
|
|
|
U64(0xBDE94E8E, 0x43D0C8EC), U64(0x3D52EEED, 0x1CBEA317), /* ~= 10^67 */ |
|
1640
|
|
|
|
|
|
|
U64(0xED63A231, 0xD4C4FB27), U64(0x4CA7AAA8, 0x63EE4BDD), /* ~= 10^68 */ |
|
1641
|
|
|
|
|
|
|
U64(0x945E455F, 0x24FB1CF8), U64(0x8FE8CAA9, 0x3E74EF6A), /* ~= 10^69 */ |
|
1642
|
|
|
|
|
|
|
U64(0xB975D6B6, 0xEE39E436), U64(0xB3E2FD53, 0x8E122B44), /* ~= 10^70 */ |
|
1643
|
|
|
|
|
|
|
U64(0xE7D34C64, 0xA9C85D44), U64(0x60DBBCA8, 0x7196B616), /* ~= 10^71 */ |
|
1644
|
|
|
|
|
|
|
U64(0x90E40FBE, 0xEA1D3A4A), U64(0xBC8955E9, 0x46FE31CD), /* ~= 10^72 */ |
|
1645
|
|
|
|
|
|
|
U64(0xB51D13AE, 0xA4A488DD), U64(0x6BABAB63, 0x98BDBE41), /* ~= 10^73 */ |
|
1646
|
|
|
|
|
|
|
U64(0xE264589A, 0x4DCDAB14), U64(0xC696963C, 0x7EED2DD1), /* ~= 10^74 */ |
|
1647
|
|
|
|
|
|
|
U64(0x8D7EB760, 0x70A08AEC), U64(0xFC1E1DE5, 0xCF543CA2), /* ~= 10^75 */ |
|
1648
|
|
|
|
|
|
|
U64(0xB0DE6538, 0x8CC8ADA8), U64(0x3B25A55F, 0x43294BCB), /* ~= 10^76 */ |
|
1649
|
|
|
|
|
|
|
U64(0xDD15FE86, 0xAFFAD912), U64(0x49EF0EB7, 0x13F39EBE), /* ~= 10^77 */ |
|
1650
|
|
|
|
|
|
|
U64(0x8A2DBF14, 0x2DFCC7AB), U64(0x6E356932, 0x6C784337), /* ~= 10^78 */ |
|
1651
|
|
|
|
|
|
|
U64(0xACB92ED9, 0x397BF996), U64(0x49C2C37F, 0x07965404), /* ~= 10^79 */ |
|
1652
|
|
|
|
|
|
|
U64(0xD7E77A8F, 0x87DAF7FB), U64(0xDC33745E, 0xC97BE906), /* ~= 10^80 */ |
|
1653
|
|
|
|
|
|
|
U64(0x86F0AC99, 0xB4E8DAFD), U64(0x69A028BB, 0x3DED71A3), /* ~= 10^81 */ |
|
1654
|
|
|
|
|
|
|
U64(0xA8ACD7C0, 0x222311BC), U64(0xC40832EA, 0x0D68CE0C), /* ~= 10^82 */ |
|
1655
|
|
|
|
|
|
|
U64(0xD2D80DB0, 0x2AABD62B), U64(0xF50A3FA4, 0x90C30190), /* ~= 10^83 */ |
|
1656
|
|
|
|
|
|
|
U64(0x83C7088E, 0x1AAB65DB), U64(0x792667C6, 0xDA79E0FA), /* ~= 10^84 */ |
|
1657
|
|
|
|
|
|
|
U64(0xA4B8CAB1, 0xA1563F52), U64(0x577001B8, 0x91185938), /* ~= 10^85 */ |
|
1658
|
|
|
|
|
|
|
U64(0xCDE6FD5E, 0x09ABCF26), U64(0xED4C0226, 0xB55E6F86), /* ~= 10^86 */ |
|
1659
|
|
|
|
|
|
|
U64(0x80B05E5A, 0xC60B6178), U64(0x544F8158, 0x315B05B4), /* ~= 10^87 */ |
|
1660
|
|
|
|
|
|
|
U64(0xA0DC75F1, 0x778E39D6), U64(0x696361AE, 0x3DB1C721), /* ~= 10^88 */ |
|
1661
|
|
|
|
|
|
|
U64(0xC913936D, 0xD571C84C), U64(0x03BC3A19, 0xCD1E38E9), /* ~= 10^89 */ |
|
1662
|
|
|
|
|
|
|
U64(0xFB587849, 0x4ACE3A5F), U64(0x04AB48A0, 0x4065C723), /* ~= 10^90 */ |
|
1663
|
|
|
|
|
|
|
U64(0x9D174B2D, 0xCEC0E47B), U64(0x62EB0D64, 0x283F9C76), /* ~= 10^91 */ |
|
1664
|
|
|
|
|
|
|
U64(0xC45D1DF9, 0x42711D9A), U64(0x3BA5D0BD, 0x324F8394), /* ~= 10^92 */ |
|
1665
|
|
|
|
|
|
|
U64(0xF5746577, 0x930D6500), U64(0xCA8F44EC, 0x7EE36479), /* ~= 10^93 */ |
|
1666
|
|
|
|
|
|
|
U64(0x9968BF6A, 0xBBE85F20), U64(0x7E998B13, 0xCF4E1ECB), /* ~= 10^94 */ |
|
1667
|
|
|
|
|
|
|
U64(0xBFC2EF45, 0x6AE276E8), U64(0x9E3FEDD8, 0xC321A67E), /* ~= 10^95 */ |
|
1668
|
|
|
|
|
|
|
U64(0xEFB3AB16, 0xC59B14A2), U64(0xC5CFE94E, 0xF3EA101E), /* ~= 10^96 */ |
|
1669
|
|
|
|
|
|
|
U64(0x95D04AEE, 0x3B80ECE5), U64(0xBBA1F1D1, 0x58724A12), /* ~= 10^97 */ |
|
1670
|
|
|
|
|
|
|
U64(0xBB445DA9, 0xCA61281F), U64(0x2A8A6E45, 0xAE8EDC97), /* ~= 10^98 */ |
|
1671
|
|
|
|
|
|
|
U64(0xEA157514, 0x3CF97226), U64(0xF52D09D7, 0x1A3293BD), /* ~= 10^99 */ |
|
1672
|
|
|
|
|
|
|
U64(0x924D692C, 0xA61BE758), U64(0x593C2626, 0x705F9C56), /* ~= 10^100 */ |
|
1673
|
|
|
|
|
|
|
U64(0xB6E0C377, 0xCFA2E12E), U64(0x6F8B2FB0, 0x0C77836C), /* ~= 10^101 */ |
|
1674
|
|
|
|
|
|
|
U64(0xE498F455, 0xC38B997A), U64(0x0B6DFB9C, 0x0F956447), /* ~= 10^102 */ |
|
1675
|
|
|
|
|
|
|
U64(0x8EDF98B5, 0x9A373FEC), U64(0x4724BD41, 0x89BD5EAC), /* ~= 10^103 */ |
|
1676
|
|
|
|
|
|
|
U64(0xB2977EE3, 0x00C50FE7), U64(0x58EDEC91, 0xEC2CB657), /* ~= 10^104 */ |
|
1677
|
|
|
|
|
|
|
U64(0xDF3D5E9B, 0xC0F653E1), U64(0x2F2967B6, 0x6737E3ED), /* ~= 10^105 */ |
|
1678
|
|
|
|
|
|
|
U64(0x8B865B21, 0x5899F46C), U64(0xBD79E0D2, 0x0082EE74), /* ~= 10^106 */ |
|
1679
|
|
|
|
|
|
|
U64(0xAE67F1E9, 0xAEC07187), U64(0xECD85906, 0x80A3AA11), /* ~= 10^107 */ |
|
1680
|
|
|
|
|
|
|
U64(0xDA01EE64, 0x1A708DE9), U64(0xE80E6F48, 0x20CC9495), /* ~= 10^108 */ |
|
1681
|
|
|
|
|
|
|
U64(0x884134FE, 0x908658B2), U64(0x3109058D, 0x147FDCDD), /* ~= 10^109 */ |
|
1682
|
|
|
|
|
|
|
U64(0xAA51823E, 0x34A7EEDE), U64(0xBD4B46F0, 0x599FD415), /* ~= 10^110 */ |
|
1683
|
|
|
|
|
|
|
U64(0xD4E5E2CD, 0xC1D1EA96), U64(0x6C9E18AC, 0x7007C91A), /* ~= 10^111 */ |
|
1684
|
|
|
|
|
|
|
U64(0x850FADC0, 0x9923329E), U64(0x03E2CF6B, 0xC604DDB0), /* ~= 10^112 */ |
|
1685
|
|
|
|
|
|
|
U64(0xA6539930, 0xBF6BFF45), U64(0x84DB8346, 0xB786151C), /* ~= 10^113 */ |
|
1686
|
|
|
|
|
|
|
U64(0xCFE87F7C, 0xEF46FF16), U64(0xE6126418, 0x65679A63), /* ~= 10^114 */ |
|
1687
|
|
|
|
|
|
|
U64(0x81F14FAE, 0x158C5F6E), U64(0x4FCB7E8F, 0x3F60C07E), /* ~= 10^115 */ |
|
1688
|
|
|
|
|
|
|
U64(0xA26DA399, 0x9AEF7749), U64(0xE3BE5E33, 0x0F38F09D), /* ~= 10^116 */ |
|
1689
|
|
|
|
|
|
|
U64(0xCB090C80, 0x01AB551C), U64(0x5CADF5BF, 0xD3072CC5), /* ~= 10^117 */ |
|
1690
|
|
|
|
|
|
|
U64(0xFDCB4FA0, 0x02162A63), U64(0x73D9732F, 0xC7C8F7F6), /* ~= 10^118 */ |
|
1691
|
|
|
|
|
|
|
U64(0x9E9F11C4, 0x014DDA7E), U64(0x2867E7FD, 0xDCDD9AFA), /* ~= 10^119 */ |
|
1692
|
|
|
|
|
|
|
U64(0xC646D635, 0x01A1511D), U64(0xB281E1FD, 0x541501B8), /* ~= 10^120 */ |
|
1693
|
|
|
|
|
|
|
U64(0xF7D88BC2, 0x4209A565), U64(0x1F225A7C, 0xA91A4226), /* ~= 10^121 */ |
|
1694
|
|
|
|
|
|
|
U64(0x9AE75759, 0x6946075F), U64(0x3375788D, 0xE9B06958), /* ~= 10^122 */ |
|
1695
|
|
|
|
|
|
|
U64(0xC1A12D2F, 0xC3978937), U64(0x0052D6B1, 0x641C83AE), /* ~= 10^123 */ |
|
1696
|
|
|
|
|
|
|
U64(0xF209787B, 0xB47D6B84), U64(0xC0678C5D, 0xBD23A49A), /* ~= 10^124 */ |
|
1697
|
|
|
|
|
|
|
U64(0x9745EB4D, 0x50CE6332), U64(0xF840B7BA, 0x963646E0), /* ~= 10^125 */ |
|
1698
|
|
|
|
|
|
|
U64(0xBD176620, 0xA501FBFF), U64(0xB650E5A9, 0x3BC3D898), /* ~= 10^126 */ |
|
1699
|
|
|
|
|
|
|
U64(0xEC5D3FA8, 0xCE427AFF), U64(0xA3E51F13, 0x8AB4CEBE), /* ~= 10^127 */ |
|
1700
|
|
|
|
|
|
|
U64(0x93BA47C9, 0x80E98CDF), U64(0xC66F336C, 0x36B10137), /* ~= 10^128 */ |
|
1701
|
|
|
|
|
|
|
U64(0xB8A8D9BB, 0xE123F017), U64(0xB80B0047, 0x445D4184), /* ~= 10^129 */ |
|
1702
|
|
|
|
|
|
|
U64(0xE6D3102A, 0xD96CEC1D), U64(0xA60DC059, 0x157491E5), /* ~= 10^130 */ |
|
1703
|
|
|
|
|
|
|
U64(0x9043EA1A, 0xC7E41392), U64(0x87C89837, 0xAD68DB2F), /* ~= 10^131 */ |
|
1704
|
|
|
|
|
|
|
U64(0xB454E4A1, 0x79DD1877), U64(0x29BABE45, 0x98C311FB), /* ~= 10^132 */ |
|
1705
|
|
|
|
|
|
|
U64(0xE16A1DC9, 0xD8545E94), U64(0xF4296DD6, 0xFEF3D67A), /* ~= 10^133 */ |
|
1706
|
|
|
|
|
|
|
U64(0x8CE2529E, 0x2734BB1D), U64(0x1899E4A6, 0x5F58660C), /* ~= 10^134 */ |
|
1707
|
|
|
|
|
|
|
U64(0xB01AE745, 0xB101E9E4), U64(0x5EC05DCF, 0xF72E7F8F), /* ~= 10^135 */ |
|
1708
|
|
|
|
|
|
|
U64(0xDC21A117, 0x1D42645D), U64(0x76707543, 0xF4FA1F73), /* ~= 10^136 */ |
|
1709
|
|
|
|
|
|
|
U64(0x899504AE, 0x72497EBA), U64(0x6A06494A, 0x791C53A8), /* ~= 10^137 */ |
|
1710
|
|
|
|
|
|
|
U64(0xABFA45DA, 0x0EDBDE69), U64(0x0487DB9D, 0x17636892), /* ~= 10^138 */ |
|
1711
|
|
|
|
|
|
|
U64(0xD6F8D750, 0x9292D603), U64(0x45A9D284, 0x5D3C42B6), /* ~= 10^139 */ |
|
1712
|
|
|
|
|
|
|
U64(0x865B8692, 0x5B9BC5C2), U64(0x0B8A2392, 0xBA45A9B2), /* ~= 10^140 */ |
|
1713
|
|
|
|
|
|
|
U64(0xA7F26836, 0xF282B732), U64(0x8E6CAC77, 0x68D7141E), /* ~= 10^141 */ |
|
1714
|
|
|
|
|
|
|
U64(0xD1EF0244, 0xAF2364FF), U64(0x3207D795, 0x430CD926), /* ~= 10^142 */ |
|
1715
|
|
|
|
|
|
|
U64(0x8335616A, 0xED761F1F), U64(0x7F44E6BD, 0x49E807B8), /* ~= 10^143 */ |
|
1716
|
|
|
|
|
|
|
U64(0xA402B9C5, 0xA8D3A6E7), U64(0x5F16206C, 0x9C6209A6), /* ~= 10^144 */ |
|
1717
|
|
|
|
|
|
|
U64(0xCD036837, 0x130890A1), U64(0x36DBA887, 0xC37A8C0F), /* ~= 10^145 */ |
|
1718
|
|
|
|
|
|
|
U64(0x80222122, 0x6BE55A64), U64(0xC2494954, 0xDA2C9789), /* ~= 10^146 */ |
|
1719
|
|
|
|
|
|
|
U64(0xA02AA96B, 0x06DEB0FD), U64(0xF2DB9BAA, 0x10B7BD6C), /* ~= 10^147 */ |
|
1720
|
|
|
|
|
|
|
U64(0xC83553C5, 0xC8965D3D), U64(0x6F928294, 0x94E5ACC7), /* ~= 10^148 */ |
|
1721
|
|
|
|
|
|
|
U64(0xFA42A8B7, 0x3ABBF48C), U64(0xCB772339, 0xBA1F17F9), /* ~= 10^149 */ |
|
1722
|
|
|
|
|
|
|
U64(0x9C69A972, 0x84B578D7), U64(0xFF2A7604, 0x14536EFB), /* ~= 10^150 */ |
|
1723
|
|
|
|
|
|
|
U64(0xC38413CF, 0x25E2D70D), U64(0xFEF51385, 0x19684ABA), /* ~= 10^151 */ |
|
1724
|
|
|
|
|
|
|
U64(0xF46518C2, 0xEF5B8CD1), U64(0x7EB25866, 0x5FC25D69), /* ~= 10^152 */ |
|
1725
|
|
|
|
|
|
|
U64(0x98BF2F79, 0xD5993802), U64(0xEF2F773F, 0xFBD97A61), /* ~= 10^153 */ |
|
1726
|
|
|
|
|
|
|
U64(0xBEEEFB58, 0x4AFF8603), U64(0xAAFB550F, 0xFACFD8FA), /* ~= 10^154 */ |
|
1727
|
|
|
|
|
|
|
U64(0xEEAABA2E, 0x5DBF6784), U64(0x95BA2A53, 0xF983CF38), /* ~= 10^155 */ |
|
1728
|
|
|
|
|
|
|
U64(0x952AB45C, 0xFA97A0B2), U64(0xDD945A74, 0x7BF26183), /* ~= 10^156 */ |
|
1729
|
|
|
|
|
|
|
U64(0xBA756174, 0x393D88DF), U64(0x94F97111, 0x9AEEF9E4), /* ~= 10^157 */ |
|
1730
|
|
|
|
|
|
|
U64(0xE912B9D1, 0x478CEB17), U64(0x7A37CD56, 0x01AAB85D), /* ~= 10^158 */ |
|
1731
|
|
|
|
|
|
|
U64(0x91ABB422, 0xCCB812EE), U64(0xAC62E055, 0xC10AB33A), /* ~= 10^159 */ |
|
1732
|
|
|
|
|
|
|
U64(0xB616A12B, 0x7FE617AA), U64(0x577B986B, 0x314D6009), /* ~= 10^160 */ |
|
1733
|
|
|
|
|
|
|
U64(0xE39C4976, 0x5FDF9D94), U64(0xED5A7E85, 0xFDA0B80B), /* ~= 10^161 */ |
|
1734
|
|
|
|
|
|
|
U64(0x8E41ADE9, 0xFBEBC27D), U64(0x14588F13, 0xBE847307), /* ~= 10^162 */ |
|
1735
|
|
|
|
|
|
|
U64(0xB1D21964, 0x7AE6B31C), U64(0x596EB2D8, 0xAE258FC8), /* ~= 10^163 */ |
|
1736
|
|
|
|
|
|
|
U64(0xDE469FBD, 0x99A05FE3), U64(0x6FCA5F8E, 0xD9AEF3BB), /* ~= 10^164 */ |
|
1737
|
|
|
|
|
|
|
U64(0x8AEC23D6, 0x80043BEE), U64(0x25DE7BB9, 0x480D5854), /* ~= 10^165 */ |
|
1738
|
|
|
|
|
|
|
U64(0xADA72CCC, 0x20054AE9), U64(0xAF561AA7, 0x9A10AE6A), /* ~= 10^166 */ |
|
1739
|
|
|
|
|
|
|
U64(0xD910F7FF, 0x28069DA4), U64(0x1B2BA151, 0x8094DA04), /* ~= 10^167 */ |
|
1740
|
|
|
|
|
|
|
U64(0x87AA9AFF, 0x79042286), U64(0x90FB44D2, 0xF05D0842), /* ~= 10^168 */ |
|
1741
|
|
|
|
|
|
|
U64(0xA99541BF, 0x57452B28), U64(0x353A1607, 0xAC744A53), /* ~= 10^169 */ |
|
1742
|
|
|
|
|
|
|
U64(0xD3FA922F, 0x2D1675F2), U64(0x42889B89, 0x97915CE8), /* ~= 10^170 */ |
|
1743
|
|
|
|
|
|
|
U64(0x847C9B5D, 0x7C2E09B7), U64(0x69956135, 0xFEBADA11), /* ~= 10^171 */ |
|
1744
|
|
|
|
|
|
|
U64(0xA59BC234, 0xDB398C25), U64(0x43FAB983, 0x7E699095), /* ~= 10^172 */ |
|
1745
|
|
|
|
|
|
|
U64(0xCF02B2C2, 0x1207EF2E), U64(0x94F967E4, 0x5E03F4BB), /* ~= 10^173 */ |
|
1746
|
|
|
|
|
|
|
U64(0x8161AFB9, 0x4B44F57D), U64(0x1D1BE0EE, 0xBAC278F5), /* ~= 10^174 */ |
|
1747
|
|
|
|
|
|
|
U64(0xA1BA1BA7, 0x9E1632DC), U64(0x6462D92A, 0x69731732), /* ~= 10^175 */ |
|
1748
|
|
|
|
|
|
|
U64(0xCA28A291, 0x859BBF93), U64(0x7D7B8F75, 0x03CFDCFE), /* ~= 10^176 */ |
|
1749
|
|
|
|
|
|
|
U64(0xFCB2CB35, 0xE702AF78), U64(0x5CDA7352, 0x44C3D43E), /* ~= 10^177 */ |
|
1750
|
|
|
|
|
|
|
U64(0x9DEFBF01, 0xB061ADAB), U64(0x3A088813, 0x6AFA64A7), /* ~= 10^178 */ |
|
1751
|
|
|
|
|
|
|
U64(0xC56BAEC2, 0x1C7A1916), U64(0x088AAA18, 0x45B8FDD0), /* ~= 10^179 */ |
|
1752
|
|
|
|
|
|
|
U64(0xF6C69A72, 0xA3989F5B), U64(0x8AAD549E, 0x57273D45), /* ~= 10^180 */ |
|
1753
|
|
|
|
|
|
|
U64(0x9A3C2087, 0xA63F6399), U64(0x36AC54E2, 0xF678864B), /* ~= 10^181 */ |
|
1754
|
|
|
|
|
|
|
U64(0xC0CB28A9, 0x8FCF3C7F), U64(0x84576A1B, 0xB416A7DD), /* ~= 10^182 */ |
|
1755
|
|
|
|
|
|
|
U64(0xF0FDF2D3, 0xF3C30B9F), U64(0x656D44A2, 0xA11C51D5), /* ~= 10^183 */ |
|
1756
|
|
|
|
|
|
|
U64(0x969EB7C4, 0x7859E743), U64(0x9F644AE5, 0xA4B1B325), /* ~= 10^184 */ |
|
1757
|
|
|
|
|
|
|
U64(0xBC4665B5, 0x96706114), U64(0x873D5D9F, 0x0DDE1FEE), /* ~= 10^185 */ |
|
1758
|
|
|
|
|
|
|
U64(0xEB57FF22, 0xFC0C7959), U64(0xA90CB506, 0xD155A7EA), /* ~= 10^186 */ |
|
1759
|
|
|
|
|
|
|
U64(0x9316FF75, 0xDD87CBD8), U64(0x09A7F124, 0x42D588F2), /* ~= 10^187 */ |
|
1760
|
|
|
|
|
|
|
U64(0xB7DCBF53, 0x54E9BECE), U64(0x0C11ED6D, 0x538AEB2F), /* ~= 10^188 */ |
|
1761
|
|
|
|
|
|
|
U64(0xE5D3EF28, 0x2A242E81), U64(0x8F1668C8, 0xA86DA5FA), /* ~= 10^189 */ |
|
1762
|
|
|
|
|
|
|
U64(0x8FA47579, 0x1A569D10), U64(0xF96E017D, 0x694487BC), /* ~= 10^190 */ |
|
1763
|
|
|
|
|
|
|
U64(0xB38D92D7, 0x60EC4455), U64(0x37C981DC, 0xC395A9AC), /* ~= 10^191 */ |
|
1764
|
|
|
|
|
|
|
U64(0xE070F78D, 0x3927556A), U64(0x85BBE253, 0xF47B1417), /* ~= 10^192 */ |
|
1765
|
|
|
|
|
|
|
U64(0x8C469AB8, 0x43B89562), U64(0x93956D74, 0x78CCEC8E), /* ~= 10^193 */ |
|
1766
|
|
|
|
|
|
|
U64(0xAF584166, 0x54A6BABB), U64(0x387AC8D1, 0x970027B2), /* ~= 10^194 */ |
|
1767
|
|
|
|
|
|
|
U64(0xDB2E51BF, 0xE9D0696A), U64(0x06997B05, 0xFCC0319E), /* ~= 10^195 */ |
|
1768
|
|
|
|
|
|
|
U64(0x88FCF317, 0xF22241E2), U64(0x441FECE3, 0xBDF81F03), /* ~= 10^196 */ |
|
1769
|
|
|
|
|
|
|
U64(0xAB3C2FDD, 0xEEAAD25A), U64(0xD527E81C, 0xAD7626C3), /* ~= 10^197 */ |
|
1770
|
|
|
|
|
|
|
U64(0xD60B3BD5, 0x6A5586F1), U64(0x8A71E223, 0xD8D3B074), /* ~= 10^198 */ |
|
1771
|
|
|
|
|
|
|
U64(0x85C70565, 0x62757456), U64(0xF6872D56, 0x67844E49), /* ~= 10^199 */ |
|
1772
|
|
|
|
|
|
|
U64(0xA738C6BE, 0xBB12D16C), U64(0xB428F8AC, 0x016561DB), /* ~= 10^200 */ |
|
1773
|
|
|
|
|
|
|
U64(0xD106F86E, 0x69D785C7), U64(0xE13336D7, 0x01BEBA52), /* ~= 10^201 */ |
|
1774
|
|
|
|
|
|
|
U64(0x82A45B45, 0x0226B39C), U64(0xECC00246, 0x61173473), /* ~= 10^202 */ |
|
1775
|
|
|
|
|
|
|
U64(0xA34D7216, 0x42B06084), U64(0x27F002D7, 0xF95D0190), /* ~= 10^203 */ |
|
1776
|
|
|
|
|
|
|
U64(0xCC20CE9B, 0xD35C78A5), U64(0x31EC038D, 0xF7B441F4), /* ~= 10^204 */ |
|
1777
|
|
|
|
|
|
|
U64(0xFF290242, 0xC83396CE), U64(0x7E670471, 0x75A15271), /* ~= 10^205 */ |
|
1778
|
|
|
|
|
|
|
U64(0x9F79A169, 0xBD203E41), U64(0x0F0062C6, 0xE984D386), /* ~= 10^206 */ |
|
1779
|
|
|
|
|
|
|
U64(0xC75809C4, 0x2C684DD1), U64(0x52C07B78, 0xA3E60868), /* ~= 10^207 */ |
|
1780
|
|
|
|
|
|
|
U64(0xF92E0C35, 0x37826145), U64(0xA7709A56, 0xCCDF8A82), /* ~= 10^208 */ |
|
1781
|
|
|
|
|
|
|
U64(0x9BBCC7A1, 0x42B17CCB), U64(0x88A66076, 0x400BB691), /* ~= 10^209 */ |
|
1782
|
|
|
|
|
|
|
U64(0xC2ABF989, 0x935DDBFE), U64(0x6ACFF893, 0xD00EA435), /* ~= 10^210 */ |
|
1783
|
|
|
|
|
|
|
U64(0xF356F7EB, 0xF83552FE), U64(0x0583F6B8, 0xC4124D43), /* ~= 10^211 */ |
|
1784
|
|
|
|
|
|
|
U64(0x98165AF3, 0x7B2153DE), U64(0xC3727A33, 0x7A8B704A), /* ~= 10^212 */ |
|
1785
|
|
|
|
|
|
|
U64(0xBE1BF1B0, 0x59E9A8D6), U64(0x744F18C0, 0x592E4C5C), /* ~= 10^213 */ |
|
1786
|
|
|
|
|
|
|
U64(0xEDA2EE1C, 0x7064130C), U64(0x1162DEF0, 0x6F79DF73), /* ~= 10^214 */ |
|
1787
|
|
|
|
|
|
|
U64(0x9485D4D1, 0xC63E8BE7), U64(0x8ADDCB56, 0x45AC2BA8), /* ~= 10^215 */ |
|
1788
|
|
|
|
|
|
|
U64(0xB9A74A06, 0x37CE2EE1), U64(0x6D953E2B, 0xD7173692), /* ~= 10^216 */ |
|
1789
|
|
|
|
|
|
|
U64(0xE8111C87, 0xC5C1BA99), U64(0xC8FA8DB6, 0xCCDD0437), /* ~= 10^217 */ |
|
1790
|
|
|
|
|
|
|
U64(0x910AB1D4, 0xDB9914A0), U64(0x1D9C9892, 0x400A22A2), /* ~= 10^218 */ |
|
1791
|
|
|
|
|
|
|
U64(0xB54D5E4A, 0x127F59C8), U64(0x2503BEB6, 0xD00CAB4B), /* ~= 10^219 */ |
|
1792
|
|
|
|
|
|
|
U64(0xE2A0B5DC, 0x971F303A), U64(0x2E44AE64, 0x840FD61D), /* ~= 10^220 */ |
|
1793
|
|
|
|
|
|
|
U64(0x8DA471A9, 0xDE737E24), U64(0x5CEAECFE, 0xD289E5D2), /* ~= 10^221 */ |
|
1794
|
|
|
|
|
|
|
U64(0xB10D8E14, 0x56105DAD), U64(0x7425A83E, 0x872C5F47), /* ~= 10^222 */ |
|
1795
|
|
|
|
|
|
|
U64(0xDD50F199, 0x6B947518), U64(0xD12F124E, 0x28F77719), /* ~= 10^223 */ |
|
1796
|
|
|
|
|
|
|
U64(0x8A5296FF, 0xE33CC92F), U64(0x82BD6B70, 0xD99AAA6F), /* ~= 10^224 */ |
|
1797
|
|
|
|
|
|
|
U64(0xACE73CBF, 0xDC0BFB7B), U64(0x636CC64D, 0x1001550B), /* ~= 10^225 */ |
|
1798
|
|
|
|
|
|
|
U64(0xD8210BEF, 0xD30EFA5A), U64(0x3C47F7E0, 0x5401AA4E), /* ~= 10^226 */ |
|
1799
|
|
|
|
|
|
|
U64(0x8714A775, 0xE3E95C78), U64(0x65ACFAEC, 0x34810A71), /* ~= 10^227 */ |
|
1800
|
|
|
|
|
|
|
U64(0xA8D9D153, 0x5CE3B396), U64(0x7F1839A7, 0x41A14D0D), /* ~= 10^228 */ |
|
1801
|
|
|
|
|
|
|
U64(0xD31045A8, 0x341CA07C), U64(0x1EDE4811, 0x1209A050), /* ~= 10^229 */ |
|
1802
|
|
|
|
|
|
|
U64(0x83EA2B89, 0x2091E44D), U64(0x934AED0A, 0xAB460432), /* ~= 10^230 */ |
|
1803
|
|
|
|
|
|
|
U64(0xA4E4B66B, 0x68B65D60), U64(0xF81DA84D, 0x5617853F), /* ~= 10^231 */ |
|
1804
|
|
|
|
|
|
|
U64(0xCE1DE406, 0x42E3F4B9), U64(0x36251260, 0xAB9D668E), /* ~= 10^232 */ |
|
1805
|
|
|
|
|
|
|
U64(0x80D2AE83, 0xE9CE78F3), U64(0xC1D72B7C, 0x6B426019), /* ~= 10^233 */ |
|
1806
|
|
|
|
|
|
|
U64(0xA1075A24, 0xE4421730), U64(0xB24CF65B, 0x8612F81F), /* ~= 10^234 */ |
|
1807
|
|
|
|
|
|
|
U64(0xC94930AE, 0x1D529CFC), U64(0xDEE033F2, 0x6797B627), /* ~= 10^235 */ |
|
1808
|
|
|
|
|
|
|
U64(0xFB9B7CD9, 0xA4A7443C), U64(0x169840EF, 0x017DA3B1), /* ~= 10^236 */ |
|
1809
|
|
|
|
|
|
|
U64(0x9D412E08, 0x06E88AA5), U64(0x8E1F2895, 0x60EE864E), /* ~= 10^237 */ |
|
1810
|
|
|
|
|
|
|
U64(0xC491798A, 0x08A2AD4E), U64(0xF1A6F2BA, 0xB92A27E2), /* ~= 10^238 */ |
|
1811
|
|
|
|
|
|
|
U64(0xF5B5D7EC, 0x8ACB58A2), U64(0xAE10AF69, 0x6774B1DB), /* ~= 10^239 */ |
|
1812
|
|
|
|
|
|
|
U64(0x9991A6F3, 0xD6BF1765), U64(0xACCA6DA1, 0xE0A8EF29), /* ~= 10^240 */ |
|
1813
|
|
|
|
|
|
|
U64(0xBFF610B0, 0xCC6EDD3F), U64(0x17FD090A, 0x58D32AF3), /* ~= 10^241 */ |
|
1814
|
|
|
|
|
|
|
U64(0xEFF394DC, 0xFF8A948E), U64(0xDDFC4B4C, 0xEF07F5B0), /* ~= 10^242 */ |
|
1815
|
|
|
|
|
|
|
U64(0x95F83D0A, 0x1FB69CD9), U64(0x4ABDAF10, 0x1564F98E), /* ~= 10^243 */ |
|
1816
|
|
|
|
|
|
|
U64(0xBB764C4C, 0xA7A4440F), U64(0x9D6D1AD4, 0x1ABE37F1), /* ~= 10^244 */ |
|
1817
|
|
|
|
|
|
|
U64(0xEA53DF5F, 0xD18D5513), U64(0x84C86189, 0x216DC5ED), /* ~= 10^245 */ |
|
1818
|
|
|
|
|
|
|
U64(0x92746B9B, 0xE2F8552C), U64(0x32FD3CF5, 0xB4E49BB4), /* ~= 10^246 */ |
|
1819
|
|
|
|
|
|
|
U64(0xB7118682, 0xDBB66A77), U64(0x3FBC8C33, 0x221DC2A1), /* ~= 10^247 */ |
|
1820
|
|
|
|
|
|
|
U64(0xE4D5E823, 0x92A40515), U64(0x0FABAF3F, 0xEAA5334A), /* ~= 10^248 */ |
|
1821
|
|
|
|
|
|
|
U64(0x8F05B116, 0x3BA6832D), U64(0x29CB4D87, 0xF2A7400E), /* ~= 10^249 */ |
|
1822
|
|
|
|
|
|
|
U64(0xB2C71D5B, 0xCA9023F8), U64(0x743E20E9, 0xEF511012), /* ~= 10^250 */ |
|
1823
|
|
|
|
|
|
|
U64(0xDF78E4B2, 0xBD342CF6), U64(0x914DA924, 0x6B255416), /* ~= 10^251 */ |
|
1824
|
|
|
|
|
|
|
U64(0x8BAB8EEF, 0xB6409C1A), U64(0x1AD089B6, 0xC2F7548E), /* ~= 10^252 */ |
|
1825
|
|
|
|
|
|
|
U64(0xAE9672AB, 0xA3D0C320), U64(0xA184AC24, 0x73B529B1), /* ~= 10^253 */ |
|
1826
|
|
|
|
|
|
|
U64(0xDA3C0F56, 0x8CC4F3E8), U64(0xC9E5D72D, 0x90A2741E), /* ~= 10^254 */ |
|
1827
|
|
|
|
|
|
|
U64(0x88658996, 0x17FB1871), U64(0x7E2FA67C, 0x7A658892), /* ~= 10^255 */ |
|
1828
|
|
|
|
|
|
|
U64(0xAA7EEBFB, 0x9DF9DE8D), U64(0xDDBB901B, 0x98FEEAB7), /* ~= 10^256 */ |
|
1829
|
|
|
|
|
|
|
U64(0xD51EA6FA, 0x85785631), U64(0x552A7422, 0x7F3EA565), /* ~= 10^257 */ |
|
1830
|
|
|
|
|
|
|
U64(0x8533285C, 0x936B35DE), U64(0xD53A8895, 0x8F87275F), /* ~= 10^258 */ |
|
1831
|
|
|
|
|
|
|
U64(0xA67FF273, 0xB8460356), U64(0x8A892ABA, 0xF368F137), /* ~= 10^259 */ |
|
1832
|
|
|
|
|
|
|
U64(0xD01FEF10, 0xA657842C), U64(0x2D2B7569, 0xB0432D85), /* ~= 10^260 */ |
|
1833
|
|
|
|
|
|
|
U64(0x8213F56A, 0x67F6B29B), U64(0x9C3B2962, 0x0E29FC73), /* ~= 10^261 */ |
|
1834
|
|
|
|
|
|
|
U64(0xA298F2C5, 0x01F45F42), U64(0x8349F3BA, 0x91B47B8F), /* ~= 10^262 */ |
|
1835
|
|
|
|
|
|
|
U64(0xCB3F2F76, 0x42717713), U64(0x241C70A9, 0x36219A73), /* ~= 10^263 */ |
|
1836
|
|
|
|
|
|
|
U64(0xFE0EFB53, 0xD30DD4D7), U64(0xED238CD3, 0x83AA0110), /* ~= 10^264 */ |
|
1837
|
|
|
|
|
|
|
U64(0x9EC95D14, 0x63E8A506), U64(0xF4363804, 0x324A40AA), /* ~= 10^265 */ |
|
1838
|
|
|
|
|
|
|
U64(0xC67BB459, 0x7CE2CE48), U64(0xB143C605, 0x3EDCD0D5), /* ~= 10^266 */ |
|
1839
|
|
|
|
|
|
|
U64(0xF81AA16F, 0xDC1B81DA), U64(0xDD94B786, 0x8E94050A), /* ~= 10^267 */ |
|
1840
|
|
|
|
|
|
|
U64(0x9B10A4E5, 0xE9913128), U64(0xCA7CF2B4, 0x191C8326), /* ~= 10^268 */ |
|
1841
|
|
|
|
|
|
|
U64(0xC1D4CE1F, 0x63F57D72), U64(0xFD1C2F61, 0x1F63A3F0), /* ~= 10^269 */ |
|
1842
|
|
|
|
|
|
|
U64(0xF24A01A7, 0x3CF2DCCF), U64(0xBC633B39, 0x673C8CEC), /* ~= 10^270 */ |
|
1843
|
|
|
|
|
|
|
U64(0x976E4108, 0x8617CA01), U64(0xD5BE0503, 0xE085D813), /* ~= 10^271 */ |
|
1844
|
|
|
|
|
|
|
U64(0xBD49D14A, 0xA79DBC82), U64(0x4B2D8644, 0xD8A74E18), /* ~= 10^272 */ |
|
1845
|
|
|
|
|
|
|
U64(0xEC9C459D, 0x51852BA2), U64(0xDDF8E7D6, 0x0ED1219E), /* ~= 10^273 */ |
|
1846
|
|
|
|
|
|
|
U64(0x93E1AB82, 0x52F33B45), U64(0xCABB90E5, 0xC942B503), /* ~= 10^274 */ |
|
1847
|
|
|
|
|
|
|
U64(0xB8DA1662, 0xE7B00A17), U64(0x3D6A751F, 0x3B936243), /* ~= 10^275 */ |
|
1848
|
|
|
|
|
|
|
U64(0xE7109BFB, 0xA19C0C9D), U64(0x0CC51267, 0x0A783AD4), /* ~= 10^276 */ |
|
1849
|
|
|
|
|
|
|
U64(0x906A617D, 0x450187E2), U64(0x27FB2B80, 0x668B24C5), /* ~= 10^277 */ |
|
1850
|
|
|
|
|
|
|
U64(0xB484F9DC, 0x9641E9DA), U64(0xB1F9F660, 0x802DEDF6), /* ~= 10^278 */ |
|
1851
|
|
|
|
|
|
|
U64(0xE1A63853, 0xBBD26451), U64(0x5E7873F8, 0xA0396973), /* ~= 10^279 */ |
|
1852
|
|
|
|
|
|
|
U64(0x8D07E334, 0x55637EB2), U64(0xDB0B487B, 0x6423E1E8), /* ~= 10^280 */ |
|
1853
|
|
|
|
|
|
|
U64(0xB049DC01, 0x6ABC5E5F), U64(0x91CE1A9A, 0x3D2CDA62), /* ~= 10^281 */ |
|
1854
|
|
|
|
|
|
|
U64(0xDC5C5301, 0xC56B75F7), U64(0x7641A140, 0xCC7810FB), /* ~= 10^282 */ |
|
1855
|
|
|
|
|
|
|
U64(0x89B9B3E1, 0x1B6329BA), U64(0xA9E904C8, 0x7FCB0A9D), /* ~= 10^283 */ |
|
1856
|
|
|
|
|
|
|
U64(0xAC2820D9, 0x623BF429), U64(0x546345FA, 0x9FBDCD44), /* ~= 10^284 */ |
|
1857
|
|
|
|
|
|
|
U64(0xD732290F, 0xBACAF133), U64(0xA97C1779, 0x47AD4095), /* ~= 10^285 */ |
|
1858
|
|
|
|
|
|
|
U64(0x867F59A9, 0xD4BED6C0), U64(0x49ED8EAB, 0xCCCC485D), /* ~= 10^286 */ |
|
1859
|
|
|
|
|
|
|
U64(0xA81F3014, 0x49EE8C70), U64(0x5C68F256, 0xBFFF5A74), /* ~= 10^287 */ |
|
1860
|
|
|
|
|
|
|
U64(0xD226FC19, 0x5C6A2F8C), U64(0x73832EEC, 0x6FFF3111), /* ~= 10^288 */ |
|
1861
|
|
|
|
|
|
|
U64(0x83585D8F, 0xD9C25DB7), U64(0xC831FD53, 0xC5FF7EAB), /* ~= 10^289 */ |
|
1862
|
|
|
|
|
|
|
U64(0xA42E74F3, 0xD032F525), U64(0xBA3E7CA8, 0xB77F5E55), /* ~= 10^290 */ |
|
1863
|
|
|
|
|
|
|
U64(0xCD3A1230, 0xC43FB26F), U64(0x28CE1BD2, 0xE55F35EB), /* ~= 10^291 */ |
|
1864
|
|
|
|
|
|
|
U64(0x80444B5E, 0x7AA7CF85), U64(0x7980D163, 0xCF5B81B3), /* ~= 10^292 */ |
|
1865
|
|
|
|
|
|
|
U64(0xA0555E36, 0x1951C366), U64(0xD7E105BC, 0xC332621F), /* ~= 10^293 */ |
|
1866
|
|
|
|
|
|
|
U64(0xC86AB5C3, 0x9FA63440), U64(0x8DD9472B, 0xF3FEFAA7), /* ~= 10^294 */ |
|
1867
|
|
|
|
|
|
|
U64(0xFA856334, 0x878FC150), U64(0xB14F98F6, 0xF0FEB951), /* ~= 10^295 */ |
|
1868
|
|
|
|
|
|
|
U64(0x9C935E00, 0xD4B9D8D2), U64(0x6ED1BF9A, 0x569F33D3), /* ~= 10^296 */ |
|
1869
|
|
|
|
|
|
|
U64(0xC3B83581, 0x09E84F07), U64(0x0A862F80, 0xEC4700C8), /* ~= 10^297 */ |
|
1870
|
|
|
|
|
|
|
U64(0xF4A642E1, 0x4C6262C8), U64(0xCD27BB61, 0x2758C0FA), /* ~= 10^298 */ |
|
1871
|
|
|
|
|
|
|
U64(0x98E7E9CC, 0xCFBD7DBD), U64(0x8038D51C, 0xB897789C), /* ~= 10^299 */ |
|
1872
|
|
|
|
|
|
|
U64(0xBF21E440, 0x03ACDD2C), U64(0xE0470A63, 0xE6BD56C3), /* ~= 10^300 */ |
|
1873
|
|
|
|
|
|
|
U64(0xEEEA5D50, 0x04981478), U64(0x1858CCFC, 0xE06CAC74), /* ~= 10^301 */ |
|
1874
|
|
|
|
|
|
|
U64(0x95527A52, 0x02DF0CCB), U64(0x0F37801E, 0x0C43EBC8), /* ~= 10^302 */ |
|
1875
|
|
|
|
|
|
|
U64(0xBAA718E6, 0x8396CFFD), U64(0xD3056025, 0x8F54E6BA), /* ~= 10^303 */ |
|
1876
|
|
|
|
|
|
|
U64(0xE950DF20, 0x247C83FD), U64(0x47C6B82E, 0xF32A2069), /* ~= 10^304 */ |
|
1877
|
|
|
|
|
|
|
U64(0x91D28B74, 0x16CDD27E), U64(0x4CDC331D, 0x57FA5441), /* ~= 10^305 */ |
|
1878
|
|
|
|
|
|
|
U64(0xB6472E51, 0x1C81471D), U64(0xE0133FE4, 0xADF8E952), /* ~= 10^306 */ |
|
1879
|
|
|
|
|
|
|
U64(0xE3D8F9E5, 0x63A198E5), U64(0x58180FDD, 0xD97723A6), /* ~= 10^307 */ |
|
1880
|
|
|
|
|
|
|
U64(0x8E679C2F, 0x5E44FF8F), U64(0x570F09EA, 0xA7EA7648), /* ~= 10^308 */ |
|
1881
|
|
|
|
|
|
|
U64(0xB201833B, 0x35D63F73), U64(0x2CD2CC65, 0x51E513DA), /* ~= 10^309 */ |
|
1882
|
|
|
|
|
|
|
U64(0xDE81E40A, 0x034BCF4F), U64(0xF8077F7E, 0xA65E58D1), /* ~= 10^310 */ |
|
1883
|
|
|
|
|
|
|
U64(0x8B112E86, 0x420F6191), U64(0xFB04AFAF, 0x27FAF782), /* ~= 10^311 */ |
|
1884
|
|
|
|
|
|
|
U64(0xADD57A27, 0xD29339F6), U64(0x79C5DB9A, 0xF1F9B563), /* ~= 10^312 */ |
|
1885
|
|
|
|
|
|
|
U64(0xD94AD8B1, 0xC7380874), U64(0x18375281, 0xAE7822BC), /* ~= 10^313 */ |
|
1886
|
|
|
|
|
|
|
U64(0x87CEC76F, 0x1C830548), U64(0x8F229391, 0x0D0B15B5), /* ~= 10^314 */ |
|
1887
|
|
|
|
|
|
|
U64(0xA9C2794A, 0xE3A3C69A), U64(0xB2EB3875, 0x504DDB22), /* ~= 10^315 */ |
|
1888
|
|
|
|
|
|
|
U64(0xD433179D, 0x9C8CB841), U64(0x5FA60692, 0xA46151EB), /* ~= 10^316 */ |
|
1889
|
|
|
|
|
|
|
U64(0x849FEEC2, 0x81D7F328), U64(0xDBC7C41B, 0xA6BCD333), /* ~= 10^317 */ |
|
1890
|
|
|
|
|
|
|
U64(0xA5C7EA73, 0x224DEFF3), U64(0x12B9B522, 0x906C0800), /* ~= 10^318 */ |
|
1891
|
|
|
|
|
|
|
U64(0xCF39E50F, 0xEAE16BEF), U64(0xD768226B, 0x34870A00), /* ~= 10^319 */ |
|
1892
|
|
|
|
|
|
|
U64(0x81842F29, 0xF2CCE375), U64(0xE6A11583, 0x00D46640), /* ~= 10^320 */ |
|
1893
|
|
|
|
|
|
|
U64(0xA1E53AF4, 0x6F801C53), U64(0x60495AE3, 0xC1097FD0), /* ~= 10^321 */ |
|
1894
|
|
|
|
|
|
|
U64(0xCA5E89B1, 0x8B602368), U64(0x385BB19C, 0xB14BDFC4), /* ~= 10^322 */ |
|
1895
|
|
|
|
|
|
|
U64(0xFCF62C1D, 0xEE382C42), U64(0x46729E03, 0xDD9ED7B5), /* ~= 10^323 */ |
|
1896
|
|
|
|
|
|
|
U64(0x9E19DB92, 0xB4E31BA9), U64(0x6C07A2C2, 0x6A8346D1) /* ~= 10^324 */ |
|
1897
|
|
|
|
|
|
|
}; |
|
1898
|
|
|
|
|
|
|
|
|
1899
|
|
|
|
|
|
|
/** |
|
1900
|
|
|
|
|
|
|
Get the cached pow10 value from `pow10_sig_table`. |
|
1901
|
|
|
|
|
|
|
@param exp10 The exponent of pow(10, e). This value must in range |
|
1902
|
|
|
|
|
|
|
`POW10_SIG_TABLE_MIN_EXP` to `POW10_SIG_TABLE_MAX_EXP`. |
|
1903
|
|
|
|
|
|
|
@param hi The highest 64 bits of pow(10, e). |
|
1904
|
|
|
|
|
|
|
@param lo The lower 64 bits after `hi`. |
|
1905
|
|
|
|
|
|
|
*/ |
|
1906
|
|
|
|
|
|
|
static_inline void pow10_table_get_sig(i32 exp10, u64 *hi, u64 *lo) { |
|
1907
|
1
|
|
|
|
|
|
i32 idx = exp10 - (POW10_SIG_TABLE_MIN_EXP); |
|
1908
|
1
|
|
|
|
|
|
*hi = pow10_sig_table[idx * 2]; |
|
1909
|
1
|
|
|
|
|
|
*lo = pow10_sig_table[idx * 2 + 1]; |
|
1910
|
1
|
|
|
|
|
|
} |
|
1911
|
|
|
|
|
|
|
|
|
1912
|
|
|
|
|
|
|
/** |
|
1913
|
|
|
|
|
|
|
Get the exponent (base 2) for highest 64 bits significand in `pow10_sig_table`. |
|
1914
|
|
|
|
|
|
|
*/ |
|
1915
|
|
|
|
|
|
|
static_inline void pow10_table_get_exp(i32 exp10, i32 *exp2) { |
|
1916
|
|
|
|
|
|
|
/* e2 = floor(log2(pow(10, e))) - 64 + 1 */ |
|
1917
|
|
|
|
|
|
|
/* = floor(e * log2(10) - 63) */ |
|
1918
|
0
|
|
|
|
|
|
*exp2 = (exp10 * 217706 - 4128768) >> 16; |
|
1919
|
0
|
|
|
|
|
|
} |
|
1920
|
|
|
|
|
|
|
|
|
1921
|
|
|
|
|
|
|
#endif |
|
1922
|
|
|
|
|
|
|
|
|
1923
|
|
|
|
|
|
|
|
|
1924
|
|
|
|
|
|
|
|
|
1925
|
|
|
|
|
|
|
/*============================================================================== |
|
1926
|
|
|
|
|
|
|
* MARK: - Number and Bit Utils (Private) |
|
1927
|
|
|
|
|
|
|
*============================================================================*/ |
|
1928
|
|
|
|
|
|
|
|
|
1929
|
|
|
|
|
|
|
/** Convert bits to double. */ |
|
1930
|
|
|
|
|
|
|
static_inline f64 f64_from_bits(u64 u) { |
|
1931
|
|
|
|
|
|
|
f64 f; |
|
1932
|
0
|
|
|
|
|
|
memcpy(&f, &u, sizeof(u)); |
|
1933
|
0
|
|
|
|
|
|
return f; |
|
1934
|
|
|
|
|
|
|
} |
|
1935
|
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
/** Convert double to bits. */ |
|
1937
|
|
|
|
|
|
|
static_inline u64 f64_to_bits(f64 f) { |
|
1938
|
|
|
|
|
|
|
u64 u; |
|
1939
|
|
|
|
|
|
|
memcpy(&u, &f, sizeof(u)); |
|
1940
|
|
|
|
|
|
|
return u; |
|
1941
|
|
|
|
|
|
|
} |
|
1942
|
|
|
|
|
|
|
|
|
1943
|
|
|
|
|
|
|
/** Convert double to bits. */ |
|
1944
|
|
|
|
|
|
|
static_inline u32 f32_to_bits(f32 f) { |
|
1945
|
|
|
|
|
|
|
u32 u; |
|
1946
|
0
|
|
|
|
|
|
memcpy(&u, &f, sizeof(u)); |
|
1947
|
0
|
|
|
|
|
|
return u; |
|
1948
|
|
|
|
|
|
|
} |
|
1949
|
|
|
|
|
|
|
|
|
1950
|
|
|
|
|
|
|
/** Get 'infinity' bits with sign. */ |
|
1951
|
|
|
|
|
|
|
static_inline u64 f64_bits_inf(bool sign) { |
|
1952
|
|
|
|
|
|
|
#if YYJSON_HAS_IEEE_754 |
|
1953
|
0
|
|
|
|
|
|
return F64_BITS_INF | ((u64)sign << 63); |
|
1954
|
|
|
|
|
|
|
#elif defined(INFINITY) |
|
1955
|
|
|
|
|
|
|
return f64_to_bits(sign ? -INFINITY : INFINITY); |
|
1956
|
|
|
|
|
|
|
#else |
|
1957
|
|
|
|
|
|
|
return f64_to_bits(sign ? -HUGE_VAL : HUGE_VAL); |
|
1958
|
|
|
|
|
|
|
#endif |
|
1959
|
|
|
|
|
|
|
} |
|
1960
|
|
|
|
|
|
|
|
|
1961
|
|
|
|
|
|
|
/** Get 'nan' bits with sign. */ |
|
1962
|
|
|
|
|
|
|
static_inline u64 f64_bits_nan(bool sign) { |
|
1963
|
|
|
|
|
|
|
#if YYJSON_HAS_IEEE_754 |
|
1964
|
0
|
|
|
|
|
|
return F64_BITS_NAN | ((u64)sign << 63); |
|
1965
|
|
|
|
|
|
|
#elif defined(NAN) |
|
1966
|
|
|
|
|
|
|
return f64_to_bits(sign ? (f64)-NAN : (f64)NAN); |
|
1967
|
|
|
|
|
|
|
#else |
|
1968
|
|
|
|
|
|
|
return f64_to_bits((sign ? -0.0 : 0.0) / 0.0); |
|
1969
|
|
|
|
|
|
|
#endif |
|
1970
|
|
|
|
|
|
|
} |
|
1971
|
|
|
|
|
|
|
|
|
1972
|
|
|
|
|
|
|
/** Casting double to float, allow overflow. */ |
|
1973
|
|
|
|
|
|
|
#if yyjson_has_attribute(no_sanitize) |
|
1974
|
|
|
|
|
|
|
__attribute__((no_sanitize("undefined"))) |
|
1975
|
|
|
|
|
|
|
#elif yyjson_gcc_available(4, 9, 0) |
|
1976
|
|
|
|
|
|
|
__attribute__((__no_sanitize_undefined__)) |
|
1977
|
|
|
|
|
|
|
#endif |
|
1978
|
|
|
|
|
|
|
static_inline f32 f64_to_f32(f64 val) { |
|
1979
|
0
|
|
|
|
|
|
return (f32)val; |
|
1980
|
|
|
|
|
|
|
} |
|
1981
|
|
|
|
|
|
|
|
|
1982
|
|
|
|
|
|
|
/** Returns the number of leading 0-bits in value (input should not be 0). */ |
|
1983
|
|
|
|
|
|
|
static_inline u32 u64_lz_bits(u64 v) { |
|
1984
|
|
|
|
|
|
|
#if GCC_HAS_CLZLL |
|
1985
|
0
|
|
|
|
|
|
return (u32)__builtin_clzll(v); |
|
1986
|
|
|
|
|
|
|
#elif MSC_HAS_BIT_SCAN_64 |
|
1987
|
|
|
|
|
|
|
unsigned long r; |
|
1988
|
|
|
|
|
|
|
_BitScanReverse64(&r, v); |
|
1989
|
|
|
|
|
|
|
return (u32)63 - (u32)r; |
|
1990
|
|
|
|
|
|
|
#elif MSC_HAS_BIT_SCAN |
|
1991
|
|
|
|
|
|
|
unsigned long hi, lo; |
|
1992
|
|
|
|
|
|
|
bool hi_set = _BitScanReverse(&hi, (u32)(v >> 32)) != 0; |
|
1993
|
|
|
|
|
|
|
_BitScanReverse(&lo, (u32)v); |
|
1994
|
|
|
|
|
|
|
hi |= 32; |
|
1995
|
|
|
|
|
|
|
return (u32)63 - (u32)(hi_set ? hi : lo); |
|
1996
|
|
|
|
|
|
|
#else |
|
1997
|
|
|
|
|
|
|
/* branchless, use De Bruijn sequence */ |
|
1998
|
|
|
|
|
|
|
/* see: https://www.chessprogramming.org/BitScan */ |
|
1999
|
|
|
|
|
|
|
const u8 table[64] = { |
|
2000
|
|
|
|
|
|
|
63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2, |
|
2001
|
|
|
|
|
|
|
9, 5, 28, 11, 13, 21, 42, 19, 25, 31, 34, 40, 46, 52, 59, 1, |
|
2002
|
|
|
|
|
|
|
17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41, 53, 18, |
|
2003
|
|
|
|
|
|
|
38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0 |
|
2004
|
|
|
|
|
|
|
}; |
|
2005
|
|
|
|
|
|
|
v |= v >> 1; |
|
2006
|
|
|
|
|
|
|
v |= v >> 2; |
|
2007
|
|
|
|
|
|
|
v |= v >> 4; |
|
2008
|
|
|
|
|
|
|
v |= v >> 8; |
|
2009
|
|
|
|
|
|
|
v |= v >> 16; |
|
2010
|
|
|
|
|
|
|
v |= v >> 32; |
|
2011
|
|
|
|
|
|
|
return table[(v * U64(0x03F79D71, 0xB4CB0A89)) >> 58]; |
|
2012
|
|
|
|
|
|
|
#endif |
|
2013
|
|
|
|
|
|
|
} |
|
2014
|
|
|
|
|
|
|
|
|
2015
|
|
|
|
|
|
|
/** Returns the number of trailing 0-bits in value (input should not be 0). */ |
|
2016
|
|
|
|
|
|
|
static_inline u32 u64_tz_bits(u64 v) { |
|
2017
|
|
|
|
|
|
|
#if GCC_HAS_CTZLL |
|
2018
|
1
|
|
|
|
|
|
return (u32)__builtin_ctzll(v); |
|
2019
|
|
|
|
|
|
|
#elif MSC_HAS_BIT_SCAN_64 |
|
2020
|
|
|
|
|
|
|
unsigned long r; |
|
2021
|
|
|
|
|
|
|
_BitScanForward64(&r, v); |
|
2022
|
|
|
|
|
|
|
return (u32)r; |
|
2023
|
|
|
|
|
|
|
#elif MSC_HAS_BIT_SCAN |
|
2024
|
|
|
|
|
|
|
unsigned long lo, hi; |
|
2025
|
|
|
|
|
|
|
bool lo_set = _BitScanForward(&lo, (u32)(v)) != 0; |
|
2026
|
|
|
|
|
|
|
_BitScanForward(&hi, (u32)(v >> 32)); |
|
2027
|
|
|
|
|
|
|
hi += 32; |
|
2028
|
|
|
|
|
|
|
return lo_set ? lo : hi; |
|
2029
|
|
|
|
|
|
|
#else |
|
2030
|
|
|
|
|
|
|
/* branchless, use De Bruijn sequence */ |
|
2031
|
|
|
|
|
|
|
/* see: https://www.chessprogramming.org/BitScan */ |
|
2032
|
|
|
|
|
|
|
const u8 table[64] = { |
|
2033
|
|
|
|
|
|
|
0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, |
|
2034
|
|
|
|
|
|
|
62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, |
|
2035
|
|
|
|
|
|
|
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, |
|
2036
|
|
|
|
|
|
|
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 |
|
2037
|
|
|
|
|
|
|
}; |
|
2038
|
|
|
|
|
|
|
return table[((v & (~v + 1)) * U64(0x022FDD63, 0xCC95386D)) >> 58]; |
|
2039
|
|
|
|
|
|
|
#endif |
|
2040
|
|
|
|
|
|
|
} |
|
2041
|
|
|
|
|
|
|
|
|
2042
|
|
|
|
|
|
|
/** Multiplies two 64-bit unsigned integers (a * b), |
|
2043
|
|
|
|
|
|
|
returns the 128-bit result as 'hi' and 'lo'. */ |
|
2044
|
|
|
|
|
|
|
static_inline void u128_mul(u64 a, u64 b, u64 *hi, u64 *lo) { |
|
2045
|
|
|
|
|
|
|
#if YYJSON_HAS_INT128 |
|
2046
|
1
|
|
|
|
|
|
u128 m = (u128)a * b; |
|
2047
|
1
|
|
|
|
|
|
*hi = (u64)(m >> 64); |
|
2048
|
1
|
|
|
|
|
|
*lo = (u64)(m); |
|
2049
|
|
|
|
|
|
|
#elif MSC_HAS_UMUL128 |
|
2050
|
|
|
|
|
|
|
*lo = _umul128(a, b, hi); |
|
2051
|
|
|
|
|
|
|
#else |
|
2052
|
|
|
|
|
|
|
u32 a0 = (u32)(a), a1 = (u32)(a >> 32); |
|
2053
|
|
|
|
|
|
|
u32 b0 = (u32)(b), b1 = (u32)(b >> 32); |
|
2054
|
|
|
|
|
|
|
u64 p00 = (u64)a0 * b0, p01 = (u64)a0 * b1; |
|
2055
|
|
|
|
|
|
|
u64 p10 = (u64)a1 * b0, p11 = (u64)a1 * b1; |
|
2056
|
|
|
|
|
|
|
u64 m0 = p01 + (p00 >> 32); |
|
2057
|
|
|
|
|
|
|
u32 m00 = (u32)(m0), m01 = (u32)(m0 >> 32); |
|
2058
|
|
|
|
|
|
|
u64 m1 = p10 + m00; |
|
2059
|
|
|
|
|
|
|
u32 m10 = (u32)(m1), m11 = (u32)(m1 >> 32); |
|
2060
|
|
|
|
|
|
|
*hi = p11 + m01 + m11; |
|
2061
|
|
|
|
|
|
|
*lo = ((u64)m10 << 32) | (u32)p00; |
|
2062
|
|
|
|
|
|
|
#endif |
|
2063
|
1
|
|
|
|
|
|
} |
|
2064
|
|
|
|
|
|
|
|
|
2065
|
|
|
|
|
|
|
/** Multiplies two 64-bit unsigned integers and add a value (a * b + c), |
|
2066
|
|
|
|
|
|
|
returns the 128-bit result as 'hi' and 'lo'. */ |
|
2067
|
|
|
|
|
|
|
static_inline void u128_mul_add(u64 a, u64 b, u64 c, u64 *hi, u64 *lo) { |
|
2068
|
|
|
|
|
|
|
#if YYJSON_HAS_INT128 |
|
2069
|
1
|
|
|
|
|
|
u128 m = (u128)a * b + c; |
|
2070
|
1
|
|
|
|
|
|
*hi = (u64)(m >> 64); |
|
2071
|
1
|
|
|
|
|
|
*lo = (u64)(m); |
|
2072
|
|
|
|
|
|
|
#else |
|
2073
|
|
|
|
|
|
|
u64 h, l, t; |
|
2074
|
|
|
|
|
|
|
u128_mul(a, b, &h, &l); |
|
2075
|
|
|
|
|
|
|
t = l + c; |
|
2076
|
|
|
|
|
|
|
h += (u64)(((t < l) | (t < c))); |
|
2077
|
|
|
|
|
|
|
*hi = h; |
|
2078
|
|
|
|
|
|
|
*lo = t; |
|
2079
|
|
|
|
|
|
|
#endif |
|
2080
|
1
|
|
|
|
|
|
} |
|
2081
|
|
|
|
|
|
|
|
|
2082
|
|
|
|
|
|
|
|
|
2083
|
|
|
|
|
|
|
|
|
2084
|
|
|
|
|
|
|
/*============================================================================== |
|
2085
|
|
|
|
|
|
|
* MARK: - File Utils (Private) |
|
2086
|
|
|
|
|
|
|
* These functions are used to read and write JSON files. |
|
2087
|
|
|
|
|
|
|
*============================================================================*/ |
|
2088
|
|
|
|
|
|
|
|
|
2089
|
|
|
|
|
|
|
#define YYJSON_FOPEN_E |
|
2090
|
|
|
|
|
|
|
#if !defined(_MSC_VER) && defined(__GLIBC__) && defined(__GLIBC_PREREQ) |
|
2091
|
|
|
|
|
|
|
# if __GLIBC_PREREQ(2, 7) |
|
2092
|
|
|
|
|
|
|
# undef YYJSON_FOPEN_E |
|
2093
|
|
|
|
|
|
|
# define YYJSON_FOPEN_E "e" /* glibc extension to enable O_CLOEXEC */ |
|
2094
|
|
|
|
|
|
|
# endif |
|
2095
|
|
|
|
|
|
|
#endif |
|
2096
|
|
|
|
|
|
|
|
|
2097
|
|
|
|
|
|
|
static_inline FILE *fopen_safe(const char *path, const char *mode) { |
|
2098
|
|
|
|
|
|
|
#if YYJSON_MSC_VER >= 1400 |
|
2099
|
|
|
|
|
|
|
FILE *file = NULL; |
|
2100
|
|
|
|
|
|
|
if (fopen_s(&file, path, mode) != 0) return NULL; |
|
2101
|
|
|
|
|
|
|
return file; |
|
2102
|
|
|
|
|
|
|
#else |
|
2103
|
4
|
|
|
|
|
|
return fopen(path, mode); |
|
2104
|
|
|
|
|
|
|
#endif |
|
2105
|
|
|
|
|
|
|
} |
|
2106
|
|
|
|
|
|
|
|
|
2107
|
|
|
|
|
|
|
static_inline FILE *fopen_readonly(const char *path) { |
|
2108
|
4
|
|
|
|
|
|
return fopen_safe(path, "rb" YYJSON_FOPEN_E); |
|
2109
|
|
|
|
|
|
|
} |
|
2110
|
|
|
|
|
|
|
|
|
2111
|
|
|
|
|
|
|
static_inline FILE *fopen_writeonly(const char *path) { |
|
2112
|
3
|
|
|
|
|
|
return fopen_safe(path, "wb" YYJSON_FOPEN_E); |
|
2113
|
|
|
|
|
|
|
} |
|
2114
|
|
|
|
|
|
|
|
|
2115
|
|
|
|
|
|
|
static_inline usize fread_safe(void *buf, usize size, FILE *file) { |
|
2116
|
|
|
|
|
|
|
#if YYJSON_MSC_VER >= 1400 |
|
2117
|
|
|
|
|
|
|
return fread_s(buf, size, 1, size, file); |
|
2118
|
|
|
|
|
|
|
#else |
|
2119
|
3
|
|
|
|
|
|
return fread(buf, 1, size, file); |
|
2120
|
|
|
|
|
|
|
#endif |
|
2121
|
|
|
|
|
|
|
} |
|
2122
|
|
|
|
|
|
|
|
|
2123
|
|
|
|
|
|
|
|
|
2124
|
|
|
|
|
|
|
|
|
2125
|
|
|
|
|
|
|
/*============================================================================== |
|
2126
|
|
|
|
|
|
|
* MARK: - Size Utils (Private) |
|
2127
|
|
|
|
|
|
|
* These functions are used for memory allocation. |
|
2128
|
|
|
|
|
|
|
*============================================================================*/ |
|
2129
|
|
|
|
|
|
|
|
|
2130
|
|
|
|
|
|
|
/** Returns whether the size is overflow after increment. */ |
|
2131
|
|
|
|
|
|
|
static_inline bool size_add_is_overflow(usize size, usize add) { |
|
2132
|
|
|
|
|
|
|
return size > (size + add); |
|
2133
|
|
|
|
|
|
|
} |
|
2134
|
|
|
|
|
|
|
|
|
2135
|
|
|
|
|
|
|
/** Returns whether the size is power of 2 (size should not be 0). */ |
|
2136
|
|
|
|
|
|
|
static_inline bool size_is_pow2(usize size) { |
|
2137
|
0
|
|
|
|
|
|
return (size & (size - 1)) == 0; |
|
2138
|
|
|
|
|
|
|
} |
|
2139
|
|
|
|
|
|
|
|
|
2140
|
|
|
|
|
|
|
/** Align size upwards (may overflow). */ |
|
2141
|
|
|
|
|
|
|
static_inline usize size_align_up(usize size, usize align) { |
|
2142
|
15033
|
50
|
|
|
|
|
if (size_is_pow2(align)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2143
|
15033
|
|
|
|
|
|
return (size + (align - 1)) & ~(align - 1); |
|
2144
|
|
|
|
|
|
|
} else { |
|
2145
|
0
|
|
|
|
|
|
return size + align - (size + align - 1) % align - 1; |
|
2146
|
|
|
|
|
|
|
} |
|
2147
|
|
|
|
|
|
|
} |
|
2148
|
|
|
|
|
|
|
|
|
2149
|
|
|
|
|
|
|
/** Align size downwards. */ |
|
2150
|
|
|
|
|
|
|
static_inline usize size_align_down(usize size, usize align) { |
|
2151
|
0
|
0
|
|
|
|
|
if (size_is_pow2(align)) { |
|
2152
|
0
|
|
|
|
|
|
return size & ~(align - 1); |
|
2153
|
|
|
|
|
|
|
} else { |
|
2154
|
0
|
|
|
|
|
|
return size - (size % align); |
|
2155
|
|
|
|
|
|
|
} |
|
2156
|
|
|
|
|
|
|
} |
|
2157
|
|
|
|
|
|
|
|
|
2158
|
|
|
|
|
|
|
/** Align address upwards (may overflow). */ |
|
2159
|
|
|
|
|
|
|
static_inline void *mem_align_up(void *mem, usize align) { |
|
2160
|
|
|
|
|
|
|
usize size; |
|
2161
|
0
|
|
|
|
|
|
memcpy(&size, &mem, sizeof(usize)); |
|
2162
|
0
|
|
|
|
|
|
size = size_align_up(size, align); |
|
2163
|
0
|
|
|
|
|
|
memcpy(&mem, &size, sizeof(usize)); |
|
2164
|
0
|
|
|
|
|
|
return mem; |
|
2165
|
|
|
|
|
|
|
} |
|
2166
|
|
|
|
|
|
|
|
|
2167
|
|
|
|
|
|
|
|
|
2168
|
|
|
|
|
|
|
|
|
2169
|
|
|
|
|
|
|
/*============================================================================== |
|
2170
|
|
|
|
|
|
|
* MARK: - Default Memory Allocator (Private) |
|
2171
|
|
|
|
|
|
|
* This is a simple libc memory allocator wrapper. |
|
2172
|
|
|
|
|
|
|
*============================================================================*/ |
|
2173
|
|
|
|
|
|
|
|
|
2174
|
90598
|
|
|
|
|
|
static void *default_malloc(void *ctx, usize size) { |
|
2175
|
90598
|
|
|
|
|
|
return malloc(size); |
|
2176
|
|
|
|
|
|
|
} |
|
2177
|
|
|
|
|
|
|
|
|
2178
|
53
|
|
|
|
|
|
static void *default_realloc(void *ctx, void *ptr, usize old_size, usize size) { |
|
2179
|
53
|
|
|
|
|
|
return realloc(ptr, size); |
|
2180
|
|
|
|
|
|
|
} |
|
2181
|
|
|
|
|
|
|
|
|
2182
|
75555
|
|
|
|
|
|
static void default_free(void *ctx, void *ptr) { |
|
2183
|
75555
|
|
|
|
|
|
free(ptr); |
|
2184
|
75555
|
|
|
|
|
|
} |
|
2185
|
|
|
|
|
|
|
|
|
2186
|
|
|
|
|
|
|
static const yyjson_alc YYJSON_DEFAULT_ALC = { |
|
2187
|
|
|
|
|
|
|
default_malloc, default_realloc, default_free, NULL |
|
2188
|
|
|
|
|
|
|
}; |
|
2189
|
|
|
|
|
|
|
|
|
2190
|
|
|
|
|
|
|
|
|
2191
|
|
|
|
|
|
|
|
|
2192
|
|
|
|
|
|
|
/*============================================================================== |
|
2193
|
|
|
|
|
|
|
* MARK: - Null Memory Allocator (Private) |
|
2194
|
|
|
|
|
|
|
* This allocator is just a placeholder to ensure that the internal |
|
2195
|
|
|
|
|
|
|
* malloc/realloc/free function pointers are not null. |
|
2196
|
|
|
|
|
|
|
*============================================================================*/ |
|
2197
|
|
|
|
|
|
|
|
|
2198
|
0
|
|
|
|
|
|
static void *null_malloc(void *ctx, usize size) { |
|
2199
|
0
|
|
|
|
|
|
return NULL; |
|
2200
|
|
|
|
|
|
|
} |
|
2201
|
|
|
|
|
|
|
|
|
2202
|
0
|
|
|
|
|
|
static void *null_realloc(void *ctx, void *ptr, usize old_size, usize size) { |
|
2203
|
0
|
|
|
|
|
|
return NULL; |
|
2204
|
|
|
|
|
|
|
} |
|
2205
|
|
|
|
|
|
|
|
|
2206
|
0
|
|
|
|
|
|
static void null_free(void *ctx, void *ptr) { |
|
2207
|
0
|
|
|
|
|
|
return; |
|
2208
|
|
|
|
|
|
|
} |
|
2209
|
|
|
|
|
|
|
|
|
2210
|
|
|
|
|
|
|
static const yyjson_alc YYJSON_NULL_ALC = { |
|
2211
|
|
|
|
|
|
|
null_malloc, null_realloc, null_free, NULL |
|
2212
|
|
|
|
|
|
|
}; |
|
2213
|
|
|
|
|
|
|
|
|
2214
|
|
|
|
|
|
|
|
|
2215
|
|
|
|
|
|
|
|
|
2216
|
|
|
|
|
|
|
/*============================================================================== |
|
2217
|
|
|
|
|
|
|
* MARK: - Pool Memory Allocator (Public) |
|
2218
|
|
|
|
|
|
|
* This allocator is initialized with a fixed-size buffer. |
|
2219
|
|
|
|
|
|
|
* The buffer is split into multiple memory chunks for memory allocation. |
|
2220
|
|
|
|
|
|
|
*============================================================================*/ |
|
2221
|
|
|
|
|
|
|
|
|
2222
|
|
|
|
|
|
|
/** memory chunk header */ |
|
2223
|
|
|
|
|
|
|
typedef struct pool_chunk { |
|
2224
|
|
|
|
|
|
|
usize size; /* chunk memory size, include chunk header */ |
|
2225
|
|
|
|
|
|
|
struct pool_chunk *next; /* linked list, nullable */ |
|
2226
|
|
|
|
|
|
|
/* char mem[]; flexible array member */ |
|
2227
|
|
|
|
|
|
|
} pool_chunk; |
|
2228
|
|
|
|
|
|
|
|
|
2229
|
|
|
|
|
|
|
/** allocator ctx header */ |
|
2230
|
|
|
|
|
|
|
typedef struct pool_ctx { |
|
2231
|
|
|
|
|
|
|
usize size; /* total memory size, include ctx header */ |
|
2232
|
|
|
|
|
|
|
pool_chunk *free_list; /* linked list, nullable */ |
|
2233
|
|
|
|
|
|
|
/* pool_chunk chunks[]; flexible array member */ |
|
2234
|
|
|
|
|
|
|
} pool_ctx; |
|
2235
|
|
|
|
|
|
|
|
|
2236
|
|
|
|
|
|
|
/** align up the input size to chunk size */ |
|
2237
|
|
|
|
|
|
|
static_inline void pool_size_align(usize *size) { |
|
2238
|
0
|
|
|
|
|
|
*size = size_align_up(*size, sizeof(pool_chunk)) + sizeof(pool_chunk); |
|
2239
|
0
|
|
|
|
|
|
} |
|
2240
|
|
|
|
|
|
|
|
|
2241
|
0
|
|
|
|
|
|
static void *pool_malloc(void *ctx_ptr, usize size) { |
|
2242
|
|
|
|
|
|
|
/* assert(size != 0) */ |
|
2243
|
0
|
|
|
|
|
|
pool_ctx *ctx = (pool_ctx *)ctx_ptr; |
|
2244
|
0
|
|
|
|
|
|
pool_chunk *next, *prev = NULL, *cur = ctx->free_list; |
|
2245
|
|
|
|
|
|
|
|
|
2246
|
0
|
0
|
|
|
|
|
if (unlikely(size >= ctx->size)) return NULL; |
|
2247
|
|
|
|
|
|
|
pool_size_align(&size); |
|
2248
|
|
|
|
|
|
|
|
|
2249
|
0
|
0
|
|
|
|
|
while (cur) { |
|
2250
|
0
|
0
|
|
|
|
|
if (cur->size < size) { |
|
2251
|
|
|
|
|
|
|
/* not enough space, try next chunk */ |
|
2252
|
0
|
|
|
|
|
|
prev = cur; |
|
2253
|
0
|
|
|
|
|
|
cur = cur->next; |
|
2254
|
0
|
|
|
|
|
|
continue; |
|
2255
|
|
|
|
|
|
|
} |
|
2256
|
0
|
0
|
|
|
|
|
if (cur->size >= size + sizeof(pool_chunk) * 2) { |
|
2257
|
|
|
|
|
|
|
/* too much space, split this chunk */ |
|
2258
|
0
|
|
|
|
|
|
next = (pool_chunk *)(void *)((u8 *)cur + size); |
|
2259
|
0
|
|
|
|
|
|
next->size = cur->size - size; |
|
2260
|
0
|
|
|
|
|
|
next->next = cur->next; |
|
2261
|
0
|
|
|
|
|
|
cur->size = size; |
|
2262
|
|
|
|
|
|
|
} else { |
|
2263
|
|
|
|
|
|
|
/* just enough space, use whole chunk */ |
|
2264
|
0
|
|
|
|
|
|
next = cur->next; |
|
2265
|
|
|
|
|
|
|
} |
|
2266
|
0
|
0
|
|
|
|
|
if (prev) prev->next = next; |
|
2267
|
0
|
|
|
|
|
|
else ctx->free_list = next; |
|
2268
|
0
|
|
|
|
|
|
return (void *)(cur + 1); |
|
2269
|
|
|
|
|
|
|
} |
|
2270
|
0
|
|
|
|
|
|
return NULL; |
|
2271
|
|
|
|
|
|
|
} |
|
2272
|
|
|
|
|
|
|
|
|
2273
|
0
|
|
|
|
|
|
static void pool_free(void *ctx_ptr, void *ptr) { |
|
2274
|
|
|
|
|
|
|
/* assert(ptr != NULL) */ |
|
2275
|
0
|
|
|
|
|
|
pool_ctx *ctx = (pool_ctx *)ctx_ptr; |
|
2276
|
0
|
|
|
|
|
|
pool_chunk *cur = ((pool_chunk *)ptr) - 1; |
|
2277
|
0
|
|
|
|
|
|
pool_chunk *prev = NULL, *next = ctx->free_list; |
|
2278
|
|
|
|
|
|
|
|
|
2279
|
0
|
0
|
|
|
|
|
while (next && next < cur) { |
|
|
|
0
|
|
|
|
|
|
|
2280
|
0
|
|
|
|
|
|
prev = next; |
|
2281
|
0
|
|
|
|
|
|
next = next->next; |
|
2282
|
|
|
|
|
|
|
} |
|
2283
|
0
|
0
|
|
|
|
|
if (prev) prev->next = cur; |
|
2284
|
0
|
|
|
|
|
|
else ctx->free_list = cur; |
|
2285
|
0
|
|
|
|
|
|
cur->next = next; |
|
2286
|
|
|
|
|
|
|
|
|
2287
|
0
|
0
|
|
|
|
|
if (next && ((u8 *)cur + cur->size) == (u8 *)next) { |
|
|
|
0
|
|
|
|
|
|
|
2288
|
|
|
|
|
|
|
/* merge cur to higher chunk */ |
|
2289
|
0
|
|
|
|
|
|
cur->size += next->size; |
|
2290
|
0
|
|
|
|
|
|
cur->next = next->next; |
|
2291
|
|
|
|
|
|
|
} |
|
2292
|
0
|
0
|
|
|
|
|
if (prev && ((u8 *)prev + prev->size) == (u8 *)cur) { |
|
|
|
0
|
|
|
|
|
|
|
2293
|
|
|
|
|
|
|
/* merge cur to lower chunk */ |
|
2294
|
0
|
|
|
|
|
|
prev->size += cur->size; |
|
2295
|
0
|
|
|
|
|
|
prev->next = cur->next; |
|
2296
|
|
|
|
|
|
|
} |
|
2297
|
0
|
|
|
|
|
|
} |
|
2298
|
|
|
|
|
|
|
|
|
2299
|
0
|
|
|
|
|
|
static void *pool_realloc(void *ctx_ptr, void *ptr, |
|
2300
|
|
|
|
|
|
|
usize old_size, usize size) { |
|
2301
|
|
|
|
|
|
|
/* assert(ptr != NULL && size != 0 && old_size < size) */ |
|
2302
|
0
|
|
|
|
|
|
pool_ctx *ctx = (pool_ctx *)ctx_ptr; |
|
2303
|
0
|
|
|
|
|
|
pool_chunk *cur = ((pool_chunk *)ptr) - 1, *prev, *next, *tmp; |
|
2304
|
|
|
|
|
|
|
|
|
2305
|
|
|
|
|
|
|
/* check size */ |
|
2306
|
0
|
0
|
|
|
|
|
if (unlikely(size >= ctx->size)) return NULL; |
|
2307
|
|
|
|
|
|
|
pool_size_align(&old_size); |
|
2308
|
|
|
|
|
|
|
pool_size_align(&size); |
|
2309
|
0
|
0
|
|
|
|
|
if (unlikely(old_size == size)) return ptr; |
|
2310
|
|
|
|
|
|
|
|
|
2311
|
|
|
|
|
|
|
/* find next and prev chunk */ |
|
2312
|
0
|
|
|
|
|
|
prev = NULL; |
|
2313
|
0
|
|
|
|
|
|
next = ctx->free_list; |
|
2314
|
0
|
0
|
|
|
|
|
while (next && next < cur) { |
|
|
|
0
|
|
|
|
|
|
|
2315
|
0
|
|
|
|
|
|
prev = next; |
|
2316
|
0
|
|
|
|
|
|
next = next->next; |
|
2317
|
|
|
|
|
|
|
} |
|
2318
|
|
|
|
|
|
|
|
|
2319
|
0
|
0
|
|
|
|
|
if ((u8 *)cur + cur->size == (u8 *)next && cur->size + next->size >= size) { |
|
|
|
0
|
|
|
|
|
|
|
2320
|
|
|
|
|
|
|
/* merge to higher chunk if they are contiguous */ |
|
2321
|
0
|
|
|
|
|
|
usize free_size = cur->size + next->size - size; |
|
2322
|
0
|
0
|
|
|
|
|
if (free_size > sizeof(pool_chunk) * 2) { |
|
2323
|
0
|
|
|
|
|
|
tmp = (pool_chunk *)(void *)((u8 *)cur + size); |
|
2324
|
0
|
0
|
|
|
|
|
if (prev) prev->next = tmp; |
|
2325
|
0
|
|
|
|
|
|
else ctx->free_list = tmp; |
|
2326
|
0
|
|
|
|
|
|
tmp->next = next->next; |
|
2327
|
0
|
|
|
|
|
|
tmp->size = free_size; |
|
2328
|
0
|
|
|
|
|
|
cur->size = size; |
|
2329
|
|
|
|
|
|
|
} else { |
|
2330
|
0
|
0
|
|
|
|
|
if (prev) prev->next = next->next; |
|
2331
|
0
|
|
|
|
|
|
else ctx->free_list = next->next; |
|
2332
|
0
|
|
|
|
|
|
cur->size += next->size; |
|
2333
|
|
|
|
|
|
|
} |
|
2334
|
0
|
|
|
|
|
|
return ptr; |
|
2335
|
|
|
|
|
|
|
} else { |
|
2336
|
|
|
|
|
|
|
/* fallback to malloc and memcpy */ |
|
2337
|
0
|
|
|
|
|
|
void *new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk)); |
|
2338
|
0
|
0
|
|
|
|
|
if (new_ptr) { |
|
2339
|
0
|
|
|
|
|
|
memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk)); |
|
2340
|
0
|
|
|
|
|
|
pool_free(ctx_ptr, ptr); |
|
2341
|
|
|
|
|
|
|
} |
|
2342
|
0
|
|
|
|
|
|
return new_ptr; |
|
2343
|
|
|
|
|
|
|
} |
|
2344
|
|
|
|
|
|
|
} |
|
2345
|
|
|
|
|
|
|
|
|
2346
|
0
|
|
|
|
|
|
bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) { |
|
2347
|
|
|
|
|
|
|
pool_chunk *chunk; |
|
2348
|
|
|
|
|
|
|
pool_ctx *ctx; |
|
2349
|
|
|
|
|
|
|
|
|
2350
|
0
|
0
|
|
|
|
|
if (unlikely(!alc)) return false; |
|
2351
|
0
|
|
|
|
|
|
*alc = YYJSON_NULL_ALC; |
|
2352
|
0
|
0
|
|
|
|
|
if (size < sizeof(pool_ctx) * 4) return false; |
|
2353
|
0
|
|
|
|
|
|
ctx = (pool_ctx *)mem_align_up(buf, sizeof(pool_ctx)); |
|
2354
|
0
|
0
|
|
|
|
|
if (unlikely(!ctx)) return false; |
|
2355
|
0
|
|
|
|
|
|
size -= (usize)((u8 *)ctx - (u8 *)buf); |
|
2356
|
0
|
|
|
|
|
|
size = size_align_down(size, sizeof(pool_ctx)); |
|
2357
|
|
|
|
|
|
|
|
|
2358
|
0
|
|
|
|
|
|
chunk = (pool_chunk *)(ctx + 1); |
|
2359
|
0
|
|
|
|
|
|
chunk->size = size - sizeof(pool_ctx); |
|
2360
|
0
|
|
|
|
|
|
chunk->next = NULL; |
|
2361
|
0
|
|
|
|
|
|
ctx->size = size; |
|
2362
|
0
|
|
|
|
|
|
ctx->free_list = chunk; |
|
2363
|
|
|
|
|
|
|
|
|
2364
|
0
|
|
|
|
|
|
alc->malloc = pool_malloc; |
|
2365
|
0
|
|
|
|
|
|
alc->realloc = pool_realloc; |
|
2366
|
0
|
|
|
|
|
|
alc->free = pool_free; |
|
2367
|
0
|
|
|
|
|
|
alc->ctx = (void *)ctx; |
|
2368
|
0
|
|
|
|
|
|
return true; |
|
2369
|
|
|
|
|
|
|
} |
|
2370
|
|
|
|
|
|
|
|
|
2371
|
|
|
|
|
|
|
|
|
2372
|
|
|
|
|
|
|
|
|
2373
|
|
|
|
|
|
|
/*============================================================================== |
|
2374
|
|
|
|
|
|
|
* MARK: - Dynamic Memory Allocator (Public) |
|
2375
|
|
|
|
|
|
|
* This allocator allocates memory on demand and does not immediately release |
|
2376
|
|
|
|
|
|
|
* unused memory. Instead, it places the unused memory into a freelist for |
|
2377
|
|
|
|
|
|
|
* potential reuse in the future. It is only when the entire allocator is |
|
2378
|
|
|
|
|
|
|
* destroyed that all previously allocated memory is released at once. |
|
2379
|
|
|
|
|
|
|
*============================================================================*/ |
|
2380
|
|
|
|
|
|
|
|
|
2381
|
|
|
|
|
|
|
/** memory chunk header */ |
|
2382
|
|
|
|
|
|
|
typedef struct dyn_chunk { |
|
2383
|
|
|
|
|
|
|
usize size; /* chunk size, include header */ |
|
2384
|
|
|
|
|
|
|
struct dyn_chunk *next; |
|
2385
|
|
|
|
|
|
|
/* char mem[]; flexible array member */ |
|
2386
|
|
|
|
|
|
|
} dyn_chunk; |
|
2387
|
|
|
|
|
|
|
|
|
2388
|
|
|
|
|
|
|
/** allocator ctx header */ |
|
2389
|
|
|
|
|
|
|
typedef struct { |
|
2390
|
|
|
|
|
|
|
dyn_chunk free_list; /* dummy header, sorted from small to large */ |
|
2391
|
|
|
|
|
|
|
dyn_chunk used_list; /* dummy header */ |
|
2392
|
|
|
|
|
|
|
} dyn_ctx; |
|
2393
|
|
|
|
|
|
|
|
|
2394
|
|
|
|
|
|
|
/** align up the input size to chunk size */ |
|
2395
|
|
|
|
|
|
|
static_inline bool dyn_size_align(usize *size) { |
|
2396
|
0
|
|
|
|
|
|
usize alc_size = *size + sizeof(dyn_chunk); |
|
2397
|
0
|
|
|
|
|
|
alc_size = size_align_up(alc_size, YYJSON_ALC_DYN_MIN_SIZE); |
|
2398
|
0
|
0
|
|
|
|
|
if (unlikely(alc_size < *size)) return false; /* overflow */ |
|
|
|
0
|
|
|
|
|
|
|
2399
|
0
|
|
|
|
|
|
*size = alc_size; |
|
2400
|
0
|
|
|
|
|
|
return true; |
|
2401
|
|
|
|
|
|
|
} |
|
2402
|
|
|
|
|
|
|
|
|
2403
|
|
|
|
|
|
|
/** remove a chunk from list (the chunk must already be in the list) */ |
|
2404
|
|
|
|
|
|
|
static_inline void dyn_chunk_list_remove(dyn_chunk *list, dyn_chunk *chunk) { |
|
2405
|
0
|
|
|
|
|
|
dyn_chunk *prev = list, *cur; |
|
2406
|
0
|
0
|
|
|
|
|
for (cur = prev->next; cur; cur = cur->next) { |
|
|
|
0
|
|
|
|
|
|
|
2407
|
0
|
0
|
|
|
|
|
if (cur == chunk) { |
|
|
|
0
|
|
|
|
|
|
|
2408
|
0
|
|
|
|
|
|
prev->next = cur->next; |
|
2409
|
0
|
|
|
|
|
|
cur->next = NULL; |
|
2410
|
0
|
|
|
|
|
|
return; |
|
2411
|
|
|
|
|
|
|
} |
|
2412
|
0
|
|
|
|
|
|
prev = cur; |
|
2413
|
|
|
|
|
|
|
} |
|
2414
|
|
|
|
|
|
|
} |
|
2415
|
|
|
|
|
|
|
|
|
2416
|
|
|
|
|
|
|
/** add a chunk to list header (the chunk must not be in the list) */ |
|
2417
|
|
|
|
|
|
|
static_inline void dyn_chunk_list_add(dyn_chunk *list, dyn_chunk *chunk) { |
|
2418
|
0
|
|
|
|
|
|
chunk->next = list->next; |
|
2419
|
0
|
|
|
|
|
|
list->next = chunk; |
|
2420
|
0
|
|
|
|
|
|
} |
|
2421
|
|
|
|
|
|
|
|
|
2422
|
0
|
|
|
|
|
|
static void *dyn_malloc(void *ctx_ptr, usize size) { |
|
2423
|
|
|
|
|
|
|
/* assert(size != 0) */ |
|
2424
|
0
|
|
|
|
|
|
const yyjson_alc def = YYJSON_DEFAULT_ALC; |
|
2425
|
0
|
|
|
|
|
|
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; |
|
2426
|
|
|
|
|
|
|
dyn_chunk *chunk, *prev; |
|
2427
|
0
|
0
|
|
|
|
|
if (unlikely(!dyn_size_align(&size))) return NULL; |
|
2428
|
|
|
|
|
|
|
|
|
2429
|
|
|
|
|
|
|
/* freelist is empty, create new chunk */ |
|
2430
|
0
|
0
|
|
|
|
|
if (!ctx->free_list.next) { |
|
2431
|
0
|
|
|
|
|
|
chunk = (dyn_chunk *)def.malloc(def.ctx, size); |
|
2432
|
0
|
0
|
|
|
|
|
if (unlikely(!chunk)) return NULL; |
|
2433
|
0
|
|
|
|
|
|
chunk->size = size; |
|
2434
|
0
|
|
|
|
|
|
chunk->next = NULL; |
|
2435
|
0
|
|
|
|
|
|
dyn_chunk_list_add(&ctx->used_list, chunk); |
|
2436
|
0
|
|
|
|
|
|
return (void *)(chunk + 1); |
|
2437
|
|
|
|
|
|
|
} |
|
2438
|
|
|
|
|
|
|
|
|
2439
|
|
|
|
|
|
|
/* find a large enough chunk, or resize the largest chunk */ |
|
2440
|
0
|
|
|
|
|
|
prev = &ctx->free_list; |
|
2441
|
|
|
|
|
|
|
while (true) { |
|
2442
|
0
|
|
|
|
|
|
chunk = prev->next; |
|
2443
|
0
|
0
|
|
|
|
|
if (chunk->size >= size) { /* enough size, reuse this chunk */ |
|
2444
|
0
|
|
|
|
|
|
prev->next = chunk->next; |
|
2445
|
0
|
|
|
|
|
|
dyn_chunk_list_add(&ctx->used_list, chunk); |
|
2446
|
0
|
|
|
|
|
|
return (void *)(chunk + 1); |
|
2447
|
|
|
|
|
|
|
} |
|
2448
|
0
|
0
|
|
|
|
|
if (!chunk->next) { /* resize the largest chunk */ |
|
2449
|
0
|
|
|
|
|
|
chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size); |
|
2450
|
0
|
0
|
|
|
|
|
if (unlikely(!chunk)) return NULL; |
|
2451
|
0
|
|
|
|
|
|
prev->next = NULL; |
|
2452
|
0
|
|
|
|
|
|
chunk->size = size; |
|
2453
|
0
|
|
|
|
|
|
dyn_chunk_list_add(&ctx->used_list, chunk); |
|
2454
|
0
|
|
|
|
|
|
return (void *)(chunk + 1); |
|
2455
|
|
|
|
|
|
|
} |
|
2456
|
0
|
|
|
|
|
|
prev = chunk; |
|
2457
|
|
|
|
|
|
|
} |
|
2458
|
|
|
|
|
|
|
} |
|
2459
|
|
|
|
|
|
|
|
|
2460
|
0
|
|
|
|
|
|
static void *dyn_realloc(void *ctx_ptr, void *ptr, |
|
2461
|
|
|
|
|
|
|
usize old_size, usize size) { |
|
2462
|
|
|
|
|
|
|
/* assert(ptr != NULL && size != 0 && old_size < size) */ |
|
2463
|
0
|
|
|
|
|
|
const yyjson_alc def = YYJSON_DEFAULT_ALC; |
|
2464
|
0
|
|
|
|
|
|
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; |
|
2465
|
0
|
|
|
|
|
|
dyn_chunk *new_chunk, *chunk = (dyn_chunk *)ptr - 1; |
|
2466
|
0
|
0
|
|
|
|
|
if (unlikely(!dyn_size_align(&size))) return NULL; |
|
2467
|
0
|
0
|
|
|
|
|
if (chunk->size >= size) return ptr; |
|
2468
|
|
|
|
|
|
|
|
|
2469
|
0
|
|
|
|
|
|
dyn_chunk_list_remove(&ctx->used_list, chunk); |
|
2470
|
0
|
|
|
|
|
|
new_chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size); |
|
2471
|
0
|
0
|
|
|
|
|
if (likely(new_chunk)) { |
|
2472
|
0
|
|
|
|
|
|
new_chunk->size = size; |
|
2473
|
0
|
|
|
|
|
|
chunk = new_chunk; |
|
2474
|
|
|
|
|
|
|
} |
|
2475
|
0
|
|
|
|
|
|
dyn_chunk_list_add(&ctx->used_list, chunk); |
|
2476
|
0
|
0
|
|
|
|
|
return new_chunk ? (void *)(new_chunk + 1) : NULL; |
|
2477
|
|
|
|
|
|
|
} |
|
2478
|
|
|
|
|
|
|
|
|
2479
|
0
|
|
|
|
|
|
static void dyn_free(void *ctx_ptr, void *ptr) { |
|
2480
|
|
|
|
|
|
|
/* assert(ptr != NULL) */ |
|
2481
|
0
|
|
|
|
|
|
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; |
|
2482
|
0
|
|
|
|
|
|
dyn_chunk *chunk = (dyn_chunk *)ptr - 1, *prev; |
|
2483
|
|
|
|
|
|
|
|
|
2484
|
0
|
|
|
|
|
|
dyn_chunk_list_remove(&ctx->used_list, chunk); |
|
2485
|
0
|
0
|
|
|
|
|
for (prev = &ctx->free_list; prev; prev = prev->next) { |
|
2486
|
0
|
0
|
|
|
|
|
if (!prev->next || prev->next->size >= chunk->size) { |
|
|
|
0
|
|
|
|
|
|
|
2487
|
0
|
|
|
|
|
|
chunk->next = prev->next; |
|
2488
|
0
|
|
|
|
|
|
prev->next = chunk; |
|
2489
|
0
|
|
|
|
|
|
break; |
|
2490
|
|
|
|
|
|
|
} |
|
2491
|
|
|
|
|
|
|
} |
|
2492
|
0
|
|
|
|
|
|
} |
|
2493
|
|
|
|
|
|
|
|
|
2494
|
0
|
|
|
|
|
|
yyjson_alc *yyjson_alc_dyn_new(void) { |
|
2495
|
0
|
|
|
|
|
|
const yyjson_alc def = YYJSON_DEFAULT_ALC; |
|
2496
|
0
|
|
|
|
|
|
usize hdr_len = sizeof(yyjson_alc) + sizeof(dyn_ctx); |
|
2497
|
0
|
|
|
|
|
|
yyjson_alc *alc = (yyjson_alc *)def.malloc(def.ctx, hdr_len); |
|
2498
|
0
|
|
|
|
|
|
dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1); |
|
2499
|
0
|
0
|
|
|
|
|
if (unlikely(!alc)) return NULL; |
|
2500
|
0
|
|
|
|
|
|
alc->malloc = dyn_malloc; |
|
2501
|
0
|
|
|
|
|
|
alc->realloc = dyn_realloc; |
|
2502
|
0
|
|
|
|
|
|
alc->free = dyn_free; |
|
2503
|
0
|
|
|
|
|
|
alc->ctx = alc + 1; |
|
2504
|
0
|
|
|
|
|
|
memset(ctx, 0, sizeof(*ctx)); |
|
2505
|
0
|
|
|
|
|
|
return alc; |
|
2506
|
|
|
|
|
|
|
} |
|
2507
|
|
|
|
|
|
|
|
|
2508
|
0
|
|
|
|
|
|
void yyjson_alc_dyn_free(yyjson_alc *alc) { |
|
2509
|
0
|
|
|
|
|
|
const yyjson_alc def = YYJSON_DEFAULT_ALC; |
|
2510
|
0
|
|
|
|
|
|
dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1); |
|
2511
|
|
|
|
|
|
|
dyn_chunk *chunk, *next; |
|
2512
|
0
|
0
|
|
|
|
|
if (unlikely(!alc)) return; |
|
2513
|
0
|
0
|
|
|
|
|
for (chunk = ctx->free_list.next; chunk; chunk = next) { |
|
2514
|
0
|
|
|
|
|
|
next = chunk->next; |
|
2515
|
0
|
|
|
|
|
|
def.free(def.ctx, chunk); |
|
2516
|
|
|
|
|
|
|
} |
|
2517
|
0
|
0
|
|
|
|
|
for (chunk = ctx->used_list.next; chunk; chunk = next) { |
|
2518
|
0
|
|
|
|
|
|
next = chunk->next; |
|
2519
|
0
|
|
|
|
|
|
def.free(def.ctx, chunk); |
|
2520
|
|
|
|
|
|
|
} |
|
2521
|
0
|
|
|
|
|
|
def.free(def.ctx, alc); |
|
2522
|
|
|
|
|
|
|
} |
|
2523
|
|
|
|
|
|
|
|
|
2524
|
|
|
|
|
|
|
|
|
2525
|
|
|
|
|
|
|
|
|
2526
|
|
|
|
|
|
|
/*============================================================================== |
|
2527
|
|
|
|
|
|
|
* MARK: - JSON Struct Utils (Public) |
|
2528
|
|
|
|
|
|
|
* These functions are used for creating, copying, releasing, and comparing |
|
2529
|
|
|
|
|
|
|
* JSON documents and values. They are widely used throughout this library. |
|
2530
|
|
|
|
|
|
|
*============================================================================*/ |
|
2531
|
|
|
|
|
|
|
|
|
2532
|
|
|
|
|
|
|
static_inline void unsafe_yyjson_str_pool_release(yyjson_str_pool *pool, |
|
2533
|
|
|
|
|
|
|
yyjson_alc *alc) { |
|
2534
|
20112
|
|
|
|
|
|
yyjson_str_chunk *chunk = pool->chunks, *next; |
|
2535
|
35203
|
100
|
|
|
|
|
while (chunk) { |
|
2536
|
15091
|
|
|
|
|
|
next = chunk->next; |
|
2537
|
15091
|
|
|
|
|
|
alc->free(alc->ctx, chunk); |
|
2538
|
15091
|
|
|
|
|
|
chunk = next; |
|
2539
|
|
|
|
|
|
|
} |
|
2540
|
20112
|
|
|
|
|
|
} |
|
2541
|
|
|
|
|
|
|
|
|
2542
|
|
|
|
|
|
|
static_inline void unsafe_yyjson_val_pool_release(yyjson_val_pool *pool, |
|
2543
|
|
|
|
|
|
|
yyjson_alc *alc) { |
|
2544
|
20112
|
|
|
|
|
|
yyjson_val_chunk *chunk = pool->chunks, *next; |
|
2545
|
40225
|
100
|
|
|
|
|
while (chunk) { |
|
2546
|
20113
|
|
|
|
|
|
next = chunk->next; |
|
2547
|
20113
|
|
|
|
|
|
alc->free(alc->ctx, chunk); |
|
2548
|
20113
|
|
|
|
|
|
chunk = next; |
|
2549
|
|
|
|
|
|
|
} |
|
2550
|
20112
|
|
|
|
|
|
} |
|
2551
|
|
|
|
|
|
|
|
|
2552
|
15091
|
|
|
|
|
|
bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool, |
|
2553
|
|
|
|
|
|
|
const yyjson_alc *alc, usize len) { |
|
2554
|
|
|
|
|
|
|
yyjson_str_chunk *chunk; |
|
2555
|
|
|
|
|
|
|
usize size, max_len; |
|
2556
|
|
|
|
|
|
|
|
|
2557
|
|
|
|
|
|
|
/* create a new chunk */ |
|
2558
|
15091
|
|
|
|
|
|
max_len = USIZE_MAX - sizeof(yyjson_str_chunk); |
|
2559
|
15091
|
50
|
|
|
|
|
if (unlikely(len > max_len)) return false; |
|
2560
|
15091
|
|
|
|
|
|
size = len + sizeof(yyjson_str_chunk); |
|
2561
|
15091
|
|
|
|
|
|
size = yyjson_max(pool->chunk_size, size); |
|
2562
|
15091
|
|
|
|
|
|
chunk = (yyjson_str_chunk *)alc->malloc(alc->ctx, size); |
|
2563
|
15091
|
50
|
|
|
|
|
if (unlikely(!chunk)) return false; |
|
2564
|
|
|
|
|
|
|
|
|
2565
|
|
|
|
|
|
|
/* insert the new chunk as the head of the linked list */ |
|
2566
|
15091
|
|
|
|
|
|
chunk->next = pool->chunks; |
|
2567
|
15091
|
|
|
|
|
|
chunk->chunk_size = size; |
|
2568
|
15091
|
|
|
|
|
|
pool->chunks = chunk; |
|
2569
|
15091
|
|
|
|
|
|
pool->cur = (char *)chunk + sizeof(yyjson_str_chunk); |
|
2570
|
15091
|
|
|
|
|
|
pool->end = (char *)chunk + size; |
|
2571
|
|
|
|
|
|
|
|
|
2572
|
|
|
|
|
|
|
/* the next chunk is twice the size of the current one */ |
|
2573
|
15091
|
|
|
|
|
|
size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max); |
|
2574
|
15091
|
50
|
|
|
|
|
if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */ |
|
2575
|
15091
|
|
|
|
|
|
pool->chunk_size = size; |
|
2576
|
15091
|
|
|
|
|
|
return true; |
|
2577
|
|
|
|
|
|
|
} |
|
2578
|
|
|
|
|
|
|
|
|
2579
|
20113
|
|
|
|
|
|
bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool, |
|
2580
|
|
|
|
|
|
|
const yyjson_alc *alc, usize count) { |
|
2581
|
|
|
|
|
|
|
yyjson_val_chunk *chunk; |
|
2582
|
|
|
|
|
|
|
usize size, max_count; |
|
2583
|
|
|
|
|
|
|
|
|
2584
|
|
|
|
|
|
|
/* create a new chunk */ |
|
2585
|
20113
|
|
|
|
|
|
max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1; |
|
2586
|
20113
|
50
|
|
|
|
|
if (unlikely(count > max_count)) return false; |
|
2587
|
20113
|
|
|
|
|
|
size = (count + 1) * sizeof(yyjson_mut_val); |
|
2588
|
20113
|
|
|
|
|
|
size = yyjson_max(pool->chunk_size, size); |
|
2589
|
20113
|
|
|
|
|
|
chunk = (yyjson_val_chunk *)alc->malloc(alc->ctx, size); |
|
2590
|
20113
|
50
|
|
|
|
|
if (unlikely(!chunk)) return false; |
|
2591
|
|
|
|
|
|
|
|
|
2592
|
|
|
|
|
|
|
/* insert the new chunk as the head of the linked list */ |
|
2593
|
20113
|
|
|
|
|
|
chunk->next = pool->chunks; |
|
2594
|
20113
|
|
|
|
|
|
chunk->chunk_size = size; |
|
2595
|
20113
|
|
|
|
|
|
pool->chunks = chunk; |
|
2596
|
20113
|
|
|
|
|
|
pool->cur = (yyjson_mut_val *)(void *)((u8 *)chunk) + 1; |
|
2597
|
20113
|
|
|
|
|
|
pool->end = (yyjson_mut_val *)(void *)((u8 *)chunk + size); |
|
2598
|
|
|
|
|
|
|
|
|
2599
|
|
|
|
|
|
|
/* the next chunk is twice the size of the current one */ |
|
2600
|
20113
|
|
|
|
|
|
size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max); |
|
2601
|
20113
|
50
|
|
|
|
|
if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */ |
|
2602
|
20113
|
|
|
|
|
|
pool->chunk_size = size; |
|
2603
|
20113
|
|
|
|
|
|
return true; |
|
2604
|
|
|
|
|
|
|
} |
|
2605
|
|
|
|
|
|
|
|
|
2606
|
0
|
|
|
|
|
|
bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc, size_t len) { |
|
2607
|
0
|
|
|
|
|
|
usize max_size = USIZE_MAX - sizeof(yyjson_str_chunk); |
|
2608
|
0
|
0
|
|
|
|
|
if (!doc || !len || len > max_size) return false; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2609
|
0
|
|
|
|
|
|
doc->str_pool.chunk_size = len + sizeof(yyjson_str_chunk); |
|
2610
|
0
|
|
|
|
|
|
return true; |
|
2611
|
|
|
|
|
|
|
} |
|
2612
|
|
|
|
|
|
|
|
|
2613
|
0
|
|
|
|
|
|
bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count) { |
|
2614
|
0
|
|
|
|
|
|
usize max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1; |
|
2615
|
0
|
0
|
|
|
|
|
if (!doc || !count || count > max_count) return false; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2616
|
0
|
|
|
|
|
|
doc->val_pool.chunk_size = (count + 1) * sizeof(yyjson_mut_val); |
|
2617
|
0
|
|
|
|
|
|
return true; |
|
2618
|
|
|
|
|
|
|
} |
|
2619
|
|
|
|
|
|
|
|
|
2620
|
20112
|
|
|
|
|
|
void yyjson_mut_doc_free(yyjson_mut_doc *doc) { |
|
2621
|
20112
|
50
|
|
|
|
|
if (doc) { |
|
2622
|
20112
|
|
|
|
|
|
yyjson_alc alc = doc->alc; |
|
2623
|
20112
|
|
|
|
|
|
memset(&doc->alc, 0, sizeof(alc)); |
|
2624
|
20112
|
|
|
|
|
|
unsafe_yyjson_str_pool_release(&doc->str_pool, &alc); |
|
2625
|
20112
|
|
|
|
|
|
unsafe_yyjson_val_pool_release(&doc->val_pool, &alc); |
|
2626
|
20112
|
|
|
|
|
|
alc.free(alc.ctx, doc); |
|
2627
|
|
|
|
|
|
|
} |
|
2628
|
20112
|
|
|
|
|
|
} |
|
2629
|
|
|
|
|
|
|
|
|
2630
|
20112
|
|
|
|
|
|
yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc) { |
|
2631
|
|
|
|
|
|
|
yyjson_mut_doc *doc; |
|
2632
|
20112
|
50
|
|
|
|
|
if (!alc) alc = &YYJSON_DEFAULT_ALC; |
|
2633
|
20112
|
|
|
|
|
|
doc = (yyjson_mut_doc *)alc->malloc(alc->ctx, sizeof(yyjson_mut_doc)); |
|
2634
|
20112
|
50
|
|
|
|
|
if (!doc) return NULL; |
|
2635
|
20112
|
|
|
|
|
|
memset(doc, 0, sizeof(yyjson_mut_doc)); |
|
2636
|
|
|
|
|
|
|
|
|
2637
|
20112
|
|
|
|
|
|
doc->alc = *alc; |
|
2638
|
20112
|
|
|
|
|
|
doc->str_pool.chunk_size = YYJSON_MUT_DOC_STR_POOL_INIT_SIZE; |
|
2639
|
20112
|
|
|
|
|
|
doc->str_pool.chunk_size_max = YYJSON_MUT_DOC_STR_POOL_MAX_SIZE; |
|
2640
|
20112
|
|
|
|
|
|
doc->val_pool.chunk_size = YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE; |
|
2641
|
20112
|
|
|
|
|
|
doc->val_pool.chunk_size_max = YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE; |
|
2642
|
20112
|
|
|
|
|
|
return doc; |
|
2643
|
|
|
|
|
|
|
} |
|
2644
|
|
|
|
|
|
|
|
|
2645
|
10074
|
|
|
|
|
|
yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, const yyjson_alc *alc) { |
|
2646
|
|
|
|
|
|
|
yyjson_mut_doc *m_doc; |
|
2647
|
|
|
|
|
|
|
yyjson_mut_val *m_val; |
|
2648
|
|
|
|
|
|
|
|
|
2649
|
10074
|
50
|
|
|
|
|
if (!doc || !doc->root) return NULL; |
|
|
|
50
|
|
|
|
|
|
|
2650
|
10074
|
|
|
|
|
|
m_doc = yyjson_mut_doc_new(alc); |
|
2651
|
10074
|
50
|
|
|
|
|
if (!m_doc) return NULL; |
|
2652
|
10074
|
|
|
|
|
|
m_val = yyjson_val_mut_copy(m_doc, doc->root); |
|
2653
|
10074
|
50
|
|
|
|
|
if (!m_val) { |
|
2654
|
0
|
|
|
|
|
|
yyjson_mut_doc_free(m_doc); |
|
2655
|
0
|
|
|
|
|
|
return NULL; |
|
2656
|
|
|
|
|
|
|
} |
|
2657
|
|
|
|
|
|
|
yyjson_mut_doc_set_root(m_doc, m_val); |
|
2658
|
10074
|
|
|
|
|
|
return m_doc; |
|
2659
|
|
|
|
|
|
|
} |
|
2660
|
|
|
|
|
|
|
|
|
2661
|
0
|
|
|
|
|
|
yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc, |
|
2662
|
|
|
|
|
|
|
const yyjson_alc *alc) { |
|
2663
|
|
|
|
|
|
|
yyjson_mut_doc *m_doc; |
|
2664
|
|
|
|
|
|
|
yyjson_mut_val *m_val; |
|
2665
|
|
|
|
|
|
|
|
|
2666
|
0
|
0
|
|
|
|
|
if (!doc) return NULL; |
|
2667
|
0
|
0
|
|
|
|
|
if (!doc->root) return yyjson_mut_doc_new(alc); |
|
2668
|
|
|
|
|
|
|
|
|
2669
|
0
|
|
|
|
|
|
m_doc = yyjson_mut_doc_new(alc); |
|
2670
|
0
|
0
|
|
|
|
|
if (!m_doc) return NULL; |
|
2671
|
0
|
|
|
|
|
|
m_val = yyjson_mut_val_mut_copy(m_doc, doc->root); |
|
2672
|
0
|
0
|
|
|
|
|
if (!m_val) { |
|
2673
|
0
|
|
|
|
|
|
yyjson_mut_doc_free(m_doc); |
|
2674
|
0
|
|
|
|
|
|
return NULL; |
|
2675
|
|
|
|
|
|
|
} |
|
2676
|
|
|
|
|
|
|
yyjson_mut_doc_set_root(m_doc, m_val); |
|
2677
|
0
|
|
|
|
|
|
return m_doc; |
|
2678
|
|
|
|
|
|
|
} |
|
2679
|
|
|
|
|
|
|
|
|
2680
|
10078
|
|
|
|
|
|
yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc, |
|
2681
|
|
|
|
|
|
|
yyjson_val *i_vals) { |
|
2682
|
|
|
|
|
|
|
/* |
|
2683
|
|
|
|
|
|
|
The immutable object or array stores all sub-values in a contiguous memory, |
|
2684
|
|
|
|
|
|
|
We copy them to another contiguous memory as mutable values, |
|
2685
|
|
|
|
|
|
|
then reconnect the mutable values with the original relationship. |
|
2686
|
|
|
|
|
|
|
*/ |
|
2687
|
|
|
|
|
|
|
usize i_vals_len; |
|
2688
|
|
|
|
|
|
|
yyjson_mut_val *m_vals, *m_val; |
|
2689
|
|
|
|
|
|
|
yyjson_val *i_val, *i_end; |
|
2690
|
|
|
|
|
|
|
|
|
2691
|
10078
|
50
|
|
|
|
|
if (!m_doc || !i_vals) return NULL; |
|
|
|
50
|
|
|
|
|
|
|
2692
|
10078
|
|
|
|
|
|
i_end = unsafe_yyjson_get_next(i_vals); |
|
2693
|
10078
|
100
|
|
|
|
|
i_vals_len = (usize)(unsafe_yyjson_get_next(i_vals) - i_vals); |
|
2694
|
10078
|
|
|
|
|
|
m_vals = unsafe_yyjson_mut_val(m_doc, i_vals_len); |
|
2695
|
10078
|
50
|
|
|
|
|
if (!m_vals) return NULL; |
|
2696
|
10078
|
|
|
|
|
|
i_val = i_vals; |
|
2697
|
10078
|
|
|
|
|
|
m_val = m_vals; |
|
2698
|
|
|
|
|
|
|
|
|
2699
|
55624
|
100
|
|
|
|
|
for (; i_val < i_end; i_val++, m_val++) { |
|
2700
|
45546
|
|
|
|
|
|
yyjson_type type = unsafe_yyjson_get_type(i_val); |
|
2701
|
45546
|
|
|
|
|
|
m_val->tag = i_val->tag; |
|
2702
|
45546
|
|
|
|
|
|
m_val->uni.u64 = i_val->uni.u64; |
|
2703
|
57728
|
100
|
|
|
|
|
if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { |
|
|
|
50
|
|
|
|
|
|
|
2704
|
12182
|
|
|
|
|
|
const char *str = i_val->uni.str; |
|
2705
|
12182
|
100
|
|
|
|
|
usize str_len = unsafe_yyjson_get_len(i_val); |
|
2706
|
12182
|
|
|
|
|
|
m_val->uni.str = unsafe_yyjson_mut_strncpy(m_doc, str, str_len); |
|
2707
|
12182
|
50
|
|
|
|
|
if (!m_val->uni.str) return NULL; |
|
2708
|
33364
|
100
|
|
|
|
|
} else if (type == YYJSON_TYPE_ARR) { |
|
2709
|
141
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(i_val); |
|
2710
|
141
|
100
|
|
|
|
|
if (len > 0) { |
|
2711
|
138
|
|
|
|
|
|
yyjson_val *ii_val = i_val + 1, *ii_next; |
|
2712
|
138
|
|
|
|
|
|
yyjson_mut_val *mm_val = m_val + 1, *mm_ctn = m_val, *mm_next; |
|
2713
|
11182
|
100
|
|
|
|
|
while (len-- > 1) { |
|
2714
|
11044
|
|
|
|
|
|
ii_next = unsafe_yyjson_get_next(ii_val); |
|
2715
|
11044
|
|
|
|
|
|
mm_next = mm_val + (ii_next - ii_val); |
|
2716
|
11044
|
|
|
|
|
|
mm_val->next = mm_next; |
|
2717
|
11044
|
|
|
|
|
|
ii_val = ii_next; |
|
2718
|
11044
|
|
|
|
|
|
mm_val = mm_next; |
|
2719
|
|
|
|
|
|
|
} |
|
2720
|
138
|
|
|
|
|
|
mm_val->next = mm_ctn + 1; |
|
2721
|
138
|
|
|
|
|
|
mm_ctn->uni.ptr = mm_val; |
|
2722
|
|
|
|
|
|
|
} |
|
2723
|
33223
|
100
|
|
|
|
|
} else if (type == YYJSON_TYPE_OBJ) { |
|
2724
|
11090
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(i_val); |
|
2725
|
11090
|
100
|
|
|
|
|
if (len > 0) { |
|
2726
|
11084
|
|
|
|
|
|
yyjson_val *ii_key = i_val + 1, *ii_nextkey; |
|
2727
|
11084
|
|
|
|
|
|
yyjson_mut_val *mm_key = m_val + 1, *mm_ctn = m_val; |
|
2728
|
|
|
|
|
|
|
yyjson_mut_val *mm_nextkey; |
|
2729
|
12143
|
100
|
|
|
|
|
while (len-- > 1) { |
|
2730
|
1059
|
|
|
|
|
|
ii_nextkey = unsafe_yyjson_get_next(ii_key + 1); |
|
2731
|
1059
|
|
|
|
|
|
mm_nextkey = mm_key + (ii_nextkey - ii_key); |
|
2732
|
1059
|
|
|
|
|
|
mm_key->next = mm_key + 1; |
|
2733
|
1059
|
|
|
|
|
|
mm_key->next->next = mm_nextkey; |
|
2734
|
1059
|
|
|
|
|
|
ii_key = ii_nextkey; |
|
2735
|
1059
|
|
|
|
|
|
mm_key = mm_nextkey; |
|
2736
|
|
|
|
|
|
|
} |
|
2737
|
11084
|
|
|
|
|
|
mm_key->next = mm_key + 1; |
|
2738
|
11084
|
|
|
|
|
|
mm_key->next->next = mm_ctn + 1; |
|
2739
|
11084
|
|
|
|
|
|
mm_ctn->uni.ptr = mm_key; |
|
2740
|
|
|
|
|
|
|
} |
|
2741
|
|
|
|
|
|
|
} |
|
2742
|
|
|
|
|
|
|
} |
|
2743
|
10078
|
|
|
|
|
|
return m_vals; |
|
2744
|
|
|
|
|
|
|
} |
|
2745
|
|
|
|
|
|
|
|
|
2746
|
20083
|
100
|
|
|
|
|
static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc, |
|
2747
|
|
|
|
|
|
|
yyjson_mut_val *m_vals) { |
|
2748
|
|
|
|
|
|
|
/* |
|
2749
|
|
|
|
|
|
|
The mutable object or array stores all sub-values in a circular linked |
|
2750
|
|
|
|
|
|
|
list, so we can traverse them in the same loop. The traversal starts from |
|
2751
|
|
|
|
|
|
|
the last item, continues with the first item in a list, and ends with the |
|
2752
|
|
|
|
|
|
|
second to last item, which needs to be linked to the last item to close the |
|
2753
|
|
|
|
|
|
|
circle. |
|
2754
|
|
|
|
|
|
|
*/ |
|
2755
|
20083
|
|
|
|
|
|
yyjson_mut_val *m_val = unsafe_yyjson_mut_val(m_doc, 1); |
|
2756
|
20083
|
50
|
|
|
|
|
if (unlikely(!m_val)) return NULL; |
|
2757
|
20083
|
|
|
|
|
|
m_val->tag = m_vals->tag; |
|
2758
|
|
|
|
|
|
|
|
|
2759
|
20083
|
|
|
|
|
|
switch (unsafe_yyjson_get_type(m_vals)) { |
|
2760
|
5020
|
|
|
|
|
|
case YYJSON_TYPE_OBJ: |
|
2761
|
|
|
|
|
|
|
case YYJSON_TYPE_ARR: |
|
2762
|
5020
|
100
|
|
|
|
|
if (unsafe_yyjson_get_len(m_vals) > 0) { |
|
2763
|
5017
|
|
|
|
|
|
yyjson_mut_val *last = (yyjson_mut_val *)m_vals->uni.ptr; |
|
2764
|
5017
|
|
|
|
|
|
yyjson_mut_val *next = last->next, *prev; |
|
2765
|
5017
|
|
|
|
|
|
prev = unsafe_yyjson_mut_val_mut_copy(m_doc, last); |
|
2766
|
5017
|
50
|
|
|
|
|
if (!prev) return NULL; |
|
2767
|
5017
|
|
|
|
|
|
m_val->uni.ptr = (void *)prev; |
|
2768
|
15046
|
100
|
|
|
|
|
while (next != last) { |
|
2769
|
10029
|
|
|
|
|
|
prev->next = unsafe_yyjson_mut_val_mut_copy(m_doc, next); |
|
2770
|
10029
|
50
|
|
|
|
|
if (!prev->next) return NULL; |
|
2771
|
10029
|
|
|
|
|
|
prev = prev->next; |
|
2772
|
10029
|
|
|
|
|
|
next = next->next; |
|
2773
|
|
|
|
|
|
|
} |
|
2774
|
5017
|
|
|
|
|
|
prev->next = (yyjson_mut_val *)m_val->uni.ptr; |
|
2775
|
|
|
|
|
|
|
} |
|
2776
|
5020
|
|
|
|
|
|
break; |
|
2777
|
27
|
|
|
|
|
|
case YYJSON_TYPE_RAW: |
|
2778
|
|
|
|
|
|
|
case YYJSON_TYPE_STR: { |
|
2779
|
27
|
|
|
|
|
|
const char *str = m_vals->uni.str; |
|
2780
|
27
|
100
|
|
|
|
|
usize str_len = unsafe_yyjson_get_len(m_vals); |
|
2781
|
27
|
|
|
|
|
|
m_val->uni.str = unsafe_yyjson_mut_strncpy(m_doc, str, str_len); |
|
2782
|
27
|
50
|
|
|
|
|
if (!m_val->uni.str) return NULL; |
|
2783
|
27
|
|
|
|
|
|
break; |
|
2784
|
|
|
|
|
|
|
} |
|
2785
|
15036
|
|
|
|
|
|
default: |
|
2786
|
15036
|
|
|
|
|
|
m_val->uni = m_vals->uni; |
|
2787
|
15036
|
|
|
|
|
|
break; |
|
2788
|
|
|
|
|
|
|
} |
|
2789
|
20083
|
|
|
|
|
|
return m_val; |
|
2790
|
|
|
|
|
|
|
} |
|
2791
|
|
|
|
|
|
|
|
|
2792
|
5037
|
|
|
|
|
|
yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc, |
|
2793
|
|
|
|
|
|
|
yyjson_mut_val *val) { |
|
2794
|
5037
|
50
|
|
|
|
|
if (doc && val) return unsafe_yyjson_mut_val_mut_copy(doc, val); |
|
|
|
50
|
|
|
|
|
|
|
2795
|
0
|
|
|
|
|
|
return NULL; |
|
2796
|
|
|
|
|
|
|
} |
|
2797
|
|
|
|
|
|
|
|
|
2798
|
|
|
|
|
|
|
/* Count the number of values and the total length of the strings. */ |
|
2799
|
0
|
|
|
|
|
|
static void yyjson_mut_stat(yyjson_mut_val *val, |
|
2800
|
|
|
|
|
|
|
usize *val_sum, usize *str_sum) { |
|
2801
|
0
|
|
|
|
|
|
yyjson_type type = unsafe_yyjson_get_type(val); |
|
2802
|
0
|
|
|
|
|
|
*val_sum += 1; |
|
2803
|
0
|
0
|
|
|
|
|
if (type == YYJSON_TYPE_ARR || type == YYJSON_TYPE_OBJ) { |
|
|
|
0
|
|
|
|
|
|
|
2804
|
0
|
|
|
|
|
|
yyjson_mut_val *child = (yyjson_mut_val *)val->uni.ptr; |
|
2805
|
0
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(val), i; |
|
2806
|
0
|
|
|
|
|
|
len <<= (u8)(type == YYJSON_TYPE_OBJ); |
|
2807
|
0
|
|
|
|
|
|
*val_sum += len; |
|
2808
|
0
|
0
|
|
|
|
|
for (i = 0; i < len; i++) { |
|
2809
|
0
|
|
|
|
|
|
yyjson_type stype = unsafe_yyjson_get_type(child); |
|
2810
|
0
|
0
|
|
|
|
|
if (stype == YYJSON_TYPE_STR || stype == YYJSON_TYPE_RAW) { |
|
|
|
0
|
|
|
|
|
|
|
2811
|
0
|
|
|
|
|
|
*str_sum += unsafe_yyjson_get_len(child) + 1; |
|
2812
|
0
|
0
|
|
|
|
|
} else if (stype == YYJSON_TYPE_ARR || stype == YYJSON_TYPE_OBJ) { |
|
|
|
0
|
|
|
|
|
|
|
2813
|
0
|
|
|
|
|
|
yyjson_mut_stat(child, val_sum, str_sum); |
|
2814
|
0
|
|
|
|
|
|
*val_sum -= 1; |
|
2815
|
|
|
|
|
|
|
} |
|
2816
|
0
|
|
|
|
|
|
child = child->next; |
|
2817
|
|
|
|
|
|
|
} |
|
2818
|
0
|
0
|
|
|
|
|
} else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { |
|
|
|
0
|
|
|
|
|
|
|
2819
|
0
|
|
|
|
|
|
*str_sum += unsafe_yyjson_get_len(val) + 1; |
|
2820
|
|
|
|
|
|
|
} |
|
2821
|
0
|
|
|
|
|
|
} |
|
2822
|
|
|
|
|
|
|
|
|
2823
|
|
|
|
|
|
|
/* Copy mutable values to immutable value pool. */ |
|
2824
|
0
|
|
|
|
|
|
static usize yyjson_imut_copy(yyjson_val **val_ptr, char **buf_ptr, |
|
2825
|
|
|
|
|
|
|
yyjson_mut_val *mval) { |
|
2826
|
0
|
|
|
|
|
|
yyjson_val *val = *val_ptr; |
|
2827
|
0
|
|
|
|
|
|
yyjson_type type = unsafe_yyjson_get_type(mval); |
|
2828
|
0
|
0
|
|
|
|
|
if (type == YYJSON_TYPE_ARR || type == YYJSON_TYPE_OBJ) { |
|
|
|
0
|
|
|
|
|
|
|
2829
|
0
|
|
|
|
|
|
yyjson_mut_val *child = (yyjson_mut_val *)mval->uni.ptr; |
|
2830
|
0
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(mval), i; |
|
2831
|
0
|
|
|
|
|
|
usize val_sum = 1; |
|
2832
|
0
|
0
|
|
|
|
|
if (type == YYJSON_TYPE_OBJ) { |
|
2833
|
0
|
0
|
|
|
|
|
if (len) child = child->next->next; |
|
2834
|
0
|
|
|
|
|
|
len <<= 1; |
|
2835
|
|
|
|
|
|
|
} else { |
|
2836
|
0
|
0
|
|
|
|
|
if (len) child = child->next; |
|
2837
|
|
|
|
|
|
|
} |
|
2838
|
0
|
|
|
|
|
|
*val_ptr = val + 1; |
|
2839
|
0
|
0
|
|
|
|
|
for (i = 0; i < len; i++) { |
|
2840
|
0
|
|
|
|
|
|
val_sum += yyjson_imut_copy(val_ptr, buf_ptr, child); |
|
2841
|
0
|
|
|
|
|
|
child = child->next; |
|
2842
|
|
|
|
|
|
|
} |
|
2843
|
0
|
|
|
|
|
|
val->tag = mval->tag; |
|
2844
|
0
|
|
|
|
|
|
val->uni.ofs = val_sum * sizeof(yyjson_val); |
|
2845
|
0
|
|
|
|
|
|
return val_sum; |
|
2846
|
0
|
0
|
|
|
|
|
} else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { |
|
|
|
0
|
|
|
|
|
|
|
2847
|
0
|
|
|
|
|
|
char *buf = *buf_ptr; |
|
2848
|
0
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(mval); |
|
2849
|
0
|
|
|
|
|
|
memcpy((void *)buf, (const void *)mval->uni.str, len); |
|
2850
|
0
|
|
|
|
|
|
buf[len] = '\0'; |
|
2851
|
0
|
|
|
|
|
|
val->tag = mval->tag; |
|
2852
|
0
|
|
|
|
|
|
val->uni.str = buf; |
|
2853
|
0
|
|
|
|
|
|
*val_ptr = val + 1; |
|
2854
|
0
|
|
|
|
|
|
*buf_ptr = buf + len + 1; |
|
2855
|
0
|
|
|
|
|
|
return 1; |
|
2856
|
|
|
|
|
|
|
} else { |
|
2857
|
0
|
|
|
|
|
|
val->tag = mval->tag; |
|
2858
|
0
|
|
|
|
|
|
val->uni = mval->uni; |
|
2859
|
0
|
|
|
|
|
|
*val_ptr = val + 1; |
|
2860
|
0
|
|
|
|
|
|
return 1; |
|
2861
|
|
|
|
|
|
|
} |
|
2862
|
|
|
|
|
|
|
} |
|
2863
|
|
|
|
|
|
|
|
|
2864
|
0
|
|
|
|
|
|
yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *mdoc, |
|
2865
|
|
|
|
|
|
|
const yyjson_alc *alc) { |
|
2866
|
0
|
0
|
|
|
|
|
if (!mdoc) return NULL; |
|
2867
|
0
|
|
|
|
|
|
return yyjson_mut_val_imut_copy(mdoc->root, alc); |
|
2868
|
|
|
|
|
|
|
} |
|
2869
|
|
|
|
|
|
|
|
|
2870
|
0
|
|
|
|
|
|
yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *mval, |
|
2871
|
|
|
|
|
|
|
const yyjson_alc *alc) { |
|
2872
|
0
|
|
|
|
|
|
usize val_num = 0, str_sum = 0, hdr_size, buf_size; |
|
2873
|
0
|
|
|
|
|
|
yyjson_doc *doc = NULL; |
|
2874
|
0
|
|
|
|
|
|
yyjson_val *val_hdr = NULL; |
|
2875
|
|
|
|
|
|
|
|
|
2876
|
|
|
|
|
|
|
/* This value should be NULL here. Setting a non-null value suppresses |
|
2877
|
|
|
|
|
|
|
warning from the clang analyzer. */ |
|
2878
|
0
|
|
|
|
|
|
char *str_hdr = (char *)(void *)&str_sum; |
|
2879
|
0
|
0
|
|
|
|
|
if (!mval) return NULL; |
|
2880
|
0
|
0
|
|
|
|
|
if (!alc) alc = &YYJSON_DEFAULT_ALC; |
|
2881
|
|
|
|
|
|
|
|
|
2882
|
|
|
|
|
|
|
/* traverse the input value to get pool size */ |
|
2883
|
0
|
|
|
|
|
|
yyjson_mut_stat(mval, &val_num, &str_sum); |
|
2884
|
|
|
|
|
|
|
|
|
2885
|
|
|
|
|
|
|
/* create doc and val pool */ |
|
2886
|
0
|
|
|
|
|
|
hdr_size = size_align_up(sizeof(yyjson_doc), sizeof(yyjson_val)); |
|
2887
|
0
|
|
|
|
|
|
buf_size = hdr_size + val_num * sizeof(yyjson_val); |
|
2888
|
0
|
|
|
|
|
|
doc = (yyjson_doc *)alc->malloc(alc->ctx, buf_size); |
|
2889
|
0
|
0
|
|
|
|
|
if (!doc) return NULL; |
|
2890
|
0
|
|
|
|
|
|
memset(doc, 0, sizeof(yyjson_doc)); |
|
2891
|
0
|
|
|
|
|
|
val_hdr = (yyjson_val *)(void *)((char *)(void *)doc + hdr_size); |
|
2892
|
0
|
|
|
|
|
|
doc->root = val_hdr; |
|
2893
|
0
|
|
|
|
|
|
doc->alc = *alc; |
|
2894
|
|
|
|
|
|
|
|
|
2895
|
|
|
|
|
|
|
/* create str pool */ |
|
2896
|
0
|
0
|
|
|
|
|
if (str_sum > 0) { |
|
2897
|
0
|
|
|
|
|
|
str_hdr = (char *)alc->malloc(alc->ctx, str_sum); |
|
2898
|
0
|
|
|
|
|
|
doc->str_pool = str_hdr; |
|
2899
|
0
|
0
|
|
|
|
|
if (!str_hdr) { |
|
2900
|
0
|
|
|
|
|
|
alc->free(alc->ctx, (void *)doc); |
|
2901
|
0
|
|
|
|
|
|
return NULL; |
|
2902
|
|
|
|
|
|
|
} |
|
2903
|
|
|
|
|
|
|
} |
|
2904
|
|
|
|
|
|
|
|
|
2905
|
|
|
|
|
|
|
/* copy vals and strs */ |
|
2906
|
0
|
|
|
|
|
|
doc->val_read = yyjson_imut_copy(&val_hdr, &str_hdr, mval); |
|
2907
|
0
|
|
|
|
|
|
doc->dat_read = str_sum + 1; |
|
2908
|
0
|
|
|
|
|
|
return doc; |
|
2909
|
|
|
|
|
|
|
} |
|
2910
|
|
|
|
|
|
|
|
|
2911
|
|
|
|
|
|
|
static_inline bool unsafe_yyjson_num_equals(void *lhs, void *rhs) { |
|
2912
|
11
|
|
|
|
|
|
yyjson_val_uni *luni = &((yyjson_val *)lhs)->uni; |
|
2913
|
11
|
|
|
|
|
|
yyjson_val_uni *runi = &((yyjson_val *)rhs)->uni; |
|
2914
|
11
|
|
|
|
|
|
yyjson_subtype lt = unsafe_yyjson_get_subtype(lhs); |
|
2915
|
11
|
|
|
|
|
|
yyjson_subtype rt = unsafe_yyjson_get_subtype(rhs); |
|
2916
|
11
|
50
|
|
|
|
|
if (lt == rt) return luni->u64 == runi->u64; |
|
|
|
0
|
|
|
|
|
|
|
2917
|
0
|
0
|
|
|
|
|
if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2918
|
0
|
0
|
|
|
|
|
return luni->i64 >= 0 && luni->u64 == runi->u64; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2919
|
|
|
|
|
|
|
} |
|
2920
|
0
|
0
|
|
|
|
|
if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2921
|
0
|
0
|
|
|
|
|
return runi->i64 >= 0 && luni->u64 == runi->u64; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2922
|
|
|
|
|
|
|
} |
|
2923
|
0
|
|
|
|
|
|
return false; |
|
2924
|
|
|
|
|
|
|
} |
|
2925
|
|
|
|
|
|
|
|
|
2926
|
|
|
|
|
|
|
static_inline bool unsafe_yyjson_str_equals(void *lhs, void *rhs) { |
|
2927
|
0
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(lhs); |
|
2928
|
0
|
0
|
|
|
|
|
if (len != unsafe_yyjson_get_len(rhs)) return false; |
|
|
|
0
|
|
|
|
|
|
|
2929
|
0
|
|
|
|
|
|
return !memcmp(unsafe_yyjson_get_str(lhs), |
|
2930
|
0
|
|
|
|
|
|
unsafe_yyjson_get_str(rhs), len); |
|
2931
|
|
|
|
|
|
|
} |
|
2932
|
|
|
|
|
|
|
|
|
2933
|
0
|
|
|
|
|
|
bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { |
|
2934
|
0
|
|
|
|
|
|
yyjson_type type = unsafe_yyjson_get_type(lhs); |
|
2935
|
0
|
0
|
|
|
|
|
if (type != unsafe_yyjson_get_type(rhs)) return false; |
|
2936
|
|
|
|
|
|
|
|
|
2937
|
0
|
|
|
|
|
|
switch (type) { |
|
2938
|
0
|
|
|
|
|
|
case YYJSON_TYPE_OBJ: { |
|
2939
|
0
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(lhs); |
|
2940
|
0
|
0
|
|
|
|
|
if (len != unsafe_yyjson_get_len(rhs)) return false; |
|
2941
|
0
|
0
|
|
|
|
|
if (len > 0) { |
|
2942
|
|
|
|
|
|
|
yyjson_obj_iter iter; |
|
2943
|
|
|
|
|
|
|
yyjson_obj_iter_init(rhs, &iter); |
|
2944
|
0
|
|
|
|
|
|
lhs = unsafe_yyjson_get_first(lhs); |
|
2945
|
0
|
0
|
|
|
|
|
while (len-- > 0) { |
|
2946
|
0
|
0
|
|
|
|
|
rhs = yyjson_obj_iter_getn(&iter, lhs->uni.str, |
|
2947
|
|
|
|
|
|
|
unsafe_yyjson_get_len(lhs)); |
|
2948
|
0
|
0
|
|
|
|
|
if (!rhs) return false; |
|
2949
|
0
|
0
|
|
|
|
|
if (!unsafe_yyjson_equals(lhs + 1, rhs)) return false; |
|
2950
|
0
|
|
|
|
|
|
lhs = unsafe_yyjson_get_next(lhs + 1); |
|
2951
|
|
|
|
|
|
|
} |
|
2952
|
|
|
|
|
|
|
} |
|
2953
|
|
|
|
|
|
|
/* yyjson allows duplicate keys, so the check may be inaccurate */ |
|
2954
|
0
|
|
|
|
|
|
return true; |
|
2955
|
|
|
|
|
|
|
} |
|
2956
|
|
|
|
|
|
|
|
|
2957
|
0
|
|
|
|
|
|
case YYJSON_TYPE_ARR: { |
|
2958
|
0
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(lhs); |
|
2959
|
0
|
0
|
|
|
|
|
if (len != unsafe_yyjson_get_len(rhs)) return false; |
|
2960
|
0
|
0
|
|
|
|
|
if (len > 0) { |
|
2961
|
0
|
|
|
|
|
|
lhs = unsafe_yyjson_get_first(lhs); |
|
2962
|
0
|
|
|
|
|
|
rhs = unsafe_yyjson_get_first(rhs); |
|
2963
|
0
|
0
|
|
|
|
|
while (len-- > 0) { |
|
2964
|
0
|
0
|
|
|
|
|
if (!unsafe_yyjson_equals(lhs, rhs)) return false; |
|
2965
|
0
|
|
|
|
|
|
lhs = unsafe_yyjson_get_next(lhs); |
|
2966
|
0
|
|
|
|
|
|
rhs = unsafe_yyjson_get_next(rhs); |
|
2967
|
|
|
|
|
|
|
} |
|
2968
|
|
|
|
|
|
|
} |
|
2969
|
0
|
|
|
|
|
|
return true; |
|
2970
|
|
|
|
|
|
|
} |
|
2971
|
|
|
|
|
|
|
|
|
2972
|
0
|
|
|
|
|
|
case YYJSON_TYPE_NUM: |
|
2973
|
0
|
|
|
|
|
|
return unsafe_yyjson_num_equals(lhs, rhs); |
|
2974
|
|
|
|
|
|
|
|
|
2975
|
0
|
|
|
|
|
|
case YYJSON_TYPE_RAW: |
|
2976
|
|
|
|
|
|
|
case YYJSON_TYPE_STR: |
|
2977
|
0
|
|
|
|
|
|
return unsafe_yyjson_str_equals(lhs, rhs); |
|
2978
|
|
|
|
|
|
|
|
|
2979
|
0
|
|
|
|
|
|
case YYJSON_TYPE_NULL: |
|
2980
|
|
|
|
|
|
|
case YYJSON_TYPE_BOOL: |
|
2981
|
0
|
|
|
|
|
|
return lhs->tag == rhs->tag; |
|
2982
|
|
|
|
|
|
|
|
|
2983
|
0
|
|
|
|
|
|
default: |
|
2984
|
0
|
|
|
|
|
|
return false; |
|
2985
|
|
|
|
|
|
|
} |
|
2986
|
|
|
|
|
|
|
} |
|
2987
|
|
|
|
|
|
|
|
|
2988
|
21
|
|
|
|
|
|
bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { |
|
2989
|
21
|
|
|
|
|
|
yyjson_type type = unsafe_yyjson_get_type(lhs); |
|
2990
|
21
|
50
|
|
|
|
|
if (type != unsafe_yyjson_get_type(rhs)) return false; |
|
2991
|
|
|
|
|
|
|
|
|
2992
|
21
|
|
|
|
|
|
switch (type) { |
|
2993
|
3
|
|
|
|
|
|
case YYJSON_TYPE_OBJ: { |
|
2994
|
3
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(lhs); |
|
2995
|
3
|
50
|
|
|
|
|
if (len != unsafe_yyjson_get_len(rhs)) return false; |
|
2996
|
3
|
50
|
|
|
|
|
if (len > 0) { |
|
2997
|
|
|
|
|
|
|
yyjson_mut_obj_iter iter; |
|
2998
|
|
|
|
|
|
|
yyjson_mut_obj_iter_init(rhs, &iter); |
|
2999
|
3
|
|
|
|
|
|
lhs = (yyjson_mut_val *)lhs->uni.ptr; |
|
3000
|
6
|
100
|
|
|
|
|
while (len-- > 0) { |
|
3001
|
4
|
50
|
|
|
|
|
rhs = yyjson_mut_obj_iter_getn(&iter, lhs->uni.str, |
|
3002
|
|
|
|
|
|
|
unsafe_yyjson_get_len(lhs)); |
|
3003
|
5
|
50
|
|
|
|
|
if (!rhs) return false; |
|
3004
|
4
|
100
|
|
|
|
|
if (!unsafe_yyjson_mut_equals(lhs->next, rhs)) return false; |
|
3005
|
3
|
|
|
|
|
|
lhs = lhs->next->next; |
|
3006
|
|
|
|
|
|
|
} |
|
3007
|
|
|
|
|
|
|
} |
|
3008
|
|
|
|
|
|
|
/* yyjson allows duplicate keys, so the check may be inaccurate */ |
|
3009
|
2
|
|
|
|
|
|
return true; |
|
3010
|
|
|
|
|
|
|
} |
|
3011
|
|
|
|
|
|
|
|
|
3012
|
5
|
|
|
|
|
|
case YYJSON_TYPE_ARR: { |
|
3013
|
5
|
|
|
|
|
|
usize len = unsafe_yyjson_get_len(lhs); |
|
3014
|
5
|
50
|
|
|
|
|
if (len != unsafe_yyjson_get_len(rhs)) return false; |
|
3015
|
5
|
50
|
|
|
|
|
if (len > 0) { |
|
3016
|
5
|
|
|
|
|
|
lhs = (yyjson_mut_val *)lhs->uni.ptr; |
|
3017
|
5
|
|
|
|
|
|
rhs = (yyjson_mut_val *)rhs->uni.ptr; |
|
3018
|
13
|
100
|
|
|
|
|
while (len-- > 0) { |
|
3019
|
10
|
100
|
|
|
|
|
if (!unsafe_yyjson_mut_equals(lhs, rhs)) return false; |
|
3020
|
8
|
|
|
|
|
|
lhs = lhs->next; |
|
3021
|
8
|
|
|
|
|
|
rhs = rhs->next; |
|
3022
|
|
|
|
|
|
|
} |
|
3023
|
|
|
|
|
|
|
} |
|
3024
|
3
|
|
|
|
|
|
return true; |
|
3025
|
|
|
|
|
|
|
} |
|
3026
|
|
|
|
|
|
|
|
|
3027
|
11
|
|
|
|
|
|
case YYJSON_TYPE_NUM: |
|
3028
|
11
|
|
|
|
|
|
return unsafe_yyjson_num_equals(lhs, rhs); |
|
3029
|
|
|
|
|
|
|
|
|
3030
|
0
|
|
|
|
|
|
case YYJSON_TYPE_RAW: |
|
3031
|
|
|
|
|
|
|
case YYJSON_TYPE_STR: |
|
3032
|
0
|
|
|
|
|
|
return unsafe_yyjson_str_equals(lhs, rhs); |
|
3033
|
|
|
|
|
|
|
|
|
3034
|
2
|
|
|
|
|
|
case YYJSON_TYPE_NULL: |
|
3035
|
|
|
|
|
|
|
case YYJSON_TYPE_BOOL: |
|
3036
|
2
|
|
|
|
|
|
return lhs->tag == rhs->tag; |
|
3037
|
|
|
|
|
|
|
|
|
3038
|
0
|
|
|
|
|
|
default: |
|
3039
|
0
|
|
|
|
|
|
return false; |
|
3040
|
|
|
|
|
|
|
} |
|
3041
|
|
|
|
|
|
|
} |
|
3042
|
|
|
|
|
|
|
|
|
3043
|
0
|
|
|
|
|
|
bool yyjson_locate_pos(const char *str, size_t len, size_t pos, |
|
3044
|
|
|
|
|
|
|
size_t *line, size_t *col, size_t *chr) { |
|
3045
|
0
|
|
|
|
|
|
usize line_sum = 0, line_pos = 0, chr_sum = 0; |
|
3046
|
0
|
|
|
|
|
|
const u8 *cur = (const u8 *)str; |
|
3047
|
0
|
|
|
|
|
|
const u8 *end = cur + pos; |
|
3048
|
|
|
|
|
|
|
|
|
3049
|
0
|
0
|
|
|
|
|
if (!str || pos > len) { |
|
|
|
0
|
|
|
|
|
|
|
3050
|
0
|
0
|
|
|
|
|
if (line) *line = 0; |
|
3051
|
0
|
0
|
|
|
|
|
if (col) *col = 0; |
|
3052
|
0
|
0
|
|
|
|
|
if (chr) *chr = 0; |
|
3053
|
0
|
|
|
|
|
|
return false; |
|
3054
|
|
|
|
|
|
|
} |
|
3055
|
|
|
|
|
|
|
|
|
3056
|
0
|
0
|
|
|
|
|
if (pos >= 3 && is_utf8_bom(cur)) cur += 3; /* don't count BOM */ |
|
|
|
0
|
|
|
|
|
|
|
3057
|
0
|
0
|
|
|
|
|
while (cur < end) { |
|
3058
|
0
|
|
|
|
|
|
u8 c = *cur; |
|
3059
|
0
|
|
|
|
|
|
chr_sum += 1; |
|
3060
|
0
|
0
|
|
|
|
|
if (likely(c < 0x80)) { /* 0xxxxxxx (0x00-0x7F) ASCII */ |
|
3061
|
0
|
0
|
|
|
|
|
if (c == '\n') { |
|
3062
|
0
|
|
|
|
|
|
line_sum += 1; |
|
3063
|
0
|
|
|
|
|
|
line_pos = chr_sum; |
|
3064
|
|
|
|
|
|
|
} |
|
3065
|
0
|
|
|
|
|
|
cur += 1; |
|
3066
|
|
|
|
|
|
|
} |
|
3067
|
0
|
0
|
|
|
|
|
else if (c < 0xC0) cur += 1; /* 10xxxxxx (0x80-0xBF) Invalid */ |
|
3068
|
0
|
0
|
|
|
|
|
else if (c < 0xE0) cur += 2; /* 110xxxxx (0xC0-0xDF) 2-byte UTF-8 */ |
|
3069
|
0
|
0
|
|
|
|
|
else if (c < 0xF0) cur += 3; /* 1110xxxx (0xE0-0xEF) 3-byte UTF-8 */ |
|
3070
|
0
|
0
|
|
|
|
|
else if (c < 0xF8) cur += 4; /* 11110xxx (0xF0-0xF7) 4-byte UTF-8 */ |
|
3071
|
0
|
|
|
|
|
|
else cur += 1; /* 11111xxx (0xF8-0xFF) Invalid */ |
|
3072
|
|
|
|
|
|
|
} |
|
3073
|
0
|
0
|
|
|
|
|
if (line) *line = line_sum + 1; |
|
3074
|
0
|
0
|
|
|
|
|
if (col) *col = chr_sum - line_pos + 1; |
|
3075
|
0
|
0
|
|
|
|
|
if (chr) *chr = chr_sum; |
|
3076
|
0
|
|
|
|
|
|
return true; |
|
3077
|
|
|
|
|
|
|
} |
|
3078
|
|
|
|
|
|
|
|
|
3079
|
|
|
|
|
|
|
|
|
3080
|
|
|
|
|
|
|
|
|
3081
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_READER /* reader begin */ |
|
3082
|
|
|
|
|
|
|
|
|
3083
|
|
|
|
|
|
|
/* Check read flag, avoids `always false` warning when disabled. */ |
|
3084
|
|
|
|
|
|
|
#define has_flg(_flg) unlikely(has_rflag(flg, YYJSON_READ_##_flg, 0)) |
|
3085
|
|
|
|
|
|
|
#define has_allow(_flg) unlikely(has_rflag(flg, YYJSON_READ_ALLOW_##_flg, 1)) |
|
3086
|
|
|
|
|
|
|
#define YYJSON_READ_ALLOW_TRIVIA (YYJSON_READ_ALLOW_COMMENTS | \ |
|
3087
|
|
|
|
|
|
|
YYJSON_READ_ALLOW_EXT_WHITESPACE) |
|
3088
|
|
|
|
|
|
|
static_inline bool has_rflag(yyjson_read_flag flg, yyjson_read_flag chk, |
|
3089
|
|
|
|
|
|
|
bool non_standard) { |
|
3090
|
|
|
|
|
|
|
#if YYJSON_DISABLE_NON_STANDARD |
|
3091
|
|
|
|
|
|
|
if (non_standard) return false; |
|
3092
|
|
|
|
|
|
|
#endif |
|
3093
|
74635
|
|
|
|
|
|
return (flg & chk) != 0; |
|
3094
|
|
|
|
|
|
|
} |
|
3095
|
|
|
|
|
|
|
|
|
3096
|
|
|
|
|
|
|
|
|
3097
|
|
|
|
|
|
|
|
|
3098
|
|
|
|
|
|
|
/*============================================================================== |
|
3099
|
|
|
|
|
|
|
* MARK: - JSON Reader Utils (Private) |
|
3100
|
|
|
|
|
|
|
* These functions are used by JSON reader to read literals and comments. |
|
3101
|
|
|
|
|
|
|
*============================================================================*/ |
|
3102
|
|
|
|
|
|
|
|
|
3103
|
|
|
|
|
|
|
/** Read `true` literal, `*ptr[0]` should be `t`. */ |
|
3104
|
|
|
|
|
|
|
static_inline bool read_true(u8 **ptr, yyjson_val *val) { |
|
3105
|
2
|
|
|
|
|
|
u8 *cur = *ptr; |
|
3106
|
12
|
0
|
|
|
|
|
if (likely(byte_match_4(cur, "true"))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
3107
|
12
|
|
|
|
|
|
val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; |
|
3108
|
12
|
|
|
|
|
|
*ptr = cur + 4; |
|
3109
|
12
|
|
|
|
|
|
return true; |
|
3110
|
|
|
|
|
|
|
} |
|
3111
|
0
|
|
|
|
|
|
return false; |
|
3112
|
|
|
|
|
|
|
} |
|
3113
|
|
|
|
|
|
|
|
|
3114
|
|
|
|
|
|
|
/** Read `false` literal, `*ptr[0]` should be `f`. */ |
|
3115
|
|
|
|
|
|
|
static_inline bool read_false(u8 **ptr, yyjson_val *val) { |
|
3116
|
5
|
|
|
|
|
|
u8 *cur = *ptr; |
|
3117
|
6
|
0
|
|
|
|
|
if (likely(byte_match_4(cur + 1, "alse"))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
3118
|
5
|
|
|
|
|
|
val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; |
|
3119
|
5
|
|
|
|
|
|
*ptr = cur + 5; |
|
3120
|
5
|
|
|
|
|
|
return true; |
|
3121
|
|
|
|
|
|
|
} |
|
3122
|
0
|
|
|
|
|
|
return false; |
|
3123
|
|
|
|
|
|
|
} |
|
3124
|
|
|
|
|
|
|
|
|
3125
|
|
|
|
|
|
|
/** Read `null` literal, `*ptr[0]` should be `n`. */ |
|
3126
|
|
|
|
|
|
|
static_inline bool read_null(u8 **ptr, yyjson_val *val) { |
|
3127
|
4
|
|
|
|
|
|
u8 *cur = *ptr; |
|
3128
|
11
|
0
|
|
|
|
|
if (likely(byte_match_4(cur, "null"))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
3129
|
8
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NULL; |
|
3130
|
8
|
|
|
|
|
|
*ptr = cur + 4; |
|
3131
|
8
|
|
|
|
|
|
return true; |
|
3132
|
|
|
|
|
|
|
} |
|
3133
|
3
|
|
|
|
|
|
return false; |
|
3134
|
|
|
|
|
|
|
} |
|
3135
|
|
|
|
|
|
|
|
|
3136
|
|
|
|
|
|
|
/** Read `Inf` or `Infinity` literal (ignoring case). */ |
|
3137
|
|
|
|
|
|
|
static_inline bool read_inf(u8 **ptr, u8 **pre, |
|
3138
|
|
|
|
|
|
|
yyjson_read_flag flg, yyjson_val *val) { |
|
3139
|
0
|
|
|
|
|
|
u8 *hdr = *ptr; |
|
3140
|
0
|
|
|
|
|
|
u8 *cur = *ptr; |
|
3141
|
0
|
|
|
|
|
|
u8 **end = ptr; |
|
3142
|
0
|
|
|
|
|
|
bool sign = (*cur == '-'); |
|
3143
|
0
|
0
|
|
|
|
|
if (*cur == '+' && !has_allow(EXT_NUMBER)) return false; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3144
|
0
|
|
|
|
|
|
cur += char_is_sign(*cur); |
|
3145
|
0
|
0
|
|
|
|
|
if (char_to_lower(cur[0]) == 'i' && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3146
|
0
|
0
|
|
|
|
|
char_to_lower(cur[1]) == 'n' && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3147
|
0
|
0
|
|
|
|
|
char_to_lower(cur[2]) == 'f') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3148
|
0
|
0
|
|
|
|
|
if (char_to_lower(cur[3]) == 'i') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3149
|
0
|
0
|
|
|
|
|
if (char_to_lower(cur[4]) == 'n' && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3150
|
0
|
0
|
|
|
|
|
char_to_lower(cur[5]) == 'i' && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3151
|
0
|
0
|
|
|
|
|
char_to_lower(cur[6]) == 't' && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3152
|
0
|
0
|
|
|
|
|
char_to_lower(cur[7]) == 'y') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3153
|
0
|
|
|
|
|
|
cur += 8; |
|
3154
|
|
|
|
|
|
|
} else { |
|
3155
|
0
|
|
|
|
|
|
return false; |
|
3156
|
|
|
|
|
|
|
} |
|
3157
|
|
|
|
|
|
|
} else { |
|
3158
|
0
|
|
|
|
|
|
cur += 3; |
|
3159
|
|
|
|
|
|
|
} |
|
3160
|
0
|
|
|
|
|
|
*end = cur; |
|
3161
|
0
|
0
|
|
|
|
|
if (has_flg(NUMBER_AS_RAW)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3162
|
0
|
|
|
|
|
|
**pre = '\0'; /* add null-terminator for previous raw string */ |
|
3163
|
0
|
|
|
|
|
|
*pre = cur; /* save end position for current raw string */ |
|
3164
|
0
|
|
|
|
|
|
val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; |
|
3165
|
0
|
|
|
|
|
|
val->uni.str = (const char *)hdr; |
|
3166
|
|
|
|
|
|
|
} else { |
|
3167
|
0
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; |
|
3168
|
0
|
|
|
|
|
|
val->uni.u64 = f64_bits_inf(sign); |
|
3169
|
|
|
|
|
|
|
} |
|
3170
|
0
|
|
|
|
|
|
return true; |
|
3171
|
|
|
|
|
|
|
} |
|
3172
|
0
|
|
|
|
|
|
return false; |
|
3173
|
|
|
|
|
|
|
} |
|
3174
|
|
|
|
|
|
|
|
|
3175
|
|
|
|
|
|
|
/** Read `NaN` literal (ignoring case). */ |
|
3176
|
|
|
|
|
|
|
static_inline bool read_nan(u8 **ptr, u8 **pre, |
|
3177
|
|
|
|
|
|
|
yyjson_read_flag flg, yyjson_val *val) { |
|
3178
|
0
|
|
|
|
|
|
u8 *hdr = *ptr; |
|
3179
|
0
|
|
|
|
|
|
u8 *cur = *ptr; |
|
3180
|
0
|
|
|
|
|
|
u8 **end = ptr; |
|
3181
|
0
|
|
|
|
|
|
bool sign = (*cur == '-'); |
|
3182
|
0
|
0
|
|
|
|
|
if (*cur == '+' && !has_allow(EXT_NUMBER)) return false; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3183
|
0
|
|
|
|
|
|
cur += char_is_sign(*cur); |
|
3184
|
0
|
0
|
|
|
|
|
if (char_to_lower(cur[0]) == 'n' && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3185
|
0
|
0
|
|
|
|
|
char_to_lower(cur[1]) == 'a' && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3186
|
0
|
0
|
|
|
|
|
char_to_lower(cur[2]) == 'n') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3187
|
0
|
|
|
|
|
|
cur += 3; |
|
3188
|
0
|
|
|
|
|
|
*end = cur; |
|
3189
|
0
|
0
|
|
|
|
|
if (has_flg(NUMBER_AS_RAW)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3190
|
0
|
|
|
|
|
|
**pre = '\0'; /* add null-terminator for previous raw string */ |
|
3191
|
0
|
|
|
|
|
|
*pre = cur; /* save end position for current raw string */ |
|
3192
|
0
|
|
|
|
|
|
val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; |
|
3193
|
0
|
|
|
|
|
|
val->uni.str = (const char *)hdr; |
|
3194
|
|
|
|
|
|
|
} else { |
|
3195
|
0
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; |
|
3196
|
0
|
|
|
|
|
|
val->uni.u64 = f64_bits_nan(sign); |
|
3197
|
|
|
|
|
|
|
} |
|
3198
|
0
|
|
|
|
|
|
return true; |
|
3199
|
|
|
|
|
|
|
} |
|
3200
|
0
|
|
|
|
|
|
return false; |
|
3201
|
|
|
|
|
|
|
} |
|
3202
|
|
|
|
|
|
|
|
|
3203
|
|
|
|
|
|
|
/** Read `Inf`, `Infinity` or `NaN` literal (ignoring case). */ |
|
3204
|
|
|
|
|
|
|
static_inline bool read_inf_or_nan(u8 **ptr, u8 **pre, |
|
3205
|
|
|
|
|
|
|
yyjson_read_flag flg, yyjson_val *val) { |
|
3206
|
0
|
0
|
|
|
|
|
if (read_inf(ptr, pre, flg, val)) return true; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3207
|
0
|
0
|
|
|
|
|
if (read_nan(ptr, pre, flg, val)) return true; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3208
|
0
|
|
|
|
|
|
return false; |
|
3209
|
|
|
|
|
|
|
} |
|
3210
|
|
|
|
|
|
|
|
|
3211
|
|
|
|
|
|
|
/** Read a JSON number as raw string. */ |
|
3212
|
0
|
|
|
|
|
|
static_noinline bool read_num_raw(u8 **ptr, u8 **pre, yyjson_read_flag flg, |
|
3213
|
|
|
|
|
|
|
yyjson_val *val, const char **msg) { |
|
3214
|
|
|
|
|
|
|
#define return_err(_pos, _msg) do { \ |
|
3215
|
|
|
|
|
|
|
*msg = _msg; *end = _pos; return false; \ |
|
3216
|
|
|
|
|
|
|
} while (false) |
|
3217
|
|
|
|
|
|
|
|
|
3218
|
|
|
|
|
|
|
#define return_raw() do { \ |
|
3219
|
|
|
|
|
|
|
val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ |
|
3220
|
|
|
|
|
|
|
val->uni.str = (const char *)hdr; \ |
|
3221
|
|
|
|
|
|
|
**pre = '\0'; *pre = cur; *end = cur; return true; \ |
|
3222
|
|
|
|
|
|
|
} while (false) |
|
3223
|
|
|
|
|
|
|
|
|
3224
|
0
|
|
|
|
|
|
u8 *hdr = *ptr; |
|
3225
|
0
|
|
|
|
|
|
u8 *cur = *ptr; |
|
3226
|
0
|
|
|
|
|
|
u8 **end = ptr; |
|
3227
|
|
|
|
|
|
|
|
|
3228
|
|
|
|
|
|
|
/* skip sign */ |
|
3229
|
0
|
|
|
|
|
|
cur += (*cur == '-'); |
|
3230
|
|
|
|
|
|
|
|
|
3231
|
|
|
|
|
|
|
/* read first digit, check leading zero */ |
|
3232
|
0
|
0
|
|
|
|
|
while (unlikely(!char_is_digit(*cur))) { |
|
3233
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_NUMBER)) { |
|
3234
|
0
|
0
|
|
|
|
|
if (*cur == '+' && cur == hdr) { /* leading `+` sign */ |
|
|
|
0
|
|
|
|
|
|
|
3235
|
0
|
|
|
|
|
|
cur++; |
|
3236
|
0
|
|
|
|
|
|
continue; |
|
3237
|
|
|
|
|
|
|
} |
|
3238
|
0
|
0
|
|
|
|
|
if (*cur == '.' && char_is_digit(cur[1])) { /* e.g. '.123' */ |
|
|
|
0
|
|
|
|
|
|
|
3239
|
0
|
|
|
|
|
|
goto read_double; |
|
3240
|
|
|
|
|
|
|
} |
|
3241
|
|
|
|
|
|
|
} |
|
3242
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
3243
|
0
|
0
|
|
|
|
|
if (read_inf_or_nan(ptr, pre, flg, val)) return true; |
|
3244
|
|
|
|
|
|
|
} |
|
3245
|
0
|
|
|
|
|
|
return_err(cur, "no digit after sign"); |
|
3246
|
|
|
|
|
|
|
} |
|
3247
|
|
|
|
|
|
|
|
|
3248
|
|
|
|
|
|
|
/* read integral part */ |
|
3249
|
0
|
0
|
|
|
|
|
if (*cur == '0') { |
|
3250
|
0
|
|
|
|
|
|
cur++; |
|
3251
|
0
|
0
|
|
|
|
|
if (unlikely(char_is_digit(*cur))) { |
|
3252
|
0
|
|
|
|
|
|
return_err(cur - 1, "number with leading zero is not allowed"); |
|
3253
|
|
|
|
|
|
|
} |
|
3254
|
0
|
0
|
|
|
|
|
if (!char_is_fp(*cur)) { |
|
3255
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_NUMBER) && char_to_lower(*cur) == 'x') { /* hex */ |
|
|
|
0
|
|
|
|
|
|
|
3256
|
0
|
0
|
|
|
|
|
if (!char_is_hex(*++cur)) return_err(cur, "invalid hex number"); |
|
3257
|
0
|
0
|
|
|
|
|
while(char_is_hex(*cur)) cur++; |
|
3258
|
|
|
|
|
|
|
} |
|
3259
|
0
|
|
|
|
|
|
return_raw(); |
|
3260
|
|
|
|
|
|
|
} |
|
3261
|
|
|
|
|
|
|
} else { |
|
3262
|
0
|
0
|
|
|
|
|
while (char_is_digit(*cur)) cur++; |
|
3263
|
0
|
0
|
|
|
|
|
if (!char_is_fp(*cur)) return_raw(); |
|
3264
|
|
|
|
|
|
|
} |
|
3265
|
|
|
|
|
|
|
|
|
3266
|
0
|
|
|
|
|
|
read_double: |
|
3267
|
|
|
|
|
|
|
/* read fraction part */ |
|
3268
|
0
|
0
|
|
|
|
|
if (*cur == '.') { |
|
3269
|
0
|
|
|
|
|
|
cur++; |
|
3270
|
0
|
0
|
|
|
|
|
if (!char_is_digit(*cur)) { |
|
3271
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_NUMBER)) { |
|
3272
|
0
|
0
|
|
|
|
|
if (!char_is_exp(*cur)) return_raw(); |
|
3273
|
|
|
|
|
|
|
} else { |
|
3274
|
0
|
|
|
|
|
|
return_err(cur, "no digit after decimal point"); |
|
3275
|
|
|
|
|
|
|
} |
|
3276
|
|
|
|
|
|
|
} |
|
3277
|
0
|
0
|
|
|
|
|
while (char_is_digit(*cur)) cur++; |
|
3278
|
|
|
|
|
|
|
} |
|
3279
|
|
|
|
|
|
|
|
|
3280
|
|
|
|
|
|
|
/* read exponent part */ |
|
3281
|
0
|
0
|
|
|
|
|
if (char_is_exp(*cur)) { |
|
3282
|
0
|
|
|
|
|
|
cur += 1 + char_is_sign(cur[1]); |
|
3283
|
0
|
0
|
|
|
|
|
if (!char_is_digit(*cur++)) { |
|
3284
|
0
|
|
|
|
|
|
return_err(cur, "no digit after exponent sign"); |
|
3285
|
|
|
|
|
|
|
} |
|
3286
|
0
|
0
|
|
|
|
|
while (char_is_digit(*cur)) cur++; |
|
3287
|
|
|
|
|
|
|
} |
|
3288
|
|
|
|
|
|
|
|
|
3289
|
0
|
|
|
|
|
|
return_raw(); |
|
3290
|
|
|
|
|
|
|
|
|
3291
|
|
|
|
|
|
|
#undef return_err |
|
3292
|
|
|
|
|
|
|
#undef return_raw |
|
3293
|
|
|
|
|
|
|
} |
|
3294
|
|
|
|
|
|
|
|
|
3295
|
|
|
|
|
|
|
/** Read a hex number. */ |
|
3296
|
0
|
|
|
|
|
|
static_noinline bool read_num_hex(u8 **ptr, u8 **pre, yyjson_read_flag flg, |
|
3297
|
|
|
|
|
|
|
yyjson_val *val, const char **msg) { |
|
3298
|
0
|
|
|
|
|
|
u8 *hdr = *ptr; |
|
3299
|
0
|
|
|
|
|
|
u8 *cur = *ptr; |
|
3300
|
0
|
|
|
|
|
|
u8 **end = ptr; |
|
3301
|
0
|
|
|
|
|
|
u64 sig = 0, i = 0; |
|
3302
|
|
|
|
|
|
|
bool sign; |
|
3303
|
|
|
|
|
|
|
|
|
3304
|
|
|
|
|
|
|
/* skip sign and '0x' */ |
|
3305
|
0
|
|
|
|
|
|
sign = (*cur == '-'); |
|
3306
|
0
|
0
|
|
|
|
|
cur += (*cur == '-' || *cur == '+') + 2; |
|
|
|
0
|
|
|
|
|
|
|
3307
|
|
|
|
|
|
|
|
|
3308
|
|
|
|
|
|
|
/* read hex */ |
|
3309
|
0
|
0
|
|
|
|
|
for(; i < 16; i++) { |
|
3310
|
0
|
|
|
|
|
|
u8 c = hex_conv_table[cur[i]]; |
|
3311
|
0
|
0
|
|
|
|
|
if (c == 0xF0) break; |
|
3312
|
0
|
|
|
|
|
|
sig <<= 4; |
|
3313
|
0
|
|
|
|
|
|
sig |= c; |
|
3314
|
|
|
|
|
|
|
} |
|
3315
|
|
|
|
|
|
|
|
|
3316
|
|
|
|
|
|
|
/* check error */ |
|
3317
|
0
|
0
|
|
|
|
|
if (unlikely(i == 0)) { |
|
3318
|
0
|
|
|
|
|
|
*msg = "invalid hex number"; |
|
3319
|
0
|
|
|
|
|
|
return false; |
|
3320
|
|
|
|
|
|
|
} |
|
3321
|
|
|
|
|
|
|
|
|
3322
|
|
|
|
|
|
|
/* check overflow */ |
|
3323
|
0
|
0
|
|
|
|
|
if (unlikely(i == 16)) { |
|
3324
|
0
|
0
|
|
|
|
|
if (char_is_hex(cur[16]) || (sign && sig > ((u64)1 << 63))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3325
|
0
|
0
|
|
|
|
|
if (!has_flg(BIGNUM_AS_RAW)) { |
|
3326
|
0
|
|
|
|
|
|
*msg = "hex number overflow"; |
|
3327
|
0
|
|
|
|
|
|
return false; |
|
3328
|
|
|
|
|
|
|
} |
|
3329
|
0
|
|
|
|
|
|
cur += 16; |
|
3330
|
0
|
0
|
|
|
|
|
while (char_is_hex(*cur)) cur++; |
|
3331
|
0
|
|
|
|
|
|
**pre = '\0'; |
|
3332
|
0
|
|
|
|
|
|
val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; |
|
3333
|
0
|
|
|
|
|
|
val->uni.str = (const char *)hdr; |
|
3334
|
0
|
|
|
|
|
|
*pre = cur; *end = cur; |
|
3335
|
0
|
|
|
|
|
|
return true; |
|
3336
|
|
|
|
|
|
|
} |
|
3337
|
|
|
|
|
|
|
} |
|
3338
|
|
|
|
|
|
|
|
|
3339
|
0
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); |
|
3340
|
0
|
0
|
|
|
|
|
val->uni.u64 = (u64)(sign ? (u64)(~(sig) + 1) : (u64)(sig)); |
|
3341
|
0
|
|
|
|
|
|
*end = cur + i; |
|
3342
|
0
|
|
|
|
|
|
return true; |
|
3343
|
|
|
|
|
|
|
} |
|
3344
|
|
|
|
|
|
|
|
|
3345
|
|
|
|
|
|
|
/** |
|
3346
|
|
|
|
|
|
|
Skip trivia (whitespace and comments). |
|
3347
|
|
|
|
|
|
|
This function should be used only when `char_is_trivia()` returns true. |
|
3348
|
|
|
|
|
|
|
@param ptr (inout) Input current position, output end position. |
|
3349
|
|
|
|
|
|
|
@param eof JSON end position. |
|
3350
|
|
|
|
|
|
|
@param flg JSON read flags. |
|
3351
|
|
|
|
|
|
|
@return true if at least one character was skipped. |
|
3352
|
|
|
|
|
|
|
false if no characters were skipped, |
|
3353
|
|
|
|
|
|
|
or if a multi-line comment is unterminated; |
|
3354
|
|
|
|
|
|
|
in the latter case, `ptr` will be set to `eof`. |
|
3355
|
|
|
|
|
|
|
*/ |
|
3356
|
0
|
|
|
|
|
|
static_noinline bool skip_trivia(u8 **ptr, u8 *eof, yyjson_read_flag flg) { |
|
3357
|
0
|
|
|
|
|
|
u8 *hdr = *ptr, *cur = *ptr; |
|
3358
|
|
|
|
|
|
|
usize len; |
|
3359
|
|
|
|
|
|
|
|
|
3360
|
0
|
0
|
|
|
|
|
while (cur < eof) { |
|
3361
|
0
|
|
|
|
|
|
u8 *loop_begin = cur; |
|
3362
|
|
|
|
|
|
|
|
|
3363
|
|
|
|
|
|
|
/* skip standard whitespace */ |
|
3364
|
0
|
0
|
|
|
|
|
while(char_is_space(*cur)) cur++; |
|
3365
|
|
|
|
|
|
|
|
|
3366
|
|
|
|
|
|
|
/* skip extended whitespace */ |
|
3367
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_WHITESPACE)) { |
|
3368
|
0
|
0
|
|
|
|
|
while (char_is_space_ext(*cur)) { |
|
3369
|
0
|
|
|
|
|
|
cur += (len = ext_space_len(cur)); |
|
3370
|
0
|
0
|
|
|
|
|
if (!len) break; |
|
3371
|
|
|
|
|
|
|
} |
|
3372
|
|
|
|
|
|
|
} |
|
3373
|
|
|
|
|
|
|
|
|
3374
|
|
|
|
|
|
|
/* skip comment, do not validate encoding */ |
|
3375
|
0
|
0
|
|
|
|
|
if (has_allow(COMMENTS) && cur[0] == '/') { |
|
|
|
0
|
|
|
|
|
|
|
3376
|
0
|
0
|
|
|
|
|
if (cur[1] == '/') { /* single-line comment */ |
|
3377
|
0
|
|
|
|
|
|
cur += 2; |
|
3378
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_WHITESPACE)) { |
|
3379
|
0
|
0
|
|
|
|
|
while (cur < eof) { |
|
3380
|
0
|
0
|
|
|
|
|
if (char_is_eol_ext(*cur)) { |
|
3381
|
0
|
|
|
|
|
|
cur += (len = ext_eol_len(cur)); |
|
3382
|
0
|
0
|
|
|
|
|
if (len) break; |
|
3383
|
|
|
|
|
|
|
} |
|
3384
|
0
|
|
|
|
|
|
cur++; |
|
3385
|
|
|
|
|
|
|
} |
|
3386
|
|
|
|
|
|
|
} else { |
|
3387
|
0
|
0
|
|
|
|
|
while (cur < eof && !char_is_eol(*cur)) cur++; |
|
|
|
0
|
|
|
|
|
|
|
3388
|
|
|
|
|
|
|
} |
|
3389
|
0
|
0
|
|
|
|
|
} else if (cur[1] == '*') { /* multi-line comment */ |
|
3390
|
0
|
|
|
|
|
|
cur += 2; |
|
3391
|
0
|
0
|
|
|
|
|
while (!byte_match_2(cur, "*/") && cur < eof) cur++; |
|
|
|
0
|
|
|
|
|
|
|
3392
|
0
|
0
|
|
|
|
|
if (cur == eof) { |
|
3393
|
0
|
|
|
|
|
|
*ptr = eof; |
|
3394
|
0
|
|
|
|
|
|
return false; /* unclosed comment */ |
|
3395
|
|
|
|
|
|
|
} |
|
3396
|
0
|
|
|
|
|
|
cur += 2; |
|
3397
|
|
|
|
|
|
|
} |
|
3398
|
|
|
|
|
|
|
} |
|
3399
|
0
|
0
|
|
|
|
|
if (cur == loop_begin) break; |
|
3400
|
|
|
|
|
|
|
} |
|
3401
|
0
|
|
|
|
|
|
*ptr = cur; |
|
3402
|
0
|
|
|
|
|
|
return cur > hdr; |
|
3403
|
|
|
|
|
|
|
} |
|
3404
|
|
|
|
|
|
|
|
|
3405
|
|
|
|
|
|
|
/** |
|
3406
|
|
|
|
|
|
|
Check truncated UTF-8 character. |
|
3407
|
|
|
|
|
|
|
Return true if `cur` starts a valid UTF-8 sequence that is truncated. |
|
3408
|
|
|
|
|
|
|
*/ |
|
3409
|
0
|
|
|
|
|
|
static bool is_truncated_utf8(u8 *cur, u8 *eof) { |
|
3410
|
|
|
|
|
|
|
u8 c0, c1, c2; |
|
3411
|
0
|
|
|
|
|
|
usize len = (usize)(eof - cur); |
|
3412
|
0
|
0
|
|
|
|
|
if (cur >= eof || len >= 4) return false; |
|
|
|
0
|
|
|
|
|
|
|
3413
|
0
|
|
|
|
|
|
c0 = cur[0]; c1 = cur[1]; c2 = cur[2]; |
|
3414
|
|
|
|
|
|
|
/* 1-byte UTF-8, not truncated */ |
|
3415
|
0
|
0
|
|
|
|
|
if (c0 < 0x80) return false; |
|
3416
|
0
|
0
|
|
|
|
|
if (len == 1) { |
|
3417
|
|
|
|
|
|
|
/* 2-byte UTF-8, truncated */ |
|
3418
|
0
|
0
|
|
|
|
|
if ((c0 & 0xE0) == 0xC0 && (c0 & 0x1E) != 0x00) return true; |
|
|
|
0
|
|
|
|
|
|
|
3419
|
|
|
|
|
|
|
/* 3-byte UTF-8, truncated */ |
|
3420
|
0
|
0
|
|
|
|
|
if ((c0 & 0xF0) == 0xE0) return true; |
|
3421
|
|
|
|
|
|
|
/* 4-byte UTF-8, truncated */ |
|
3422
|
0
|
0
|
|
|
|
|
if ((c0 & 0xF8) == 0xF0 && (c0 & 0x07) <= 0x04) return true; |
|
|
|
0
|
|
|
|
|
|
|
3423
|
0
|
0
|
|
|
|
|
} else if (len == 2) { |
|
3424
|
|
|
|
|
|
|
/* 3-byte UTF-8, truncated */ |
|
3425
|
0
|
0
|
|
|
|
|
if ((c0 & 0xF0) == 0xE0 && (c1 & 0xC0) == 0x80) { |
|
|
|
0
|
|
|
|
|
|
|
3426
|
0
|
|
|
|
|
|
u8 t = (u8)(((c0 & 0x0F) << 1) | ((c1 & 0x20) >> 5)); |
|
3427
|
0
|
0
|
|
|
|
|
return 0x01 <= t && t != 0x1B; |
|
|
|
0
|
|
|
|
|
|
|
3428
|
|
|
|
|
|
|
} |
|
3429
|
|
|
|
|
|
|
/* 4-byte UTF-8, truncated */ |
|
3430
|
0
|
0
|
|
|
|
|
if ((c0 & 0xF8) == 0xF0 && (c1 & 0xC0) == 0x80) { |
|
|
|
0
|
|
|
|
|
|
|
3431
|
0
|
|
|
|
|
|
u8 t = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4)); |
|
3432
|
0
|
0
|
|
|
|
|
return 0x01 <= t && t <= 0x10; |
|
|
|
0
|
|
|
|
|
|
|
3433
|
|
|
|
|
|
|
} |
|
3434
|
0
|
0
|
|
|
|
|
} else if (len == 3) { |
|
3435
|
|
|
|
|
|
|
/* 4 bytes UTF-8, truncated */ |
|
3436
|
0
|
0
|
|
|
|
|
if ((c0 & 0xF8) == 0xF0 && (c1 & 0xC0) == 0x80 && (c2 & 0xC0) == 0x80) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3437
|
0
|
|
|
|
|
|
u8 t = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4)); |
|
3438
|
0
|
0
|
|
|
|
|
return 0x01 <= t && t <= 0x10; |
|
|
|
0
|
|
|
|
|
|
|
3439
|
|
|
|
|
|
|
} |
|
3440
|
|
|
|
|
|
|
} |
|
3441
|
0
|
|
|
|
|
|
return false; |
|
3442
|
|
|
|
|
|
|
} |
|
3443
|
|
|
|
|
|
|
|
|
3444
|
|
|
|
|
|
|
/** |
|
3445
|
|
|
|
|
|
|
Check truncated string. |
|
3446
|
|
|
|
|
|
|
Returns true if `cur` match `str` but is truncated. |
|
3447
|
|
|
|
|
|
|
The `str` should be lowercase ASCII letters. |
|
3448
|
|
|
|
|
|
|
*/ |
|
3449
|
9
|
|
|
|
|
|
static bool is_truncated_str(u8 *cur, u8 *eof, const char *str, |
|
3450
|
|
|
|
|
|
|
bool case_sensitive) { |
|
3451
|
9
|
|
|
|
|
|
usize len = strlen(str); |
|
3452
|
9
|
50
|
|
|
|
|
if (cur + len <= eof || eof <= cur) return false; |
|
|
|
0
|
|
|
|
|
|
|
3453
|
0
|
0
|
|
|
|
|
if (case_sensitive) { |
|
3454
|
0
|
|
|
|
|
|
return memcmp(cur, str, (usize)(eof - cur)) == 0; |
|
3455
|
|
|
|
|
|
|
} |
|
3456
|
0
|
0
|
|
|
|
|
for (; cur < eof; cur++, str++) { |
|
3457
|
0
|
0
|
|
|
|
|
if (char_to_lower(*cur) != *(const u8 *)str) return false; |
|
3458
|
|
|
|
|
|
|
} |
|
3459
|
0
|
|
|
|
|
|
return true; |
|
3460
|
|
|
|
|
|
|
} |
|
3461
|
|
|
|
|
|
|
|
|
3462
|
|
|
|
|
|
|
/** |
|
3463
|
|
|
|
|
|
|
Check truncated JSON on parsing errors. |
|
3464
|
|
|
|
|
|
|
Returns true if the input is valid but truncated. |
|
3465
|
|
|
|
|
|
|
*/ |
|
3466
|
4
|
|
|
|
|
|
static_noinline bool is_truncated_end(u8 *hdr, u8 *cur, u8 *eof, |
|
3467
|
|
|
|
|
|
|
yyjson_read_code code, |
|
3468
|
|
|
|
|
|
|
yyjson_read_flag flg) { |
|
3469
|
4
|
50
|
|
|
|
|
if (cur >= eof) return true; |
|
3470
|
4
|
100
|
|
|
|
|
if (code == YYJSON_READ_ERROR_LITERAL) { |
|
3471
|
6
|
|
|
|
|
|
if (is_truncated_str(cur, eof, "true", true) || |
|
3472
|
6
|
50
|
|
|
|
|
is_truncated_str(cur, eof, "false", true) || |
|
3473
|
3
|
|
|
|
|
|
is_truncated_str(cur, eof, "null", true)) { |
|
3474
|
0
|
|
|
|
|
|
return true; |
|
3475
|
|
|
|
|
|
|
} |
|
3476
|
|
|
|
|
|
|
} |
|
3477
|
4
|
100
|
|
|
|
|
if (code == YYJSON_READ_ERROR_UNEXPECTED_CHARACTER || |
|
3478
|
3
|
50
|
|
|
|
|
code == YYJSON_READ_ERROR_INVALID_NUMBER || |
|
3479
|
3
|
50
|
|
|
|
|
code == YYJSON_READ_ERROR_LITERAL) { |
|
3480
|
8
|
50
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
3481
|
0
|
0
|
|
|
|
|
if (*cur == '-') cur++; |
|
3482
|
0
|
|
|
|
|
|
if (is_truncated_str(cur, eof, "infinity", false) || |
|
3483
|
0
|
|
|
|
|
|
is_truncated_str(cur, eof, "nan", false)) { |
|
3484
|
0
|
|
|
|
|
|
return true; |
|
3485
|
|
|
|
|
|
|
} |
|
3486
|
|
|
|
|
|
|
} |
|
3487
|
|
|
|
|
|
|
} |
|
3488
|
4
|
50
|
|
|
|
|
if (code == YYJSON_READ_ERROR_UNEXPECTED_CONTENT) { |
|
3489
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
3490
|
0
|
|
|
|
|
|
if (hdr + 3 <= cur && |
|
3491
|
0
|
|
|
|
|
|
is_truncated_str(cur - 3, eof, "infinity", false)) { |
|
3492
|
0
|
|
|
|
|
|
return true; /* e.g. infin would be read as inf + in */ |
|
3493
|
|
|
|
|
|
|
} |
|
3494
|
|
|
|
|
|
|
} |
|
3495
|
|
|
|
|
|
|
} |
|
3496
|
4
|
50
|
|
|
|
|
if (code == YYJSON_READ_ERROR_INVALID_STRING) { |
|
3497
|
0
|
|
|
|
|
|
usize len = (usize)(eof - cur); |
|
3498
|
|
|
|
|
|
|
|
|
3499
|
|
|
|
|
|
|
/* unicode escape sequence */ |
|
3500
|
0
|
0
|
|
|
|
|
if (*cur == '\\') { |
|
3501
|
0
|
0
|
|
|
|
|
if (len == 1) return true; |
|
3502
|
0
|
0
|
|
|
|
|
if (len <= 5) { |
|
3503
|
0
|
0
|
|
|
|
|
if (*++cur != 'u') return false; |
|
3504
|
0
|
0
|
|
|
|
|
for (++cur; cur < eof; cur++) { |
|
3505
|
0
|
0
|
|
|
|
|
if (!char_is_hex(*cur)) return false; |
|
3506
|
|
|
|
|
|
|
} |
|
3507
|
0
|
|
|
|
|
|
return true; |
|
3508
|
0
|
0
|
|
|
|
|
} else if (len <= 11) { |
|
3509
|
|
|
|
|
|
|
/* incomplete surrogate pair? */ |
|
3510
|
|
|
|
|
|
|
u16 hi; |
|
3511
|
0
|
0
|
|
|
|
|
if (*++cur != 'u') return false; |
|
3512
|
0
|
0
|
|
|
|
|
if (!hex_load_4(++cur, &hi)) return false; |
|
3513
|
0
|
0
|
|
|
|
|
if ((hi & 0xF800) != 0xD800) return false; |
|
3514
|
0
|
|
|
|
|
|
cur += 4; |
|
3515
|
0
|
0
|
|
|
|
|
if (cur >= eof) return true; |
|
3516
|
|
|
|
|
|
|
/* valid low surrogate is DC00...DFFF */ |
|
3517
|
0
|
0
|
|
|
|
|
if (*cur != '\\') return false; |
|
3518
|
0
|
0
|
|
|
|
|
if (++cur >= eof) return true; |
|
3519
|
0
|
0
|
|
|
|
|
if (*cur != 'u') return false; |
|
3520
|
0
|
0
|
|
|
|
|
if (++cur >= eof) return true; |
|
3521
|
0
|
0
|
|
|
|
|
if (*cur != 'd' && *cur != 'D') return false; |
|
|
|
0
|
|
|
|
|
|
|
3522
|
0
|
0
|
|
|
|
|
if (++cur >= eof) return true; |
|
3523
|
0
|
0
|
|
|
|
|
if ((*cur < 'c' || *cur > 'f') && (*cur < 'C' || *cur > 'F')) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3524
|
0
|
|
|
|
|
|
return false; |
|
3525
|
0
|
0
|
|
|
|
|
if (++cur >= eof) return true; |
|
3526
|
0
|
0
|
|
|
|
|
if (!char_is_hex(*cur)) return false; |
|
3527
|
0
|
|
|
|
|
|
return true; |
|
3528
|
|
|
|
|
|
|
} |
|
3529
|
0
|
|
|
|
|
|
return false; |
|
3530
|
|
|
|
|
|
|
} |
|
3531
|
|
|
|
|
|
|
|
|
3532
|
|
|
|
|
|
|
/* 2 to 4 bytes UTF-8 */ |
|
3533
|
0
|
0
|
|
|
|
|
if (is_truncated_utf8(cur, eof)) { |
|
3534
|
0
|
|
|
|
|
|
return true; |
|
3535
|
|
|
|
|
|
|
} |
|
3536
|
|
|
|
|
|
|
} |
|
3537
|
8
|
50
|
|
|
|
|
if (has_allow(COMMENTS)) { |
|
3538
|
0
|
0
|
|
|
|
|
if (code == YYJSON_READ_ERROR_INVALID_COMMENT) { |
|
3539
|
|
|
|
|
|
|
/* unclosed multiline comment */ |
|
3540
|
0
|
|
|
|
|
|
return true; |
|
3541
|
|
|
|
|
|
|
} |
|
3542
|
0
|
0
|
|
|
|
|
if (code == YYJSON_READ_ERROR_UNEXPECTED_CHARACTER && |
|
3543
|
0
|
0
|
|
|
|
|
*cur == '/' && cur + 1 == eof) { |
|
|
|
0
|
|
|
|
|
|
|
3544
|
|
|
|
|
|
|
/* truncated beginning of comment */ |
|
3545
|
0
|
|
|
|
|
|
return true; |
|
3546
|
|
|
|
|
|
|
} |
|
3547
|
|
|
|
|
|
|
} |
|
3548
|
4
|
100
|
|
|
|
|
if (code == YYJSON_READ_ERROR_UNEXPECTED_CHARACTER && |
|
3549
|
2
|
50
|
|
|
|
|
has_allow(BOM)) { |
|
3550
|
|
|
|
|
|
|
/* truncated UTF-8 BOM */ |
|
3551
|
0
|
|
|
|
|
|
usize len = (usize)(eof - cur); |
|
3552
|
0
|
0
|
|
|
|
|
if (cur == hdr && len < 3 && !memcmp(hdr, "\xEF\xBB\xBF", len)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3553
|
0
|
|
|
|
|
|
return true; |
|
3554
|
|
|
|
|
|
|
} |
|
3555
|
|
|
|
|
|
|
} |
|
3556
|
4
|
|
|
|
|
|
return false; |
|
3557
|
|
|
|
|
|
|
} |
|
3558
|
|
|
|
|
|
|
|
|
3559
|
|
|
|
|
|
|
|
|
3560
|
|
|
|
|
|
|
|
|
3561
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_FAST_FP_CONV /* FP_READER */ |
|
3562
|
|
|
|
|
|
|
|
|
3563
|
|
|
|
|
|
|
/*============================================================================== |
|
3564
|
|
|
|
|
|
|
* MARK: - BigInt For Floating Point Number Reader (Private) |
|
3565
|
|
|
|
|
|
|
* |
|
3566
|
|
|
|
|
|
|
* The bigint algorithm is used by floating-point number reader to get correctly |
|
3567
|
|
|
|
|
|
|
* rounded result for numbers with lots of digits. This part of code is rarely |
|
3568
|
|
|
|
|
|
|
* used for common numbers. |
|
3569
|
|
|
|
|
|
|
*============================================================================*/ |
|
3570
|
|
|
|
|
|
|
|
|
3571
|
|
|
|
|
|
|
/** Unsigned arbitrarily large integer */ |
|
3572
|
|
|
|
|
|
|
typedef struct bigint { |
|
3573
|
|
|
|
|
|
|
u32 used; /* used chunks count, should not be 0 */ |
|
3574
|
|
|
|
|
|
|
u64 bits[64]; /* chunks (58 is enough here) */ |
|
3575
|
|
|
|
|
|
|
} bigint; |
|
3576
|
|
|
|
|
|
|
|
|
3577
|
|
|
|
|
|
|
/** |
|
3578
|
|
|
|
|
|
|
Evaluate 'big += val'. |
|
3579
|
|
|
|
|
|
|
@param big A big number (can be 0). |
|
3580
|
|
|
|
|
|
|
@param val An unsigned integer (can be 0). |
|
3581
|
|
|
|
|
|
|
*/ |
|
3582
|
|
|
|
|
|
|
static_inline void bigint_add_u64(bigint *big, u64 val) { |
|
3583
|
|
|
|
|
|
|
u32 idx, max; |
|
3584
|
0
|
|
|
|
|
|
u64 num = big->bits[0]; |
|
3585
|
0
|
|
|
|
|
|
u64 add = num + val; |
|
3586
|
0
|
|
|
|
|
|
big->bits[0] = add; |
|
3587
|
0
|
0
|
|
|
|
|
if (likely((add >= num) || (add >= val))) return; |
|
|
|
0
|
|
|
|
|
|
|
3588
|
0
|
0
|
|
|
|
|
for ((void)(idx = 1), max = big->used; idx < max; idx++) { |
|
3589
|
0
|
0
|
|
|
|
|
if (likely(big->bits[idx] != U64_MAX)) { |
|
3590
|
0
|
|
|
|
|
|
big->bits[idx] += 1; |
|
3591
|
0
|
|
|
|
|
|
return; |
|
3592
|
|
|
|
|
|
|
} |
|
3593
|
0
|
|
|
|
|
|
big->bits[idx] = 0; |
|
3594
|
|
|
|
|
|
|
} |
|
3595
|
0
|
|
|
|
|
|
big->bits[big->used++] = 1; |
|
3596
|
|
|
|
|
|
|
} |
|
3597
|
|
|
|
|
|
|
|
|
3598
|
|
|
|
|
|
|
/** |
|
3599
|
|
|
|
|
|
|
Evaluate 'big *= val'. |
|
3600
|
|
|
|
|
|
|
@param big A big number (can be 0). |
|
3601
|
|
|
|
|
|
|
@param val An unsigned integer (cannot be 0). |
|
3602
|
|
|
|
|
|
|
*/ |
|
3603
|
|
|
|
|
|
|
static_inline void bigint_mul_u64(bigint *big, u64 val) { |
|
3604
|
0
|
|
|
|
|
|
u32 idx = 0, max = big->used; |
|
3605
|
0
|
|
|
|
|
|
u64 hi, lo, carry = 0; |
|
3606
|
0
|
0
|
|
|
|
|
for (; idx < max; idx++) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3607
|
0
|
0
|
|
|
|
|
if (big->bits[idx]) break; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3608
|
|
|
|
|
|
|
} |
|
3609
|
0
|
0
|
|
|
|
|
for (; idx < max; idx++) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3610
|
0
|
|
|
|
|
|
u128_mul_add(big->bits[idx], val, carry, &hi, &lo); |
|
3611
|
0
|
|
|
|
|
|
big->bits[idx] = lo; |
|
3612
|
0
|
|
|
|
|
|
carry = hi; |
|
3613
|
|
|
|
|
|
|
} |
|
3614
|
0
|
0
|
|
|
|
|
if (carry) big->bits[big->used++] = carry; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3615
|
0
|
|
|
|
|
|
} |
|
3616
|
|
|
|
|
|
|
|
|
3617
|
|
|
|
|
|
|
/** |
|
3618
|
|
|
|
|
|
|
Evaluate 'big *= 2^exp'. |
|
3619
|
|
|
|
|
|
|
@param big A big number (can be 0). |
|
3620
|
|
|
|
|
|
|
@param exp An exponent integer (can be 0). |
|
3621
|
|
|
|
|
|
|
*/ |
|
3622
|
|
|
|
|
|
|
static_inline void bigint_mul_pow2(bigint *big, u32 exp) { |
|
3623
|
0
|
|
|
|
|
|
u32 shft = exp % 64; |
|
3624
|
0
|
|
|
|
|
|
u32 move = exp / 64; |
|
3625
|
0
|
|
|
|
|
|
u32 idx = big->used; |
|
3626
|
0
|
|
|
|
|
|
if (unlikely(shft == 0)) { |
|
3627
|
0
|
0
|
|
|
|
|
for (; idx > 0; idx--) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3628
|
0
|
|
|
|
|
|
big->bits[idx + move - 1] = big->bits[idx - 1]; |
|
3629
|
|
|
|
|
|
|
} |
|
3630
|
0
|
|
|
|
|
|
big->used += move; |
|
3631
|
0
|
0
|
|
|
|
|
while (move) big->bits[--move] = 0; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3632
|
|
|
|
|
|
|
} else { |
|
3633
|
0
|
|
|
|
|
|
big->bits[idx] = 0; |
|
3634
|
0
|
0
|
|
|
|
|
for (; idx > 0; idx--) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3635
|
0
|
|
|
|
|
|
u64 num = big->bits[idx] << shft; |
|
3636
|
0
|
|
|
|
|
|
num |= big->bits[idx - 1] >> (64 - shft); |
|
3637
|
0
|
|
|
|
|
|
big->bits[idx + move] = num; |
|
3638
|
|
|
|
|
|
|
} |
|
3639
|
0
|
|
|
|
|
|
big->bits[move] = big->bits[0] << shft; |
|
3640
|
0
|
|
|
|
|
|
big->used += move + (big->bits[big->used + move] > 0); |
|
3641
|
0
|
0
|
|
|
|
|
while (move) big->bits[--move] = 0; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3642
|
|
|
|
|
|
|
} |
|
3643
|
0
|
|
|
|
|
|
} |
|
3644
|
|
|
|
|
|
|
|
|
3645
|
|
|
|
|
|
|
/** |
|
3646
|
|
|
|
|
|
|
Evaluate 'big *= 10^exp'. |
|
3647
|
|
|
|
|
|
|
@param big A big number (can be 0). |
|
3648
|
|
|
|
|
|
|
@param exp An exponent integer (cannot be 0). |
|
3649
|
|
|
|
|
|
|
*/ |
|
3650
|
|
|
|
|
|
|
static_inline void bigint_mul_pow10(bigint *big, i32 exp) { |
|
3651
|
0
|
0
|
|
|
|
|
for (; exp >= U64_POW10_MAX_EXACT_EXP; exp -= U64_POW10_MAX_EXACT_EXP) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3652
|
0
|
|
|
|
|
|
bigint_mul_u64(big, u64_pow10_table[U64_POW10_MAX_EXACT_EXP]); |
|
3653
|
|
|
|
|
|
|
} |
|
3654
|
0
|
0
|
|
|
|
|
if (exp) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3655
|
0
|
|
|
|
|
|
bigint_mul_u64(big, u64_pow10_table[exp]); |
|
3656
|
|
|
|
|
|
|
} |
|
3657
|
0
|
|
|
|
|
|
} |
|
3658
|
|
|
|
|
|
|
|
|
3659
|
|
|
|
|
|
|
/** |
|
3660
|
|
|
|
|
|
|
Compare two bigint. |
|
3661
|
|
|
|
|
|
|
@return -1 if 'a < b', +1 if 'a > b', 0 if 'a == b'. |
|
3662
|
|
|
|
|
|
|
*/ |
|
3663
|
|
|
|
|
|
|
static_inline i32 bigint_cmp(bigint *a, bigint *b) { |
|
3664
|
0
|
|
|
|
|
|
u32 idx = a->used; |
|
3665
|
0
|
0
|
|
|
|
|
if (a->used < b->used) return -1; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3666
|
0
|
0
|
|
|
|
|
if (a->used > b->used) return +1; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3667
|
0
|
0
|
|
|
|
|
while (idx-- > 0) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3668
|
0
|
|
|
|
|
|
u64 av = a->bits[idx]; |
|
3669
|
0
|
|
|
|
|
|
u64 bv = b->bits[idx]; |
|
3670
|
0
|
0
|
|
|
|
|
if (av < bv) return -1; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3671
|
0
|
0
|
|
|
|
|
if (av > bv) return +1; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3672
|
|
|
|
|
|
|
} |
|
3673
|
0
|
|
|
|
|
|
return 0; |
|
3674
|
|
|
|
|
|
|
} |
|
3675
|
|
|
|
|
|
|
|
|
3676
|
|
|
|
|
|
|
/** |
|
3677
|
|
|
|
|
|
|
Evaluate 'big = val'. |
|
3678
|
|
|
|
|
|
|
@param big A big number (can be 0). |
|
3679
|
|
|
|
|
|
|
@param val An unsigned integer (can be 0). |
|
3680
|
|
|
|
|
|
|
*/ |
|
3681
|
|
|
|
|
|
|
static_inline void bigint_set_u64(bigint *big, u64 val) { |
|
3682
|
0
|
|
|
|
|
|
big->used = 1; |
|
3683
|
0
|
|
|
|
|
|
big->bits[0] = val; |
|
3684
|
0
|
|
|
|
|
|
} |
|
3685
|
|
|
|
|
|
|
|
|
3686
|
|
|
|
|
|
|
/** Set a bigint with floating point number string. */ |
|
3687
|
0
|
|
|
|
|
|
static_noinline void bigint_set_buf(bigint *big, u64 sig, i32 *exp, |
|
3688
|
|
|
|
|
|
|
u8 *sig_cut, u8 *sig_end, u8 *dot_pos) { |
|
3689
|
|
|
|
|
|
|
|
|
3690
|
0
|
0
|
|
|
|
|
if (unlikely(!sig_cut)) { |
|
3691
|
|
|
|
|
|
|
/* no digit cut, set significant part only */ |
|
3692
|
|
|
|
|
|
|
bigint_set_u64(big, sig); |
|
3693
|
0
|
|
|
|
|
|
return; |
|
3694
|
|
|
|
|
|
|
|
|
3695
|
|
|
|
|
|
|
} else { |
|
3696
|
|
|
|
|
|
|
/* some digits were cut, read them from 'sig_cut' to 'sig_end' */ |
|
3697
|
0
|
|
|
|
|
|
u8 *hdr = sig_cut; |
|
3698
|
0
|
|
|
|
|
|
u8 *cur = hdr; |
|
3699
|
0
|
|
|
|
|
|
u32 len = 0; |
|
3700
|
0
|
|
|
|
|
|
u64 val = 0; |
|
3701
|
0
|
|
|
|
|
|
bool dig_big_cut = false; |
|
3702
|
0
|
|
|
|
|
|
bool has_dot = (hdr < dot_pos) & (dot_pos < sig_end); |
|
3703
|
0
|
|
|
|
|
|
u32 dig_len_total = U64_SAFE_DIG + (u32)(sig_end - hdr) - has_dot; |
|
3704
|
|
|
|
|
|
|
|
|
3705
|
0
|
|
|
|
|
|
sig -= (*sig_cut >= '5'); /* sig was rounded before */ |
|
3706
|
0
|
0
|
|
|
|
|
if (dig_len_total > F64_MAX_DEC_DIG) { |
|
3707
|
0
|
|
|
|
|
|
dig_big_cut = true; |
|
3708
|
0
|
|
|
|
|
|
sig_end -= dig_len_total - (F64_MAX_DEC_DIG + 1); |
|
3709
|
0
|
|
|
|
|
|
sig_end -= (dot_pos + 1 == sig_end); |
|
3710
|
0
|
|
|
|
|
|
dig_len_total = (F64_MAX_DEC_DIG + 1); |
|
3711
|
|
|
|
|
|
|
} |
|
3712
|
0
|
|
|
|
|
|
*exp -= (i32)dig_len_total - U64_SAFE_DIG; |
|
3713
|
|
|
|
|
|
|
|
|
3714
|
0
|
|
|
|
|
|
big->used = 1; |
|
3715
|
0
|
|
|
|
|
|
big->bits[0] = sig; |
|
3716
|
0
|
0
|
|
|
|
|
while (cur < sig_end) { |
|
3717
|
0
|
0
|
|
|
|
|
if (likely(cur != dot_pos)) { |
|
3718
|
0
|
|
|
|
|
|
val = val * 10 + (u8)(*cur++ - '0'); |
|
3719
|
0
|
|
|
|
|
|
len++; |
|
3720
|
0
|
0
|
|
|
|
|
if (unlikely(cur == sig_end && dig_big_cut)) { |
|
|
|
0
|
|
|
|
|
|
|
3721
|
|
|
|
|
|
|
/* The last digit must be non-zero, */ |
|
3722
|
|
|
|
|
|
|
/* set it to '1' for correct rounding. */ |
|
3723
|
0
|
|
|
|
|
|
val = val - (val % 10) + 1; |
|
3724
|
|
|
|
|
|
|
} |
|
3725
|
0
|
0
|
|
|
|
|
if (len == U64_SAFE_DIG || cur == sig_end) { |
|
|
|
0
|
|
|
|
|
|
|
3726
|
0
|
|
|
|
|
|
bigint_mul_pow10(big, (i32)len); |
|
3727
|
|
|
|
|
|
|
bigint_add_u64(big, val); |
|
3728
|
0
|
|
|
|
|
|
val = 0; |
|
3729
|
0
|
|
|
|
|
|
len = 0; |
|
3730
|
|
|
|
|
|
|
} |
|
3731
|
|
|
|
|
|
|
} else { |
|
3732
|
0
|
|
|
|
|
|
cur++; |
|
3733
|
|
|
|
|
|
|
} |
|
3734
|
|
|
|
|
|
|
} |
|
3735
|
|
|
|
|
|
|
} |
|
3736
|
|
|
|
|
|
|
} |
|
3737
|
|
|
|
|
|
|
|
|
3738
|
|
|
|
|
|
|
|
|
3739
|
|
|
|
|
|
|
|
|
3740
|
|
|
|
|
|
|
/*============================================================================== |
|
3741
|
|
|
|
|
|
|
* MARK: - Diy Floating Point (Private) |
|
3742
|
|
|
|
|
|
|
*============================================================================*/ |
|
3743
|
|
|
|
|
|
|
|
|
3744
|
|
|
|
|
|
|
/** "Do It Yourself Floating Point" struct. */ |
|
3745
|
|
|
|
|
|
|
typedef struct diy_fp { |
|
3746
|
|
|
|
|
|
|
u64 sig; /* significand */ |
|
3747
|
|
|
|
|
|
|
i32 exp; /* exponent, base 2 */ |
|
3748
|
|
|
|
|
|
|
i32 pad; /* padding, useless */ |
|
3749
|
|
|
|
|
|
|
} diy_fp; |
|
3750
|
|
|
|
|
|
|
|
|
3751
|
|
|
|
|
|
|
/** Get cached rounded diy_fp with pow(10, e) The input value must in range |
|
3752
|
|
|
|
|
|
|
[POW10_SIG_TABLE_MIN_EXP, POW10_SIG_TABLE_MAX_EXP]. */ |
|
3753
|
|
|
|
|
|
|
static_inline diy_fp diy_fp_get_cached_pow10(i32 exp10) { |
|
3754
|
|
|
|
|
|
|
diy_fp fp; |
|
3755
|
|
|
|
|
|
|
u64 sig_ext; |
|
3756
|
|
|
|
|
|
|
pow10_table_get_sig(exp10, &fp.sig, &sig_ext); |
|
3757
|
|
|
|
|
|
|
pow10_table_get_exp(exp10, &fp.exp); |
|
3758
|
0
|
|
|
|
|
|
fp.sig += (sig_ext >> 63); |
|
3759
|
0
|
|
|
|
|
|
return fp; |
|
3760
|
|
|
|
|
|
|
} |
|
3761
|
|
|
|
|
|
|
|
|
3762
|
|
|
|
|
|
|
/** Returns fp * fp2. */ |
|
3763
|
|
|
|
|
|
|
static_inline diy_fp diy_fp_mul(diy_fp fp, diy_fp fp2) { |
|
3764
|
|
|
|
|
|
|
u64 hi, lo; |
|
3765
|
0
|
|
|
|
|
|
u128_mul(fp.sig, fp2.sig, &hi, &lo); |
|
3766
|
0
|
|
|
|
|
|
fp.sig = hi + (lo >> 63); |
|
3767
|
0
|
|
|
|
|
|
fp.exp += fp2.exp + 64; |
|
3768
|
0
|
|
|
|
|
|
return fp; |
|
3769
|
|
|
|
|
|
|
} |
|
3770
|
|
|
|
|
|
|
|
|
3771
|
|
|
|
|
|
|
/** Convert diy_fp to IEEE-754 raw value. */ |
|
3772
|
|
|
|
|
|
|
static_inline u64 diy_fp_to_ieee_raw(diy_fp fp) { |
|
3773
|
0
|
|
|
|
|
|
u64 sig = fp.sig; |
|
3774
|
0
|
|
|
|
|
|
i32 exp = fp.exp; |
|
3775
|
|
|
|
|
|
|
u32 lz_bits; |
|
3776
|
0
|
|
|
|
|
|
if (unlikely(fp.sig == 0)) return 0; |
|
3777
|
|
|
|
|
|
|
|
|
3778
|
0
|
|
|
|
|
|
lz_bits = u64_lz_bits(sig); |
|
3779
|
0
|
|
|
|
|
|
sig <<= lz_bits; |
|
3780
|
0
|
|
|
|
|
|
sig >>= F64_BITS - F64_SIG_FULL_BITS; |
|
3781
|
0
|
|
|
|
|
|
exp -= (i32)lz_bits; |
|
3782
|
0
|
|
|
|
|
|
exp += F64_BITS - F64_SIG_FULL_BITS; |
|
3783
|
0
|
|
|
|
|
|
exp += F64_SIG_BITS; |
|
3784
|
|
|
|
|
|
|
|
|
3785
|
0
|
0
|
|
|
|
|
if (unlikely(exp >= F64_MAX_BIN_EXP)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3786
|
|
|
|
|
|
|
/* overflow */ |
|
3787
|
0
|
|
|
|
|
|
return F64_BITS_INF; |
|
3788
|
0
|
0
|
|
|
|
|
} else if (likely(exp >= F64_MIN_BIN_EXP - 1)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3789
|
|
|
|
|
|
|
/* normal */ |
|
3790
|
0
|
|
|
|
|
|
exp += F64_EXP_BIAS; |
|
3791
|
0
|
|
|
|
|
|
return ((u64)exp << F64_SIG_BITS) | (sig & F64_SIG_MASK); |
|
3792
|
0
|
0
|
|
|
|
|
} else if (likely(exp >= F64_MIN_BIN_EXP - F64_SIG_FULL_BITS)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3793
|
|
|
|
|
|
|
/* subnormal */ |
|
3794
|
0
|
|
|
|
|
|
return sig >> (F64_MIN_BIN_EXP - exp - 1); |
|
3795
|
|
|
|
|
|
|
} else { |
|
3796
|
|
|
|
|
|
|
/* underflow */ |
|
3797
|
0
|
|
|
|
|
|
return 0; |
|
3798
|
|
|
|
|
|
|
} |
|
3799
|
|
|
|
|
|
|
} |
|
3800
|
|
|
|
|
|
|
|
|
3801
|
|
|
|
|
|
|
|
|
3802
|
|
|
|
|
|
|
|
|
3803
|
|
|
|
|
|
|
/*============================================================================== |
|
3804
|
|
|
|
|
|
|
* MARK: - Number Reader (Private) |
|
3805
|
|
|
|
|
|
|
*============================================================================*/ |
|
3806
|
|
|
|
|
|
|
|
|
3807
|
|
|
|
|
|
|
/** |
|
3808
|
|
|
|
|
|
|
Read a JSON number. |
|
3809
|
|
|
|
|
|
|
|
|
3810
|
|
|
|
|
|
|
1. This function assume that the floating-point number is in IEEE-754 format. |
|
3811
|
|
|
|
|
|
|
2. This function support uint64/int64/double number. If an integer number |
|
3812
|
|
|
|
|
|
|
cannot fit in uint64/int64, it will returns as a double number. If a double |
|
3813
|
|
|
|
|
|
|
number is infinite, the return value is based on flag. |
|
3814
|
|
|
|
|
|
|
3. This function (with inline attribute) may generate a lot of instructions. |
|
3815
|
|
|
|
|
|
|
*/ |
|
3816
|
|
|
|
|
|
|
static_inline bool read_num(u8 **ptr, u8 **pre, yyjson_read_flag flg, |
|
3817
|
|
|
|
|
|
|
yyjson_val *val, const char **msg) { |
|
3818
|
|
|
|
|
|
|
#define return_err(_pos, _msg) do { \ |
|
3819
|
|
|
|
|
|
|
*msg = _msg; \ |
|
3820
|
|
|
|
|
|
|
*end = _pos; \ |
|
3821
|
|
|
|
|
|
|
return false; \ |
|
3822
|
|
|
|
|
|
|
} while (false) |
|
3823
|
|
|
|
|
|
|
|
|
3824
|
|
|
|
|
|
|
#define return_0() do { \ |
|
3825
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \ |
|
3826
|
|
|
|
|
|
|
val->uni.u64 = 0; \ |
|
3827
|
|
|
|
|
|
|
*end = cur; return true; \ |
|
3828
|
|
|
|
|
|
|
} while (false) |
|
3829
|
|
|
|
|
|
|
|
|
3830
|
|
|
|
|
|
|
#define return_i64(_v) do { \ |
|
3831
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \ |
|
3832
|
|
|
|
|
|
|
val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \ |
|
3833
|
|
|
|
|
|
|
*end = cur; return true; \ |
|
3834
|
|
|
|
|
|
|
} while (false) |
|
3835
|
|
|
|
|
|
|
|
|
3836
|
|
|
|
|
|
|
#define return_f64(_v) do { \ |
|
3837
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ |
|
3838
|
|
|
|
|
|
|
val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \ |
|
3839
|
|
|
|
|
|
|
*end = cur; return true; \ |
|
3840
|
|
|
|
|
|
|
} while (false) |
|
3841
|
|
|
|
|
|
|
|
|
3842
|
|
|
|
|
|
|
#define return_f64_bin(_v) do { \ |
|
3843
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ |
|
3844
|
|
|
|
|
|
|
val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \ |
|
3845
|
|
|
|
|
|
|
*end = cur; return true; \ |
|
3846
|
|
|
|
|
|
|
} while (false) |
|
3847
|
|
|
|
|
|
|
|
|
3848
|
|
|
|
|
|
|
#define return_inf() do { \ |
|
3849
|
|
|
|
|
|
|
if (has_flg(BIGNUM_AS_RAW)) return_raw(); \ |
|
3850
|
|
|
|
|
|
|
if (has_allow(INF_AND_NAN)) return_f64_bin(F64_BITS_INF); \ |
|
3851
|
|
|
|
|
|
|
else return_err(hdr, "number is infinity when parsed as double"); \ |
|
3852
|
|
|
|
|
|
|
} while (false) |
|
3853
|
|
|
|
|
|
|
|
|
3854
|
|
|
|
|
|
|
#define return_raw() do { \ |
|
3855
|
|
|
|
|
|
|
**pre = '\0'; /* add null-terminator for previous raw string */ \ |
|
3856
|
|
|
|
|
|
|
val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ |
|
3857
|
|
|
|
|
|
|
val->uni.str = (const char *)hdr; \ |
|
3858
|
|
|
|
|
|
|
*pre = cur; *end = cur; return true; \ |
|
3859
|
|
|
|
|
|
|
} while (false) |
|
3860
|
|
|
|
|
|
|
|
|
3861
|
34148
|
|
|
|
|
|
u8 *sig_cut = NULL; /* significant part cutting position for long number */ |
|
3862
|
34148
|
|
|
|
|
|
u8 *sig_end = NULL; /* significant part ending position */ |
|
3863
|
34148
|
|
|
|
|
|
u8 *dot_pos = NULL; /* decimal point position */ |
|
3864
|
|
|
|
|
|
|
|
|
3865
|
34148
|
|
|
|
|
|
u64 sig = 0; /* significant part of the number */ |
|
3866
|
34148
|
|
|
|
|
|
i32 exp = 0; /* exponent part of the number */ |
|
3867
|
|
|
|
|
|
|
|
|
3868
|
|
|
|
|
|
|
bool exp_sign; /* temporary exponent sign from literal part */ |
|
3869
|
34148
|
|
|
|
|
|
i64 exp_sig = 0; /* temporary exponent number from significant part */ |
|
3870
|
34148
|
|
|
|
|
|
i64 exp_lit = 0; /* temporary exponent number from exponent literal part */ |
|
3871
|
|
|
|
|
|
|
u64 num; /* temporary number for reading */ |
|
3872
|
|
|
|
|
|
|
u8 *tmp; /* temporary cursor for reading */ |
|
3873
|
|
|
|
|
|
|
|
|
3874
|
34148
|
|
|
|
|
|
u8 *hdr = *ptr; |
|
3875
|
34148
|
|
|
|
|
|
u8 *cur = *ptr; |
|
3876
|
34148
|
|
|
|
|
|
u8 **end = ptr; |
|
3877
|
|
|
|
|
|
|
bool sign; |
|
3878
|
|
|
|
|
|
|
|
|
3879
|
|
|
|
|
|
|
/* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */ |
|
3880
|
34152
|
0
|
|
|
|
|
if (has_flg(NUMBER_AS_RAW)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
3881
|
0
|
|
|
|
|
|
return read_num_raw(ptr, pre, flg, val, msg); |
|
3882
|
|
|
|
|
|
|
} |
|
3883
|
|
|
|
|
|
|
|
|
3884
|
34148
|
|
|
|
|
|
sign = (*hdr == '-'); |
|
3885
|
34148
|
|
|
|
|
|
cur += sign; |
|
3886
|
|
|
|
|
|
|
|
|
3887
|
|
|
|
|
|
|
/* begin with a leading zero or non-digit */ |
|
3888
|
68296
|
0
|
|
|
|
|
while (unlikely(!char_is_nonzero(*cur))) { /* 0 or non-digit char */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
3889
|
0
|
0
|
|
|
|
|
if (unlikely(*cur != '0')) { /* non-digit char */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3890
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_NUMBER)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3891
|
0
|
0
|
|
|
|
|
if (*cur == '+' && cur == hdr) { /* leading `+` sign */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3892
|
0
|
|
|
|
|
|
cur++; |
|
3893
|
0
|
|
|
|
|
|
continue; |
|
3894
|
|
|
|
|
|
|
} |
|
3895
|
0
|
0
|
|
|
|
|
if (*cur == '.' && char_is_digit(cur[1])) { /* e.g. '.123' */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3896
|
0
|
|
|
|
|
|
goto leading_dot; |
|
3897
|
|
|
|
|
|
|
} |
|
3898
|
|
|
|
|
|
|
} |
|
3899
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3900
|
0
|
0
|
|
|
|
|
if (read_inf_or_nan(ptr, pre, flg, val)) return true; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3901
|
|
|
|
|
|
|
} |
|
3902
|
0
|
|
|
|
|
|
return_err(cur, "no digit after sign"); |
|
3903
|
|
|
|
|
|
|
} |
|
3904
|
|
|
|
|
|
|
/* begin with 0 */ |
|
3905
|
0
|
0
|
|
|
|
|
if (likely(!char_is_digit_or_fp(*++cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3906
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_NUMBER) && char_to_lower(*cur) == 'x') { /* hex */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3907
|
0
|
|
|
|
|
|
return read_num_hex(ptr, pre, flg, val, msg); |
|
3908
|
|
|
|
|
|
|
} |
|
3909
|
0
|
|
|
|
|
|
return_0(); |
|
3910
|
|
|
|
|
|
|
} |
|
3911
|
0
|
0
|
|
|
|
|
if (likely(*cur == '.')) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3912
|
0
|
|
|
|
|
|
leading_dot: |
|
3913
|
0
|
|
|
|
|
|
dot_pos = cur++; |
|
3914
|
0
|
0
|
|
|
|
|
if (unlikely(!char_is_digit(*cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3915
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_NUMBER)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3916
|
0
|
0
|
|
|
|
|
if (char_is_exp(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3917
|
0
|
|
|
|
|
|
goto digi_exp_more; |
|
3918
|
|
|
|
|
|
|
} else { |
|
3919
|
0
|
|
|
|
|
|
return_f64_bin(0); |
|
3920
|
|
|
|
|
|
|
} |
|
3921
|
|
|
|
|
|
|
} |
|
3922
|
0
|
|
|
|
|
|
return_err(cur, "no digit after decimal point"); |
|
3923
|
|
|
|
|
|
|
} |
|
3924
|
0
|
0
|
|
|
|
|
while (unlikely(*cur == '0')) cur++; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3925
|
0
|
0
|
|
|
|
|
if (likely(char_is_digit(*cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3926
|
|
|
|
|
|
|
/* first non-zero digit after decimal point */ |
|
3927
|
0
|
|
|
|
|
|
sig = (u64)(*cur - '0'); /* read first digit */ |
|
3928
|
0
|
|
|
|
|
|
cur--; |
|
3929
|
0
|
|
|
|
|
|
goto digi_frac_1; /* continue read fraction part */ |
|
3930
|
|
|
|
|
|
|
} |
|
3931
|
|
|
|
|
|
|
} |
|
3932
|
0
|
0
|
|
|
|
|
if (unlikely(char_is_digit(*cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3933
|
0
|
|
|
|
|
|
return_err(cur - 1, "number with leading zero is not allowed"); |
|
3934
|
|
|
|
|
|
|
} |
|
3935
|
0
|
0
|
|
|
|
|
if (unlikely(char_is_exp(*cur))) { /* 0 with any exponent is still 0 */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3936
|
0
|
|
|
|
|
|
cur += (usize)1 + char_is_sign(cur[1]); |
|
3937
|
0
|
0
|
|
|
|
|
if (unlikely(!char_is_digit(*cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3938
|
0
|
|
|
|
|
|
return_err(cur, "no digit after exponent sign"); |
|
3939
|
|
|
|
|
|
|
} |
|
3940
|
0
|
0
|
|
|
|
|
while (char_is_digit(*++cur)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3941
|
|
|
|
|
|
|
} |
|
3942
|
0
|
|
|
|
|
|
return_f64_bin(0); |
|
3943
|
|
|
|
|
|
|
} |
|
3944
|
|
|
|
|
|
|
|
|
3945
|
|
|
|
|
|
|
/* begin with non-zero digit */ |
|
3946
|
34148
|
|
|
|
|
|
sig = (u64)(*cur - '0'); |
|
3947
|
|
|
|
|
|
|
|
|
3948
|
|
|
|
|
|
|
/* |
|
3949
|
|
|
|
|
|
|
Read integral part, same as the following code. |
|
3950
|
|
|
|
|
|
|
|
|
3951
|
|
|
|
|
|
|
for (int i = 1; i <= 18; i++) { |
|
3952
|
|
|
|
|
|
|
num = cur[i] - '0'; |
|
3953
|
|
|
|
|
|
|
if (num <= 9) sig = num + sig * 10; |
|
3954
|
|
|
|
|
|
|
else goto digi_sepr_i; |
|
3955
|
|
|
|
|
|
|
} |
|
3956
|
|
|
|
|
|
|
*/ |
|
3957
|
|
|
|
|
|
|
#define expr_intg(i) \ |
|
3958
|
|
|
|
|
|
|
if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \ |
|
3959
|
|
|
|
|
|
|
else { goto digi_sepr_##i; } |
|
3960
|
34148
|
0
|
|
|
|
|
repeat_in_1_18(expr_intg) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3961
|
|
|
|
|
|
|
#undef expr_intg |
|
3962
|
|
|
|
|
|
|
|
|
3963
|
|
|
|
|
|
|
|
|
3964
|
0
|
|
|
|
|
|
cur += 19; /* skip continuous 19 digits */ |
|
3965
|
0
|
0
|
|
|
|
|
if (!char_is_digit_or_fp(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3966
|
|
|
|
|
|
|
/* this number is an integer consisting of 19 digits */ |
|
3967
|
0
|
0
|
|
|
|
|
if (sign && (sig > ((u64)1 << 63))) { /* overflow */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3968
|
0
|
0
|
|
|
|
|
if (has_flg(BIGNUM_AS_RAW)) return_raw(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3969
|
0
|
0
|
|
|
|
|
return_f64(unsafe_yyjson_u64_to_f64(sig)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3970
|
|
|
|
|
|
|
} |
|
3971
|
0
|
0
|
|
|
|
|
return_i64(sig); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3972
|
|
|
|
|
|
|
} |
|
3973
|
0
|
|
|
|
|
|
goto digi_intg_more; /* read more digits in integral part */ |
|
3974
|
|
|
|
|
|
|
|
|
3975
|
|
|
|
|
|
|
|
|
3976
|
|
|
|
|
|
|
/* process first non-digit character */ |
|
3977
|
|
|
|
|
|
|
#define expr_sepr(i) \ |
|
3978
|
|
|
|
|
|
|
digi_sepr_##i: \ |
|
3979
|
|
|
|
|
|
|
if (likely(!char_is_fp(cur[i]))) { cur += i; return_i64(sig); } \ |
|
3980
|
|
|
|
|
|
|
dot_pos = cur + i; \ |
|
3981
|
|
|
|
|
|
|
if (likely(cur[i] == '.')) goto digi_frac_##i; \ |
|
3982
|
|
|
|
|
|
|
cur += i; sig_end = cur; goto digi_exp_more; |
|
3983
|
68296
|
0
|
|
|
|
|
repeat_in_1_18(expr_sepr) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3984
|
|
|
|
|
|
|
#undef expr_sepr |
|
3985
|
|
|
|
|
|
|
|
|
3986
|
|
|
|
|
|
|
|
|
3987
|
|
|
|
|
|
|
/* read fraction part */ |
|
3988
|
|
|
|
|
|
|
#define expr_frac(i) \ |
|
3989
|
|
|
|
|
|
|
digi_frac_##i: \ |
|
3990
|
|
|
|
|
|
|
if (likely((num = (u64)(cur[i + 1] - (u8)'0')) <= 9)) \ |
|
3991
|
|
|
|
|
|
|
sig = num + sig * 10; \ |
|
3992
|
|
|
|
|
|
|
else { goto digi_stop_##i; } |
|
3993
|
2
|
0
|
|
|
|
|
repeat_in_1_18(expr_frac) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3994
|
|
|
|
|
|
|
#undef expr_frac |
|
3995
|
|
|
|
|
|
|
|
|
3996
|
0
|
|
|
|
|
|
cur += 20; /* skip 19 digits and 1 decimal point */ |
|
3997
|
0
|
0
|
|
|
|
|
if (!char_is_digit(*cur)) goto digi_frac_end; /* fraction part end */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3998
|
0
|
|
|
|
|
|
goto digi_frac_more; /* read more digits in fraction part */ |
|
3999
|
|
|
|
|
|
|
|
|
4000
|
|
|
|
|
|
|
|
|
4001
|
|
|
|
|
|
|
/* significant part end */ |
|
4002
|
|
|
|
|
|
|
#define expr_stop(i) \ |
|
4003
|
|
|
|
|
|
|
digi_stop_##i: \ |
|
4004
|
|
|
|
|
|
|
cur += i + 1; \ |
|
4005
|
|
|
|
|
|
|
goto digi_frac_end; |
|
4006
|
2
|
|
|
|
|
|
repeat_in_1_18(expr_stop) |
|
4007
|
|
|
|
|
|
|
#undef expr_stop |
|
4008
|
|
|
|
|
|
|
|
|
4009
|
|
|
|
|
|
|
|
|
4010
|
|
|
|
|
|
|
/* read more digits in integral part */ |
|
4011
|
0
|
|
|
|
|
|
digi_intg_more: |
|
4012
|
0
|
0
|
|
|
|
|
if (char_is_digit(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4013
|
0
|
0
|
|
|
|
|
if (!char_is_digit_or_fp(cur[1])) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4014
|
|
|
|
|
|
|
/* this number is an integer consisting of 20 digits */ |
|
4015
|
0
|
|
|
|
|
|
num = (u64)(*cur - '0'); |
|
4016
|
0
|
0
|
|
|
|
|
if ((sig < (U64_MAX / 10)) || |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4017
|
0
|
0
|
|
|
|
|
(sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4018
|
0
|
|
|
|
|
|
sig = num + sig * 10; |
|
4019
|
0
|
|
|
|
|
|
cur++; |
|
4020
|
|
|
|
|
|
|
/* convert to double if overflow */ |
|
4021
|
0
|
0
|
|
|
|
|
if (sign) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4022
|
0
|
0
|
|
|
|
|
if (has_flg(BIGNUM_AS_RAW)) return_raw(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4023
|
0
|
0
|
|
|
|
|
return_f64(unsafe_yyjson_u64_to_f64(sig)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4024
|
|
|
|
|
|
|
} |
|
4025
|
0
|
0
|
|
|
|
|
return_i64(sig); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4026
|
|
|
|
|
|
|
} |
|
4027
|
|
|
|
|
|
|
} |
|
4028
|
|
|
|
|
|
|
} |
|
4029
|
|
|
|
|
|
|
|
|
4030
|
0
|
0
|
|
|
|
|
if (char_is_exp(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4031
|
0
|
|
|
|
|
|
dot_pos = cur; |
|
4032
|
0
|
|
|
|
|
|
goto digi_exp_more; |
|
4033
|
|
|
|
|
|
|
} |
|
4034
|
|
|
|
|
|
|
|
|
4035
|
0
|
0
|
|
|
|
|
if (*cur == '.') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4036
|
0
|
|
|
|
|
|
dot_pos = cur++; |
|
4037
|
0
|
0
|
|
|
|
|
if (unlikely(!char_is_digit(*cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4038
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_NUMBER)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4039
|
0
|
|
|
|
|
|
goto digi_frac_end; |
|
4040
|
|
|
|
|
|
|
} |
|
4041
|
0
|
|
|
|
|
|
return_err(cur, "no digit after decimal point"); |
|
4042
|
|
|
|
|
|
|
} |
|
4043
|
|
|
|
|
|
|
} |
|
4044
|
|
|
|
|
|
|
|
|
4045
|
|
|
|
|
|
|
|
|
4046
|
|
|
|
|
|
|
/* read more digits in fraction part */ |
|
4047
|
0
|
|
|
|
|
|
digi_frac_more: |
|
4048
|
0
|
|
|
|
|
|
sig_cut = cur; /* too large to fit in u64, excess digits need to be cut */ |
|
4049
|
0
|
|
|
|
|
|
sig += (*cur >= '5'); /* round */ |
|
4050
|
0
|
0
|
|
|
|
|
while (char_is_digit(*++cur)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4051
|
0
|
0
|
|
|
|
|
if (!dot_pos) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4052
|
0
|
0
|
|
|
|
|
if (!char_is_fp(*cur) && has_flg(BIGNUM_AS_RAW)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4053
|
0
|
|
|
|
|
|
return_raw(); /* it's a large integer */ |
|
4054
|
|
|
|
|
|
|
} |
|
4055
|
0
|
|
|
|
|
|
dot_pos = cur; |
|
4056
|
0
|
0
|
|
|
|
|
if (*cur == '.') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4057
|
0
|
0
|
|
|
|
|
if (unlikely(!char_is_digit(*++cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4058
|
0
|
0
|
|
|
|
|
if (!has_allow(EXT_NUMBER)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4059
|
0
|
|
|
|
|
|
return_err(cur, "no digit after decimal point"); |
|
4060
|
|
|
|
|
|
|
} |
|
4061
|
|
|
|
|
|
|
} |
|
4062
|
0
|
0
|
|
|
|
|
while (char_is_digit(*cur)) cur++; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4063
|
|
|
|
|
|
|
} |
|
4064
|
|
|
|
|
|
|
} |
|
4065
|
0
|
|
|
|
|
|
exp_sig = (i64)(dot_pos - sig_cut); |
|
4066
|
0
|
|
|
|
|
|
exp_sig += (dot_pos < sig_cut); |
|
4067
|
|
|
|
|
|
|
|
|
4068
|
|
|
|
|
|
|
/* ignore trailing zeros */ |
|
4069
|
0
|
|
|
|
|
|
tmp = cur - 1; |
|
4070
|
0
|
0
|
|
|
|
|
while ((*tmp == '0' || *tmp == '.') && tmp > hdr) tmp--; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4071
|
0
|
0
|
|
|
|
|
if (tmp < sig_cut) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4072
|
0
|
|
|
|
|
|
sig_cut = NULL; |
|
4073
|
|
|
|
|
|
|
} else { |
|
4074
|
0
|
|
|
|
|
|
sig_end = cur; |
|
4075
|
|
|
|
|
|
|
} |
|
4076
|
|
|
|
|
|
|
|
|
4077
|
0
|
0
|
|
|
|
|
if (char_is_exp(*cur)) goto digi_exp_more; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4078
|
0
|
|
|
|
|
|
goto digi_exp_finish; |
|
4079
|
|
|
|
|
|
|
|
|
4080
|
|
|
|
|
|
|
|
|
4081
|
|
|
|
|
|
|
/* fraction part end */ |
|
4082
|
2
|
|
|
|
|
|
digi_frac_end: |
|
4083
|
2
|
0
|
|
|
|
|
if (unlikely(dot_pos + 1 == cur)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4084
|
0
|
0
|
|
|
|
|
if (!has_allow(EXT_NUMBER)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4085
|
0
|
|
|
|
|
|
return_err(cur, "no digit after decimal point"); |
|
4086
|
|
|
|
|
|
|
} |
|
4087
|
|
|
|
|
|
|
} |
|
4088
|
2
|
|
|
|
|
|
sig_end = cur; |
|
4089
|
2
|
|
|
|
|
|
exp_sig = -(i64)((u64)(cur - dot_pos) - 1); |
|
4090
|
4
|
0
|
|
|
|
|
if (likely(!char_is_exp(*cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4091
|
2
|
0
|
|
|
|
|
if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4092
|
0
|
|
|
|
|
|
return_f64_bin(0); /* underflow */ |
|
4093
|
|
|
|
|
|
|
} |
|
4094
|
2
|
|
|
|
|
|
exp = (i32)exp_sig; |
|
4095
|
2
|
|
|
|
|
|
goto digi_finish; |
|
4096
|
|
|
|
|
|
|
} else { |
|
4097
|
0
|
|
|
|
|
|
goto digi_exp_more; |
|
4098
|
|
|
|
|
|
|
} |
|
4099
|
|
|
|
|
|
|
|
|
4100
|
|
|
|
|
|
|
|
|
4101
|
|
|
|
|
|
|
/* read exponent part */ |
|
4102
|
0
|
|
|
|
|
|
digi_exp_more: |
|
4103
|
0
|
|
|
|
|
|
exp_sign = (*++cur == '-'); |
|
4104
|
0
|
|
|
|
|
|
cur += char_is_sign(*cur); |
|
4105
|
0
|
0
|
|
|
|
|
if (unlikely(!char_is_digit(*cur))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4106
|
0
|
|
|
|
|
|
return_err(cur, "no digit after exponent sign"); |
|
4107
|
|
|
|
|
|
|
} |
|
4108
|
0
|
0
|
|
|
|
|
while (*cur == '0') cur++; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4109
|
|
|
|
|
|
|
|
|
4110
|
|
|
|
|
|
|
/* read exponent literal */ |
|
4111
|
0
|
|
|
|
|
|
tmp = cur; |
|
4112
|
0
|
0
|
|
|
|
|
while (char_is_digit(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4113
|
0
|
|
|
|
|
|
exp_lit = (i64)((u8)(*cur++ - '0') + (u64)exp_lit * 10); |
|
4114
|
|
|
|
|
|
|
} |
|
4115
|
0
|
0
|
|
|
|
|
if (unlikely(cur - tmp >= U64_SAFE_DIG)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4116
|
0
|
0
|
|
|
|
|
if (exp_sign) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4117
|
0
|
|
|
|
|
|
return_f64_bin(0); /* underflow */ |
|
4118
|
|
|
|
|
|
|
} else { |
|
4119
|
0
|
0
|
|
|
|
|
return_inf(); /* overflow */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4120
|
|
|
|
|
|
|
} |
|
4121
|
|
|
|
|
|
|
} |
|
4122
|
0
|
0
|
|
|
|
|
exp_sig += exp_sign ? -exp_lit : exp_lit; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4123
|
|
|
|
|
|
|
|
|
4124
|
|
|
|
|
|
|
|
|
4125
|
|
|
|
|
|
|
/* validate exponent value */ |
|
4126
|
0
|
|
|
|
|
|
digi_exp_finish: |
|
4127
|
0
|
0
|
|
|
|
|
if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4128
|
0
|
|
|
|
|
|
return_f64_bin(0); /* underflow */ |
|
4129
|
|
|
|
|
|
|
} |
|
4130
|
0
|
0
|
|
|
|
|
if (unlikely(exp_sig > F64_MAX_DEC_EXP)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4131
|
0
|
0
|
|
|
|
|
return_inf(); /* overflow */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4132
|
|
|
|
|
|
|
} |
|
4133
|
0
|
|
|
|
|
|
exp = (i32)exp_sig; |
|
4134
|
|
|
|
|
|
|
|
|
4135
|
|
|
|
|
|
|
|
|
4136
|
|
|
|
|
|
|
/* all digit read finished */ |
|
4137
|
2
|
|
|
|
|
|
digi_finish: |
|
4138
|
|
|
|
|
|
|
|
|
4139
|
|
|
|
|
|
|
/* |
|
4140
|
|
|
|
|
|
|
Fast path 1: |
|
4141
|
|
|
|
|
|
|
|
|
4142
|
|
|
|
|
|
|
1. The floating-point number calculation should be accurate, see the |
|
4143
|
|
|
|
|
|
|
comments of macro `YYJSON_DOUBLE_MATH_CORRECT`. |
|
4144
|
|
|
|
|
|
|
2. Correct rounding should be performed (fegetround() == FE_TONEAREST). |
|
4145
|
|
|
|
|
|
|
3. The input of floating point number calculation does not lose precision, |
|
4146
|
|
|
|
|
|
|
which means: 64 - leading_zero(input) - trailing_zero(input) < 53. |
|
4147
|
|
|
|
|
|
|
|
|
4148
|
|
|
|
|
|
|
We don't check all available inputs here, because that would make the code |
|
4149
|
|
|
|
|
|
|
more complicated, and not friendly to branch predictor. |
|
4150
|
|
|
|
|
|
|
*/ |
|
4151
|
|
|
|
|
|
|
#if YYJSON_DOUBLE_MATH_CORRECT |
|
4152
|
2
|
0
|
|
|
|
|
if (sig < ((u64)1 << 53) && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4153
|
2
|
0
|
|
|
|
|
exp >= -F64_POW10_MAX_EXACT_EXP && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4154
|
2
|
0
|
|
|
|
|
exp <= +F64_POW10_MAX_EXACT_EXP) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4155
|
2
|
|
|
|
|
|
f64 dbl = (f64)sig; |
|
4156
|
2
|
0
|
|
|
|
|
if (exp < 0) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4157
|
2
|
|
|
|
|
|
dbl /= f64_pow10_table[-exp]; |
|
4158
|
|
|
|
|
|
|
} else { |
|
4159
|
0
|
|
|
|
|
|
dbl *= f64_pow10_table[+exp]; |
|
4160
|
|
|
|
|
|
|
} |
|
4161
|
2
|
0
|
|
|
|
|
return_f64(dbl); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4162
|
|
|
|
|
|
|
} |
|
4163
|
|
|
|
|
|
|
#endif |
|
4164
|
|
|
|
|
|
|
|
|
4165
|
|
|
|
|
|
|
/* |
|
4166
|
|
|
|
|
|
|
Fast path 2: |
|
4167
|
|
|
|
|
|
|
|
|
4168
|
|
|
|
|
|
|
To keep it simple, we only accept normal number here, |
|
4169
|
|
|
|
|
|
|
let the slow path to handle subnormal and infinity number. |
|
4170
|
|
|
|
|
|
|
*/ |
|
4171
|
0
|
0
|
|
|
|
|
if (likely(!sig_cut && |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4172
|
|
|
|
|
|
|
exp > -F64_MAX_DEC_EXP + 1 && |
|
4173
|
|
|
|
|
|
|
exp < +F64_MAX_DEC_EXP - 20)) { |
|
4174
|
|
|
|
|
|
|
/* |
|
4175
|
|
|
|
|
|
|
The result value is exactly equal to (sig * 10^exp), |
|
4176
|
|
|
|
|
|
|
the exponent part (10^exp) can be converted to (sig2 * 2^exp2). |
|
4177
|
|
|
|
|
|
|
|
|
4178
|
|
|
|
|
|
|
The sig2 can be an infinite length number, only the highest 128 bits |
|
4179
|
|
|
|
|
|
|
is cached in the pow10_sig_table. |
|
4180
|
|
|
|
|
|
|
|
|
4181
|
|
|
|
|
|
|
Now we have these bits: |
|
4182
|
|
|
|
|
|
|
sig1 (normalized 64bit) : aaaaaaaa |
|
4183
|
|
|
|
|
|
|
sig2 (higher 64bit) : bbbbbbbb |
|
4184
|
|
|
|
|
|
|
sig2_ext (lower 64bit) : cccccccc |
|
4185
|
|
|
|
|
|
|
sig2_cut (extra unknown bits) : dddddddddddd.... |
|
4186
|
|
|
|
|
|
|
|
|
4187
|
|
|
|
|
|
|
And the calculation process is: |
|
4188
|
|
|
|
|
|
|
---------------------------------------- |
|
4189
|
|
|
|
|
|
|
aaaaaaaa * |
|
4190
|
|
|
|
|
|
|
bbbbbbbbccccccccdddddddddddd.... |
|
4191
|
|
|
|
|
|
|
---------------------------------------- |
|
4192
|
|
|
|
|
|
|
abababababababab + |
|
4193
|
|
|
|
|
|
|
acacacacacacacac + |
|
4194
|
|
|
|
|
|
|
adadadadadadadadadad.... |
|
4195
|
|
|
|
|
|
|
---------------------------------------- |
|
4196
|
|
|
|
|
|
|
[hi____][lo____] + |
|
4197
|
|
|
|
|
|
|
[hi2___][lo2___] + |
|
4198
|
|
|
|
|
|
|
[unknown___________....] |
|
4199
|
|
|
|
|
|
|
---------------------------------------- |
|
4200
|
|
|
|
|
|
|
|
|
4201
|
|
|
|
|
|
|
The addition with carry may affect higher bits, but if there is a 0 |
|
4202
|
|
|
|
|
|
|
in higher bits, the bits higher than 0 will not be affected. |
|
4203
|
|
|
|
|
|
|
|
|
4204
|
|
|
|
|
|
|
`lo2` + `unknown` may get a carry bit and may affect `hi2`, the max |
|
4205
|
|
|
|
|
|
|
value of `hi2` is 0xFFFFFFFFFFFFFFFE, so `hi2` will not overflow. |
|
4206
|
|
|
|
|
|
|
|
|
4207
|
|
|
|
|
|
|
`lo` + `hi2` may also get a carry bit and may affect `hi`, but only |
|
4208
|
|
|
|
|
|
|
the highest significant 53 bits of `hi` is needed. If there is a 0 |
|
4209
|
|
|
|
|
|
|
in the lower bits of `hi`, then all the following bits can be dropped. |
|
4210
|
|
|
|
|
|
|
|
|
4211
|
|
|
|
|
|
|
To convert the result to IEEE-754 double number, we need to perform |
|
4212
|
|
|
|
|
|
|
correct rounding: |
|
4213
|
|
|
|
|
|
|
1. if bit 54 is 0, round down, |
|
4214
|
|
|
|
|
|
|
2. if bit 54 is 1 and any bit beyond bit 54 is 1, round up, |
|
4215
|
|
|
|
|
|
|
3. if bit 54 is 1 and all bits beyond bit 54 are 0, round to even, |
|
4216
|
|
|
|
|
|
|
as the extra bits is unknown, this case will not be handled here. |
|
4217
|
|
|
|
|
|
|
*/ |
|
4218
|
|
|
|
|
|
|
|
|
4219
|
|
|
|
|
|
|
u64 raw; |
|
4220
|
|
|
|
|
|
|
u64 sig1, sig2, sig2_ext, hi, lo, hi2, lo2, add, bits; |
|
4221
|
|
|
|
|
|
|
i32 exp2; |
|
4222
|
|
|
|
|
|
|
u32 lz; |
|
4223
|
0
|
|
|
|
|
|
bool exact = false, carry, round_up; |
|
4224
|
|
|
|
|
|
|
|
|
4225
|
|
|
|
|
|
|
/* convert (10^exp) to (sig2 * 2^exp2) */ |
|
4226
|
0
|
|
|
|
|
|
pow10_table_get_sig(exp, &sig2, &sig2_ext); |
|
4227
|
0
|
|
|
|
|
|
pow10_table_get_exp(exp, &exp2); |
|
4228
|
|
|
|
|
|
|
|
|
4229
|
|
|
|
|
|
|
/* normalize and multiply */ |
|
4230
|
0
|
|
|
|
|
|
lz = u64_lz_bits(sig); |
|
4231
|
0
|
|
|
|
|
|
sig1 = sig << lz; |
|
4232
|
0
|
|
|
|
|
|
exp2 -= (i32)lz; |
|
4233
|
0
|
|
|
|
|
|
u128_mul(sig1, sig2, &hi, &lo); |
|
4234
|
|
|
|
|
|
|
|
|
4235
|
|
|
|
|
|
|
/* |
|
4236
|
|
|
|
|
|
|
The `hi` is in range [0x4000000000000000, 0xFFFFFFFFFFFFFFFE], |
|
4237
|
|
|
|
|
|
|
To get normalized value, `hi` should be shifted to the left by 0 or 1. |
|
4238
|
|
|
|
|
|
|
|
|
4239
|
|
|
|
|
|
|
The highest significant 53 bits is used by IEEE-754 double number, |
|
4240
|
|
|
|
|
|
|
and the bit 54 is used to detect rounding direction. |
|
4241
|
|
|
|
|
|
|
|
|
4242
|
|
|
|
|
|
|
The lowest (64 - 54 - 1) bits is used to check whether it contains 0. |
|
4243
|
|
|
|
|
|
|
*/ |
|
4244
|
0
|
|
|
|
|
|
bits = hi & (((u64)1 << (64 - 54 - 1)) - 1); |
|
4245
|
0
|
0
|
|
|
|
|
if (bits - 1 < (((u64)1 << (64 - 54 - 1)) - 2)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4246
|
|
|
|
|
|
|
/* |
|
4247
|
|
|
|
|
|
|
(bits != 0 && bits != 0x1FF) => (bits - 1 < 0x1FF - 1) |
|
4248
|
|
|
|
|
|
|
The `bits` is not zero, so we don't need to check `round to even` |
|
4249
|
|
|
|
|
|
|
case. The `bits` contains bit `0`, so we can drop the extra bits |
|
4250
|
|
|
|
|
|
|
after `0`. |
|
4251
|
|
|
|
|
|
|
*/ |
|
4252
|
0
|
|
|
|
|
|
exact = true; |
|
4253
|
|
|
|
|
|
|
|
|
4254
|
|
|
|
|
|
|
} else { |
|
4255
|
|
|
|
|
|
|
/* |
|
4256
|
|
|
|
|
|
|
(bits == 0 || bits == 0x1FF) |
|
4257
|
|
|
|
|
|
|
The `bits` is filled with all `0` or all `1`, so we need to check |
|
4258
|
|
|
|
|
|
|
lower bits with another 64-bit multiplication. |
|
4259
|
|
|
|
|
|
|
*/ |
|
4260
|
0
|
|
|
|
|
|
u128_mul(sig1, sig2_ext, &hi2, &lo2); |
|
4261
|
|
|
|
|
|
|
|
|
4262
|
0
|
|
|
|
|
|
add = lo + hi2; |
|
4263
|
0
|
0
|
|
|
|
|
if (add + 1 > (u64)1) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4264
|
|
|
|
|
|
|
/* |
|
4265
|
|
|
|
|
|
|
(add != 0 && add != U64_MAX) => (add + 1 > 1) |
|
4266
|
|
|
|
|
|
|
The `add` is not zero, so we don't need to check `round to |
|
4267
|
|
|
|
|
|
|
even` case. The `add` contains bit `0`, so we can drop the |
|
4268
|
|
|
|
|
|
|
extra bits after `0`. The `hi` cannot be U64_MAX, so it will |
|
4269
|
|
|
|
|
|
|
not overflow. |
|
4270
|
|
|
|
|
|
|
*/ |
|
4271
|
0
|
0
|
|
|
|
|
carry = add < lo || add < hi2; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4272
|
0
|
|
|
|
|
|
hi += carry; |
|
4273
|
0
|
|
|
|
|
|
exact = true; |
|
4274
|
|
|
|
|
|
|
} |
|
4275
|
|
|
|
|
|
|
} |
|
4276
|
|
|
|
|
|
|
|
|
4277
|
0
|
0
|
|
|
|
|
if (exact) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4278
|
|
|
|
|
|
|
/* normalize */ |
|
4279
|
0
|
|
|
|
|
|
lz = hi < ((u64)1 << 63); |
|
4280
|
0
|
|
|
|
|
|
hi <<= lz; |
|
4281
|
0
|
|
|
|
|
|
exp2 -= (i32)lz; |
|
4282
|
0
|
|
|
|
|
|
exp2 += 64; |
|
4283
|
|
|
|
|
|
|
|
|
4284
|
|
|
|
|
|
|
/* test the bit 54 and get rounding direction */ |
|
4285
|
0
|
|
|
|
|
|
round_up = (hi & ((u64)1 << (64 - 54))) > (u64)0; |
|
4286
|
0
|
0
|
|
|
|
|
hi += (round_up ? ((u64)1 << (64 - 54)) : (u64)0); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4287
|
|
|
|
|
|
|
|
|
4288
|
|
|
|
|
|
|
/* test overflow */ |
|
4289
|
0
|
0
|
|
|
|
|
if (hi < ((u64)1 << (64 - 54))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4290
|
0
|
|
|
|
|
|
hi = ((u64)1 << 63); |
|
4291
|
0
|
|
|
|
|
|
exp2 += 1; |
|
4292
|
|
|
|
|
|
|
} |
|
4293
|
|
|
|
|
|
|
|
|
4294
|
|
|
|
|
|
|
/* This is a normal number, convert it to IEEE-754 format. */ |
|
4295
|
0
|
|
|
|
|
|
hi >>= F64_BITS - F64_SIG_FULL_BITS; |
|
4296
|
0
|
|
|
|
|
|
exp2 += F64_BITS - F64_SIG_FULL_BITS + F64_SIG_BITS; |
|
4297
|
0
|
|
|
|
|
|
exp2 += F64_EXP_BIAS; |
|
4298
|
0
|
|
|
|
|
|
raw = ((u64)exp2 << F64_SIG_BITS) | (hi & F64_SIG_MASK); |
|
4299
|
0
|
|
|
|
|
|
return_f64_bin(raw); |
|
4300
|
|
|
|
|
|
|
} |
|
4301
|
|
|
|
|
|
|
} |
|
4302
|
|
|
|
|
|
|
|
|
4303
|
|
|
|
|
|
|
/* |
|
4304
|
|
|
|
|
|
|
Slow path: read double number exactly with diyfp. |
|
4305
|
|
|
|
|
|
|
1. Use cached diyfp to get an approximation value. |
|
4306
|
|
|
|
|
|
|
2. Use bigcomp to check the approximation value if needed. |
|
4307
|
|
|
|
|
|
|
|
|
4308
|
|
|
|
|
|
|
This algorithm refers to google's double-conversion project: |
|
4309
|
|
|
|
|
|
|
https://github.com/google/double-conversion |
|
4310
|
|
|
|
|
|
|
*/ |
|
4311
|
|
|
|
|
|
|
{ |
|
4312
|
0
|
|
|
|
|
|
const i32 ERR_ULP_LOG = 3; |
|
4313
|
0
|
|
|
|
|
|
const i32 ERR_ULP = 1 << ERR_ULP_LOG; |
|
4314
|
0
|
|
|
|
|
|
const i32 ERR_CACHED_POW = ERR_ULP / 2; |
|
4315
|
0
|
|
|
|
|
|
const i32 ERR_MUL_FIXED = ERR_ULP / 2; |
|
4316
|
0
|
|
|
|
|
|
const i32 DIY_SIG_BITS = 64; |
|
4317
|
0
|
|
|
|
|
|
const i32 EXP_BIAS = F64_EXP_BIAS + F64_SIG_BITS; |
|
4318
|
0
|
|
|
|
|
|
const i32 EXP_SUBNORMAL = -EXP_BIAS + 1; |
|
4319
|
|
|
|
|
|
|
|
|
4320
|
|
|
|
|
|
|
u64 fp_err; |
|
4321
|
|
|
|
|
|
|
u32 bits; |
|
4322
|
|
|
|
|
|
|
i32 order_of_magnitude; |
|
4323
|
|
|
|
|
|
|
i32 effective_significand_size; |
|
4324
|
|
|
|
|
|
|
i32 precision_digits_count; |
|
4325
|
|
|
|
|
|
|
u64 precision_bits; |
|
4326
|
|
|
|
|
|
|
u64 half_way; |
|
4327
|
|
|
|
|
|
|
|
|
4328
|
|
|
|
|
|
|
u64 raw; |
|
4329
|
|
|
|
|
|
|
diy_fp fp, fp_upper; |
|
4330
|
|
|
|
|
|
|
bigint big_full, big_comp; |
|
4331
|
|
|
|
|
|
|
i32 cmp; |
|
4332
|
|
|
|
|
|
|
|
|
4333
|
0
|
|
|
|
|
|
fp.sig = sig; |
|
4334
|
0
|
|
|
|
|
|
fp.exp = 0; |
|
4335
|
0
|
0
|
|
|
|
|
fp_err = sig_cut ? (u64)(ERR_ULP / 2) : (u64)0; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4336
|
|
|
|
|
|
|
|
|
4337
|
|
|
|
|
|
|
/* normalize */ |
|
4338
|
0
|
|
|
|
|
|
bits = u64_lz_bits(fp.sig); |
|
4339
|
0
|
|
|
|
|
|
fp.sig <<= bits; |
|
4340
|
0
|
|
|
|
|
|
fp.exp -= (i32)bits; |
|
4341
|
0
|
|
|
|
|
|
fp_err <<= bits; |
|
4342
|
|
|
|
|
|
|
|
|
4343
|
|
|
|
|
|
|
/* multiply and add error */ |
|
4344
|
0
|
|
|
|
|
|
fp = diy_fp_mul(fp, diy_fp_get_cached_pow10(exp)); |
|
4345
|
0
|
|
|
|
|
|
fp_err += (u64)ERR_CACHED_POW + (fp_err != 0) + (u64)ERR_MUL_FIXED; |
|
4346
|
|
|
|
|
|
|
|
|
4347
|
|
|
|
|
|
|
/* normalize */ |
|
4348
|
0
|
|
|
|
|
|
bits = u64_lz_bits(fp.sig); |
|
4349
|
0
|
|
|
|
|
|
fp.sig <<= bits; |
|
4350
|
0
|
|
|
|
|
|
fp.exp -= (i32)bits; |
|
4351
|
0
|
|
|
|
|
|
fp_err <<= bits; |
|
4352
|
|
|
|
|
|
|
|
|
4353
|
|
|
|
|
|
|
/* effective significand */ |
|
4354
|
0
|
|
|
|
|
|
order_of_magnitude = DIY_SIG_BITS + fp.exp; |
|
4355
|
0
|
0
|
|
|
|
|
if (likely(order_of_magnitude >= EXP_SUBNORMAL + F64_SIG_FULL_BITS)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4356
|
0
|
|
|
|
|
|
effective_significand_size = F64_SIG_FULL_BITS; |
|
4357
|
0
|
0
|
|
|
|
|
} else if (order_of_magnitude <= EXP_SUBNORMAL) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4358
|
0
|
|
|
|
|
|
effective_significand_size = 0; |
|
4359
|
|
|
|
|
|
|
} else { |
|
4360
|
0
|
|
|
|
|
|
effective_significand_size = order_of_magnitude - EXP_SUBNORMAL; |
|
4361
|
|
|
|
|
|
|
} |
|
4362
|
|
|
|
|
|
|
|
|
4363
|
|
|
|
|
|
|
/* precision digits count */ |
|
4364
|
0
|
|
|
|
|
|
precision_digits_count = DIY_SIG_BITS - effective_significand_size; |
|
4365
|
0
|
0
|
|
|
|
|
if (unlikely(precision_digits_count + ERR_ULP_LOG >= DIY_SIG_BITS)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4366
|
0
|
|
|
|
|
|
i32 shr = (precision_digits_count + ERR_ULP_LOG) - DIY_SIG_BITS + 1; |
|
4367
|
0
|
|
|
|
|
|
fp.sig >>= shr; |
|
4368
|
0
|
|
|
|
|
|
fp.exp += shr; |
|
4369
|
0
|
|
|
|
|
|
fp_err = (fp_err >> shr) + 1 + (u32)ERR_ULP; |
|
4370
|
0
|
|
|
|
|
|
precision_digits_count -= shr; |
|
4371
|
|
|
|
|
|
|
} |
|
4372
|
|
|
|
|
|
|
|
|
4373
|
|
|
|
|
|
|
/* half way */ |
|
4374
|
0
|
|
|
|
|
|
precision_bits = fp.sig & (((u64)1 << precision_digits_count) - 1); |
|
4375
|
0
|
|
|
|
|
|
precision_bits *= (u32)ERR_ULP; |
|
4376
|
0
|
|
|
|
|
|
half_way = (u64)1 << (precision_digits_count - 1); |
|
4377
|
0
|
|
|
|
|
|
half_way *= (u32)ERR_ULP; |
|
4378
|
|
|
|
|
|
|
|
|
4379
|
|
|
|
|
|
|
/* rounding */ |
|
4380
|
0
|
|
|
|
|
|
fp.sig >>= precision_digits_count; |
|
4381
|
0
|
|
|
|
|
|
fp.sig += (precision_bits >= half_way + fp_err); |
|
4382
|
0
|
0
|
|
|
|
|
fp.exp += precision_digits_count; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4383
|
|
|
|
|
|
|
|
|
4384
|
|
|
|
|
|
|
/* get IEEE double raw value */ |
|
4385
|
0
|
|
|
|
|
|
raw = diy_fp_to_ieee_raw(fp); |
|
4386
|
0
|
0
|
|
|
|
|
if (unlikely(raw == F64_BITS_INF)) return_inf(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4387
|
0
|
0
|
|
|
|
|
if (likely(precision_bits <= half_way - fp_err || |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4388
|
|
|
|
|
|
|
precision_bits >= half_way + fp_err)) { |
|
4389
|
0
|
|
|
|
|
|
return_f64_bin(raw); /* number is accurate */ |
|
4390
|
|
|
|
|
|
|
} |
|
4391
|
|
|
|
|
|
|
/* now the number is the correct value, or the next lower value */ |
|
4392
|
|
|
|
|
|
|
|
|
4393
|
|
|
|
|
|
|
/* upper boundary */ |
|
4394
|
0
|
0
|
|
|
|
|
if (raw & F64_EXP_MASK) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4395
|
0
|
|
|
|
|
|
fp_upper.sig = (raw & F64_SIG_MASK) + ((u64)1 << F64_SIG_BITS); |
|
4396
|
0
|
|
|
|
|
|
fp_upper.exp = (i32)((raw & F64_EXP_MASK) >> F64_SIG_BITS); |
|
4397
|
|
|
|
|
|
|
} else { |
|
4398
|
0
|
|
|
|
|
|
fp_upper.sig = (raw & F64_SIG_MASK); |
|
4399
|
0
|
|
|
|
|
|
fp_upper.exp = 1; |
|
4400
|
|
|
|
|
|
|
} |
|
4401
|
0
|
|
|
|
|
|
fp_upper.exp -= F64_EXP_BIAS + F64_SIG_BITS; |
|
4402
|
0
|
|
|
|
|
|
fp_upper.sig <<= 1; |
|
4403
|
0
|
|
|
|
|
|
fp_upper.exp -= 1; |
|
4404
|
0
|
|
|
|
|
|
fp_upper.sig += 1; /* add half ulp */ |
|
4405
|
|
|
|
|
|
|
|
|
4406
|
|
|
|
|
|
|
/* compare with bigint */ |
|
4407
|
0
|
|
|
|
|
|
bigint_set_buf(&big_full, sig, &exp, sig_cut, sig_end, dot_pos); |
|
4408
|
0
|
|
|
|
|
|
bigint_set_u64(&big_comp, fp_upper.sig); |
|
4409
|
0
|
0
|
|
|
|
|
if (exp >= 0) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4410
|
0
|
|
|
|
|
|
bigint_mul_pow10(&big_full, +exp); |
|
4411
|
|
|
|
|
|
|
} else { |
|
4412
|
0
|
|
|
|
|
|
bigint_mul_pow10(&big_comp, -exp); |
|
4413
|
|
|
|
|
|
|
} |
|
4414
|
0
|
0
|
|
|
|
|
if (fp_upper.exp > 0) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4415
|
0
|
0
|
|
|
|
|
bigint_mul_pow2(&big_comp, (u32)+fp_upper.exp); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4416
|
|
|
|
|
|
|
} else { |
|
4417
|
0
|
0
|
|
|
|
|
bigint_mul_pow2(&big_full, (u32)-fp_upper.exp); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4418
|
|
|
|
|
|
|
} |
|
4419
|
0
|
|
|
|
|
|
cmp = bigint_cmp(&big_full, &big_comp); |
|
4420
|
0
|
0
|
|
|
|
|
if (likely(cmp != 0)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4421
|
|
|
|
|
|
|
/* round down or round up */ |
|
4422
|
0
|
|
|
|
|
|
raw += (cmp > 0); |
|
4423
|
|
|
|
|
|
|
} else { |
|
4424
|
|
|
|
|
|
|
/* falls midway, round to even */ |
|
4425
|
0
|
|
|
|
|
|
raw += (raw & 1); |
|
4426
|
|
|
|
|
|
|
} |
|
4427
|
|
|
|
|
|
|
|
|
4428
|
0
|
0
|
|
|
|
|
if (unlikely(raw == F64_BITS_INF)) return_inf(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4429
|
0
|
|
|
|
|
|
return_f64_bin(raw); |
|
4430
|
|
|
|
|
|
|
} |
|
4431
|
|
|
|
|
|
|
|
|
4432
|
|
|
|
|
|
|
#undef return_err |
|
4433
|
|
|
|
|
|
|
#undef return_inf |
|
4434
|
|
|
|
|
|
|
#undef return_0 |
|
4435
|
|
|
|
|
|
|
#undef return_i64 |
|
4436
|
|
|
|
|
|
|
#undef return_f64 |
|
4437
|
|
|
|
|
|
|
#undef return_f64_bin |
|
4438
|
|
|
|
|
|
|
#undef return_raw |
|
4439
|
|
|
|
|
|
|
} |
|
4440
|
|
|
|
|
|
|
|
|
4441
|
|
|
|
|
|
|
|
|
4442
|
|
|
|
|
|
|
|
|
4443
|
|
|
|
|
|
|
#else /* FP_READER */ |
|
4444
|
|
|
|
|
|
|
|
|
4445
|
|
|
|
|
|
|
/** |
|
4446
|
|
|
|
|
|
|
Read a JSON number. |
|
4447
|
|
|
|
|
|
|
This is a fallback function if the custom number reader is disabled. |
|
4448
|
|
|
|
|
|
|
This function use libc's strtod() to read floating-point number. |
|
4449
|
|
|
|
|
|
|
*/ |
|
4450
|
|
|
|
|
|
|
static_inline bool read_num(u8 **ptr, u8 **pre, yyjson_read_flag flg, |
|
4451
|
|
|
|
|
|
|
yyjson_val *val, const char **msg) { |
|
4452
|
|
|
|
|
|
|
#define return_err(_pos, _msg) do { \ |
|
4453
|
|
|
|
|
|
|
*msg = _msg; \ |
|
4454
|
|
|
|
|
|
|
*end = _pos; \ |
|
4455
|
|
|
|
|
|
|
return false; \ |
|
4456
|
|
|
|
|
|
|
} while (false) |
|
4457
|
|
|
|
|
|
|
|
|
4458
|
|
|
|
|
|
|
#define return_0() do { \ |
|
4459
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \ |
|
4460
|
|
|
|
|
|
|
val->uni.u64 = 0; \ |
|
4461
|
|
|
|
|
|
|
*end = cur; return true; \ |
|
4462
|
|
|
|
|
|
|
} while (false) |
|
4463
|
|
|
|
|
|
|
|
|
4464
|
|
|
|
|
|
|
#define return_i64(_v) do { \ |
|
4465
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \ |
|
4466
|
|
|
|
|
|
|
val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \ |
|
4467
|
|
|
|
|
|
|
*end = cur; return true; \ |
|
4468
|
|
|
|
|
|
|
} while (false) |
|
4469
|
|
|
|
|
|
|
|
|
4470
|
|
|
|
|
|
|
#define return_f64(_v) do { \ |
|
4471
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ |
|
4472
|
|
|
|
|
|
|
val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \ |
|
4473
|
|
|
|
|
|
|
*end = cur; return true; \ |
|
4474
|
|
|
|
|
|
|
} while (false) |
|
4475
|
|
|
|
|
|
|
|
|
4476
|
|
|
|
|
|
|
#define return_f64_bin(_v) do { \ |
|
4477
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ |
|
4478
|
|
|
|
|
|
|
val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \ |
|
4479
|
|
|
|
|
|
|
*end = cur; return true; \ |
|
4480
|
|
|
|
|
|
|
} while (false) |
|
4481
|
|
|
|
|
|
|
|
|
4482
|
|
|
|
|
|
|
#define return_inf() do { \ |
|
4483
|
|
|
|
|
|
|
if (has_flg(BIGNUM_AS_RAW)) return_raw(); \ |
|
4484
|
|
|
|
|
|
|
if (has_allow(INF_AND_NAN)) return_f64_bin(F64_BITS_INF); \ |
|
4485
|
|
|
|
|
|
|
else return_err(hdr, "number is infinity when parsed as double"); \ |
|
4486
|
|
|
|
|
|
|
} while (false) |
|
4487
|
|
|
|
|
|
|
|
|
4488
|
|
|
|
|
|
|
#define return_raw() do { \ |
|
4489
|
|
|
|
|
|
|
val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ |
|
4490
|
|
|
|
|
|
|
val->uni.str = (const char *)hdr; \ |
|
4491
|
|
|
|
|
|
|
**pre = '\0'; *pre = cur; *end = cur; return true; \ |
|
4492
|
|
|
|
|
|
|
} while (false) |
|
4493
|
|
|
|
|
|
|
|
|
4494
|
|
|
|
|
|
|
u64 sig, num; |
|
4495
|
|
|
|
|
|
|
u8 *hdr = *ptr; |
|
4496
|
|
|
|
|
|
|
u8 *cur = *ptr; |
|
4497
|
|
|
|
|
|
|
u8 **end = ptr; |
|
4498
|
|
|
|
|
|
|
u8 *dot = NULL; |
|
4499
|
|
|
|
|
|
|
u8 *f64_end = NULL; |
|
4500
|
|
|
|
|
|
|
bool sign; |
|
4501
|
|
|
|
|
|
|
|
|
4502
|
|
|
|
|
|
|
/* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */ |
|
4503
|
|
|
|
|
|
|
if (has_flg(NUMBER_AS_RAW)) { |
|
4504
|
|
|
|
|
|
|
return read_num_raw(ptr, pre, flg, val, msg); |
|
4505
|
|
|
|
|
|
|
} |
|
4506
|
|
|
|
|
|
|
|
|
4507
|
|
|
|
|
|
|
sign = (*hdr == '-'); |
|
4508
|
|
|
|
|
|
|
cur += sign; |
|
4509
|
|
|
|
|
|
|
sig = (u8)(*cur - '0'); |
|
4510
|
|
|
|
|
|
|
|
|
4511
|
|
|
|
|
|
|
/* read first digit, check leading zero */ |
|
4512
|
|
|
|
|
|
|
while (unlikely(!char_is_digit(*cur))) { |
|
4513
|
|
|
|
|
|
|
if (has_allow(EXT_NUMBER)) { |
|
4514
|
|
|
|
|
|
|
if (*cur == '+' && cur == hdr) { /* leading `+` sign */ |
|
4515
|
|
|
|
|
|
|
cur++; |
|
4516
|
|
|
|
|
|
|
sig = (u8)(*cur - '0'); |
|
4517
|
|
|
|
|
|
|
continue; |
|
4518
|
|
|
|
|
|
|
} |
|
4519
|
|
|
|
|
|
|
if (*cur == '.' && char_is_num(cur[1])) { /* no integer part */ |
|
4520
|
|
|
|
|
|
|
goto read_double; /* e.g. '.123' */ |
|
4521
|
|
|
|
|
|
|
} |
|
4522
|
|
|
|
|
|
|
} |
|
4523
|
|
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
4524
|
|
|
|
|
|
|
if (read_inf_or_nan(ptr, pre, flg, val)) return true; |
|
4525
|
|
|
|
|
|
|
} |
|
4526
|
|
|
|
|
|
|
return_err(cur, "no digit after sign"); |
|
4527
|
|
|
|
|
|
|
} |
|
4528
|
|
|
|
|
|
|
if (*cur == '0') { |
|
4529
|
|
|
|
|
|
|
cur++; |
|
4530
|
|
|
|
|
|
|
if (unlikely(char_is_digit(*cur))) { |
|
4531
|
|
|
|
|
|
|
return_err(cur - 1, "number with leading zero is not allowed"); |
|
4532
|
|
|
|
|
|
|
} |
|
4533
|
|
|
|
|
|
|
if (!char_is_fp(*cur)) { |
|
4534
|
|
|
|
|
|
|
if (has_allow(EXT_NUMBER) && |
|
4535
|
|
|
|
|
|
|
(*cur == 'x' || *cur == 'X')) { /* hex integer */ |
|
4536
|
|
|
|
|
|
|
return read_num_hex(ptr, pre, flg, val, msg); |
|
4537
|
|
|
|
|
|
|
} |
|
4538
|
|
|
|
|
|
|
return_0(); |
|
4539
|
|
|
|
|
|
|
} |
|
4540
|
|
|
|
|
|
|
goto read_double; |
|
4541
|
|
|
|
|
|
|
} |
|
4542
|
|
|
|
|
|
|
|
|
4543
|
|
|
|
|
|
|
/* read continuous digits, up to 19 characters */ |
|
4544
|
|
|
|
|
|
|
#define expr_intg(i) \ |
|
4545
|
|
|
|
|
|
|
if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \ |
|
4546
|
|
|
|
|
|
|
else { cur += i; goto intg_end; } |
|
4547
|
|
|
|
|
|
|
repeat_in_1_18(expr_intg) |
|
4548
|
|
|
|
|
|
|
#undef expr_intg |
|
4549
|
|
|
|
|
|
|
|
|
4550
|
|
|
|
|
|
|
/* here are 19 continuous digits, skip them */ |
|
4551
|
|
|
|
|
|
|
cur += 19; |
|
4552
|
|
|
|
|
|
|
if (char_is_digit(cur[0]) && !char_is_digit_or_fp(cur[1])) { |
|
4553
|
|
|
|
|
|
|
/* this number is an integer consisting of 20 digits */ |
|
4554
|
|
|
|
|
|
|
num = (u8)(*cur - '0'); |
|
4555
|
|
|
|
|
|
|
if ((sig < (U64_MAX / 10)) || |
|
4556
|
|
|
|
|
|
|
(sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) { |
|
4557
|
|
|
|
|
|
|
sig = num + sig * 10; |
|
4558
|
|
|
|
|
|
|
cur++; |
|
4559
|
|
|
|
|
|
|
if (sign) { |
|
4560
|
|
|
|
|
|
|
if (has_flg(BIGNUM_AS_RAW)) return_raw(); |
|
4561
|
|
|
|
|
|
|
return_f64(unsafe_yyjson_u64_to_f64(sig)); |
|
4562
|
|
|
|
|
|
|
} |
|
4563
|
|
|
|
|
|
|
return_i64(sig); |
|
4564
|
|
|
|
|
|
|
} |
|
4565
|
|
|
|
|
|
|
} |
|
4566
|
|
|
|
|
|
|
|
|
4567
|
|
|
|
|
|
|
intg_end: |
|
4568
|
|
|
|
|
|
|
/* continuous digits ended */ |
|
4569
|
|
|
|
|
|
|
if (!char_is_digit_or_fp(*cur)) { |
|
4570
|
|
|
|
|
|
|
/* this number is an integer consisting of 1 to 19 digits */ |
|
4571
|
|
|
|
|
|
|
if (sign && (sig > ((u64)1 << 63))) { |
|
4572
|
|
|
|
|
|
|
if (has_flg(BIGNUM_AS_RAW)) return_raw(); |
|
4573
|
|
|
|
|
|
|
return_f64(unsafe_yyjson_u64_to_f64(sig)); |
|
4574
|
|
|
|
|
|
|
} |
|
4575
|
|
|
|
|
|
|
return_i64(sig); |
|
4576
|
|
|
|
|
|
|
} |
|
4577
|
|
|
|
|
|
|
|
|
4578
|
|
|
|
|
|
|
read_double: |
|
4579
|
|
|
|
|
|
|
/* this number should be read as double */ |
|
4580
|
|
|
|
|
|
|
while (char_is_digit(*cur)) cur++; |
|
4581
|
|
|
|
|
|
|
if (!char_is_fp(*cur) && has_flg(BIGNUM_AS_RAW)) { |
|
4582
|
|
|
|
|
|
|
return_raw(); /* it's a large integer */ |
|
4583
|
|
|
|
|
|
|
} |
|
4584
|
|
|
|
|
|
|
while (*cur == '.') { |
|
4585
|
|
|
|
|
|
|
/* skip fraction part */ |
|
4586
|
|
|
|
|
|
|
dot = cur; |
|
4587
|
|
|
|
|
|
|
cur++; |
|
4588
|
|
|
|
|
|
|
if (!char_is_digit(*cur)) { |
|
4589
|
|
|
|
|
|
|
if (has_allow(EXT_NUMBER)) { |
|
4590
|
|
|
|
|
|
|
break; |
|
4591
|
|
|
|
|
|
|
} else { |
|
4592
|
|
|
|
|
|
|
return_err(cur, "no digit after decimal point"); |
|
4593
|
|
|
|
|
|
|
} |
|
4594
|
|
|
|
|
|
|
} |
|
4595
|
|
|
|
|
|
|
cur++; |
|
4596
|
|
|
|
|
|
|
while (char_is_digit(*cur)) cur++; |
|
4597
|
|
|
|
|
|
|
break; |
|
4598
|
|
|
|
|
|
|
} |
|
4599
|
|
|
|
|
|
|
if (char_is_exp(*cur)) { |
|
4600
|
|
|
|
|
|
|
/* skip exponent part */ |
|
4601
|
|
|
|
|
|
|
cur += 1 + char_is_sign(cur[1]); |
|
4602
|
|
|
|
|
|
|
if (!char_is_digit(*cur)) { |
|
4603
|
|
|
|
|
|
|
return_err(cur, "no digit after exponent sign"); |
|
4604
|
|
|
|
|
|
|
} |
|
4605
|
|
|
|
|
|
|
cur++; |
|
4606
|
|
|
|
|
|
|
while (char_is_digit(*cur)) cur++; |
|
4607
|
|
|
|
|
|
|
} |
|
4608
|
|
|
|
|
|
|
|
|
4609
|
|
|
|
|
|
|
/* |
|
4610
|
|
|
|
|
|
|
libc's strtod() is used to parse the floating-point number. |
|
4611
|
|
|
|
|
|
|
|
|
4612
|
|
|
|
|
|
|
Note that the decimal point character used by strtod() is locale-dependent, |
|
4613
|
|
|
|
|
|
|
and the rounding direction may affected by fesetround(). |
|
4614
|
|
|
|
|
|
|
|
|
4615
|
|
|
|
|
|
|
For currently known locales, (en, zh, ja, ko, am, he, hi) use '.' as the |
|
4616
|
|
|
|
|
|
|
decimal point, while other locales use ',' as the decimal point. |
|
4617
|
|
|
|
|
|
|
|
|
4618
|
|
|
|
|
|
|
Here strtod() is called twice for different locales, but if another thread |
|
4619
|
|
|
|
|
|
|
happens calls setlocale() between two strtod(), parsing may still fail. |
|
4620
|
|
|
|
|
|
|
*/ |
|
4621
|
|
|
|
|
|
|
val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end); |
|
4622
|
|
|
|
|
|
|
if (unlikely(f64_end != cur)) { |
|
4623
|
|
|
|
|
|
|
/* replace '.' with ',' for locale */ |
|
4624
|
|
|
|
|
|
|
bool cut = (*cur == ','); |
|
4625
|
|
|
|
|
|
|
if (cut) *cur = ' '; |
|
4626
|
|
|
|
|
|
|
if (dot) *dot = ','; |
|
4627
|
|
|
|
|
|
|
val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end); |
|
4628
|
|
|
|
|
|
|
/* restore ',' to '.' */ |
|
4629
|
|
|
|
|
|
|
if (cut) *cur = ','; |
|
4630
|
|
|
|
|
|
|
if (dot) *dot = '.'; |
|
4631
|
|
|
|
|
|
|
if (unlikely(f64_end != cur)) { |
|
4632
|
|
|
|
|
|
|
return_err(hdr, "strtod() failed to parse the number"); |
|
4633
|
|
|
|
|
|
|
} |
|
4634
|
|
|
|
|
|
|
} |
|
4635
|
|
|
|
|
|
|
if (unlikely(val->uni.f64 >= HUGE_VAL || val->uni.f64 <= -HUGE_VAL)) { |
|
4636
|
|
|
|
|
|
|
return_inf(); |
|
4637
|
|
|
|
|
|
|
} |
|
4638
|
|
|
|
|
|
|
val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; |
|
4639
|
|
|
|
|
|
|
*end = cur; |
|
4640
|
|
|
|
|
|
|
return true; |
|
4641
|
|
|
|
|
|
|
|
|
4642
|
|
|
|
|
|
|
#undef return_err |
|
4643
|
|
|
|
|
|
|
#undef return_0 |
|
4644
|
|
|
|
|
|
|
#undef return_i64 |
|
4645
|
|
|
|
|
|
|
#undef return_f64 |
|
4646
|
|
|
|
|
|
|
#undef return_f64_bin |
|
4647
|
|
|
|
|
|
|
#undef return_inf |
|
4648
|
|
|
|
|
|
|
#undef return_raw |
|
4649
|
|
|
|
|
|
|
} |
|
4650
|
|
|
|
|
|
|
|
|
4651
|
|
|
|
|
|
|
#endif /* FP_READER */ |
|
4652
|
|
|
|
|
|
|
|
|
4653
|
|
|
|
|
|
|
|
|
4654
|
|
|
|
|
|
|
|
|
4655
|
|
|
|
|
|
|
/*============================================================================== |
|
4656
|
|
|
|
|
|
|
* MARK: - String Reader (Private) |
|
4657
|
|
|
|
|
|
|
*============================================================================*/ |
|
4658
|
|
|
|
|
|
|
|
|
4659
|
|
|
|
|
|
|
/** Read unicode escape sequence. */ |
|
4660
|
|
|
|
|
|
|
static_inline bool read_uni_esc(u8 **src_ptr, u8 **dst_ptr, const char **msg) { |
|
4661
|
|
|
|
|
|
|
#define return_err(_end, _msg) *msg = _msg; *src_ptr = _end; return false |
|
4662
|
|
|
|
|
|
|
|
|
4663
|
9
|
|
|
|
|
|
u8 *src = *src_ptr; |
|
4664
|
9
|
|
|
|
|
|
u8 *dst = *dst_ptr; |
|
4665
|
|
|
|
|
|
|
u16 hi, lo; |
|
4666
|
|
|
|
|
|
|
u32 uni; |
|
4667
|
|
|
|
|
|
|
|
|
4668
|
0
|
|
|
|
|
|
src += 2; /* skip `\u` */ |
|
4669
|
9
|
0
|
|
|
|
|
if (unlikely(!hex_load_4(src, &hi))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4670
|
0
|
|
|
|
|
|
return_err(src - 2, "invalid escaped sequence in string"); |
|
4671
|
|
|
|
|
|
|
} |
|
4672
|
9
|
|
|
|
|
|
src += 4; /* skip hex */ |
|
4673
|
9
|
0
|
|
|
|
|
if (likely((hi & 0xF800) != 0xD800)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4674
|
|
|
|
|
|
|
/* a BMP character */ |
|
4675
|
8
|
0
|
|
|
|
|
if (hi >= 0x800) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4676
|
3
|
|
|
|
|
|
*dst++ = (u8)(0xE0 | (hi >> 12)); |
|
4677
|
3
|
|
|
|
|
|
*dst++ = (u8)(0x80 | ((hi >> 6) & 0x3F)); |
|
4678
|
3
|
|
|
|
|
|
*dst++ = (u8)(0x80 | (hi & 0x3F)); |
|
4679
|
5
|
0
|
|
|
|
|
} else if (hi >= 0x80) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4680
|
3
|
|
|
|
|
|
*dst++ = (u8)(0xC0 | (hi >> 6)); |
|
4681
|
3
|
|
|
|
|
|
*dst++ = (u8)(0x80 | (hi & 0x3F)); |
|
4682
|
|
|
|
|
|
|
} else { |
|
4683
|
2
|
|
|
|
|
|
*dst++ = (u8)hi; |
|
4684
|
|
|
|
|
|
|
} |
|
4685
|
|
|
|
|
|
|
} else { |
|
4686
|
|
|
|
|
|
|
/* a non-BMP character, represented as a surrogate pair */ |
|
4687
|
1
|
0
|
|
|
|
|
if (unlikely((hi & 0xFC00) != 0xD800)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4688
|
0
|
|
|
|
|
|
return_err(src - 6, "invalid high surrogate in string"); |
|
4689
|
|
|
|
|
|
|
} |
|
4690
|
1
|
0
|
|
|
|
|
if (unlikely(!byte_match_2(src, "\\u"))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4691
|
0
|
|
|
|
|
|
return_err(src - 6, "no low surrogate in string"); |
|
4692
|
|
|
|
|
|
|
} |
|
4693
|
2
|
0
|
|
|
|
|
if (unlikely(!hex_load_4(src + 2, &lo))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4694
|
0
|
|
|
|
|
|
return_err(src - 6, "invalid escape in string"); |
|
4695
|
|
|
|
|
|
|
} |
|
4696
|
1
|
0
|
|
|
|
|
if (unlikely((lo & 0xFC00) != 0xDC00)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4697
|
0
|
|
|
|
|
|
return_err(src - 6, "invalid low surrogate in string"); |
|
4698
|
|
|
|
|
|
|
} |
|
4699
|
1
|
|
|
|
|
|
uni = ((((u32)hi - 0xD800) << 10) | |
|
4700
|
1
|
|
|
|
|
|
((u32)lo - 0xDC00)) + 0x10000; |
|
4701
|
1
|
|
|
|
|
|
*dst++ = (u8)(0xF0 | (uni >> 18)); |
|
4702
|
1
|
|
|
|
|
|
*dst++ = (u8)(0x80 | ((uni >> 12) & 0x3F)); |
|
4703
|
1
|
|
|
|
|
|
*dst++ = (u8)(0x80 | ((uni >> 6) & 0x3F)); |
|
4704
|
1
|
|
|
|
|
|
*dst++ = (u8)(0x80 | (uni & 0x3F)); |
|
4705
|
1
|
|
|
|
|
|
src += 6; |
|
4706
|
|
|
|
|
|
|
} |
|
4707
|
9
|
|
|
|
|
|
*src_ptr = src; |
|
4708
|
9
|
|
|
|
|
|
*dst_ptr = dst; |
|
4709
|
9
|
|
|
|
|
|
return true; |
|
4710
|
|
|
|
|
|
|
#undef return_err |
|
4711
|
|
|
|
|
|
|
} |
|
4712
|
|
|
|
|
|
|
|
|
4713
|
|
|
|
|
|
|
/** |
|
4714
|
|
|
|
|
|
|
Read a JSON string. |
|
4715
|
|
|
|
|
|
|
@param quo The quote character (single quote or double quote). |
|
4716
|
|
|
|
|
|
|
@param ptr The head pointer of string before quote (inout). |
|
4717
|
|
|
|
|
|
|
@param eof JSON end position. |
|
4718
|
|
|
|
|
|
|
@param flg JSON read flag. |
|
4719
|
|
|
|
|
|
|
@param val The string value to be written. |
|
4720
|
|
|
|
|
|
|
@param msg The error message pointer. |
|
4721
|
|
|
|
|
|
|
@param con Continuation for incremental parsing. |
|
4722
|
|
|
|
|
|
|
@return Whether success. |
|
4723
|
|
|
|
|
|
|
*/ |
|
4724
|
|
|
|
|
|
|
static_inline bool read_str_opt(u8 quo, u8 **ptr, u8 *eof, yyjson_read_flag flg, |
|
4725
|
|
|
|
|
|
|
yyjson_val *val, const char **msg, u8 *con[2]) { |
|
4726
|
|
|
|
|
|
|
/* |
|
4727
|
|
|
|
|
|
|
GCC may sometimes load variables into registers too early, causing |
|
4728
|
|
|
|
|
|
|
unnecessary instructions and performance degradation. This inline assembly |
|
4729
|
|
|
|
|
|
|
serves as a hint to GCC: 'This variable will be modified, so avoid loading |
|
4730
|
|
|
|
|
|
|
it too early.' Other compilers like MSVC, Clang, and ICC can generate the |
|
4731
|
|
|
|
|
|
|
expected instructions without needing this hint. |
|
4732
|
|
|
|
|
|
|
|
|
4733
|
|
|
|
|
|
|
Check out this example: https://godbolt.org/z/YG6a5W5Ec |
|
4734
|
|
|
|
|
|
|
*/ |
|
4735
|
|
|
|
|
|
|
#define return_err(_end, _msg) do { \ |
|
4736
|
|
|
|
|
|
|
*msg = _msg; \ |
|
4737
|
|
|
|
|
|
|
*end = _end; \ |
|
4738
|
|
|
|
|
|
|
if (con) { con[0] = _end; con[1] = dst; } \ |
|
4739
|
|
|
|
|
|
|
return false; \ |
|
4740
|
|
|
|
|
|
|
} while (false) |
|
4741
|
|
|
|
|
|
|
|
|
4742
|
16234
|
|
|
|
|
|
u8 *hdr = *ptr + 1; |
|
4743
|
16234
|
|
|
|
|
|
u8 **end = ptr; |
|
4744
|
16234
|
|
|
|
|
|
u8 *src = hdr, *dst = NULL, *pos; |
|
4745
|
|
|
|
|
|
|
u16 hi, lo; |
|
4746
|
|
|
|
|
|
|
u32 uni, tmp; |
|
4747
|
|
|
|
|
|
|
|
|
4748
|
|
|
|
|
|
|
/* Resume incremental parsing. */ |
|
4749
|
2
|
0
|
|
|
|
|
if (con && unlikely(con[0])) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4750
|
0
|
|
|
|
|
|
src = con[0]; |
|
4751
|
0
|
|
|
|
|
|
dst = con[1]; |
|
4752
|
0
|
0
|
|
|
|
|
if (dst) goto copy_ascii; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4753
|
|
|
|
|
|
|
} |
|
4754
|
|
|
|
|
|
|
|
|
4755
|
28487
|
|
|
|
|
|
skip_ascii: |
|
4756
|
|
|
|
|
|
|
/* |
|
4757
|
|
|
|
|
|
|
Most strings have no escaped characters, so we can jump them quickly. |
|
4758
|
|
|
|
|
|
|
|
|
4759
|
|
|
|
|
|
|
We want to make loop unrolling, as shown in the following code. Some |
|
4760
|
|
|
|
|
|
|
compiler may not generate instructions as expected, so we rewrite it with |
|
4761
|
|
|
|
|
|
|
explicit goto statements. We hope the compiler can generate instructions |
|
4762
|
|
|
|
|
|
|
like this: https://godbolt.org/z/8vjsYq |
|
4763
|
|
|
|
|
|
|
|
|
4764
|
|
|
|
|
|
|
while (true) repeat16({ |
|
4765
|
|
|
|
|
|
|
if (likely((char_is_ascii_skip(*src)))) src++; |
|
4766
|
|
|
|
|
|
|
else break; |
|
4767
|
|
|
|
|
|
|
}) |
|
4768
|
|
|
|
|
|
|
*/ |
|
4769
|
28487
|
0
|
|
|
|
|
if (quo == '"') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4770
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
4771
|
|
|
|
|
|
|
if (likely(char_is_ascii_skip(src[i]))) {} \ |
|
4772
|
|
|
|
|
|
|
else goto skip_ascii_stop##i; |
|
4773
|
|
|
|
|
|
|
|
|
4774
|
|
|
|
|
|
|
#define expr_stop(i) \ |
|
4775
|
|
|
|
|
|
|
skip_ascii_stop##i: \ |
|
4776
|
|
|
|
|
|
|
src += i; \ |
|
4777
|
|
|
|
|
|
|
goto skip_ascii_end; |
|
4778
|
|
|
|
|
|
|
|
|
4779
|
270047
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4780
|
12250
|
|
|
|
|
|
src += 16; |
|
4781
|
12250
|
|
|
|
|
|
goto skip_ascii; |
|
4782
|
16237
|
|
|
|
|
|
repeat16_incr(expr_stop) |
|
4783
|
|
|
|
|
|
|
|
|
4784
|
|
|
|
|
|
|
#undef expr_jump |
|
4785
|
|
|
|
|
|
|
#undef expr_stop |
|
4786
|
|
|
|
|
|
|
} else { |
|
4787
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
4788
|
|
|
|
|
|
|
if (likely(char_is_ascii_skip_sq(src[i]))) {} \ |
|
4789
|
|
|
|
|
|
|
else goto skip_ascii_stop_sq##i; |
|
4790
|
|
|
|
|
|
|
|
|
4791
|
|
|
|
|
|
|
#define expr_stop(i) \ |
|
4792
|
|
|
|
|
|
|
skip_ascii_stop_sq##i: \ |
|
4793
|
|
|
|
|
|
|
src += i; \ |
|
4794
|
|
|
|
|
|
|
goto skip_ascii_end; |
|
4795
|
|
|
|
|
|
|
|
|
4796
|
0
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4797
|
0
|
|
|
|
|
|
src += 16; |
|
4798
|
0
|
|
|
|
|
|
goto skip_ascii; |
|
4799
|
0
|
|
|
|
|
|
repeat16_incr(expr_stop) |
|
4800
|
|
|
|
|
|
|
|
|
4801
|
|
|
|
|
|
|
#undef expr_jump |
|
4802
|
|
|
|
|
|
|
#undef expr_stop |
|
4803
|
|
|
|
|
|
|
} |
|
4804
|
|
|
|
|
|
|
|
|
4805
|
16237
|
|
|
|
|
|
skip_ascii_end: |
|
4806
|
16237
|
|
|
|
|
|
gcc_store_barrier(*src); |
|
4807
|
16237
|
|
|
|
|
|
if (likely(*src == quo)) { |
|
4808
|
32454
|
|
|
|
|
|
val->tag = ((u64)(src - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR | |
|
4809
|
16227
|
0
|
|
|
|
|
(quo == '"' ? YYJSON_SUBTYPE_NOESC : 0); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4810
|
16227
|
|
|
|
|
|
val->uni.str = (const char *)hdr; |
|
4811
|
16227
|
|
|
|
|
|
*src = '\0'; |
|
4812
|
16227
|
|
|
|
|
|
*end = src + 1; |
|
4813
|
16227
|
0
|
|
|
|
|
if (con) con[0] = con[1] = NULL; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4814
|
16227
|
|
|
|
|
|
return true; |
|
4815
|
|
|
|
|
|
|
} |
|
4816
|
|
|
|
|
|
|
|
|
4817
|
10
|
|
|
|
|
|
skip_utf8: |
|
4818
|
10
|
0
|
|
|
|
|
if (*src & 0x80) { /* non-ASCII character */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4819
|
|
|
|
|
|
|
/* |
|
4820
|
|
|
|
|
|
|
Non-ASCII character appears here, which means that the text is likely |
|
4821
|
|
|
|
|
|
|
to be written in non-English or emoticons. According to some common |
|
4822
|
|
|
|
|
|
|
data set statistics, byte sequences of the same length may appear |
|
4823
|
|
|
|
|
|
|
consecutively. We process the byte sequences of the same length in each |
|
4824
|
|
|
|
|
|
|
loop, which is more friendly to branch prediction. |
|
4825
|
|
|
|
|
|
|
*/ |
|
4826
|
3
|
|
|
|
|
|
pos = src; |
|
4827
|
|
|
|
|
|
|
#if YYJSON_DISABLE_UTF8_VALIDATION |
|
4828
|
|
|
|
|
|
|
while (true) repeat8({ |
|
4829
|
|
|
|
|
|
|
if (likely((*src & 0xF0) == 0xE0)) src += 3; |
|
4830
|
|
|
|
|
|
|
else break; |
|
4831
|
|
|
|
|
|
|
}) |
|
4832
|
|
|
|
|
|
|
if (*src < 0x80) goto skip_ascii; |
|
4833
|
|
|
|
|
|
|
while (true) repeat8({ |
|
4834
|
|
|
|
|
|
|
if (likely((*src & 0xE0) == 0xC0)) src += 2; |
|
4835
|
|
|
|
|
|
|
else break; |
|
4836
|
|
|
|
|
|
|
}) |
|
4837
|
|
|
|
|
|
|
while (true) repeat8({ |
|
4838
|
|
|
|
|
|
|
if (likely((*src & 0xF8) == 0xF0)) src += 4; |
|
4839
|
|
|
|
|
|
|
else break; |
|
4840
|
|
|
|
|
|
|
}) |
|
4841
|
|
|
|
|
|
|
#else |
|
4842
|
3
|
|
|
|
|
|
uni = byte_load_4(src); |
|
4843
|
4
|
0
|
|
|
|
|
while (is_utf8_seq3(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4844
|
1
|
|
|
|
|
|
src += 3; |
|
4845
|
2
|
|
|
|
|
|
uni = byte_load_4(src); |
|
4846
|
|
|
|
|
|
|
} |
|
4847
|
3
|
0
|
|
|
|
|
if (is_utf8_seq1(uni)) goto skip_ascii; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4848
|
2
|
0
|
|
|
|
|
while (is_utf8_seq2(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4849
|
0
|
|
|
|
|
|
src += 2; |
|
4850
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
4851
|
|
|
|
|
|
|
} |
|
4852
|
4
|
0
|
|
|
|
|
while (is_utf8_seq4(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4853
|
2
|
|
|
|
|
|
src += 4; |
|
4854
|
4
|
|
|
|
|
|
uni = byte_load_4(src); |
|
4855
|
|
|
|
|
|
|
} |
|
4856
|
|
|
|
|
|
|
#endif |
|
4857
|
2
|
0
|
|
|
|
|
if (unlikely(pos == src)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4858
|
0
|
0
|
|
|
|
|
if (has_allow(INVALID_UNICODE)) ++src; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4859
|
0
|
0
|
|
|
|
|
else return_err(src, "invalid UTF-8 encoding in string"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4860
|
|
|
|
|
|
|
} |
|
4861
|
2
|
|
|
|
|
|
goto skip_ascii; |
|
4862
|
|
|
|
|
|
|
} |
|
4863
|
|
|
|
|
|
|
|
|
4864
|
|
|
|
|
|
|
/* The escape character appears, we need to copy it. */ |
|
4865
|
7
|
|
|
|
|
|
dst = src; |
|
4866
|
16
|
|
|
|
|
|
copy_escape: |
|
4867
|
16
|
0
|
|
|
|
|
if (likely(*src == '\\')) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4868
|
9
|
|
|
|
|
|
switch (*++src) { |
|
4869
|
0
|
|
|
|
|
|
case '"': *dst++ = '"'; src++; break; |
|
4870
|
0
|
|
|
|
|
|
case '\\': *dst++ = '\\'; src++; break; |
|
4871
|
0
|
|
|
|
|
|
case '/': *dst++ = '/'; src++; break; |
|
4872
|
0
|
|
|
|
|
|
case 'b': *dst++ = '\b'; src++; break; |
|
4873
|
0
|
|
|
|
|
|
case 'f': *dst++ = '\f'; src++; break; |
|
4874
|
0
|
|
|
|
|
|
case 'n': *dst++ = '\n'; src++; break; |
|
4875
|
0
|
|
|
|
|
|
case 'r': *dst++ = '\r'; src++; break; |
|
4876
|
0
|
|
|
|
|
|
case 't': *dst++ = '\t'; src++; break; |
|
4877
|
9
|
|
|
|
|
|
case 'u': |
|
4878
|
9
|
|
|
|
|
|
src--; |
|
4879
|
9
|
0
|
|
|
|
|
if (!read_uni_esc(&src, &dst, msg)) return_err(src, *msg); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4880
|
9
|
|
|
|
|
|
break; |
|
4881
|
0
|
|
|
|
|
|
default: { |
|
4882
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_ESCAPE)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4883
|
|
|
|
|
|
|
/* read extended escape (non-standard) */ |
|
4884
|
0
|
|
|
|
|
|
switch (*src) { |
|
4885
|
0
|
|
|
|
|
|
case '\'': *dst++ = '\''; src++; break; |
|
4886
|
0
|
|
|
|
|
|
case 'a': *dst++ = '\a'; src++; break; |
|
4887
|
0
|
|
|
|
|
|
case 'v': *dst++ = '\v'; src++; break; |
|
4888
|
0
|
|
|
|
|
|
case '?': *dst++ = '\?'; src++; break; |
|
4889
|
0
|
|
|
|
|
|
case 'e': *dst++ = 0x1B; src++; break; |
|
4890
|
0
|
|
|
|
|
|
case '0': |
|
4891
|
0
|
0
|
|
|
|
|
if (!char_is_digit(src[1])) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4892
|
0
|
|
|
|
|
|
*dst++ = '\0'; src++; break; |
|
4893
|
|
|
|
|
|
|
} |
|
4894
|
0
|
0
|
|
|
|
|
return_err(src - 1, "octal escape is not allowed"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4895
|
0
|
|
|
|
|
|
case '1': case '2': case '3': case '4': |
|
4896
|
|
|
|
|
|
|
case '5': case '6': case '7': case '8': case '9': |
|
4897
|
0
|
0
|
|
|
|
|
return_err(src - 1, "invalid number escape"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4898
|
0
|
|
|
|
|
|
case 'x': { |
|
4899
|
|
|
|
|
|
|
u8 c; |
|
4900
|
0
|
0
|
|
|
|
|
if (hex_load_2(src + 1, &c)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4901
|
0
|
|
|
|
|
|
src += 3; |
|
4902
|
0
|
0
|
|
|
|
|
if (c <= 0x7F) { /* 1-byte ASCII */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4903
|
0
|
|
|
|
|
|
*dst++ = c; |
|
4904
|
|
|
|
|
|
|
} else { /* 2-byte UTF-8 */ |
|
4905
|
0
|
|
|
|
|
|
*dst++ = (u8)(0xC0 | (c >> 6)); |
|
4906
|
0
|
|
|
|
|
|
*dst++ = (u8)(0x80 | (c & 0x3F)); |
|
4907
|
|
|
|
|
|
|
} |
|
4908
|
0
|
|
|
|
|
|
break; |
|
4909
|
|
|
|
|
|
|
} |
|
4910
|
0
|
0
|
|
|
|
|
return_err(src - 1, "invalid hex escape"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4911
|
|
|
|
|
|
|
} |
|
4912
|
0
|
|
|
|
|
|
case '\n': src++; break; |
|
4913
|
0
|
|
|
|
|
|
case '\r': src++; src += (*src == '\n'); break; |
|
4914
|
0
|
|
|
|
|
|
case 0xE2: /* Line terminator: U+2028, U+2029 */ |
|
4915
|
0
|
0
|
|
|
|
|
if ((src[1] == 0x80 && src[2] == 0xA8) || |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4916
|
0
|
0
|
|
|
|
|
(src[1] == 0x80 && src[2] == 0xA9)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4917
|
0
|
|
|
|
|
|
src += 3; |
|
4918
|
|
|
|
|
|
|
} |
|
4919
|
0
|
|
|
|
|
|
break; |
|
4920
|
0
|
|
|
|
|
|
default: |
|
4921
|
0
|
|
|
|
|
|
break; /* skip */ |
|
4922
|
|
|
|
|
|
|
} |
|
4923
|
0
|
0
|
|
|
|
|
} else if (quo == '\'' && *src == '\'') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4924
|
0
|
|
|
|
|
|
*dst++ = '\''; src++; break; |
|
4925
|
|
|
|
|
|
|
} else { |
|
4926
|
0
|
0
|
|
|
|
|
return_err(src - 1, "invalid escaped sequence in string"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4927
|
|
|
|
|
|
|
} |
|
4928
|
|
|
|
|
|
|
} |
|
4929
|
|
|
|
|
|
|
} |
|
4930
|
7
|
0
|
|
|
|
|
} else if (likely(*src == quo)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4931
|
7
|
|
|
|
|
|
val->tag = ((u64)(dst - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; |
|
4932
|
7
|
|
|
|
|
|
val->uni.str = (const char *)hdr; |
|
4933
|
7
|
|
|
|
|
|
*dst = '\0'; |
|
4934
|
7
|
|
|
|
|
|
*end = src + 1; |
|
4935
|
7
|
0
|
|
|
|
|
if (con) con[0] = con[1] = NULL; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4936
|
7
|
|
|
|
|
|
return true; |
|
4937
|
|
|
|
|
|
|
} else { |
|
4938
|
0
|
0
|
|
|
|
|
if (!has_allow(INVALID_UNICODE)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4939
|
0
|
0
|
|
|
|
|
return_err(src, "unexpected control character in string"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4940
|
|
|
|
|
|
|
} |
|
4941
|
0
|
0
|
|
|
|
|
if (src >= eof) return_err(src, "unclosed string"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4942
|
0
|
|
|
|
|
|
*dst++ = *src++; |
|
4943
|
|
|
|
|
|
|
} |
|
4944
|
|
|
|
|
|
|
|
|
4945
|
0
|
|
|
|
|
|
copy_ascii: |
|
4946
|
|
|
|
|
|
|
/* |
|
4947
|
|
|
|
|
|
|
Copy continuous ASCII, loop unrolling, same as the following code: |
|
4948
|
|
|
|
|
|
|
|
|
4949
|
|
|
|
|
|
|
while (true) repeat16({ |
|
4950
|
|
|
|
|
|
|
if (char_is_ascii_skip(*src)) *dst++ = *src++; |
|
4951
|
|
|
|
|
|
|
else break; |
|
4952
|
|
|
|
|
|
|
}) |
|
4953
|
|
|
|
|
|
|
*/ |
|
4954
|
9
|
0
|
|
|
|
|
if (quo == '"') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4955
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
4956
|
|
|
|
|
|
|
if (likely((char_is_ascii_skip(src[i])))) {} \ |
|
4957
|
|
|
|
|
|
|
else { gcc_store_barrier(src[i]); goto copy_ascii_stop_##i; } |
|
4958
|
26
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4959
|
|
|
|
|
|
|
#undef expr_jump |
|
4960
|
|
|
|
|
|
|
} else { |
|
4961
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
4962
|
|
|
|
|
|
|
if (likely((char_is_ascii_skip_sq(src[i])))) {} \ |
|
4963
|
|
|
|
|
|
|
else { gcc_store_barrier(src[i]); goto copy_ascii_stop_##i; } |
|
4964
|
0
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4965
|
|
|
|
|
|
|
#undef expr_jump |
|
4966
|
|
|
|
|
|
|
} |
|
4967
|
|
|
|
|
|
|
|
|
4968
|
0
|
|
|
|
|
|
byte_move_16(dst, src); |
|
4969
|
0
|
|
|
|
|
|
dst += 16; src += 16; |
|
4970
|
0
|
|
|
|
|
|
goto copy_ascii; |
|
4971
|
|
|
|
|
|
|
|
|
4972
|
|
|
|
|
|
|
/* |
|
4973
|
|
|
|
|
|
|
The memory is copied forward since `dst < src`. |
|
4974
|
|
|
|
|
|
|
So it's safe to move one extra byte to reduce instruction count. |
|
4975
|
|
|
|
|
|
|
*/ |
|
4976
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
4977
|
|
|
|
|
|
|
copy_ascii_stop_##i: \ |
|
4978
|
|
|
|
|
|
|
byte_move_forward(dst, src, i); \ |
|
4979
|
|
|
|
|
|
|
dst += i; src += i; \ |
|
4980
|
|
|
|
|
|
|
goto copy_utf8; |
|
4981
|
18
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4982
|
|
|
|
|
|
|
#undef expr_jump |
|
4983
|
|
|
|
|
|
|
|
|
4984
|
9
|
|
|
|
|
|
copy_utf8: |
|
4985
|
9
|
0
|
|
|
|
|
if (*src & 0x80) { /* non-ASCII character */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
4986
|
0
|
|
|
|
|
|
pos = src; |
|
4987
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
4988
|
|
|
|
|
|
|
#if YYJSON_DISABLE_UTF8_VALIDATION |
|
4989
|
|
|
|
|
|
|
while (true) repeat4({ |
|
4990
|
|
|
|
|
|
|
if ((uni & utf8_seq(b3_mask)) == utf8_seq(b3_patt)) { |
|
4991
|
|
|
|
|
|
|
byte_copy_4(dst, &uni); |
|
4992
|
|
|
|
|
|
|
dst += 3; src += 3; |
|
4993
|
|
|
|
|
|
|
uni = byte_load_4(src); |
|
4994
|
|
|
|
|
|
|
} else break; |
|
4995
|
|
|
|
|
|
|
}) |
|
4996
|
|
|
|
|
|
|
if ((uni & utf8_seq(b1_mask)) == utf8_seq(b1_patt)) goto copy_ascii; |
|
4997
|
|
|
|
|
|
|
while (true) repeat4({ |
|
4998
|
|
|
|
|
|
|
if ((uni & utf8_seq(b2_mask)) == utf8_seq(b2_patt)) { |
|
4999
|
|
|
|
|
|
|
byte_copy_2(dst, &uni); |
|
5000
|
|
|
|
|
|
|
dst += 2; src += 2; |
|
5001
|
|
|
|
|
|
|
uni = byte_load_4(src); |
|
5002
|
|
|
|
|
|
|
} else break; |
|
5003
|
|
|
|
|
|
|
}) |
|
5004
|
|
|
|
|
|
|
while (true) repeat4({ |
|
5005
|
|
|
|
|
|
|
if ((uni & utf8_seq(b4_mask)) == utf8_seq(b4_patt)) { |
|
5006
|
|
|
|
|
|
|
byte_copy_4(dst, &uni); |
|
5007
|
|
|
|
|
|
|
dst += 4; src += 4; |
|
5008
|
|
|
|
|
|
|
uni = byte_load_4(src); |
|
5009
|
|
|
|
|
|
|
} else break; |
|
5010
|
|
|
|
|
|
|
}) |
|
5011
|
|
|
|
|
|
|
#else |
|
5012
|
0
|
0
|
|
|
|
|
while (is_utf8_seq3(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5013
|
0
|
|
|
|
|
|
byte_copy_4(dst, &uni); |
|
5014
|
0
|
|
|
|
|
|
dst += 3; src += 3; |
|
5015
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
5016
|
|
|
|
|
|
|
} |
|
5017
|
0
|
0
|
|
|
|
|
if (is_utf8_seq1(uni)) goto copy_ascii; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5018
|
0
|
0
|
|
|
|
|
while (is_utf8_seq2(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5019
|
0
|
|
|
|
|
|
byte_copy_2(dst, &uni); |
|
5020
|
0
|
|
|
|
|
|
dst += 2; src += 2; |
|
5021
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
5022
|
|
|
|
|
|
|
} |
|
5023
|
0
|
0
|
|
|
|
|
while (is_utf8_seq4(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5024
|
0
|
|
|
|
|
|
byte_copy_4(dst, &uni); |
|
5025
|
0
|
|
|
|
|
|
dst += 4; src += 4; |
|
5026
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
5027
|
|
|
|
|
|
|
} |
|
5028
|
|
|
|
|
|
|
#endif |
|
5029
|
0
|
0
|
|
|
|
|
if (unlikely(pos == src)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5030
|
0
|
0
|
|
|
|
|
if (!has_allow(INVALID_UNICODE)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5031
|
0
|
0
|
|
|
|
|
return_err(src, MSG_ERR_UTF8); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5032
|
|
|
|
|
|
|
} |
|
5033
|
0
|
|
|
|
|
|
goto copy_ascii_stop_1; |
|
5034
|
|
|
|
|
|
|
} |
|
5035
|
0
|
|
|
|
|
|
goto copy_ascii; |
|
5036
|
|
|
|
|
|
|
} |
|
5037
|
9
|
|
|
|
|
|
goto copy_escape; |
|
5038
|
|
|
|
|
|
|
|
|
5039
|
|
|
|
|
|
|
#undef return_err |
|
5040
|
|
|
|
|
|
|
} |
|
5041
|
|
|
|
|
|
|
|
|
5042
|
|
|
|
|
|
|
static_inline bool read_str(u8 **ptr, u8 *eof, yyjson_read_flag flg, |
|
5043
|
|
|
|
|
|
|
yyjson_val *val, const char **msg) { |
|
5044
|
16234
|
|
|
|
|
|
return read_str_opt('\"', ptr, eof, flg, val, msg, NULL); |
|
5045
|
|
|
|
|
|
|
} |
|
5046
|
|
|
|
|
|
|
|
|
5047
|
|
|
|
|
|
|
static_inline bool read_str_con(u8 **ptr, u8 *eof, yyjson_read_flag flg, |
|
5048
|
|
|
|
|
|
|
yyjson_val *val, const char **msg, u8 **con) { |
|
5049
|
0
|
|
|
|
|
|
return read_str_opt('\"', ptr, eof, flg, val, msg, con); |
|
5050
|
|
|
|
|
|
|
} |
|
5051
|
|
|
|
|
|
|
|
|
5052
|
0
|
0
|
|
|
|
|
static_noinline bool read_str_sq(u8 **ptr, u8 *eof, yyjson_read_flag flg, |
|
5053
|
|
|
|
|
|
|
yyjson_val *val, const char **msg) { |
|
5054
|
0
|
|
|
|
|
|
return read_str_opt('\'', ptr, eof, flg, val, msg, NULL); |
|
5055
|
|
|
|
|
|
|
} |
|
5056
|
|
|
|
|
|
|
|
|
5057
|
|
|
|
|
|
|
/** Read unquoted key (identifier name). */ |
|
5058
|
0
|
|
|
|
|
|
static_noinline bool read_str_id(u8 **ptr, u8 *eof, yyjson_read_flag flg, |
|
5059
|
|
|
|
|
|
|
u8 **pre, yyjson_val *val, const char **msg) { |
|
5060
|
|
|
|
|
|
|
#define return_err(_end, _msg) do { \ |
|
5061
|
|
|
|
|
|
|
*msg = _msg; \ |
|
5062
|
|
|
|
|
|
|
*end = _end; \ |
|
5063
|
|
|
|
|
|
|
return false; \ |
|
5064
|
|
|
|
|
|
|
} while (false) |
|
5065
|
|
|
|
|
|
|
|
|
5066
|
|
|
|
|
|
|
#define return_suc(_str_end, _cur_end) do { \ |
|
5067
|
|
|
|
|
|
|
val->tag = ((u64)(_str_end - hdr) << YYJSON_TAG_BIT) | \ |
|
5068
|
|
|
|
|
|
|
(u64)(YYJSON_TYPE_STR); \ |
|
5069
|
|
|
|
|
|
|
val->uni.str = (const char *)hdr; \ |
|
5070
|
|
|
|
|
|
|
*pre = _str_end; *end = _cur_end; \ |
|
5071
|
|
|
|
|
|
|
return true; \ |
|
5072
|
|
|
|
|
|
|
} while (false) |
|
5073
|
|
|
|
|
|
|
|
|
5074
|
0
|
|
|
|
|
|
u8 *hdr = *ptr; |
|
5075
|
0
|
|
|
|
|
|
u8 **end = ptr; |
|
5076
|
0
|
|
|
|
|
|
u8 *src = hdr, *dst = NULL; |
|
5077
|
|
|
|
|
|
|
u16 hi, lo; |
|
5078
|
|
|
|
|
|
|
u32 uni, tmp; |
|
5079
|
|
|
|
|
|
|
|
|
5080
|
|
|
|
|
|
|
/* add null-terminator for previous raw string */ |
|
5081
|
0
|
|
|
|
|
|
**pre = '\0'; |
|
5082
|
|
|
|
|
|
|
|
|
5083
|
0
|
|
|
|
|
|
skip_ascii: |
|
5084
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
5085
|
|
|
|
|
|
|
if (likely(char_is_id_ascii(src[i]))) {} \ |
|
5086
|
|
|
|
|
|
|
else goto skip_ascii_stop##i; |
|
5087
|
|
|
|
|
|
|
|
|
5088
|
|
|
|
|
|
|
#define expr_stop(i) \ |
|
5089
|
|
|
|
|
|
|
skip_ascii_stop##i: \ |
|
5090
|
|
|
|
|
|
|
src += i; \ |
|
5091
|
|
|
|
|
|
|
goto skip_ascii_end; |
|
5092
|
|
|
|
|
|
|
|
|
5093
|
0
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5094
|
0
|
|
|
|
|
|
src += 16; |
|
5095
|
0
|
|
|
|
|
|
goto skip_ascii; |
|
5096
|
0
|
|
|
|
|
|
repeat16_incr(expr_stop) |
|
5097
|
|
|
|
|
|
|
|
|
5098
|
|
|
|
|
|
|
#undef expr_jump |
|
5099
|
|
|
|
|
|
|
#undef expr_stop |
|
5100
|
|
|
|
|
|
|
|
|
5101
|
0
|
|
|
|
|
|
skip_ascii_end: |
|
5102
|
0
|
|
|
|
|
|
gcc_store_barrier(*src); |
|
5103
|
0
|
0
|
|
|
|
|
if (likely(!char_is_id_next(*src))) { |
|
5104
|
0
|
|
|
|
|
|
return_suc(src, src); |
|
5105
|
|
|
|
|
|
|
} |
|
5106
|
|
|
|
|
|
|
|
|
5107
|
0
|
|
|
|
|
|
skip_utf8: |
|
5108
|
0
|
0
|
|
|
|
|
while (*src >= 0x80) { |
|
5109
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_WHITESPACE)) { |
|
5110
|
0
|
0
|
|
|
|
|
if (char_is_space_ext(*src) && ext_space_len(src)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5111
|
0
|
|
|
|
|
|
return_suc(src, src); |
|
5112
|
|
|
|
|
|
|
} |
|
5113
|
|
|
|
|
|
|
} |
|
5114
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
5115
|
0
|
0
|
|
|
|
|
if (is_utf8_seq2(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
5116
|
0
|
|
|
|
|
|
src += 2; |
|
5117
|
0
|
0
|
|
|
|
|
} else if (is_utf8_seq3(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5118
|
0
|
|
|
|
|
|
src += 3; |
|
5119
|
0
|
0
|
|
|
|
|
} else if (is_utf8_seq4(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5120
|
0
|
|
|
|
|
|
src += 4; |
|
5121
|
|
|
|
|
|
|
} else { |
|
5122
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UTF8_VALIDATION |
|
5123
|
0
|
0
|
|
|
|
|
if (!has_allow(INVALID_UNICODE)) return_err(src, MSG_ERR_UTF8); |
|
5124
|
|
|
|
|
|
|
#endif |
|
5125
|
0
|
|
|
|
|
|
src += 1; |
|
5126
|
|
|
|
|
|
|
} |
|
5127
|
|
|
|
|
|
|
} |
|
5128
|
0
|
0
|
|
|
|
|
if (char_is_id_ascii(*src)) goto skip_ascii; |
|
5129
|
|
|
|
|
|
|
|
|
5130
|
|
|
|
|
|
|
/* The escape character appears, we need to copy it. */ |
|
5131
|
0
|
|
|
|
|
|
dst = src; |
|
5132
|
0
|
|
|
|
|
|
copy_escape: |
|
5133
|
0
|
0
|
|
|
|
|
if (byte_match_2(src, "\\u")) { |
|
5134
|
0
|
0
|
|
|
|
|
if (!read_uni_esc(&src, &dst, msg)) return_err(src, *msg); |
|
5135
|
|
|
|
|
|
|
} else { |
|
5136
|
0
|
0
|
|
|
|
|
if (!char_is_id_next(*src)) return_suc(dst, src); |
|
5137
|
0
|
|
|
|
|
|
return_err(src, "unexpected character in key"); |
|
5138
|
|
|
|
|
|
|
} |
|
5139
|
|
|
|
|
|
|
|
|
5140
|
0
|
|
|
|
|
|
copy_ascii: |
|
5141
|
|
|
|
|
|
|
/* |
|
5142
|
|
|
|
|
|
|
Copy continuous ASCII, loop unrolling, same as the following code: |
|
5143
|
|
|
|
|
|
|
|
|
5144
|
|
|
|
|
|
|
while (true) repeat16({ |
|
5145
|
|
|
|
|
|
|
if (char_is_ascii_skip(*src)) *dst++ = *src++; |
|
5146
|
|
|
|
|
|
|
else break; |
|
5147
|
|
|
|
|
|
|
}) |
|
5148
|
|
|
|
|
|
|
*/ |
|
5149
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
5150
|
|
|
|
|
|
|
if (likely((char_is_id_ascii(src[i])))) {} \ |
|
5151
|
|
|
|
|
|
|
else { gcc_store_barrier(src[i]); goto copy_ascii_stop_##i; } |
|
5152
|
0
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5153
|
|
|
|
|
|
|
#undef expr_jump |
|
5154
|
|
|
|
|
|
|
|
|
5155
|
0
|
|
|
|
|
|
byte_move_16(dst, src); |
|
5156
|
0
|
|
|
|
|
|
dst += 16; src += 16; |
|
5157
|
0
|
|
|
|
|
|
goto copy_ascii; |
|
5158
|
|
|
|
|
|
|
|
|
5159
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
5160
|
|
|
|
|
|
|
copy_ascii_stop_##i: \ |
|
5161
|
|
|
|
|
|
|
byte_move_forward(dst, src, i); \ |
|
5162
|
|
|
|
|
|
|
dst += i; src += i; \ |
|
5163
|
|
|
|
|
|
|
goto copy_utf8; |
|
5164
|
0
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5165
|
|
|
|
|
|
|
#undef expr_jump |
|
5166
|
|
|
|
|
|
|
|
|
5167
|
0
|
|
|
|
|
|
copy_utf8: |
|
5168
|
0
|
0
|
|
|
|
|
while (*src >= 0x80) { /* non-ASCII character */ |
|
5169
|
0
|
0
|
|
|
|
|
if (has_allow(EXT_WHITESPACE)) { |
|
5170
|
0
|
0
|
|
|
|
|
if (char_is_space_ext(*src) && ext_space_len(src)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5171
|
0
|
|
|
|
|
|
return_suc(dst, src); |
|
5172
|
|
|
|
|
|
|
} |
|
5173
|
|
|
|
|
|
|
} |
|
5174
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
5175
|
0
|
0
|
|
|
|
|
if (is_utf8_seq2(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
5176
|
0
|
|
|
|
|
|
byte_copy_2(dst, &uni); |
|
5177
|
0
|
|
|
|
|
|
dst += 2; src += 2; |
|
5178
|
0
|
0
|
|
|
|
|
} else if (is_utf8_seq3(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5179
|
0
|
|
|
|
|
|
byte_copy_4(dst, &uni); |
|
5180
|
0
|
|
|
|
|
|
dst += 3; src += 3; |
|
5181
|
0
|
0
|
|
|
|
|
} else if (is_utf8_seq4(uni)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5182
|
0
|
|
|
|
|
|
byte_copy_4(dst, &uni); |
|
5183
|
0
|
|
|
|
|
|
dst += 4; src += 4; |
|
5184
|
|
|
|
|
|
|
} else { |
|
5185
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UTF8_VALIDATION |
|
5186
|
0
|
0
|
|
|
|
|
if (!has_allow(INVALID_UNICODE)) return_err(src, MSG_ERR_UTF8); |
|
5187
|
|
|
|
|
|
|
#endif |
|
5188
|
0
|
|
|
|
|
|
*dst = *src; |
|
5189
|
0
|
|
|
|
|
|
dst += 1; src += 1; |
|
5190
|
|
|
|
|
|
|
} |
|
5191
|
|
|
|
|
|
|
} |
|
5192
|
0
|
0
|
|
|
|
|
if (char_is_id_ascii(*src)) goto copy_ascii; |
|
5193
|
0
|
|
|
|
|
|
goto copy_escape; |
|
5194
|
|
|
|
|
|
|
|
|
5195
|
|
|
|
|
|
|
#undef return_err |
|
5196
|
|
|
|
|
|
|
#undef return_suc |
|
5197
|
|
|
|
|
|
|
} |
|
5198
|
|
|
|
|
|
|
|
|
5199
|
|
|
|
|
|
|
|
|
5200
|
|
|
|
|
|
|
|
|
5201
|
|
|
|
|
|
|
/*============================================================================== |
|
5202
|
|
|
|
|
|
|
* MARK: - JSON Reader Implementation (Private) |
|
5203
|
|
|
|
|
|
|
* |
|
5204
|
|
|
|
|
|
|
* We use goto statements to build the finite state machine (FSM). |
|
5205
|
|
|
|
|
|
|
* The FSM's state was held by program counter (PC) and the 'goto' make the |
|
5206
|
|
|
|
|
|
|
* state transitions. |
|
5207
|
|
|
|
|
|
|
*============================================================================*/ |
|
5208
|
|
|
|
|
|
|
|
|
5209
|
|
|
|
|
|
|
/** Read single value JSON document. */ |
|
5210
|
14
|
|
|
|
|
|
static_noinline yyjson_doc *read_root_single(u8 *hdr, u8 *cur, u8 *eof, |
|
5211
|
|
|
|
|
|
|
yyjson_alc alc, |
|
5212
|
|
|
|
|
|
|
yyjson_read_flag flg, |
|
5213
|
|
|
|
|
|
|
yyjson_read_err *err) { |
|
5214
|
|
|
|
|
|
|
#define return_err(_pos, _code, _msg) do { \ |
|
5215
|
|
|
|
|
|
|
if (is_truncated_end(hdr, _pos, eof, YYJSON_READ_ERROR_##_code, flg)) { \ |
|
5216
|
|
|
|
|
|
|
err->pos = (usize)(eof - hdr); \ |
|
5217
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ |
|
5218
|
|
|
|
|
|
|
err->msg = MSG_NOT_END; \ |
|
5219
|
|
|
|
|
|
|
} else { \ |
|
5220
|
|
|
|
|
|
|
err->pos = (usize)(_pos - hdr); \ |
|
5221
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_##_code; \ |
|
5222
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
5223
|
|
|
|
|
|
|
} \ |
|
5224
|
|
|
|
|
|
|
if (val_hdr) alc.free(alc.ctx, val_hdr); \ |
|
5225
|
|
|
|
|
|
|
return NULL; \ |
|
5226
|
|
|
|
|
|
|
} while (false) |
|
5227
|
|
|
|
|
|
|
|
|
5228
|
|
|
|
|
|
|
usize hdr_len; /* value count used by doc */ |
|
5229
|
|
|
|
|
|
|
usize alc_num; /* value count capacity */ |
|
5230
|
|
|
|
|
|
|
yyjson_val *val_hdr; /* the head of allocated values */ |
|
5231
|
|
|
|
|
|
|
yyjson_val *val; /* current value */ |
|
5232
|
|
|
|
|
|
|
yyjson_doc *doc; /* the JSON document, equals to val_hdr */ |
|
5233
|
|
|
|
|
|
|
const char *msg; /* error message */ |
|
5234
|
|
|
|
|
|
|
|
|
5235
|
|
|
|
|
|
|
u8 raw_end[1]; /* raw end for null-terminator */ |
|
5236
|
14
|
|
|
|
|
|
u8 *raw_ptr = raw_end; |
|
5237
|
14
|
|
|
|
|
|
u8 **pre = &raw_ptr; /* previous raw end pointer */ |
|
5238
|
|
|
|
|
|
|
|
|
5239
|
14
|
|
|
|
|
|
hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); |
|
5240
|
14
|
|
|
|
|
|
hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; |
|
5241
|
14
|
|
|
|
|
|
alc_num = hdr_len + 1; /* single value */ |
|
5242
|
|
|
|
|
|
|
|
|
5243
|
14
|
|
|
|
|
|
val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_num * sizeof(yyjson_val)); |
|
5244
|
14
|
50
|
|
|
|
|
if (unlikely(!val_hdr)) goto fail_alloc; |
|
5245
|
14
|
|
|
|
|
|
val = val_hdr + hdr_len; |
|
5246
|
|
|
|
|
|
|
|
|
5247
|
28
|
100
|
|
|
|
|
if (char_is_num(*cur)) { |
|
5248
|
4
|
50
|
|
|
|
|
if (likely(read_num(&cur, pre, flg, val, &msg))) goto doc_end; |
|
5249
|
0
|
|
|
|
|
|
goto fail_number; |
|
5250
|
|
|
|
|
|
|
} |
|
5251
|
10
|
100
|
|
|
|
|
if (*cur == '"') { |
|
5252
|
2
|
50
|
|
|
|
|
if (likely(read_str(&cur, eof, flg, val, &msg))) goto doc_end; |
|
5253
|
0
|
|
|
|
|
|
goto fail_string; |
|
5254
|
|
|
|
|
|
|
} |
|
5255
|
8
|
100
|
|
|
|
|
if (*cur == 't') { |
|
5256
|
2
|
50
|
|
|
|
|
if (likely(read_true(&cur, val))) goto doc_end; |
|
5257
|
0
|
|
|
|
|
|
goto fail_literal_true; |
|
5258
|
|
|
|
|
|
|
} |
|
5259
|
6
|
100
|
|
|
|
|
if (*cur == 'f') { |
|
5260
|
1
|
50
|
|
|
|
|
if (likely(read_false(&cur, val))) goto doc_end; |
|
5261
|
0
|
|
|
|
|
|
goto fail_literal_false; |
|
5262
|
|
|
|
|
|
|
} |
|
5263
|
5
|
100
|
|
|
|
|
if (*cur == 'n') { |
|
5264
|
4
|
100
|
|
|
|
|
if (likely(read_null(&cur, val))) goto doc_end; |
|
5265
|
6
|
50
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
5266
|
0
|
0
|
|
|
|
|
if (read_nan(&cur, pre, flg, val)) goto doc_end; |
|
5267
|
|
|
|
|
|
|
} |
|
5268
|
3
|
|
|
|
|
|
goto fail_literal_null; |
|
5269
|
|
|
|
|
|
|
} |
|
5270
|
2
|
50
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
5271
|
0
|
0
|
|
|
|
|
if (read_inf_or_nan(&cur, pre, flg, val)) goto doc_end; |
|
5272
|
|
|
|
|
|
|
} |
|
5273
|
2
|
50
|
|
|
|
|
if (has_allow(SINGLE_QUOTED_STR) && *cur == '\'') { |
|
|
|
0
|
|
|
|
|
|
|
5274
|
0
|
0
|
|
|
|
|
if (likely(read_str_sq(&cur, eof, flg, val, &msg))) goto doc_end; |
|
5275
|
0
|
|
|
|
|
|
goto fail_string; |
|
5276
|
|
|
|
|
|
|
} |
|
5277
|
1
|
|
|
|
|
|
goto fail_character; |
|
5278
|
|
|
|
|
|
|
|
|
5279
|
10
|
|
|
|
|
|
doc_end: |
|
5280
|
|
|
|
|
|
|
/* check invalid contents after json document */ |
|
5281
|
10
|
50
|
|
|
|
|
if (unlikely(cur < eof) && !has_flg(STOP_WHEN_DONE)) { |
|
|
|
0
|
|
|
|
|
|
|
5282
|
0
|
0
|
|
|
|
|
while (char_is_space(*cur)) cur++; |
|
5283
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5284
|
0
|
0
|
|
|
|
|
if (!skip_trivia(&cur, eof, flg) && cur == eof) { |
|
|
|
0
|
|
|
|
|
|
|
5285
|
0
|
|
|
|
|
|
goto fail_comment; |
|
5286
|
|
|
|
|
|
|
} |
|
5287
|
|
|
|
|
|
|
} |
|
5288
|
0
|
0
|
|
|
|
|
if (unlikely(cur < eof)) goto fail_garbage; |
|
5289
|
|
|
|
|
|
|
} |
|
5290
|
|
|
|
|
|
|
|
|
5291
|
10
|
|
|
|
|
|
**pre = '\0'; |
|
5292
|
10
|
|
|
|
|
|
doc = (yyjson_doc *)val_hdr; |
|
5293
|
10
|
|
|
|
|
|
doc->root = val_hdr + hdr_len; |
|
5294
|
10
|
|
|
|
|
|
doc->alc = alc; |
|
5295
|
10
|
|
|
|
|
|
doc->dat_read = (usize)(cur - hdr); |
|
5296
|
10
|
|
|
|
|
|
doc->val_read = 1; |
|
5297
|
20
|
50
|
|
|
|
|
doc->str_pool = has_flg(INSITU) ? NULL : (char *)hdr; |
|
5298
|
10
|
|
|
|
|
|
return doc; |
|
5299
|
|
|
|
|
|
|
|
|
5300
|
0
|
0
|
|
|
|
|
fail_string: return_err(cur, INVALID_STRING, msg); |
|
|
|
0
|
|
|
|
|
|
|
5301
|
0
|
0
|
|
|
|
|
fail_number: return_err(cur, INVALID_NUMBER, msg); |
|
|
|
0
|
|
|
|
|
|
|
5302
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(cur, MEMORY_ALLOCATION, MSG_MALLOC); |
|
|
|
0
|
|
|
|
|
|
|
5303
|
0
|
0
|
|
|
|
|
fail_literal_true: return_err(cur, LITERAL, MSG_CHAR_T); |
|
|
|
0
|
|
|
|
|
|
|
5304
|
0
|
0
|
|
|
|
|
fail_literal_false: return_err(cur, LITERAL, MSG_CHAR_F); |
|
|
|
0
|
|
|
|
|
|
|
5305
|
3
|
50
|
|
|
|
|
fail_literal_null: return_err(cur, LITERAL, MSG_CHAR_N); |
|
|
|
50
|
|
|
|
|
|
|
5306
|
1
|
50
|
|
|
|
|
fail_character: return_err(cur, UNEXPECTED_CHARACTER, MSG_CHAR); |
|
|
|
50
|
|
|
|
|
|
|
5307
|
0
|
0
|
|
|
|
|
fail_comment: return_err(cur, INVALID_COMMENT, MSG_COMMENT); |
|
|
|
0
|
|
|
|
|
|
|
5308
|
0
|
0
|
|
|
|
|
fail_garbage: return_err(cur, UNEXPECTED_CONTENT, MSG_GARBAGE); |
|
|
|
0
|
|
|
|
|
|
|
5309
|
|
|
|
|
|
|
|
|
5310
|
|
|
|
|
|
|
#undef return_err |
|
5311
|
|
|
|
|
|
|
} |
|
5312
|
|
|
|
|
|
|
|
|
5313
|
|
|
|
|
|
|
/** Read JSON document (accept all style, but optimized for minify). */ |
|
5314
|
|
|
|
|
|
|
static_inline yyjson_doc *read_root_minify(u8 *hdr, u8 *cur, u8 *eof, |
|
5315
|
|
|
|
|
|
|
yyjson_alc alc, |
|
5316
|
|
|
|
|
|
|
yyjson_read_flag flg, |
|
5317
|
|
|
|
|
|
|
yyjson_read_err *err) { |
|
5318
|
|
|
|
|
|
|
#define return_err(_pos, _code, _msg) do { \ |
|
5319
|
|
|
|
|
|
|
if (is_truncated_end(hdr, _pos, eof, YYJSON_READ_ERROR_##_code, flg)) { \ |
|
5320
|
|
|
|
|
|
|
err->pos = (usize)(eof - hdr); \ |
|
5321
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ |
|
5322
|
|
|
|
|
|
|
err->msg = MSG_NOT_END; \ |
|
5323
|
|
|
|
|
|
|
} else { \ |
|
5324
|
|
|
|
|
|
|
err->pos = (usize)(_pos - hdr); \ |
|
5325
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_##_code; \ |
|
5326
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
5327
|
|
|
|
|
|
|
} \ |
|
5328
|
|
|
|
|
|
|
if (val_hdr) alc.free(alc.ctx, val_hdr); \ |
|
5329
|
|
|
|
|
|
|
return NULL; \ |
|
5330
|
|
|
|
|
|
|
} while (false) |
|
5331
|
|
|
|
|
|
|
|
|
5332
|
|
|
|
|
|
|
#define val_incr() do { \ |
|
5333
|
|
|
|
|
|
|
val++; \ |
|
5334
|
|
|
|
|
|
|
if (unlikely(val >= val_end)) { \ |
|
5335
|
|
|
|
|
|
|
usize alc_old = alc_len; \ |
|
5336
|
|
|
|
|
|
|
usize val_ofs = (usize)(val - val_hdr); \ |
|
5337
|
|
|
|
|
|
|
usize ctn_ofs = (usize)(ctn - val_hdr); \ |
|
5338
|
|
|
|
|
|
|
alc_len += alc_len / 2; \ |
|
5339
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && (alc_len >= alc_max)) goto fail_alloc; \ |
|
5340
|
|
|
|
|
|
|
val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ |
|
5341
|
|
|
|
|
|
|
alc_old * sizeof(yyjson_val), \ |
|
5342
|
|
|
|
|
|
|
alc_len * sizeof(yyjson_val)); \ |
|
5343
|
|
|
|
|
|
|
if ((!val_tmp)) goto fail_alloc; \ |
|
5344
|
|
|
|
|
|
|
val = val_tmp + val_ofs; \ |
|
5345
|
|
|
|
|
|
|
ctn = val_tmp + ctn_ofs; \ |
|
5346
|
|
|
|
|
|
|
val_hdr = val_tmp; \ |
|
5347
|
|
|
|
|
|
|
val_end = val_tmp + (alc_len - 2); \ |
|
5348
|
|
|
|
|
|
|
} \ |
|
5349
|
|
|
|
|
|
|
} while (false) |
|
5350
|
|
|
|
|
|
|
|
|
5351
|
|
|
|
|
|
|
usize dat_len; /* data length in bytes, hint for allocator */ |
|
5352
|
|
|
|
|
|
|
usize hdr_len; /* value count used by yyjson_doc */ |
|
5353
|
|
|
|
|
|
|
usize alc_len; /* value count allocated */ |
|
5354
|
|
|
|
|
|
|
usize alc_max; /* maximum value count for allocator */ |
|
5355
|
|
|
|
|
|
|
usize ctn_len; /* the number of elements in current container */ |
|
5356
|
|
|
|
|
|
|
yyjson_val *val_hdr; /* the head of allocated values */ |
|
5357
|
|
|
|
|
|
|
yyjson_val *val_end; /* the end of allocated values */ |
|
5358
|
|
|
|
|
|
|
yyjson_val *val_tmp; /* temporary pointer for realloc */ |
|
5359
|
|
|
|
|
|
|
yyjson_val *val; /* current JSON value */ |
|
5360
|
|
|
|
|
|
|
yyjson_val *ctn; /* current container */ |
|
5361
|
|
|
|
|
|
|
yyjson_val *ctn_parent; /* parent of current container */ |
|
5362
|
|
|
|
|
|
|
yyjson_doc *doc; /* the JSON document, equals to val_hdr */ |
|
5363
|
|
|
|
|
|
|
const char *msg; /* error message */ |
|
5364
|
|
|
|
|
|
|
|
|
5365
|
|
|
|
|
|
|
u8 raw_end[1]; /* raw end for null-terminator */ |
|
5366
|
10101
|
|
|
|
|
|
u8 *raw_ptr = raw_end; |
|
5367
|
10101
|
|
|
|
|
|
u8 **pre = &raw_ptr; /* previous raw end pointer */ |
|
5368
|
|
|
|
|
|
|
|
|
5369
|
10101
|
50
|
|
|
|
|
dat_len = has_flg(STOP_WHEN_DONE) ? 256 : (usize)(eof - cur); |
|
5370
|
10101
|
|
|
|
|
|
hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); |
|
5371
|
10101
|
|
|
|
|
|
hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; |
|
5372
|
10101
|
|
|
|
|
|
alc_max = USIZE_MAX / sizeof(yyjson_val); |
|
5373
|
10101
|
|
|
|
|
|
alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_MINIFY_RATIO) + 4; |
|
5374
|
10101
|
|
|
|
|
|
alc_len = yyjson_min(alc_len, alc_max); |
|
5375
|
|
|
|
|
|
|
|
|
5376
|
10101
|
|
|
|
|
|
val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val)); |
|
5377
|
10101
|
50
|
|
|
|
|
if (unlikely(!val_hdr)) goto fail_alloc; |
|
5378
|
10101
|
|
|
|
|
|
val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */ |
|
5379
|
10101
|
|
|
|
|
|
val = val_hdr + hdr_len; |
|
5380
|
10101
|
|
|
|
|
|
ctn = val; |
|
5381
|
10101
|
|
|
|
|
|
ctn_len = 0; |
|
5382
|
|
|
|
|
|
|
|
|
5383
|
10101
|
100
|
|
|
|
|
if (*cur++ == '{') { |
|
5384
|
10077
|
|
|
|
|
|
ctn->tag = YYJSON_TYPE_OBJ; |
|
5385
|
10077
|
|
|
|
|
|
ctn->uni.ofs = 0; |
|
5386
|
10077
|
|
|
|
|
|
goto obj_key_begin; |
|
5387
|
|
|
|
|
|
|
} else { |
|
5388
|
24
|
|
|
|
|
|
ctn->tag = YYJSON_TYPE_ARR; |
|
5389
|
24
|
|
|
|
|
|
ctn->uni.ofs = 0; |
|
5390
|
24
|
|
|
|
|
|
goto arr_val_begin; |
|
5391
|
|
|
|
|
|
|
} |
|
5392
|
|
|
|
|
|
|
|
|
5393
|
226
|
|
|
|
|
|
arr_begin: |
|
5394
|
|
|
|
|
|
|
/* save current container */ |
|
5395
|
226
|
|
|
|
|
|
ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | |
|
5396
|
226
|
|
|
|
|
|
(ctn->tag & YYJSON_TAG_MASK); |
|
5397
|
|
|
|
|
|
|
|
|
5398
|
|
|
|
|
|
|
/* create a new array value, save parent container offset */ |
|
5399
|
226
|
100
|
|
|
|
|
val_incr(); |
|
|
|
50
|
|
|
|
|
|
|
5400
|
226
|
|
|
|
|
|
val->tag = YYJSON_TYPE_ARR; |
|
5401
|
226
|
|
|
|
|
|
val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); |
|
5402
|
|
|
|
|
|
|
|
|
5403
|
|
|
|
|
|
|
/* push the new array value as current container */ |
|
5404
|
226
|
|
|
|
|
|
ctn = val; |
|
5405
|
226
|
|
|
|
|
|
ctn_len = 0; |
|
5406
|
|
|
|
|
|
|
|
|
5407
|
0
|
|
|
|
|
|
arr_val_begin: |
|
5408
|
22300
|
100
|
|
|
|
|
if (*cur == '{') { |
|
5409
|
2015
|
|
|
|
|
|
cur++; |
|
5410
|
2015
|
|
|
|
|
|
goto obj_begin; |
|
5411
|
|
|
|
|
|
|
} |
|
5412
|
20285
|
100
|
|
|
|
|
if (*cur == '[') { |
|
5413
|
201
|
|
|
|
|
|
cur++; |
|
5414
|
201
|
|
|
|
|
|
goto arr_begin; |
|
5415
|
|
|
|
|
|
|
} |
|
5416
|
40168
|
100
|
|
|
|
|
if (char_is_num(*cur)) { |
|
5417
|
20067
|
100
|
|
|
|
|
val_incr(); |
|
|
|
50
|
|
|
|
|
|
|
5418
|
20067
|
|
|
|
|
|
ctn_len++; |
|
5419
|
20067
|
50
|
|
|
|
|
if (likely(read_num(&cur, pre, flg, val, &msg))) goto arr_val_end; |
|
5420
|
0
|
|
|
|
|
|
goto fail_number; |
|
5421
|
|
|
|
|
|
|
} |
|
5422
|
17
|
100
|
|
|
|
|
if (*cur == '"') { |
|
5423
|
7
|
50
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5424
|
7
|
50
|
|
|
|
|
ctn_len++; |
|
5425
|
7
|
50
|
|
|
|
|
if (likely(read_str(&cur, eof, flg, val, &msg))) goto arr_val_end; |
|
5426
|
0
|
|
|
|
|
|
goto fail_string; |
|
5427
|
|
|
|
|
|
|
} |
|
5428
|
10
|
100
|
|
|
|
|
if (*cur == 't') { |
|
5429
|
2
|
100
|
|
|
|
|
val_incr(); |
|
|
|
50
|
|
|
|
|
|
|
5430
|
2
|
|
|
|
|
|
ctn_len++; |
|
5431
|
2
|
50
|
|
|
|
|
if (likely(read_true(&cur, val))) goto arr_val_end; |
|
5432
|
0
|
|
|
|
|
|
goto fail_literal_true; |
|
5433
|
|
|
|
|
|
|
} |
|
5434
|
8
|
100
|
|
|
|
|
if (*cur == 'f') { |
|
5435
|
1
|
50
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5436
|
1
|
|
|
|
|
|
ctn_len++; |
|
5437
|
1
|
50
|
|
|
|
|
if (likely(read_false(&cur, val))) goto arr_val_end; |
|
5438
|
0
|
|
|
|
|
|
goto fail_literal_false; |
|
5439
|
|
|
|
|
|
|
} |
|
5440
|
7
|
100
|
|
|
|
|
if (*cur == 'n') { |
|
5441
|
3
|
100
|
|
|
|
|
val_incr(); |
|
|
|
50
|
|
|
|
|
|
|
5442
|
3
|
|
|
|
|
|
ctn_len++; |
|
5443
|
3
|
50
|
|
|
|
|
if (likely(read_null(&cur, val))) goto arr_val_end; |
|
5444
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
5445
|
0
|
0
|
|
|
|
|
if (read_nan(&cur, pre, flg, val)) goto arr_val_end; |
|
5446
|
|
|
|
|
|
|
} |
|
5447
|
0
|
|
|
|
|
|
goto fail_literal_null; |
|
5448
|
|
|
|
|
|
|
} |
|
5449
|
4
|
50
|
|
|
|
|
if (*cur == ']') { |
|
5450
|
4
|
|
|
|
|
|
cur++; |
|
5451
|
4
|
50
|
|
|
|
|
if (likely(ctn_len == 0)) goto arr_end; |
|
5452
|
0
|
0
|
|
|
|
|
if (has_allow(TRAILING_COMMAS)) goto arr_end; |
|
5453
|
0
|
0
|
|
|
|
|
while (*cur != ',') cur--; |
|
5454
|
0
|
|
|
|
|
|
goto fail_trailing_comma; |
|
5455
|
|
|
|
|
|
|
} |
|
5456
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5457
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5458
|
0
|
|
|
|
|
|
goto arr_val_begin; |
|
5459
|
|
|
|
|
|
|
} |
|
5460
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN) && |
|
5461
|
0
|
0
|
|
|
|
|
(*cur == 'i' || *cur == 'I' || *cur == 'N')) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5462
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5463
|
0
|
0
|
|
|
|
|
ctn_len++; |
|
5464
|
0
|
0
|
|
|
|
|
if (read_inf_or_nan(&cur, pre, flg, val)) goto arr_val_end; |
|
5465
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
5466
|
|
|
|
|
|
|
} |
|
5467
|
0
|
0
|
|
|
|
|
if (has_allow(SINGLE_QUOTED_STR) && *cur == '\'') { |
|
|
|
0
|
|
|
|
|
|
|
5468
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5469
|
0
|
|
|
|
|
|
ctn_len++; |
|
5470
|
0
|
0
|
|
|
|
|
if (likely(read_str_sq(&cur, eof, flg, val, &msg))) goto arr_val_end; |
|
5471
|
0
|
|
|
|
|
|
goto fail_string; |
|
5472
|
|
|
|
|
|
|
} |
|
5473
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5474
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto arr_val_begin; |
|
5475
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5476
|
|
|
|
|
|
|
} |
|
5477
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
5478
|
|
|
|
|
|
|
|
|
5479
|
0
|
|
|
|
|
|
arr_val_end: |
|
5480
|
22296
|
100
|
|
|
|
|
if (*cur == ',') { |
|
5481
|
22050
|
|
|
|
|
|
cur++; |
|
5482
|
22050
|
|
|
|
|
|
goto arr_val_begin; |
|
5483
|
|
|
|
|
|
|
} |
|
5484
|
246
|
50
|
|
|
|
|
if (*cur == ']') { |
|
5485
|
246
|
|
|
|
|
|
cur++; |
|
5486
|
246
|
|
|
|
|
|
goto arr_end; |
|
5487
|
|
|
|
|
|
|
} |
|
5488
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5489
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5490
|
0
|
|
|
|
|
|
goto arr_val_end; |
|
5491
|
|
|
|
|
|
|
} |
|
5492
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5493
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto arr_val_end; |
|
5494
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5495
|
|
|
|
|
|
|
} |
|
5496
|
0
|
|
|
|
|
|
goto fail_character_arr_end; |
|
5497
|
|
|
|
|
|
|
|
|
5498
|
250
|
|
|
|
|
|
arr_end: |
|
5499
|
|
|
|
|
|
|
/* get parent container */ |
|
5500
|
250
|
|
|
|
|
|
ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); |
|
5501
|
|
|
|
|
|
|
|
|
5502
|
|
|
|
|
|
|
/* save the next sibling value offset */ |
|
5503
|
250
|
|
|
|
|
|
ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); |
|
5504
|
250
|
|
|
|
|
|
ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; |
|
5505
|
250
|
100
|
|
|
|
|
if (unlikely(ctn == ctn_parent)) goto doc_end; |
|
5506
|
|
|
|
|
|
|
|
|
5507
|
|
|
|
|
|
|
/* pop parent as current container */ |
|
5508
|
226
|
|
|
|
|
|
ctn = ctn_parent; |
|
5509
|
226
|
|
|
|
|
|
ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); |
|
5510
|
226
|
100
|
|
|
|
|
if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { |
|
5511
|
25
|
|
|
|
|
|
goto obj_val_end; |
|
5512
|
|
|
|
|
|
|
} else { |
|
5513
|
201
|
|
|
|
|
|
goto arr_val_end; |
|
5514
|
|
|
|
|
|
|
} |
|
5515
|
|
|
|
|
|
|
|
|
5516
|
2034
|
|
|
|
|
|
obj_begin: |
|
5517
|
|
|
|
|
|
|
/* push container */ |
|
5518
|
2034
|
|
|
|
|
|
ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | |
|
5519
|
2034
|
|
|
|
|
|
(ctn->tag & YYJSON_TAG_MASK); |
|
5520
|
2034
|
100
|
|
|
|
|
val_incr(); |
|
|
|
50
|
|
|
|
|
|
|
5521
|
2034
|
|
|
|
|
|
val->tag = YYJSON_TYPE_OBJ; |
|
5522
|
|
|
|
|
|
|
/* offset to the parent */ |
|
5523
|
2034
|
|
|
|
|
|
val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); |
|
5524
|
2034
|
|
|
|
|
|
ctn = val; |
|
5525
|
2034
|
|
|
|
|
|
ctn_len = 0; |
|
5526
|
|
|
|
|
|
|
|
|
5527
|
0
|
|
|
|
|
|
obj_key_begin: |
|
5528
|
15175
|
100
|
|
|
|
|
if (likely(*cur == '"')) { |
|
5529
|
15169
|
100
|
|
|
|
|
val_incr(); |
|
|
|
50
|
|
|
|
|
|
|
5530
|
15169
|
50
|
|
|
|
|
ctn_len++; |
|
5531
|
15169
|
50
|
|
|
|
|
if (likely(read_str(&cur, eof, flg, val, &msg))) goto obj_key_end; |
|
5532
|
0
|
|
|
|
|
|
goto fail_string; |
|
5533
|
|
|
|
|
|
|
} |
|
5534
|
6
|
50
|
|
|
|
|
if (likely(*cur == '}')) { |
|
5535
|
6
|
|
|
|
|
|
cur++; |
|
5536
|
6
|
50
|
|
|
|
|
if (likely(ctn_len == 0)) goto obj_end; |
|
5537
|
0
|
0
|
|
|
|
|
if (has_allow(TRAILING_COMMAS)) goto obj_end; |
|
5538
|
0
|
0
|
|
|
|
|
while (*cur != ',') cur--; |
|
5539
|
0
|
|
|
|
|
|
goto fail_trailing_comma; |
|
5540
|
|
|
|
|
|
|
} |
|
5541
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5542
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5543
|
0
|
|
|
|
|
|
goto obj_key_begin; |
|
5544
|
|
|
|
|
|
|
} |
|
5545
|
0
|
0
|
|
|
|
|
if (has_allow(SINGLE_QUOTED_STR) && *cur == '\'') { |
|
|
|
0
|
|
|
|
|
|
|
5546
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5547
|
0
|
|
|
|
|
|
ctn_len++; |
|
5548
|
0
|
0
|
|
|
|
|
if (likely(read_str_sq(&cur, eof, flg, val, &msg))) goto obj_key_end; |
|
5549
|
0
|
|
|
|
|
|
goto fail_string; |
|
5550
|
|
|
|
|
|
|
} |
|
5551
|
0
|
0
|
|
|
|
|
if (has_allow(UNQUOTED_KEY) && char_is_id_start(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5552
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5553
|
0
|
|
|
|
|
|
ctn_len++; |
|
5554
|
0
|
0
|
|
|
|
|
if (read_str_id(&cur, eof, flg, pre, val, &msg)) goto obj_key_end; |
|
5555
|
0
|
|
|
|
|
|
goto fail_string; |
|
5556
|
|
|
|
|
|
|
} |
|
5557
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5558
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto obj_key_begin; |
|
5559
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5560
|
|
|
|
|
|
|
} |
|
5561
|
0
|
|
|
|
|
|
goto fail_character_obj_key; |
|
5562
|
|
|
|
|
|
|
|
|
5563
|
0
|
|
|
|
|
|
obj_key_end: |
|
5564
|
15169
|
50
|
|
|
|
|
if (*cur == ':') { |
|
5565
|
15169
|
|
|
|
|
|
cur++; |
|
5566
|
15169
|
|
|
|
|
|
goto obj_val_begin; |
|
5567
|
|
|
|
|
|
|
} |
|
5568
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5569
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5570
|
0
|
|
|
|
|
|
goto obj_key_end; |
|
5571
|
|
|
|
|
|
|
} |
|
5572
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5573
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto obj_key_end; |
|
5574
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5575
|
|
|
|
|
|
|
} |
|
5576
|
0
|
|
|
|
|
|
goto fail_character_obj_sep; |
|
5577
|
|
|
|
|
|
|
|
|
5578
|
0
|
|
|
|
|
|
obj_val_begin: |
|
5579
|
15169
|
100
|
|
|
|
|
if (*cur == '"') { |
|
5580
|
1039
|
|
|
|
|
|
val++; |
|
5581
|
1039
|
50
|
|
|
|
|
ctn_len++; |
|
5582
|
1039
|
50
|
|
|
|
|
if (likely(read_str(&cur, eof, flg, val, &msg))) goto obj_val_end; |
|
5583
|
0
|
|
|
|
|
|
goto fail_string; |
|
5584
|
|
|
|
|
|
|
} |
|
5585
|
28260
|
100
|
|
|
|
|
if (char_is_num(*cur)) { |
|
5586
|
14073
|
|
|
|
|
|
val++; |
|
5587
|
14073
|
|
|
|
|
|
ctn_len++; |
|
5588
|
14073
|
50
|
|
|
|
|
if (likely(read_num(&cur, pre, flg, val, &msg))) goto obj_val_end; |
|
5589
|
0
|
|
|
|
|
|
goto fail_number; |
|
5590
|
|
|
|
|
|
|
} |
|
5591
|
57
|
100
|
|
|
|
|
if (*cur == '{') { |
|
5592
|
19
|
|
|
|
|
|
cur++; |
|
5593
|
19
|
|
|
|
|
|
goto obj_begin; |
|
5594
|
|
|
|
|
|
|
} |
|
5595
|
38
|
100
|
|
|
|
|
if (*cur == '[') { |
|
5596
|
25
|
|
|
|
|
|
cur++; |
|
5597
|
25
|
|
|
|
|
|
goto arr_begin; |
|
5598
|
|
|
|
|
|
|
} |
|
5599
|
13
|
100
|
|
|
|
|
if (*cur == 't') { |
|
5600
|
7
|
|
|
|
|
|
val++; |
|
5601
|
7
|
|
|
|
|
|
ctn_len++; |
|
5602
|
7
|
50
|
|
|
|
|
if (likely(read_true(&cur, val))) goto obj_val_end; |
|
5603
|
0
|
|
|
|
|
|
goto fail_literal_true; |
|
5604
|
|
|
|
|
|
|
} |
|
5605
|
6
|
100
|
|
|
|
|
if (*cur == 'f') { |
|
5606
|
3
|
|
|
|
|
|
val++; |
|
5607
|
3
|
|
|
|
|
|
ctn_len++; |
|
5608
|
3
|
50
|
|
|
|
|
if (likely(read_false(&cur, val))) goto obj_val_end; |
|
5609
|
0
|
|
|
|
|
|
goto fail_literal_false; |
|
5610
|
|
|
|
|
|
|
} |
|
5611
|
3
|
50
|
|
|
|
|
if (*cur == 'n') { |
|
5612
|
3
|
|
|
|
|
|
val++; |
|
5613
|
3
|
|
|
|
|
|
ctn_len++; |
|
5614
|
3
|
50
|
|
|
|
|
if (likely(read_null(&cur, val))) goto obj_val_end; |
|
5615
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
5616
|
0
|
0
|
|
|
|
|
if (read_nan(&cur, pre, flg, val)) goto obj_val_end; |
|
5617
|
|
|
|
|
|
|
} |
|
5618
|
0
|
|
|
|
|
|
goto fail_literal_null; |
|
5619
|
|
|
|
|
|
|
} |
|
5620
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5621
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5622
|
0
|
|
|
|
|
|
goto obj_val_begin; |
|
5623
|
|
|
|
|
|
|
} |
|
5624
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN) && |
|
5625
|
0
|
0
|
|
|
|
|
(*cur == 'i' || *cur == 'I' || *cur == 'N')) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5626
|
0
|
|
|
|
|
|
val++; |
|
5627
|
0
|
0
|
|
|
|
|
ctn_len++; |
|
5628
|
0
|
0
|
|
|
|
|
if (read_inf_or_nan(&cur, pre, flg, val)) goto obj_val_end; |
|
5629
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
5630
|
|
|
|
|
|
|
} |
|
5631
|
0
|
0
|
|
|
|
|
if (has_allow(SINGLE_QUOTED_STR) && *cur == '\'') { |
|
|
|
0
|
|
|
|
|
|
|
5632
|
0
|
|
|
|
|
|
val++; |
|
5633
|
0
|
|
|
|
|
|
ctn_len++; |
|
5634
|
0
|
0
|
|
|
|
|
if (likely(read_str_sq(&cur, eof, flg, val, &msg))) goto obj_val_end; |
|
5635
|
0
|
|
|
|
|
|
goto fail_string; |
|
5636
|
|
|
|
|
|
|
} |
|
5637
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5638
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto obj_val_begin; |
|
5639
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5640
|
|
|
|
|
|
|
} |
|
5641
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
5642
|
|
|
|
|
|
|
|
|
5643
|
0
|
|
|
|
|
|
obj_val_end: |
|
5644
|
15169
|
100
|
|
|
|
|
if (likely(*cur == ',')) { |
|
5645
|
3064
|
|
|
|
|
|
cur++; |
|
5646
|
3064
|
|
|
|
|
|
goto obj_key_begin; |
|
5647
|
|
|
|
|
|
|
} |
|
5648
|
12105
|
50
|
|
|
|
|
if (likely(*cur == '}')) { |
|
5649
|
12105
|
|
|
|
|
|
cur++; |
|
5650
|
12105
|
|
|
|
|
|
goto obj_end; |
|
5651
|
|
|
|
|
|
|
} |
|
5652
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5653
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5654
|
0
|
|
|
|
|
|
goto obj_val_end; |
|
5655
|
|
|
|
|
|
|
} |
|
5656
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5657
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto obj_val_end; |
|
5658
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5659
|
|
|
|
|
|
|
} |
|
5660
|
0
|
|
|
|
|
|
goto fail_character_obj_end; |
|
5661
|
|
|
|
|
|
|
|
|
5662
|
12111
|
|
|
|
|
|
obj_end: |
|
5663
|
|
|
|
|
|
|
/* pop container */ |
|
5664
|
12111
|
|
|
|
|
|
ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); |
|
5665
|
|
|
|
|
|
|
/* point to the next value */ |
|
5666
|
12111
|
|
|
|
|
|
ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); |
|
5667
|
12111
|
|
|
|
|
|
ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ; |
|
5668
|
12111
|
100
|
|
|
|
|
if (unlikely(ctn == ctn_parent)) goto doc_end; |
|
5669
|
2034
|
|
|
|
|
|
ctn = ctn_parent; |
|
5670
|
2034
|
|
|
|
|
|
ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); |
|
5671
|
2034
|
100
|
|
|
|
|
if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { |
|
5672
|
19
|
|
|
|
|
|
goto obj_val_end; |
|
5673
|
|
|
|
|
|
|
} else { |
|
5674
|
2015
|
|
|
|
|
|
goto arr_val_end; |
|
5675
|
|
|
|
|
|
|
} |
|
5676
|
|
|
|
|
|
|
|
|
5677
|
10101
|
|
|
|
|
|
doc_end: |
|
5678
|
|
|
|
|
|
|
/* check invalid contents after json document */ |
|
5679
|
10101
|
50
|
|
|
|
|
if (unlikely(cur < eof) && !has_flg(STOP_WHEN_DONE)) { |
|
|
|
0
|
|
|
|
|
|
|
5680
|
0
|
0
|
|
|
|
|
while (char_is_space(*cur)) cur++; |
|
5681
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5682
|
0
|
0
|
|
|
|
|
if (!skip_trivia(&cur, eof, flg) && cur == eof) { |
|
|
|
0
|
|
|
|
|
|
|
5683
|
0
|
|
|
|
|
|
goto fail_comment; |
|
5684
|
|
|
|
|
|
|
} |
|
5685
|
|
|
|
|
|
|
} |
|
5686
|
0
|
0
|
|
|
|
|
if (unlikely(cur < eof)) goto fail_garbage; |
|
5687
|
|
|
|
|
|
|
} |
|
5688
|
|
|
|
|
|
|
|
|
5689
|
10101
|
|
|
|
|
|
**pre = '\0'; |
|
5690
|
10101
|
|
|
|
|
|
doc = (yyjson_doc *)val_hdr; |
|
5691
|
10101
|
|
|
|
|
|
doc->root = val_hdr + hdr_len; |
|
5692
|
10101
|
|
|
|
|
|
doc->alc = alc; |
|
5693
|
10101
|
|
|
|
|
|
doc->dat_read = (usize)(cur - hdr); |
|
5694
|
10101
|
|
|
|
|
|
doc->val_read = (usize)((val - doc->root) + 1); |
|
5695
|
20202
|
100
|
|
|
|
|
doc->str_pool = has_flg(INSITU) ? NULL : (char *)hdr; |
|
5696
|
10101
|
|
|
|
|
|
return doc; |
|
5697
|
|
|
|
|
|
|
|
|
5698
|
0
|
0
|
|
|
|
|
fail_string: return_err(cur, INVALID_STRING, msg); |
|
|
|
0
|
|
|
|
|
|
|
5699
|
0
|
0
|
|
|
|
|
fail_number: return_err(cur, INVALID_NUMBER, msg); |
|
|
|
0
|
|
|
|
|
|
|
5700
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(cur, MEMORY_ALLOCATION, MSG_MALLOC); |
|
|
|
0
|
|
|
|
|
|
|
5701
|
0
|
0
|
|
|
|
|
fail_trailing_comma: return_err(cur, JSON_STRUCTURE, MSG_COMMA); |
|
|
|
0
|
|
|
|
|
|
|
5702
|
0
|
0
|
|
|
|
|
fail_literal_true: return_err(cur, LITERAL, MSG_CHAR_T); |
|
|
|
0
|
|
|
|
|
|
|
5703
|
0
|
0
|
|
|
|
|
fail_literal_false: return_err(cur, LITERAL, MSG_CHAR_F); |
|
|
|
0
|
|
|
|
|
|
|
5704
|
0
|
0
|
|
|
|
|
fail_literal_null: return_err(cur, LITERAL, MSG_CHAR_N); |
|
|
|
0
|
|
|
|
|
|
|
5705
|
0
|
0
|
|
|
|
|
fail_character_val: return_err(cur, UNEXPECTED_CHARACTER, MSG_CHAR); |
|
|
|
0
|
|
|
|
|
|
|
5706
|
0
|
0
|
|
|
|
|
fail_character_arr_end: return_err(cur, UNEXPECTED_CHARACTER, MSG_ARR_END); |
|
|
|
0
|
|
|
|
|
|
|
5707
|
0
|
0
|
|
|
|
|
fail_character_obj_key: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_KEY); |
|
|
|
0
|
|
|
|
|
|
|
5708
|
0
|
0
|
|
|
|
|
fail_character_obj_sep: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_SEP); |
|
|
|
0
|
|
|
|
|
|
|
5709
|
0
|
0
|
|
|
|
|
fail_character_obj_end: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_END); |
|
|
|
0
|
|
|
|
|
|
|
5710
|
0
|
0
|
|
|
|
|
fail_comment: return_err(cur, INVALID_COMMENT, MSG_COMMENT); |
|
|
|
0
|
|
|
|
|
|
|
5711
|
0
|
0
|
|
|
|
|
fail_garbage: return_err(cur, UNEXPECTED_CONTENT, MSG_GARBAGE); |
|
|
|
0
|
|
|
|
|
|
|
5712
|
|
|
|
|
|
|
|
|
5713
|
|
|
|
|
|
|
#undef val_incr |
|
5714
|
|
|
|
|
|
|
#undef return_err |
|
5715
|
|
|
|
|
|
|
} |
|
5716
|
|
|
|
|
|
|
|
|
5717
|
|
|
|
|
|
|
/** Read JSON document (accept all style, but optimized for pretty). */ |
|
5718
|
|
|
|
|
|
|
static_inline yyjson_doc *read_root_pretty(u8 *hdr, u8 *cur, u8 *eof, |
|
5719
|
|
|
|
|
|
|
yyjson_alc alc, |
|
5720
|
|
|
|
|
|
|
yyjson_read_flag flg, |
|
5721
|
|
|
|
|
|
|
yyjson_read_err *err) { |
|
5722
|
|
|
|
|
|
|
#define return_err(_pos, _code, _msg) do { \ |
|
5723
|
|
|
|
|
|
|
if (is_truncated_end(hdr, _pos, eof, YYJSON_READ_ERROR_##_code, flg)) { \ |
|
5724
|
|
|
|
|
|
|
err->pos = (usize)(eof - hdr); \ |
|
5725
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ |
|
5726
|
|
|
|
|
|
|
err->msg = MSG_NOT_END; \ |
|
5727
|
|
|
|
|
|
|
} else { \ |
|
5728
|
|
|
|
|
|
|
err->pos = (usize)(_pos - hdr); \ |
|
5729
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_##_code; \ |
|
5730
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
5731
|
|
|
|
|
|
|
} \ |
|
5732
|
|
|
|
|
|
|
if (val_hdr) alc.free(alc.ctx, val_hdr); \ |
|
5733
|
|
|
|
|
|
|
return NULL; \ |
|
5734
|
|
|
|
|
|
|
} while (false) |
|
5735
|
|
|
|
|
|
|
|
|
5736
|
|
|
|
|
|
|
#define val_incr() do { \ |
|
5737
|
|
|
|
|
|
|
val++; \ |
|
5738
|
|
|
|
|
|
|
if (unlikely(val >= val_end)) { \ |
|
5739
|
|
|
|
|
|
|
usize alc_old = alc_len; \ |
|
5740
|
|
|
|
|
|
|
usize val_ofs = (usize)(val - val_hdr); \ |
|
5741
|
|
|
|
|
|
|
usize ctn_ofs = (usize)(ctn - val_hdr); \ |
|
5742
|
|
|
|
|
|
|
alc_len += alc_len / 2; \ |
|
5743
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && (alc_len >= alc_max)) goto fail_alloc; \ |
|
5744
|
|
|
|
|
|
|
val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ |
|
5745
|
|
|
|
|
|
|
alc_old * sizeof(yyjson_val), \ |
|
5746
|
|
|
|
|
|
|
alc_len * sizeof(yyjson_val)); \ |
|
5747
|
|
|
|
|
|
|
if ((!val_tmp)) goto fail_alloc; \ |
|
5748
|
|
|
|
|
|
|
val = val_tmp + val_ofs; \ |
|
5749
|
|
|
|
|
|
|
ctn = val_tmp + ctn_ofs; \ |
|
5750
|
|
|
|
|
|
|
val_hdr = val_tmp; \ |
|
5751
|
|
|
|
|
|
|
val_end = val_tmp + (alc_len - 2); \ |
|
5752
|
|
|
|
|
|
|
} \ |
|
5753
|
|
|
|
|
|
|
} while (false) |
|
5754
|
|
|
|
|
|
|
|
|
5755
|
|
|
|
|
|
|
usize dat_len; /* data length in bytes, hint for allocator */ |
|
5756
|
|
|
|
|
|
|
usize hdr_len; /* value count used by yyjson_doc */ |
|
5757
|
|
|
|
|
|
|
usize alc_len; /* value count allocated */ |
|
5758
|
|
|
|
|
|
|
usize alc_max; /* maximum value count for allocator */ |
|
5759
|
|
|
|
|
|
|
usize ctn_len; /* the number of elements in current container */ |
|
5760
|
|
|
|
|
|
|
yyjson_val *val_hdr; /* the head of allocated values */ |
|
5761
|
|
|
|
|
|
|
yyjson_val *val_end; /* the end of allocated values */ |
|
5762
|
|
|
|
|
|
|
yyjson_val *val_tmp; /* temporary pointer for realloc */ |
|
5763
|
|
|
|
|
|
|
yyjson_val *val; /* current JSON value */ |
|
5764
|
|
|
|
|
|
|
yyjson_val *ctn; /* current container */ |
|
5765
|
|
|
|
|
|
|
yyjson_val *ctn_parent; /* parent of current container */ |
|
5766
|
|
|
|
|
|
|
yyjson_doc *doc; /* the JSON document, equals to val_hdr */ |
|
5767
|
|
|
|
|
|
|
const char *msg; /* error message */ |
|
5768
|
|
|
|
|
|
|
|
|
5769
|
|
|
|
|
|
|
u8 raw_end[1]; /* raw end for null-terminator */ |
|
5770
|
3
|
|
|
|
|
|
u8 *raw_ptr = raw_end; |
|
5771
|
3
|
|
|
|
|
|
u8 **pre = &raw_ptr; /* previous raw end pointer */ |
|
5772
|
|
|
|
|
|
|
|
|
5773
|
3
|
50
|
|
|
|
|
dat_len = has_flg(STOP_WHEN_DONE) ? 256 : (usize)(eof - cur); |
|
5774
|
3
|
|
|
|
|
|
hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); |
|
5775
|
3
|
|
|
|
|
|
hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; |
|
5776
|
3
|
|
|
|
|
|
alc_max = USIZE_MAX / sizeof(yyjson_val); |
|
5777
|
3
|
|
|
|
|
|
alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_PRETTY_RATIO) + 4; |
|
5778
|
3
|
|
|
|
|
|
alc_len = yyjson_min(alc_len, alc_max); |
|
5779
|
|
|
|
|
|
|
|
|
5780
|
3
|
|
|
|
|
|
val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val)); |
|
5781
|
3
|
50
|
|
|
|
|
if (unlikely(!val_hdr)) goto fail_alloc; |
|
5782
|
3
|
|
|
|
|
|
val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */ |
|
5783
|
3
|
|
|
|
|
|
val = val_hdr + hdr_len; |
|
5784
|
3
|
|
|
|
|
|
ctn = val; |
|
5785
|
3
|
|
|
|
|
|
ctn_len = 0; |
|
5786
|
|
|
|
|
|
|
|
|
5787
|
3
|
100
|
|
|
|
|
if (*cur++ == '{') { |
|
5788
|
2
|
|
|
|
|
|
ctn->tag = YYJSON_TYPE_OBJ; |
|
5789
|
2
|
|
|
|
|
|
ctn->uni.ofs = 0; |
|
5790
|
2
|
50
|
|
|
|
|
if (*cur == '\n') cur++; |
|
5791
|
2
|
|
|
|
|
|
goto obj_key_begin; |
|
5792
|
|
|
|
|
|
|
} else { |
|
5793
|
1
|
|
|
|
|
|
ctn->tag = YYJSON_TYPE_ARR; |
|
5794
|
1
|
|
|
|
|
|
ctn->uni.ofs = 0; |
|
5795
|
1
|
50
|
|
|
|
|
if (*cur == '\n') cur++; |
|
5796
|
1
|
|
|
|
|
|
goto arr_val_begin; |
|
5797
|
|
|
|
|
|
|
} |
|
5798
|
|
|
|
|
|
|
|
|
5799
|
1
|
|
|
|
|
|
arr_begin: |
|
5800
|
|
|
|
|
|
|
/* save current container */ |
|
5801
|
1
|
|
|
|
|
|
ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | |
|
5802
|
1
|
|
|
|
|
|
(ctn->tag & YYJSON_TAG_MASK); |
|
5803
|
|
|
|
|
|
|
|
|
5804
|
|
|
|
|
|
|
/* create a new array value, save parent container offset */ |
|
5805
|
1
|
50
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5806
|
1
|
|
|
|
|
|
val->tag = YYJSON_TYPE_ARR; |
|
5807
|
1
|
|
|
|
|
|
val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); |
|
5808
|
|
|
|
|
|
|
|
|
5809
|
|
|
|
|
|
|
/* push the new array value as current container */ |
|
5810
|
1
|
|
|
|
|
|
ctn = val; |
|
5811
|
1
|
|
|
|
|
|
ctn_len = 0; |
|
5812
|
1
|
50
|
|
|
|
|
if (*cur == '\n') cur++; |
|
5813
|
|
|
|
|
|
|
|
|
5814
|
0
|
|
|
|
|
|
arr_val_begin: |
|
5815
|
|
|
|
|
|
|
#if YYJSON_IS_REAL_GCC |
|
5816
|
30
|
50
|
|
|
|
|
while (true) repeat16({ |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5817
|
|
|
|
|
|
|
if (byte_match_2(cur, " ")) cur += 2; |
|
5818
|
|
|
|
|
|
|
else break; |
|
5819
|
|
|
|
|
|
|
}) |
|
5820
|
|
|
|
|
|
|
#else |
|
5821
|
|
|
|
|
|
|
while (true) repeat16({ |
|
5822
|
|
|
|
|
|
|
if (likely(byte_match_2(cur, " "))) cur += 2; |
|
5823
|
|
|
|
|
|
|
else break; |
|
5824
|
|
|
|
|
|
|
}) |
|
5825
|
|
|
|
|
|
|
#endif |
|
5826
|
|
|
|
|
|
|
|
|
5827
|
5
|
100
|
|
|
|
|
if (*cur == '{') { |
|
5828
|
3
|
|
|
|
|
|
cur++; |
|
5829
|
3
|
|
|
|
|
|
goto obj_begin; |
|
5830
|
|
|
|
|
|
|
} |
|
5831
|
2
|
50
|
|
|
|
|
if (*cur == '[') { |
|
5832
|
0
|
|
|
|
|
|
cur++; |
|
5833
|
0
|
|
|
|
|
|
goto arr_begin; |
|
5834
|
|
|
|
|
|
|
} |
|
5835
|
4
|
50
|
|
|
|
|
if (char_is_num(*cur)) { |
|
5836
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5837
|
0
|
|
|
|
|
|
ctn_len++; |
|
5838
|
0
|
0
|
|
|
|
|
if (likely(read_num(&cur, pre, flg, val, &msg))) goto arr_val_end; |
|
5839
|
0
|
|
|
|
|
|
goto fail_number; |
|
5840
|
|
|
|
|
|
|
} |
|
5841
|
2
|
50
|
|
|
|
|
if (*cur == '"') { |
|
5842
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5843
|
0
|
0
|
|
|
|
|
ctn_len++; |
|
5844
|
0
|
0
|
|
|
|
|
if (likely(read_str(&cur, eof, flg, val, &msg))) goto arr_val_end; |
|
5845
|
0
|
|
|
|
|
|
goto fail_string; |
|
5846
|
|
|
|
|
|
|
} |
|
5847
|
2
|
100
|
|
|
|
|
if (*cur == 't') { |
|
5848
|
1
|
50
|
|
|
|
|
val_incr(); |
|
|
|
50
|
|
|
|
|
|
|
5849
|
1
|
|
|
|
|
|
ctn_len++; |
|
5850
|
1
|
50
|
|
|
|
|
if (likely(read_true(&cur, val))) goto arr_val_end; |
|
5851
|
0
|
|
|
|
|
|
goto fail_literal_true; |
|
5852
|
|
|
|
|
|
|
} |
|
5853
|
1
|
50
|
|
|
|
|
if (*cur == 'f') { |
|
5854
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5855
|
0
|
|
|
|
|
|
ctn_len++; |
|
5856
|
0
|
0
|
|
|
|
|
if (likely(read_false(&cur, val))) goto arr_val_end; |
|
5857
|
0
|
|
|
|
|
|
goto fail_literal_false; |
|
5858
|
|
|
|
|
|
|
} |
|
5859
|
1
|
50
|
|
|
|
|
if (*cur == 'n') { |
|
5860
|
1
|
50
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5861
|
1
|
|
|
|
|
|
ctn_len++; |
|
5862
|
1
|
50
|
|
|
|
|
if (likely(read_null(&cur, val))) goto arr_val_end; |
|
5863
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
5864
|
0
|
0
|
|
|
|
|
if (read_nan(&cur, pre, flg, val)) goto arr_val_end; |
|
5865
|
|
|
|
|
|
|
} |
|
5866
|
0
|
|
|
|
|
|
goto fail_literal_null; |
|
5867
|
|
|
|
|
|
|
} |
|
5868
|
0
|
0
|
|
|
|
|
if (*cur == ']') { |
|
5869
|
0
|
|
|
|
|
|
cur++; |
|
5870
|
0
|
0
|
|
|
|
|
if (likely(ctn_len == 0)) goto arr_end; |
|
5871
|
0
|
0
|
|
|
|
|
if (has_allow(TRAILING_COMMAS)) goto arr_end; |
|
5872
|
0
|
0
|
|
|
|
|
while (*cur != ',') cur--; |
|
5873
|
0
|
|
|
|
|
|
goto fail_trailing_comma; |
|
5874
|
|
|
|
|
|
|
} |
|
5875
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5876
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5877
|
0
|
|
|
|
|
|
goto arr_val_begin; |
|
5878
|
|
|
|
|
|
|
} |
|
5879
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN) && |
|
5880
|
0
|
0
|
|
|
|
|
(*cur == 'i' || *cur == 'I' || *cur == 'N')) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5881
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5882
|
0
|
0
|
|
|
|
|
ctn_len++; |
|
5883
|
0
|
0
|
|
|
|
|
if (read_inf_or_nan(&cur, pre, flg, val)) goto arr_val_end; |
|
5884
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
5885
|
|
|
|
|
|
|
} |
|
5886
|
0
|
0
|
|
|
|
|
if (has_allow(SINGLE_QUOTED_STR) && *cur == '\'') { |
|
|
|
0
|
|
|
|
|
|
|
5887
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5888
|
0
|
|
|
|
|
|
ctn_len++; |
|
5889
|
0
|
0
|
|
|
|
|
if (likely(read_str_sq(&cur, eof, flg, val, &msg))) goto arr_val_end; |
|
5890
|
0
|
|
|
|
|
|
goto fail_string; |
|
5891
|
|
|
|
|
|
|
} |
|
5892
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5893
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto arr_val_begin; |
|
5894
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5895
|
|
|
|
|
|
|
} |
|
5896
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
5897
|
|
|
|
|
|
|
|
|
5898
|
2
|
|
|
|
|
|
arr_val_end: |
|
5899
|
14
|
100
|
|
|
|
|
if (byte_match_2(cur, ",\n")) { |
|
5900
|
3
|
|
|
|
|
|
cur += 2; |
|
5901
|
3
|
|
|
|
|
|
goto arr_val_begin; |
|
5902
|
|
|
|
|
|
|
} |
|
5903
|
4
|
50
|
|
|
|
|
if (*cur == ',') { |
|
5904
|
0
|
|
|
|
|
|
cur++; |
|
5905
|
0
|
|
|
|
|
|
goto arr_val_begin; |
|
5906
|
|
|
|
|
|
|
} |
|
5907
|
4
|
100
|
|
|
|
|
if (*cur == ']') { |
|
5908
|
2
|
|
|
|
|
|
cur++; |
|
5909
|
2
|
|
|
|
|
|
goto arr_end; |
|
5910
|
|
|
|
|
|
|
} |
|
5911
|
4
|
50
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5912
|
11
|
100
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5913
|
2
|
|
|
|
|
|
goto arr_val_end; |
|
5914
|
|
|
|
|
|
|
} |
|
5915
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5916
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto arr_val_end; |
|
5917
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5918
|
|
|
|
|
|
|
} |
|
5919
|
0
|
|
|
|
|
|
goto fail_character_arr_end; |
|
5920
|
|
|
|
|
|
|
|
|
5921
|
2
|
|
|
|
|
|
arr_end: |
|
5922
|
|
|
|
|
|
|
/* get parent container */ |
|
5923
|
2
|
|
|
|
|
|
ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); |
|
5924
|
|
|
|
|
|
|
|
|
5925
|
|
|
|
|
|
|
/* save the next sibling value offset */ |
|
5926
|
2
|
|
|
|
|
|
ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); |
|
5927
|
2
|
|
|
|
|
|
ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; |
|
5928
|
2
|
100
|
|
|
|
|
if (unlikely(ctn == ctn_parent)) goto doc_end; |
|
5929
|
|
|
|
|
|
|
|
|
5930
|
|
|
|
|
|
|
/* pop parent as current container */ |
|
5931
|
1
|
|
|
|
|
|
ctn = ctn_parent; |
|
5932
|
1
|
|
|
|
|
|
ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); |
|
5933
|
1
|
50
|
|
|
|
|
if (*cur == '\n') cur++; |
|
5934
|
1
|
50
|
|
|
|
|
if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { |
|
5935
|
1
|
|
|
|
|
|
goto obj_val_end; |
|
5936
|
|
|
|
|
|
|
} else { |
|
5937
|
0
|
|
|
|
|
|
goto arr_val_end; |
|
5938
|
|
|
|
|
|
|
} |
|
5939
|
|
|
|
|
|
|
|
|
5940
|
3
|
|
|
|
|
|
obj_begin: |
|
5941
|
|
|
|
|
|
|
/* push container */ |
|
5942
|
3
|
|
|
|
|
|
ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | |
|
5943
|
3
|
|
|
|
|
|
(ctn->tag & YYJSON_TAG_MASK); |
|
5944
|
3
|
50
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5945
|
3
|
|
|
|
|
|
val->tag = YYJSON_TYPE_OBJ; |
|
5946
|
|
|
|
|
|
|
/* offset to the parent */ |
|
5947
|
3
|
|
|
|
|
|
val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); |
|
5948
|
3
|
|
|
|
|
|
ctn = val; |
|
5949
|
3
|
|
|
|
|
|
ctn_len = 0; |
|
5950
|
3
|
50
|
|
|
|
|
if (*cur == '\n') cur++; |
|
5951
|
|
|
|
|
|
|
|
|
5952
|
3
|
|
|
|
|
|
obj_key_begin: |
|
5953
|
|
|
|
|
|
|
#if YYJSON_IS_REAL_GCC |
|
5954
|
28
|
100
|
|
|
|
|
while (true) repeat16({ |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5955
|
|
|
|
|
|
|
if (byte_match_2(cur, " ")) cur += 2; |
|
5956
|
|
|
|
|
|
|
else break; |
|
5957
|
|
|
|
|
|
|
}) |
|
5958
|
|
|
|
|
|
|
#else |
|
5959
|
|
|
|
|
|
|
while (true) repeat16({ |
|
5960
|
|
|
|
|
|
|
if (likely(byte_match_2(cur, " "))) cur += 2; |
|
5961
|
|
|
|
|
|
|
else break; |
|
5962
|
|
|
|
|
|
|
}) |
|
5963
|
|
|
|
|
|
|
#endif |
|
5964
|
11
|
50
|
|
|
|
|
if (likely(*cur == '"')) { |
|
5965
|
11
|
100
|
|
|
|
|
val_incr(); |
|
|
|
50
|
|
|
|
|
|
|
5966
|
11
|
50
|
|
|
|
|
ctn_len++; |
|
5967
|
11
|
50
|
|
|
|
|
if (likely(read_str(&cur, eof, flg, val, &msg))) goto obj_key_end; |
|
5968
|
0
|
|
|
|
|
|
goto fail_string; |
|
5969
|
|
|
|
|
|
|
} |
|
5970
|
0
|
0
|
|
|
|
|
if (likely(*cur == '}')) { |
|
5971
|
0
|
|
|
|
|
|
cur++; |
|
5972
|
0
|
0
|
|
|
|
|
if (likely(ctn_len == 0)) goto obj_end; |
|
5973
|
0
|
0
|
|
|
|
|
if (has_allow(TRAILING_COMMAS)) goto obj_end; |
|
5974
|
0
|
0
|
|
|
|
|
while (*cur != ',') cur--; |
|
5975
|
0
|
|
|
|
|
|
goto fail_trailing_comma; |
|
5976
|
|
|
|
|
|
|
} |
|
5977
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
5978
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
5979
|
0
|
|
|
|
|
|
goto obj_key_begin; |
|
5980
|
|
|
|
|
|
|
} |
|
5981
|
0
|
0
|
|
|
|
|
if (has_allow(SINGLE_QUOTED_STR) && *cur == '\'') { |
|
|
|
0
|
|
|
|
|
|
|
5982
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5983
|
0
|
|
|
|
|
|
ctn_len++; |
|
5984
|
0
|
0
|
|
|
|
|
if (likely(read_str_sq(&cur, eof, flg, val, &msg))) goto obj_key_end; |
|
5985
|
0
|
|
|
|
|
|
goto fail_string; |
|
5986
|
|
|
|
|
|
|
} |
|
5987
|
0
|
0
|
|
|
|
|
if (has_allow(UNQUOTED_KEY) && char_is_id_start(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5988
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
5989
|
0
|
|
|
|
|
|
ctn_len++; |
|
5990
|
0
|
0
|
|
|
|
|
if (read_str_id(&cur, eof, flg, pre, val, &msg)) goto obj_key_end; |
|
5991
|
0
|
|
|
|
|
|
goto fail_string; |
|
5992
|
|
|
|
|
|
|
} |
|
5993
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
5994
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto obj_key_begin; |
|
5995
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
5996
|
|
|
|
|
|
|
} |
|
5997
|
0
|
|
|
|
|
|
goto fail_character_obj_key; |
|
5998
|
|
|
|
|
|
|
|
|
5999
|
0
|
|
|
|
|
|
obj_key_end: |
|
6000
|
22
|
100
|
|
|
|
|
if (byte_match_2(cur, ": ")) { |
|
6001
|
3
|
|
|
|
|
|
cur += 2; |
|
6002
|
3
|
|
|
|
|
|
goto obj_val_begin; |
|
6003
|
|
|
|
|
|
|
} |
|
6004
|
8
|
50
|
|
|
|
|
if (*cur == ':') { |
|
6005
|
8
|
|
|
|
|
|
cur++; |
|
6006
|
8
|
|
|
|
|
|
goto obj_val_begin; |
|
6007
|
|
|
|
|
|
|
} |
|
6008
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6009
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6010
|
0
|
|
|
|
|
|
goto obj_key_end; |
|
6011
|
|
|
|
|
|
|
} |
|
6012
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
6013
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto obj_key_end; |
|
6014
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
6015
|
|
|
|
|
|
|
} |
|
6016
|
0
|
|
|
|
|
|
goto fail_character_obj_sep; |
|
6017
|
|
|
|
|
|
|
|
|
6018
|
0
|
|
|
|
|
|
obj_val_begin: |
|
6019
|
11
|
100
|
|
|
|
|
if (*cur == '"') { |
|
6020
|
6
|
|
|
|
|
|
val++; |
|
6021
|
6
|
50
|
|
|
|
|
ctn_len++; |
|
6022
|
6
|
50
|
|
|
|
|
if (likely(read_str(&cur, eof, flg, val, &msg))) goto obj_val_end; |
|
6023
|
0
|
|
|
|
|
|
goto fail_string; |
|
6024
|
|
|
|
|
|
|
} |
|
6025
|
10
|
100
|
|
|
|
|
if (char_is_num(*cur)) { |
|
6026
|
4
|
|
|
|
|
|
val++; |
|
6027
|
4
|
|
|
|
|
|
ctn_len++; |
|
6028
|
4
|
50
|
|
|
|
|
if (likely(read_num(&cur, pre, flg, val, &msg))) goto obj_val_end; |
|
6029
|
0
|
|
|
|
|
|
goto fail_number; |
|
6030
|
|
|
|
|
|
|
} |
|
6031
|
1
|
50
|
|
|
|
|
if (*cur == '{') { |
|
6032
|
0
|
|
|
|
|
|
cur++; |
|
6033
|
0
|
|
|
|
|
|
goto obj_begin; |
|
6034
|
|
|
|
|
|
|
} |
|
6035
|
1
|
50
|
|
|
|
|
if (*cur == '[') { |
|
6036
|
1
|
|
|
|
|
|
cur++; |
|
6037
|
1
|
|
|
|
|
|
goto arr_begin; |
|
6038
|
|
|
|
|
|
|
} |
|
6039
|
0
|
0
|
|
|
|
|
if (*cur == 't') { |
|
6040
|
0
|
|
|
|
|
|
val++; |
|
6041
|
0
|
|
|
|
|
|
ctn_len++; |
|
6042
|
0
|
0
|
|
|
|
|
if (likely(read_true(&cur, val))) goto obj_val_end; |
|
6043
|
0
|
|
|
|
|
|
goto fail_literal_true; |
|
6044
|
|
|
|
|
|
|
} |
|
6045
|
0
|
0
|
|
|
|
|
if (*cur == 'f') { |
|
6046
|
0
|
|
|
|
|
|
val++; |
|
6047
|
0
|
|
|
|
|
|
ctn_len++; |
|
6048
|
0
|
0
|
|
|
|
|
if (likely(read_false(&cur, val))) goto obj_val_end; |
|
6049
|
0
|
|
|
|
|
|
goto fail_literal_false; |
|
6050
|
|
|
|
|
|
|
} |
|
6051
|
0
|
0
|
|
|
|
|
if (*cur == 'n') { |
|
6052
|
0
|
|
|
|
|
|
val++; |
|
6053
|
0
|
|
|
|
|
|
ctn_len++; |
|
6054
|
0
|
0
|
|
|
|
|
if (likely(read_null(&cur, val))) goto obj_val_end; |
|
6055
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
6056
|
0
|
0
|
|
|
|
|
if (read_nan(&cur, pre, flg, val)) goto obj_val_end; |
|
6057
|
|
|
|
|
|
|
} |
|
6058
|
0
|
|
|
|
|
|
goto fail_literal_null; |
|
6059
|
|
|
|
|
|
|
} |
|
6060
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6061
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6062
|
0
|
|
|
|
|
|
goto obj_val_begin; |
|
6063
|
|
|
|
|
|
|
} |
|
6064
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN) && |
|
6065
|
0
|
0
|
|
|
|
|
(*cur == 'i' || *cur == 'I' || *cur == 'N')) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
6066
|
0
|
|
|
|
|
|
val++; |
|
6067
|
0
|
0
|
|
|
|
|
ctn_len++; |
|
6068
|
0
|
0
|
|
|
|
|
if (read_inf_or_nan(&cur, pre, flg, val)) goto obj_val_end; |
|
6069
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
6070
|
|
|
|
|
|
|
} |
|
6071
|
0
|
0
|
|
|
|
|
if (has_allow(SINGLE_QUOTED_STR) && *cur == '\'') { |
|
|
|
0
|
|
|
|
|
|
|
6072
|
0
|
|
|
|
|
|
val++; |
|
6073
|
0
|
|
|
|
|
|
ctn_len++; |
|
6074
|
0
|
0
|
|
|
|
|
if (likely(read_str_sq(&cur, eof, flg, val, &msg))) goto obj_val_end; |
|
6075
|
0
|
|
|
|
|
|
goto fail_string; |
|
6076
|
|
|
|
|
|
|
} |
|
6077
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
6078
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto obj_val_begin; |
|
6079
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
6080
|
|
|
|
|
|
|
} |
|
6081
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
6082
|
|
|
|
|
|
|
|
|
6083
|
1
|
|
|
|
|
|
obj_val_end: |
|
6084
|
24
|
100
|
|
|
|
|
if (byte_match_2(cur, ",\n")) { |
|
6085
|
1
|
|
|
|
|
|
cur += 2; |
|
6086
|
1
|
|
|
|
|
|
goto obj_key_begin; |
|
6087
|
|
|
|
|
|
|
} |
|
6088
|
11
|
100
|
|
|
|
|
if (likely(*cur == ',')) { |
|
6089
|
5
|
|
|
|
|
|
cur++; |
|
6090
|
5
|
|
|
|
|
|
goto obj_key_begin; |
|
6091
|
|
|
|
|
|
|
} |
|
6092
|
6
|
100
|
|
|
|
|
if (likely(*cur == '}')) { |
|
6093
|
5
|
|
|
|
|
|
cur++; |
|
6094
|
5
|
|
|
|
|
|
goto obj_end; |
|
6095
|
|
|
|
|
|
|
} |
|
6096
|
2
|
50
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6097
|
2
|
50
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6098
|
1
|
|
|
|
|
|
goto obj_val_end; |
|
6099
|
|
|
|
|
|
|
} |
|
6100
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
6101
|
0
|
0
|
|
|
|
|
if (skip_trivia(&cur, eof, flg)) goto obj_val_end; |
|
6102
|
0
|
0
|
|
|
|
|
if (cur == eof) goto fail_comment; |
|
6103
|
|
|
|
|
|
|
} |
|
6104
|
0
|
|
|
|
|
|
goto fail_character_obj_end; |
|
6105
|
|
|
|
|
|
|
|
|
6106
|
5
|
|
|
|
|
|
obj_end: |
|
6107
|
|
|
|
|
|
|
/* pop container */ |
|
6108
|
5
|
|
|
|
|
|
ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); |
|
6109
|
|
|
|
|
|
|
/* point to the next value */ |
|
6110
|
5
|
|
|
|
|
|
ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); |
|
6111
|
5
|
|
|
|
|
|
ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ; |
|
6112
|
5
|
100
|
|
|
|
|
if (unlikely(ctn == ctn_parent)) goto doc_end; |
|
6113
|
3
|
|
|
|
|
|
ctn = ctn_parent; |
|
6114
|
3
|
|
|
|
|
|
ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); |
|
6115
|
3
|
100
|
|
|
|
|
if (*cur == '\n') cur++; |
|
6116
|
3
|
50
|
|
|
|
|
if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { |
|
6117
|
0
|
|
|
|
|
|
goto obj_val_end; |
|
6118
|
|
|
|
|
|
|
} else { |
|
6119
|
3
|
|
|
|
|
|
goto arr_val_end; |
|
6120
|
|
|
|
|
|
|
} |
|
6121
|
|
|
|
|
|
|
|
|
6122
|
3
|
|
|
|
|
|
doc_end: |
|
6123
|
|
|
|
|
|
|
/* check invalid contents after json document */ |
|
6124
|
3
|
50
|
|
|
|
|
if (unlikely(cur < eof) && !has_flg(STOP_WHEN_DONE)) { |
|
|
|
0
|
|
|
|
|
|
|
6125
|
0
|
0
|
|
|
|
|
while (char_is_space(*cur)) cur++; |
|
6126
|
0
|
0
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
6127
|
0
|
0
|
|
|
|
|
if (!skip_trivia(&cur, eof, flg) && cur == eof) { |
|
|
|
0
|
|
|
|
|
|
|
6128
|
0
|
|
|
|
|
|
goto fail_comment; |
|
6129
|
|
|
|
|
|
|
} |
|
6130
|
|
|
|
|
|
|
} |
|
6131
|
0
|
0
|
|
|
|
|
if (unlikely(cur < eof)) goto fail_garbage; |
|
6132
|
|
|
|
|
|
|
} |
|
6133
|
|
|
|
|
|
|
|
|
6134
|
3
|
|
|
|
|
|
**pre = '\0'; |
|
6135
|
3
|
|
|
|
|
|
doc = (yyjson_doc *)val_hdr; |
|
6136
|
3
|
|
|
|
|
|
doc->root = val_hdr + hdr_len; |
|
6137
|
3
|
|
|
|
|
|
doc->alc = alc; |
|
6138
|
3
|
|
|
|
|
|
doc->dat_read = (usize)(cur - hdr); |
|
6139
|
3
|
|
|
|
|
|
doc->val_read = (usize)((val - doc->root) + 1); |
|
6140
|
6
|
100
|
|
|
|
|
doc->str_pool = has_flg(INSITU) ? NULL : (char *)hdr; |
|
6141
|
3
|
|
|
|
|
|
return doc; |
|
6142
|
|
|
|
|
|
|
|
|
6143
|
0
|
0
|
|
|
|
|
fail_string: return_err(cur, INVALID_STRING, msg); |
|
|
|
0
|
|
|
|
|
|
|
6144
|
0
|
0
|
|
|
|
|
fail_number: return_err(cur, INVALID_NUMBER, msg); |
|
|
|
0
|
|
|
|
|
|
|
6145
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(cur, MEMORY_ALLOCATION, MSG_MALLOC); |
|
|
|
0
|
|
|
|
|
|
|
6146
|
0
|
0
|
|
|
|
|
fail_trailing_comma: return_err(cur, JSON_STRUCTURE, MSG_COMMA); |
|
|
|
0
|
|
|
|
|
|
|
6147
|
0
|
0
|
|
|
|
|
fail_literal_true: return_err(cur, LITERAL, MSG_CHAR_T); |
|
|
|
0
|
|
|
|
|
|
|
6148
|
0
|
0
|
|
|
|
|
fail_literal_false: return_err(cur, LITERAL, MSG_CHAR_F); |
|
|
|
0
|
|
|
|
|
|
|
6149
|
0
|
0
|
|
|
|
|
fail_literal_null: return_err(cur, LITERAL, MSG_CHAR_N); |
|
|
|
0
|
|
|
|
|
|
|
6150
|
0
|
0
|
|
|
|
|
fail_character_val: return_err(cur, UNEXPECTED_CHARACTER, MSG_CHAR); |
|
|
|
0
|
|
|
|
|
|
|
6151
|
0
|
0
|
|
|
|
|
fail_character_arr_end: return_err(cur, UNEXPECTED_CHARACTER, MSG_ARR_END); |
|
|
|
0
|
|
|
|
|
|
|
6152
|
0
|
0
|
|
|
|
|
fail_character_obj_key: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_KEY); |
|
|
|
0
|
|
|
|
|
|
|
6153
|
0
|
0
|
|
|
|
|
fail_character_obj_sep: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_SEP); |
|
|
|
0
|
|
|
|
|
|
|
6154
|
0
|
0
|
|
|
|
|
fail_character_obj_end: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_END); |
|
|
|
0
|
|
|
|
|
|
|
6155
|
0
|
0
|
|
|
|
|
fail_comment: return_err(cur, INVALID_COMMENT, MSG_COMMENT); |
|
|
|
0
|
|
|
|
|
|
|
6156
|
0
|
0
|
|
|
|
|
fail_garbage: return_err(cur, UNEXPECTED_CONTENT, MSG_GARBAGE); |
|
|
|
0
|
|
|
|
|
|
|
6157
|
|
|
|
|
|
|
|
|
6158
|
|
|
|
|
|
|
#undef val_incr |
|
6159
|
|
|
|
|
|
|
#undef return_err |
|
6160
|
|
|
|
|
|
|
} |
|
6161
|
|
|
|
|
|
|
|
|
6162
|
|
|
|
|
|
|
|
|
6163
|
|
|
|
|
|
|
|
|
6164
|
|
|
|
|
|
|
/*============================================================================== |
|
6165
|
|
|
|
|
|
|
* MARK: - JSON Reader (Public) |
|
6166
|
|
|
|
|
|
|
*============================================================================*/ |
|
6167
|
|
|
|
|
|
|
|
|
6168
|
10119
|
|
|
|
|
|
yyjson_doc *yyjson_read_opts(char *dat, usize len, |
|
6169
|
|
|
|
|
|
|
yyjson_read_flag flg, |
|
6170
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
6171
|
|
|
|
|
|
|
yyjson_read_err *err) { |
|
6172
|
|
|
|
|
|
|
#define return_err(_pos, _code, _msg) do { \ |
|
6173
|
|
|
|
|
|
|
err->pos = (usize)(_pos); \ |
|
6174
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
6175
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_##_code; \ |
|
6176
|
|
|
|
|
|
|
if (!has_flg(INSITU) && hdr) alc.free(alc.ctx, (void *)hdr); \ |
|
6177
|
|
|
|
|
|
|
return NULL; \ |
|
6178
|
|
|
|
|
|
|
} while (false) |
|
6179
|
|
|
|
|
|
|
|
|
6180
|
|
|
|
|
|
|
yyjson_read_err tmp_err; |
|
6181
|
10119
|
100
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
6182
|
|
|
|
|
|
|
yyjson_doc *doc; |
|
6183
|
10119
|
|
|
|
|
|
u8 *hdr = NULL, *eof, *cur; |
|
6184
|
|
|
|
|
|
|
|
|
6185
|
|
|
|
|
|
|
/* validate input parameters */ |
|
6186
|
10119
|
100
|
|
|
|
|
if (!err) err = &tmp_err; |
|
6187
|
10119
|
50
|
|
|
|
|
if (unlikely(!dat)) return_err(0, INVALID_PARAMETER, "input data is NULL"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
6188
|
10120
|
100
|
|
|
|
|
if (unlikely(!len)) return_err(0, INVALID_PARAMETER, "input length is 0"); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
6189
|
|
|
|
|
|
|
|
|
6190
|
|
|
|
|
|
|
/* add 4-byte zero padding for input data if necessary */ |
|
6191
|
20236
|
100
|
|
|
|
|
if (has_flg(INSITU)) { |
|
6192
|
3
|
|
|
|
|
|
hdr = (u8 *)dat; |
|
6193
|
3
|
|
|
|
|
|
eof = (u8 *)dat + len; |
|
6194
|
3
|
|
|
|
|
|
cur = (u8 *)dat; |
|
6195
|
|
|
|
|
|
|
} else { |
|
6196
|
10115
|
50
|
|
|
|
|
if (unlikely(len >= USIZE_MAX - YYJSON_PADDING_SIZE)) { |
|
6197
|
0
|
0
|
|
|
|
|
return_err(0, MEMORY_ALLOCATION, MSG_MALLOC); |
|
|
|
0
|
|
|
|
|
|
|
6198
|
|
|
|
|
|
|
} |
|
6199
|
10115
|
|
|
|
|
|
hdr = (u8 *)alc.malloc(alc.ctx, len + YYJSON_PADDING_SIZE); |
|
6200
|
10115
|
50
|
|
|
|
|
if (unlikely(!hdr)) { |
|
6201
|
0
|
0
|
|
|
|
|
return_err(0, MEMORY_ALLOCATION, MSG_MALLOC); |
|
|
|
0
|
|
|
|
|
|
|
6202
|
|
|
|
|
|
|
} |
|
6203
|
10115
|
|
|
|
|
|
eof = hdr + len; |
|
6204
|
10115
|
|
|
|
|
|
cur = hdr; |
|
6205
|
10115
|
|
|
|
|
|
memcpy(hdr, dat, len); |
|
6206
|
|
|
|
|
|
|
} |
|
6207
|
10118
|
|
|
|
|
|
memset(eof, 0, YYJSON_PADDING_SIZE); |
|
6208
|
|
|
|
|
|
|
|
|
6209
|
20236
|
50
|
|
|
|
|
if (has_allow(BOM)) { |
|
6210
|
0
|
0
|
|
|
|
|
if (len >= 3 && is_utf8_bom(cur)) cur += 3; |
|
|
|
0
|
|
|
|
|
|
|
6211
|
|
|
|
|
|
|
} |
|
6212
|
|
|
|
|
|
|
|
|
6213
|
|
|
|
|
|
|
/* skip empty contents before json document */ |
|
6214
|
20236
|
100
|
|
|
|
|
if (unlikely(!char_is_ctn(*cur))) { |
|
6215
|
28
|
50
|
|
|
|
|
while (char_is_space(*cur)) cur++; |
|
6216
|
28
|
50
|
|
|
|
|
if (unlikely(!char_is_ctn(*cur))) { |
|
6217
|
28
|
50
|
|
|
|
|
if (has_allow(TRIVIA) && char_is_trivia(*cur)) { |
|
|
|
0
|
|
|
|
|
|
|
6218
|
0
|
0
|
|
|
|
|
if (!skip_trivia(&cur, eof, flg) && cur == eof) { |
|
|
|
0
|
|
|
|
|
|
|
6219
|
0
|
0
|
|
|
|
|
return_err(cur - hdr, INVALID_COMMENT, MSG_COMMENT); |
|
|
|
0
|
|
|
|
|
|
|
6220
|
|
|
|
|
|
|
} |
|
6221
|
|
|
|
|
|
|
} |
|
6222
|
|
|
|
|
|
|
} |
|
6223
|
14
|
50
|
|
|
|
|
if (unlikely(cur >= eof)) { |
|
6224
|
0
|
0
|
|
|
|
|
return_err(0, EMPTY_CONTENT, "input data is empty"); |
|
|
|
0
|
|
|
|
|
|
|
6225
|
|
|
|
|
|
|
} |
|
6226
|
|
|
|
|
|
|
} |
|
6227
|
|
|
|
|
|
|
|
|
6228
|
|
|
|
|
|
|
/* read json document */ |
|
6229
|
20236
|
100
|
|
|
|
|
if (likely(char_is_ctn(*cur))) { |
|
6230
|
20211
|
100
|
|
|
|
|
if (char_is_space(cur[1]) && char_is_space(cur[2])) { |
|
|
|
50
|
|
|
|
|
|
|
6231
|
6
|
|
|
|
|
|
doc = read_root_pretty(hdr, cur, eof, alc, flg, err); |
|
6232
|
|
|
|
|
|
|
} else { |
|
6233
|
20202
|
|
|
|
|
|
doc = read_root_minify(hdr, cur, eof, alc, flg, err); |
|
6234
|
|
|
|
|
|
|
} |
|
6235
|
|
|
|
|
|
|
} else { |
|
6236
|
14
|
|
|
|
|
|
doc = read_root_single(hdr, cur, eof, alc, flg, err); |
|
6237
|
|
|
|
|
|
|
} |
|
6238
|
|
|
|
|
|
|
|
|
6239
|
|
|
|
|
|
|
/* check result */ |
|
6240
|
10118
|
100
|
|
|
|
|
if (likely(doc)) { |
|
6241
|
10114
|
|
|
|
|
|
memset(err, 0, sizeof(yyjson_read_err)); |
|
6242
|
|
|
|
|
|
|
} else { |
|
6243
|
|
|
|
|
|
|
/* RFC 8259: JSON text MUST be encoded using UTF-8 */ |
|
6244
|
4
|
50
|
|
|
|
|
if (err->pos == 0 && err->code != YYJSON_READ_ERROR_MEMORY_ALLOCATION) { |
|
|
|
50
|
|
|
|
|
|
|
6245
|
4
|
100
|
|
|
|
|
if (is_utf8_bom(hdr)) err->msg = MSG_ERR_BOM; |
|
6246
|
6
|
50
|
|
|
|
|
else if (len >= 4 && is_utf32_bom(hdr)) err->msg = MSG_ERR_UTF32; |
|
|
|
50
|
|
|
|
|
|
|
6247
|
6
|
50
|
|
|
|
|
else if (len >= 2 && is_utf16_bom(hdr)) err->msg = MSG_ERR_UTF16; |
|
|
|
50
|
|
|
|
|
|
|
6248
|
|
|
|
|
|
|
} |
|
6249
|
8
|
50
|
|
|
|
|
if (!has_flg(INSITU)) alc.free(alc.ctx, hdr); |
|
6250
|
|
|
|
|
|
|
} |
|
6251
|
10118
|
|
|
|
|
|
return doc; |
|
6252
|
|
|
|
|
|
|
|
|
6253
|
|
|
|
|
|
|
#undef return_err |
|
6254
|
|
|
|
|
|
|
} |
|
6255
|
|
|
|
|
|
|
|
|
6256
|
4
|
|
|
|
|
|
yyjson_doc *yyjson_read_file(const char *path, |
|
6257
|
|
|
|
|
|
|
yyjson_read_flag flg, |
|
6258
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
6259
|
|
|
|
|
|
|
yyjson_read_err *err) { |
|
6260
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
6261
|
|
|
|
|
|
|
err->pos = 0; \ |
|
6262
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
6263
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_##_code; \ |
|
6264
|
|
|
|
|
|
|
return NULL; \ |
|
6265
|
|
|
|
|
|
|
} while (false) |
|
6266
|
|
|
|
|
|
|
|
|
6267
|
|
|
|
|
|
|
yyjson_read_err tmp_err; |
|
6268
|
|
|
|
|
|
|
yyjson_doc *doc; |
|
6269
|
|
|
|
|
|
|
FILE *file; |
|
6270
|
|
|
|
|
|
|
|
|
6271
|
4
|
50
|
|
|
|
|
if (!err) err = &tmp_err; |
|
6272
|
4
|
50
|
|
|
|
|
if (unlikely(!path)) return_err(INVALID_PARAMETER, "input path is NULL"); |
|
6273
|
|
|
|
|
|
|
|
|
6274
|
4
|
|
|
|
|
|
file = fopen_readonly(path); |
|
6275
|
4
|
100
|
|
|
|
|
if (unlikely(!file)) return_err(FILE_OPEN, MSG_FREAD); |
|
6276
|
|
|
|
|
|
|
|
|
6277
|
3
|
|
|
|
|
|
doc = yyjson_read_fp(file, flg, alc_ptr, err); |
|
6278
|
3
|
|
|
|
|
|
fclose(file); |
|
6279
|
3
|
|
|
|
|
|
return doc; |
|
6280
|
|
|
|
|
|
|
|
|
6281
|
|
|
|
|
|
|
#undef return_err |
|
6282
|
|
|
|
|
|
|
} |
|
6283
|
|
|
|
|
|
|
|
|
6284
|
3
|
|
|
|
|
|
yyjson_doc *yyjson_read_fp(FILE *file, |
|
6285
|
|
|
|
|
|
|
yyjson_read_flag flg, |
|
6286
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
6287
|
|
|
|
|
|
|
yyjson_read_err *err) { |
|
6288
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
6289
|
|
|
|
|
|
|
err->pos = 0; \ |
|
6290
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
6291
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_##_code; \ |
|
6292
|
|
|
|
|
|
|
if (buf) alc.free(alc.ctx, buf); \ |
|
6293
|
|
|
|
|
|
|
return NULL; \ |
|
6294
|
|
|
|
|
|
|
} while (false) |
|
6295
|
|
|
|
|
|
|
|
|
6296
|
|
|
|
|
|
|
yyjson_read_err tmp_err; |
|
6297
|
3
|
50
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
6298
|
|
|
|
|
|
|
yyjson_doc *doc; |
|
6299
|
|
|
|
|
|
|
|
|
6300
|
3
|
|
|
|
|
|
long file_size = 0, file_pos; |
|
6301
|
3
|
|
|
|
|
|
void *buf = NULL; |
|
6302
|
3
|
|
|
|
|
|
usize buf_size = 0; |
|
6303
|
|
|
|
|
|
|
|
|
6304
|
|
|
|
|
|
|
/* validate input parameters */ |
|
6305
|
3
|
50
|
|
|
|
|
if (!err) err = &tmp_err; |
|
6306
|
3
|
50
|
|
|
|
|
if (unlikely(!file)) return_err(INVALID_PARAMETER, "input file is NULL"); |
|
|
|
0
|
|
|
|
|
|
|
6307
|
|
|
|
|
|
|
|
|
6308
|
|
|
|
|
|
|
/* get current position */ |
|
6309
|
3
|
|
|
|
|
|
file_pos = ftell(file); |
|
6310
|
3
|
50
|
|
|
|
|
if (file_pos != -1) { |
|
6311
|
|
|
|
|
|
|
/* get total file size, may fail */ |
|
6312
|
3
|
50
|
|
|
|
|
if (fseek(file, 0, SEEK_END) == 0) file_size = ftell(file); |
|
6313
|
|
|
|
|
|
|
/* reset to original position, may fail */ |
|
6314
|
3
|
50
|
|
|
|
|
if (fseek(file, file_pos, SEEK_SET) != 0) file_size = 0; |
|
6315
|
|
|
|
|
|
|
/* get file size from current postion to end */ |
|
6316
|
3
|
50
|
|
|
|
|
if (file_size > 0) file_size -= file_pos; |
|
6317
|
|
|
|
|
|
|
} |
|
6318
|
|
|
|
|
|
|
|
|
6319
|
|
|
|
|
|
|
/* read file */ |
|
6320
|
3
|
50
|
|
|
|
|
if (file_size > 0) { |
|
6321
|
|
|
|
|
|
|
/* read the entire file in one call */ |
|
6322
|
3
|
|
|
|
|
|
buf_size = (usize)file_size + YYJSON_PADDING_SIZE; |
|
6323
|
3
|
|
|
|
|
|
buf = alc.malloc(alc.ctx, buf_size); |
|
6324
|
3
|
50
|
|
|
|
|
if (buf == NULL) { |
|
6325
|
0
|
0
|
|
|
|
|
return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
6326
|
|
|
|
|
|
|
} |
|
6327
|
6
|
50
|
|
|
|
|
if (fread_safe(buf, (usize)file_size, file) != (usize)file_size) { |
|
6328
|
0
|
0
|
|
|
|
|
return_err(FILE_READ, MSG_FREAD); |
|
6329
|
|
|
|
|
|
|
} |
|
6330
|
|
|
|
|
|
|
} else { |
|
6331
|
|
|
|
|
|
|
/* failed to get file size, read it as a stream */ |
|
6332
|
0
|
|
|
|
|
|
usize chunk_min = (usize)64; |
|
6333
|
0
|
|
|
|
|
|
usize chunk_max = (usize)512 * 1024 * 1024; |
|
6334
|
0
|
|
|
|
|
|
usize chunk_now = chunk_min; |
|
6335
|
|
|
|
|
|
|
usize read_size; |
|
6336
|
|
|
|
|
|
|
void *tmp; |
|
6337
|
|
|
|
|
|
|
|
|
6338
|
0
|
|
|
|
|
|
buf_size = YYJSON_PADDING_SIZE; |
|
6339
|
|
|
|
|
|
|
while (true) { |
|
6340
|
0
|
0
|
|
|
|
|
if (buf_size + chunk_now < buf_size) { /* overflow */ |
|
6341
|
0
|
0
|
|
|
|
|
return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
6342
|
|
|
|
|
|
|
} |
|
6343
|
0
|
|
|
|
|
|
buf_size += chunk_now; |
|
6344
|
0
|
0
|
|
|
|
|
if (!buf) { |
|
6345
|
0
|
|
|
|
|
|
buf = alc.malloc(alc.ctx, buf_size); |
|
6346
|
0
|
0
|
|
|
|
|
if (!buf) return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
|
|
0
|
|
|
|
|
|
|
6347
|
|
|
|
|
|
|
} else { |
|
6348
|
0
|
|
|
|
|
|
tmp = alc.realloc(alc.ctx, buf, buf_size - chunk_now, buf_size); |
|
6349
|
0
|
0
|
|
|
|
|
if (!tmp) return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
|
|
0
|
|
|
|
|
|
|
6350
|
0
|
|
|
|
|
|
buf = tmp; |
|
6351
|
|
|
|
|
|
|
} |
|
6352
|
0
|
|
|
|
|
|
tmp = ((u8 *)buf) + buf_size - YYJSON_PADDING_SIZE - chunk_now; |
|
6353
|
0
|
|
|
|
|
|
read_size = fread_safe(tmp, chunk_now, file); |
|
6354
|
0
|
|
|
|
|
|
file_size += (long)read_size; |
|
6355
|
0
|
0
|
|
|
|
|
if (read_size != chunk_now) break; |
|
6356
|
|
|
|
|
|
|
|
|
6357
|
0
|
|
|
|
|
|
chunk_now *= 2; |
|
6358
|
0
|
0
|
|
|
|
|
if (chunk_now > chunk_max) chunk_now = chunk_max; |
|
6359
|
|
|
|
|
|
|
} |
|
6360
|
|
|
|
|
|
|
} |
|
6361
|
|
|
|
|
|
|
|
|
6362
|
|
|
|
|
|
|
/* read JSON */ |
|
6363
|
3
|
|
|
|
|
|
memset((u8 *)buf + file_size, 0, YYJSON_PADDING_SIZE); |
|
6364
|
3
|
|
|
|
|
|
flg |= YYJSON_READ_INSITU; |
|
6365
|
3
|
|
|
|
|
|
doc = yyjson_read_opts((char *)buf, (usize)file_size, flg, &alc, err); |
|
6366
|
3
|
50
|
|
|
|
|
if (doc) { |
|
6367
|
3
|
|
|
|
|
|
doc->str_pool = (char *)buf; |
|
6368
|
3
|
|
|
|
|
|
return doc; |
|
6369
|
|
|
|
|
|
|
} else { |
|
6370
|
0
|
|
|
|
|
|
alc.free(alc.ctx, buf); |
|
6371
|
0
|
|
|
|
|
|
return NULL; |
|
6372
|
|
|
|
|
|
|
} |
|
6373
|
|
|
|
|
|
|
|
|
6374
|
|
|
|
|
|
|
#undef return_err |
|
6375
|
|
|
|
|
|
|
} |
|
6376
|
|
|
|
|
|
|
|
|
6377
|
0
|
|
|
|
|
|
const char *yyjson_read_number(const char *dat, |
|
6378
|
|
|
|
|
|
|
yyjson_val *val, |
|
6379
|
|
|
|
|
|
|
yyjson_read_flag flg, |
|
6380
|
|
|
|
|
|
|
const yyjson_alc *alc, |
|
6381
|
|
|
|
|
|
|
yyjson_read_err *err) { |
|
6382
|
|
|
|
|
|
|
#define return_err(_pos, _code, _msg) do { \ |
|
6383
|
|
|
|
|
|
|
err->pos = _pos > hdr ? (usize)(_pos - hdr) : 0; \ |
|
6384
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
6385
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_##_code; \ |
|
6386
|
|
|
|
|
|
|
return NULL; \ |
|
6387
|
|
|
|
|
|
|
} while (false) |
|
6388
|
|
|
|
|
|
|
|
|
6389
|
0
|
|
|
|
|
|
u8 *hdr = constcast(u8 *)dat, *cur = hdr; |
|
6390
|
|
|
|
|
|
|
u8 raw_end[1]; /* raw end for null-terminator */ |
|
6391
|
0
|
|
|
|
|
|
u8 *raw_ptr = raw_end; |
|
6392
|
0
|
|
|
|
|
|
u8 **pre = &raw_ptr; /* previous raw end pointer */ |
|
6393
|
|
|
|
|
|
|
const char *msg; |
|
6394
|
|
|
|
|
|
|
yyjson_read_err tmp_err; |
|
6395
|
|
|
|
|
|
|
|
|
6396
|
|
|
|
|
|
|
#if YYJSON_DISABLE_FAST_FP_CONV |
|
6397
|
|
|
|
|
|
|
u8 buf[128]; |
|
6398
|
|
|
|
|
|
|
usize dat_len; |
|
6399
|
|
|
|
|
|
|
#endif |
|
6400
|
|
|
|
|
|
|
|
|
6401
|
0
|
0
|
|
|
|
|
if (!err) err = &tmp_err; |
|
6402
|
0
|
0
|
|
|
|
|
if (unlikely(!dat)) { |
|
6403
|
0
|
0
|
|
|
|
|
return_err(cur, INVALID_PARAMETER, "input data is NULL"); |
|
6404
|
|
|
|
|
|
|
} |
|
6405
|
0
|
0
|
|
|
|
|
if (unlikely(!val)) { |
|
6406
|
0
|
0
|
|
|
|
|
return_err(cur, INVALID_PARAMETER, "output value is NULL"); |
|
6407
|
|
|
|
|
|
|
} |
|
6408
|
|
|
|
|
|
|
|
|
6409
|
|
|
|
|
|
|
#if YYJSON_DISABLE_FAST_FP_CONV |
|
6410
|
|
|
|
|
|
|
if (!alc) alc = &YYJSON_DEFAULT_ALC; |
|
6411
|
|
|
|
|
|
|
dat_len = strlen(dat); |
|
6412
|
|
|
|
|
|
|
if (dat_len < sizeof(buf)) { |
|
6413
|
|
|
|
|
|
|
memcpy(buf, dat, dat_len + 1); |
|
6414
|
|
|
|
|
|
|
hdr = buf; |
|
6415
|
|
|
|
|
|
|
cur = hdr; |
|
6416
|
|
|
|
|
|
|
} else { |
|
6417
|
|
|
|
|
|
|
hdr = (u8 *)alc->malloc(alc->ctx, dat_len + 1); |
|
6418
|
|
|
|
|
|
|
cur = hdr; |
|
6419
|
|
|
|
|
|
|
if (unlikely(!hdr)) { |
|
6420
|
|
|
|
|
|
|
return_err(cur, MEMORY_ALLOCATION, MSG_MALLOC); |
|
6421
|
|
|
|
|
|
|
} |
|
6422
|
|
|
|
|
|
|
memcpy(hdr, dat, dat_len + 1); |
|
6423
|
|
|
|
|
|
|
} |
|
6424
|
|
|
|
|
|
|
hdr[dat_len] = 0; |
|
6425
|
|
|
|
|
|
|
#endif |
|
6426
|
|
|
|
|
|
|
|
|
6427
|
|
|
|
|
|
|
#if YYJSON_DISABLE_FAST_FP_CONV |
|
6428
|
|
|
|
|
|
|
if (!read_num(&cur, pre, flg, val, &msg)) { |
|
6429
|
|
|
|
|
|
|
if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr); |
|
6430
|
|
|
|
|
|
|
return_err(cur, INVALID_NUMBER, msg); |
|
6431
|
|
|
|
|
|
|
} |
|
6432
|
|
|
|
|
|
|
if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr); |
|
6433
|
|
|
|
|
|
|
if (yyjson_is_raw(val)) val->uni.str = dat; |
|
6434
|
|
|
|
|
|
|
return dat + (cur - hdr); |
|
6435
|
|
|
|
|
|
|
#else |
|
6436
|
0
|
0
|
|
|
|
|
if (!read_num(&cur, pre, flg, val, &msg)) { |
|
6437
|
0
|
0
|
|
|
|
|
return_err(cur, INVALID_NUMBER, msg); |
|
6438
|
|
|
|
|
|
|
} |
|
6439
|
0
|
|
|
|
|
|
return (const char *)cur; |
|
6440
|
|
|
|
|
|
|
#endif |
|
6441
|
|
|
|
|
|
|
|
|
6442
|
|
|
|
|
|
|
#undef return_err |
|
6443
|
|
|
|
|
|
|
} |
|
6444
|
|
|
|
|
|
|
|
|
6445
|
|
|
|
|
|
|
|
|
6446
|
|
|
|
|
|
|
|
|
6447
|
|
|
|
|
|
|
/*============================================================================== |
|
6448
|
|
|
|
|
|
|
* MARK: - Incremental JSON Reader (Public) |
|
6449
|
|
|
|
|
|
|
*============================================================================*/ |
|
6450
|
|
|
|
|
|
|
|
|
6451
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_INCR_READER |
|
6452
|
|
|
|
|
|
|
|
|
6453
|
|
|
|
|
|
|
/* labels within yyjson_incr_read() to resume incremental parsing */ |
|
6454
|
|
|
|
|
|
|
#define LABEL_doc_begin 0 |
|
6455
|
|
|
|
|
|
|
#define LABEL_arr_val_begin 1 |
|
6456
|
|
|
|
|
|
|
#define LABEL_arr_val_end 2 |
|
6457
|
|
|
|
|
|
|
#define LABEL_obj_key_begin 3 |
|
6458
|
|
|
|
|
|
|
#define LABEL_obj_key_end 4 |
|
6459
|
|
|
|
|
|
|
#define LABEL_obj_val_begin 5 |
|
6460
|
|
|
|
|
|
|
#define LABEL_obj_val_end 6 |
|
6461
|
|
|
|
|
|
|
#define LABEL_doc_end 7 |
|
6462
|
|
|
|
|
|
|
|
|
6463
|
|
|
|
|
|
|
/** State for incremental JSON reader, opaque in the API. */ |
|
6464
|
|
|
|
|
|
|
struct yyjson_incr_state { |
|
6465
|
|
|
|
|
|
|
u32 label; /* current parser goto label */ |
|
6466
|
|
|
|
|
|
|
yyjson_alc alc; /* allocator */ |
|
6467
|
|
|
|
|
|
|
yyjson_read_flag flg; /* read flags */ |
|
6468
|
|
|
|
|
|
|
u8 *hdr; /* JSON data header */ |
|
6469
|
|
|
|
|
|
|
u8 *cur; /* current position in JSON data */ |
|
6470
|
|
|
|
|
|
|
usize buf_len; /* total buffer length (without padding) */ |
|
6471
|
|
|
|
|
|
|
usize hdr_len; /* value count used by yyjson_doc */ |
|
6472
|
|
|
|
|
|
|
usize alc_len; /* value count allocated */ |
|
6473
|
|
|
|
|
|
|
usize ctn_len; /* the number of elements in current container */ |
|
6474
|
|
|
|
|
|
|
yyjson_val *val_hdr; /* the head of allocated values */ |
|
6475
|
|
|
|
|
|
|
yyjson_val *val_end; /* the end of allocated values */ |
|
6476
|
|
|
|
|
|
|
yyjson_val *val; /* current JSON value */ |
|
6477
|
|
|
|
|
|
|
yyjson_val *ctn; /* current container */ |
|
6478
|
|
|
|
|
|
|
u8 *str_con[2]; /* string parser incremental state */ |
|
6479
|
|
|
|
|
|
|
}; |
|
6480
|
|
|
|
|
|
|
|
|
6481
|
0
|
|
|
|
|
|
yyjson_incr_state *yyjson_incr_new(char *buf, size_t buf_len, |
|
6482
|
|
|
|
|
|
|
yyjson_read_flag flg, |
|
6483
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr) { |
|
6484
|
0
|
|
|
|
|
|
yyjson_incr_state *state = NULL; |
|
6485
|
0
|
0
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
6486
|
|
|
|
|
|
|
|
|
6487
|
|
|
|
|
|
|
/* remove non-standard flags */ |
|
6488
|
0
|
|
|
|
|
|
flg &= ~YYJSON_READ_JSON5; |
|
6489
|
0
|
|
|
|
|
|
flg &= ~YYJSON_READ_ALLOW_BOM; |
|
6490
|
0
|
|
|
|
|
|
flg &= ~YYJSON_READ_ALLOW_INVALID_UNICODE; |
|
6491
|
|
|
|
|
|
|
|
|
6492
|
0
|
0
|
|
|
|
|
if (unlikely(!buf)) return NULL; |
|
6493
|
0
|
0
|
|
|
|
|
if (unlikely(buf_len >= USIZE_MAX - YYJSON_PADDING_SIZE)) return NULL; |
|
6494
|
0
|
|
|
|
|
|
state = (yyjson_incr_state *)alc.malloc(alc.ctx, sizeof(*state)); |
|
6495
|
0
|
0
|
|
|
|
|
if (!state) return NULL; |
|
6496
|
0
|
|
|
|
|
|
memset(state, 0, sizeof(yyjson_incr_state)); |
|
6497
|
0
|
|
|
|
|
|
state->alc = alc; |
|
6498
|
0
|
|
|
|
|
|
state->flg = flg; |
|
6499
|
0
|
|
|
|
|
|
state->buf_len = buf_len; |
|
6500
|
|
|
|
|
|
|
|
|
6501
|
|
|
|
|
|
|
/* add 4-byte zero padding for input data if necessary */ |
|
6502
|
0
|
0
|
|
|
|
|
if (has_flg(INSITU)) { |
|
6503
|
0
|
|
|
|
|
|
state->hdr = (u8 *)buf; |
|
6504
|
|
|
|
|
|
|
} else { |
|
6505
|
0
|
|
|
|
|
|
state->hdr = (u8 *)alc.malloc(alc.ctx, buf_len + YYJSON_PADDING_SIZE); |
|
6506
|
0
|
0
|
|
|
|
|
if (unlikely(!state->hdr)) { |
|
6507
|
0
|
|
|
|
|
|
alc.free(alc.ctx, state); |
|
6508
|
0
|
|
|
|
|
|
return NULL; |
|
6509
|
|
|
|
|
|
|
} |
|
6510
|
0
|
|
|
|
|
|
memcpy(state->hdr, buf, buf_len); |
|
6511
|
|
|
|
|
|
|
} |
|
6512
|
0
|
|
|
|
|
|
memset(state->hdr + buf_len, 0, YYJSON_PADDING_SIZE); |
|
6513
|
0
|
|
|
|
|
|
state->cur = state->hdr; |
|
6514
|
0
|
|
|
|
|
|
state->label = LABEL_doc_begin; |
|
6515
|
0
|
|
|
|
|
|
return state; |
|
6516
|
|
|
|
|
|
|
} |
|
6517
|
|
|
|
|
|
|
|
|
6518
|
0
|
|
|
|
|
|
void yyjson_incr_free(yyjson_incr_state *state) { |
|
6519
|
0
|
0
|
|
|
|
|
if (state) { |
|
6520
|
0
|
|
|
|
|
|
yyjson_alc alc = state->alc; |
|
6521
|
0
|
|
|
|
|
|
memset(&state->alc, 0, sizeof(alc)); |
|
6522
|
0
|
0
|
|
|
|
|
if (state->val_hdr) { |
|
6523
|
0
|
|
|
|
|
|
alc.free(alc.ctx, (void *)state->val_hdr); |
|
6524
|
|
|
|
|
|
|
} |
|
6525
|
0
|
0
|
|
|
|
|
if (state->hdr && !(state->flg & YYJSON_READ_INSITU)) { |
|
|
|
0
|
|
|
|
|
|
|
6526
|
0
|
|
|
|
|
|
alc.free(alc.ctx, state->hdr); |
|
6527
|
|
|
|
|
|
|
} |
|
6528
|
0
|
|
|
|
|
|
alc.free(alc.ctx, state); |
|
6529
|
|
|
|
|
|
|
} |
|
6530
|
0
|
|
|
|
|
|
} |
|
6531
|
|
|
|
|
|
|
|
|
6532
|
0
|
|
|
|
|
|
yyjson_doc *yyjson_incr_read(yyjson_incr_state *state, size_t len, |
|
6533
|
|
|
|
|
|
|
yyjson_read_err *err) { |
|
6534
|
|
|
|
|
|
|
#define return_err_inv_param(_msg) do { \ |
|
6535
|
|
|
|
|
|
|
err->pos = 0; \ |
|
6536
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
6537
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; \ |
|
6538
|
|
|
|
|
|
|
return NULL; \ |
|
6539
|
|
|
|
|
|
|
} while (false) |
|
6540
|
|
|
|
|
|
|
|
|
6541
|
|
|
|
|
|
|
#define return_err(_pos, _code, _msg) do { \ |
|
6542
|
|
|
|
|
|
|
if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ |
|
6543
|
|
|
|
|
|
|
goto unexpected_end; \ |
|
6544
|
|
|
|
|
|
|
} else { \ |
|
6545
|
|
|
|
|
|
|
err->pos = (usize)(_pos - hdr); \ |
|
6546
|
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_##_code; \ |
|
6547
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
6548
|
|
|
|
|
|
|
} \ |
|
6549
|
|
|
|
|
|
|
return NULL; \ |
|
6550
|
|
|
|
|
|
|
} while (false) |
|
6551
|
|
|
|
|
|
|
|
|
6552
|
|
|
|
|
|
|
#define val_incr() do { \ |
|
6553
|
|
|
|
|
|
|
val++; \ |
|
6554
|
|
|
|
|
|
|
if (unlikely(val >= val_end)) { \ |
|
6555
|
|
|
|
|
|
|
usize alc_old = alc_len; \ |
|
6556
|
|
|
|
|
|
|
alc_len += alc_len / 2; \ |
|
6557
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && (alc_len >= alc_max)) goto fail_alloc; \ |
|
6558
|
|
|
|
|
|
|
val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ |
|
6559
|
|
|
|
|
|
|
alc_old * sizeof(yyjson_val), \ |
|
6560
|
|
|
|
|
|
|
alc_len * sizeof(yyjson_val)); \ |
|
6561
|
|
|
|
|
|
|
if ((!val_tmp)) goto fail_alloc; \ |
|
6562
|
|
|
|
|
|
|
val = val_tmp + (usize)(val - val_hdr); \ |
|
6563
|
|
|
|
|
|
|
ctn = val_tmp + (usize)(ctn - val_hdr); \ |
|
6564
|
|
|
|
|
|
|
state->val = val_tmp + (usize)(state->val - val_hdr); \ |
|
6565
|
|
|
|
|
|
|
state->val_hdr = val_hdr = val_tmp; \ |
|
6566
|
|
|
|
|
|
|
val_end = val_tmp + (alc_len - 2); \ |
|
6567
|
|
|
|
|
|
|
state->val_end = val_end; \ |
|
6568
|
|
|
|
|
|
|
} \ |
|
6569
|
|
|
|
|
|
|
} while (false) |
|
6570
|
|
|
|
|
|
|
|
|
6571
|
|
|
|
|
|
|
/* save position where it's possible to resume incremental parsing */ |
|
6572
|
|
|
|
|
|
|
#define save_incr_state(_label) do { \ |
|
6573
|
|
|
|
|
|
|
state->label = LABEL_##_label; \ |
|
6574
|
|
|
|
|
|
|
state->cur = cur; \ |
|
6575
|
|
|
|
|
|
|
state->val = val; \ |
|
6576
|
|
|
|
|
|
|
state->ctn_len = ctn_len; \ |
|
6577
|
|
|
|
|
|
|
state->hdr_len = hdr_len; \ |
|
6578
|
|
|
|
|
|
|
if (unlikely(cur >= end)) goto unexpected_end; \ |
|
6579
|
|
|
|
|
|
|
} while (false) |
|
6580
|
|
|
|
|
|
|
|
|
6581
|
|
|
|
|
|
|
#define check_maybe_truncated_number() do { \ |
|
6582
|
|
|
|
|
|
|
if (unlikely(cur >= end)) { \ |
|
6583
|
|
|
|
|
|
|
if (unlikely(cur > state->cur + INCR_NUM_MAX_LEN)) { \ |
|
6584
|
|
|
|
|
|
|
msg = "number too long"; \ |
|
6585
|
|
|
|
|
|
|
goto fail_number; \ |
|
6586
|
|
|
|
|
|
|
} \ |
|
6587
|
|
|
|
|
|
|
goto unexpected_end; \ |
|
6588
|
|
|
|
|
|
|
} \ |
|
6589
|
|
|
|
|
|
|
} while (false) |
|
6590
|
|
|
|
|
|
|
|
|
6591
|
0
|
|
|
|
|
|
u8 *hdr = NULL, *end = NULL, *cur = NULL; |
|
6592
|
|
|
|
|
|
|
yyjson_read_flag flg; |
|
6593
|
|
|
|
|
|
|
yyjson_alc alc; |
|
6594
|
|
|
|
|
|
|
usize dat_len; /* data length in bytes, hint for allocator */ |
|
6595
|
|
|
|
|
|
|
usize hdr_len; /* value count used by yyjson_doc */ |
|
6596
|
|
|
|
|
|
|
usize alc_len; /* value count allocated */ |
|
6597
|
|
|
|
|
|
|
usize alc_max; /* maximum value count for allocator */ |
|
6598
|
|
|
|
|
|
|
usize ctn_len; /* the number of elements in current container */ |
|
6599
|
|
|
|
|
|
|
yyjson_val *val_hdr; /* the head of allocated values */ |
|
6600
|
|
|
|
|
|
|
yyjson_val *val_end; /* the end of allocated values */ |
|
6601
|
|
|
|
|
|
|
yyjson_val *val_tmp; /* temporary pointer for realloc */ |
|
6602
|
|
|
|
|
|
|
yyjson_val *val; /* current JSON value */ |
|
6603
|
|
|
|
|
|
|
yyjson_val *ctn; /* current container */ |
|
6604
|
|
|
|
|
|
|
yyjson_val *ctn_parent; /* parent of current container */ |
|
6605
|
|
|
|
|
|
|
yyjson_doc *doc; /* the JSON document, equals to val_hdr */ |
|
6606
|
|
|
|
|
|
|
const char *msg; /* error message */ |
|
6607
|
|
|
|
|
|
|
|
|
6608
|
|
|
|
|
|
|
yyjson_read_err tmp_err; |
|
6609
|
|
|
|
|
|
|
u8 raw_end[1]; /* raw end for null-terminator */ |
|
6610
|
0
|
|
|
|
|
|
u8 *raw_ptr = raw_end; |
|
6611
|
0
|
|
|
|
|
|
u8 **pre = &raw_ptr; /* previous raw end pointer */ |
|
6612
|
0
|
|
|
|
|
|
u8 **con = NULL; /* for incremental string parsing */ |
|
6613
|
0
|
|
|
|
|
|
u8 saved_end = '\0'; /* saved end char */ |
|
6614
|
|
|
|
|
|
|
|
|
6615
|
|
|
|
|
|
|
/* validate input parameters */ |
|
6616
|
0
|
0
|
|
|
|
|
if (!err) err = &tmp_err; |
|
6617
|
0
|
0
|
|
|
|
|
if (unlikely(!state)) { |
|
6618
|
0
|
|
|
|
|
|
return_err_inv_param("input state is NULL"); |
|
6619
|
|
|
|
|
|
|
} |
|
6620
|
0
|
0
|
|
|
|
|
if (unlikely(!len)) { |
|
6621
|
0
|
|
|
|
|
|
return_err_inv_param("input length is 0"); |
|
6622
|
|
|
|
|
|
|
} |
|
6623
|
0
|
0
|
|
|
|
|
if (unlikely(len > state->buf_len)) { |
|
6624
|
0
|
|
|
|
|
|
return_err_inv_param("length is greater than total input length"); |
|
6625
|
|
|
|
|
|
|
} |
|
6626
|
|
|
|
|
|
|
|
|
6627
|
|
|
|
|
|
|
/* restore state saved from the previous call */ |
|
6628
|
0
|
|
|
|
|
|
hdr = state->hdr; |
|
6629
|
0
|
|
|
|
|
|
end = state->hdr + len; |
|
6630
|
0
|
|
|
|
|
|
cur = state->cur; |
|
6631
|
0
|
|
|
|
|
|
flg = state->flg; |
|
6632
|
0
|
|
|
|
|
|
alc = state->alc; |
|
6633
|
0
|
|
|
|
|
|
ctn_len = state->ctn_len; |
|
6634
|
0
|
|
|
|
|
|
hdr_len = state->hdr_len; |
|
6635
|
0
|
|
|
|
|
|
alc_len = state->alc_len; |
|
6636
|
0
|
|
|
|
|
|
val = state->val; |
|
6637
|
0
|
|
|
|
|
|
val_hdr = state->val_hdr; |
|
6638
|
0
|
|
|
|
|
|
val_end = state->val_end; |
|
6639
|
0
|
|
|
|
|
|
ctn = state->ctn; |
|
6640
|
0
|
|
|
|
|
|
con = state->str_con; |
|
6641
|
0
|
|
|
|
|
|
alc_max = USIZE_MAX / sizeof(yyjson_val); |
|
6642
|
|
|
|
|
|
|
|
|
6643
|
|
|
|
|
|
|
/* insert null terminator to make us stop at the specified end, even if |
|
6644
|
|
|
|
|
|
|
the data contains more valid JSON */ |
|
6645
|
0
|
|
|
|
|
|
saved_end = *end; |
|
6646
|
0
|
|
|
|
|
|
*end = '\0'; |
|
6647
|
|
|
|
|
|
|
|
|
6648
|
|
|
|
|
|
|
/* resume parsing from the last save point */ |
|
6649
|
0
|
|
|
|
|
|
switch (state->label) { |
|
6650
|
0
|
|
|
|
|
|
case LABEL_doc_begin: goto doc_begin; |
|
6651
|
0
|
|
|
|
|
|
case LABEL_arr_val_begin: goto arr_val_begin; |
|
6652
|
0
|
|
|
|
|
|
case LABEL_arr_val_end: goto arr_val_end; |
|
6653
|
0
|
|
|
|
|
|
case LABEL_obj_key_begin: goto obj_key_begin; |
|
6654
|
0
|
|
|
|
|
|
case LABEL_obj_key_end: goto obj_key_end; |
|
6655
|
0
|
|
|
|
|
|
case LABEL_obj_val_begin: goto obj_val_begin; |
|
6656
|
0
|
|
|
|
|
|
case LABEL_obj_val_end: goto obj_val_end; |
|
6657
|
0
|
|
|
|
|
|
case LABEL_doc_end: goto doc_end; |
|
6658
|
0
|
|
|
|
|
|
default: return_err_inv_param("invalid incremental state"); |
|
6659
|
|
|
|
|
|
|
} |
|
6660
|
|
|
|
|
|
|
|
|
6661
|
0
|
|
|
|
|
|
doc_begin: |
|
6662
|
|
|
|
|
|
|
/* skip empty contents before json document */ |
|
6663
|
0
|
0
|
|
|
|
|
if (unlikely(!char_is_ctn(*cur))) { |
|
6664
|
0
|
0
|
|
|
|
|
while (char_is_space(*cur)) cur++; |
|
6665
|
0
|
0
|
|
|
|
|
if (unlikely(cur >= end)) goto unexpected_end; /* input data is empty */ |
|
6666
|
|
|
|
|
|
|
} |
|
6667
|
|
|
|
|
|
|
|
|
6668
|
|
|
|
|
|
|
/* allocate memory for document */ |
|
6669
|
0
|
0
|
|
|
|
|
if (!val_hdr) { |
|
6670
|
0
|
|
|
|
|
|
hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); |
|
6671
|
0
|
|
|
|
|
|
hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; |
|
6672
|
0
|
0
|
|
|
|
|
if (likely(char_is_ctn(*cur))) { |
|
6673
|
0
|
0
|
|
|
|
|
dat_len = has_flg(STOP_WHEN_DONE) ? 256 : state->buf_len; |
|
6674
|
0
|
|
|
|
|
|
alc_len = hdr_len + |
|
6675
|
0
|
|
|
|
|
|
(dat_len / YYJSON_READER_ESTIMATED_MINIFY_RATIO) + 4; |
|
6676
|
0
|
|
|
|
|
|
alc_len = yyjson_min(alc_len, alc_max); |
|
6677
|
|
|
|
|
|
|
} else { |
|
6678
|
0
|
|
|
|
|
|
alc_len = hdr_len + 1; /* single value */ |
|
6679
|
|
|
|
|
|
|
} |
|
6680
|
0
|
|
|
|
|
|
val_hdr = (yyjson_val *)alc.malloc(alc.ctx, |
|
6681
|
|
|
|
|
|
|
alc_len * sizeof(yyjson_val)); |
|
6682
|
0
|
0
|
|
|
|
|
if (unlikely(!val_hdr)) goto fail_alloc; |
|
6683
|
0
|
|
|
|
|
|
val_end = val_hdr + (alc_len - 2); /* padding for kv pair reading */ |
|
6684
|
0
|
|
|
|
|
|
val = val_hdr + hdr_len; |
|
6685
|
0
|
|
|
|
|
|
ctn = val; |
|
6686
|
0
|
|
|
|
|
|
ctn_len = 0; |
|
6687
|
0
|
|
|
|
|
|
state->val_hdr = val_hdr; |
|
6688
|
0
|
|
|
|
|
|
state->val_end = val_end; |
|
6689
|
0
|
0
|
|
|
|
|
save_incr_state(doc_begin); |
|
6690
|
|
|
|
|
|
|
} |
|
6691
|
|
|
|
|
|
|
|
|
6692
|
|
|
|
|
|
|
/* read json document */ |
|
6693
|
0
|
0
|
|
|
|
|
if (*cur == '{') { |
|
6694
|
0
|
|
|
|
|
|
cur++; |
|
6695
|
0
|
|
|
|
|
|
ctn->tag = YYJSON_TYPE_OBJ; |
|
6696
|
0
|
|
|
|
|
|
ctn->uni.ofs = 0; |
|
6697
|
0
|
|
|
|
|
|
goto obj_key_begin; |
|
6698
|
|
|
|
|
|
|
} |
|
6699
|
0
|
0
|
|
|
|
|
if (*cur == '[') { |
|
6700
|
0
|
|
|
|
|
|
cur++; |
|
6701
|
0
|
|
|
|
|
|
ctn->tag = YYJSON_TYPE_ARR; |
|
6702
|
0
|
|
|
|
|
|
ctn->uni.ofs = 0; |
|
6703
|
0
|
|
|
|
|
|
goto arr_val_begin; |
|
6704
|
|
|
|
|
|
|
} |
|
6705
|
0
|
0
|
|
|
|
|
if (char_is_num(*cur)) { |
|
6706
|
0
|
0
|
|
|
|
|
if (likely(read_num(&cur, pre, flg, val, &msg))) goto doc_end; |
|
6707
|
0
|
|
|
|
|
|
goto fail_number; |
|
6708
|
|
|
|
|
|
|
} |
|
6709
|
0
|
0
|
|
|
|
|
if (*cur == '"') { |
|
6710
|
0
|
0
|
|
|
|
|
if (likely(read_str_con(&cur, end, flg, val, &msg, con))) goto doc_end; |
|
6711
|
0
|
|
|
|
|
|
goto fail_string; |
|
6712
|
|
|
|
|
|
|
} |
|
6713
|
0
|
0
|
|
|
|
|
if (*cur == 't') { |
|
6714
|
0
|
0
|
|
|
|
|
if (likely(read_true(&cur, val))) goto doc_end; |
|
6715
|
0
|
|
|
|
|
|
goto fail_literal_true; |
|
6716
|
|
|
|
|
|
|
} |
|
6717
|
0
|
0
|
|
|
|
|
if (*cur == 'f') { |
|
6718
|
0
|
0
|
|
|
|
|
if (likely(read_false(&cur, val))) goto doc_end; |
|
6719
|
0
|
|
|
|
|
|
goto fail_literal_false; |
|
6720
|
|
|
|
|
|
|
} |
|
6721
|
0
|
0
|
|
|
|
|
if (*cur == 'n') { |
|
6722
|
0
|
0
|
|
|
|
|
if (likely(read_null(&cur, val))) goto doc_end; |
|
6723
|
0
|
|
|
|
|
|
goto fail_literal_null; |
|
6724
|
|
|
|
|
|
|
} |
|
6725
|
|
|
|
|
|
|
|
|
6726
|
0
|
|
|
|
|
|
msg = "unexpected character, expected a valid root value"; |
|
6727
|
0
|
0
|
|
|
|
|
if (cur == hdr) { |
|
6728
|
|
|
|
|
|
|
/* RFC 8259: JSON text MUST be encoded using UTF-8 */ |
|
6729
|
0
|
0
|
|
|
|
|
if (is_utf8_bom(hdr)) msg = MSG_ERR_BOM; |
|
6730
|
0
|
0
|
|
|
|
|
else if (len >= 4 && is_utf32_bom(hdr)) msg = MSG_ERR_UTF32; |
|
|
|
0
|
|
|
|
|
|
|
6731
|
0
|
0
|
|
|
|
|
else if (len >= 2 && is_utf16_bom(hdr)) msg = MSG_ERR_UTF16; |
|
|
|
0
|
|
|
|
|
|
|
6732
|
|
|
|
|
|
|
} |
|
6733
|
0
|
0
|
|
|
|
|
return_err(cur, UNEXPECTED_CHARACTER, msg); |
|
6734
|
|
|
|
|
|
|
|
|
6735
|
0
|
|
|
|
|
|
arr_begin: |
|
6736
|
|
|
|
|
|
|
/* save current container */ |
|
6737
|
0
|
|
|
|
|
|
ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | |
|
6738
|
0
|
|
|
|
|
|
(ctn->tag & YYJSON_TAG_MASK); |
|
6739
|
|
|
|
|
|
|
|
|
6740
|
|
|
|
|
|
|
/* create a new array value, save parent container offset */ |
|
6741
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
6742
|
0
|
|
|
|
|
|
val->tag = YYJSON_TYPE_ARR; |
|
6743
|
0
|
|
|
|
|
|
val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); |
|
6744
|
|
|
|
|
|
|
|
|
6745
|
|
|
|
|
|
|
/* push the new array value as current container */ |
|
6746
|
0
|
|
|
|
|
|
ctn = val; |
|
6747
|
0
|
|
|
|
|
|
ctn_len = 0; |
|
6748
|
|
|
|
|
|
|
|
|
6749
|
0
|
|
|
|
|
|
arr_val_begin: |
|
6750
|
0
|
0
|
|
|
|
|
save_incr_state(arr_val_begin); |
|
6751
|
0
|
|
|
|
|
|
arr_val_continue: |
|
6752
|
0
|
0
|
|
|
|
|
if (*cur == '{') { |
|
6753
|
0
|
|
|
|
|
|
cur++; |
|
6754
|
0
|
|
|
|
|
|
goto obj_begin; |
|
6755
|
|
|
|
|
|
|
} |
|
6756
|
0
|
0
|
|
|
|
|
if (*cur == '[') { |
|
6757
|
0
|
|
|
|
|
|
cur++; |
|
6758
|
0
|
|
|
|
|
|
goto arr_begin; |
|
6759
|
|
|
|
|
|
|
} |
|
6760
|
0
|
0
|
|
|
|
|
if (char_is_num(*cur)) { |
|
6761
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
6762
|
0
|
|
|
|
|
|
ctn_len++; |
|
6763
|
0
|
0
|
|
|
|
|
if (likely(read_num(&cur, pre, flg, val, &msg))) goto arr_val_maybe_end; |
|
6764
|
0
|
|
|
|
|
|
goto fail_number; |
|
6765
|
|
|
|
|
|
|
} |
|
6766
|
0
|
0
|
|
|
|
|
if (*cur == '"') { |
|
6767
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
6768
|
0
|
0
|
|
|
|
|
ctn_len++; |
|
6769
|
0
|
0
|
|
|
|
|
if (likely(read_str_con(&cur, end, flg, val, &msg, con))) |
|
6770
|
0
|
|
|
|
|
|
goto arr_val_end; |
|
6771
|
0
|
|
|
|
|
|
goto fail_string; |
|
6772
|
|
|
|
|
|
|
} |
|
6773
|
0
|
0
|
|
|
|
|
if (*cur == 't') { |
|
6774
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
6775
|
0
|
|
|
|
|
|
ctn_len++; |
|
6776
|
0
|
0
|
|
|
|
|
if (likely(read_true(&cur, val))) goto arr_val_end; |
|
6777
|
0
|
|
|
|
|
|
goto fail_literal_true; |
|
6778
|
|
|
|
|
|
|
} |
|
6779
|
0
|
0
|
|
|
|
|
if (*cur == 'f') { |
|
6780
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
6781
|
0
|
|
|
|
|
|
ctn_len++; |
|
6782
|
0
|
0
|
|
|
|
|
if (likely(read_false(&cur, val))) goto arr_val_end; |
|
6783
|
0
|
|
|
|
|
|
goto fail_literal_false; |
|
6784
|
|
|
|
|
|
|
} |
|
6785
|
0
|
0
|
|
|
|
|
if (*cur == 'n') { |
|
6786
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
6787
|
0
|
|
|
|
|
|
ctn_len++; |
|
6788
|
0
|
0
|
|
|
|
|
if (likely(read_null(&cur, val))) goto arr_val_end; |
|
6789
|
0
|
|
|
|
|
|
goto fail_literal_null; |
|
6790
|
|
|
|
|
|
|
} |
|
6791
|
0
|
0
|
|
|
|
|
if (*cur == ']') { |
|
6792
|
0
|
|
|
|
|
|
cur++; |
|
6793
|
0
|
0
|
|
|
|
|
if (likely(ctn_len == 0)) goto arr_end; |
|
6794
|
0
|
0
|
|
|
|
|
while (*cur != ',') cur--; |
|
6795
|
0
|
|
|
|
|
|
goto fail_trailing_comma; |
|
6796
|
|
|
|
|
|
|
} |
|
6797
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6798
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6799
|
0
|
|
|
|
|
|
goto arr_val_continue; |
|
6800
|
|
|
|
|
|
|
} |
|
6801
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
6802
|
|
|
|
|
|
|
|
|
6803
|
0
|
|
|
|
|
|
arr_val_maybe_end: |
|
6804
|
|
|
|
|
|
|
/* if incremental parsing stops in the middle of a number, it may continue |
|
6805
|
|
|
|
|
|
|
with more digits, so arr val maybe didn't end yet */ |
|
6806
|
0
|
0
|
|
|
|
|
check_maybe_truncated_number(); |
|
|
|
0
|
|
|
|
|
|
|
6807
|
|
|
|
|
|
|
|
|
6808
|
0
|
|
|
|
|
|
arr_val_end: |
|
6809
|
0
|
0
|
|
|
|
|
save_incr_state(arr_val_end); |
|
6810
|
0
|
0
|
|
|
|
|
if (*cur == ',') { |
|
6811
|
0
|
|
|
|
|
|
cur++; |
|
6812
|
0
|
|
|
|
|
|
goto arr_val_begin; |
|
6813
|
|
|
|
|
|
|
} |
|
6814
|
0
|
0
|
|
|
|
|
if (*cur == ']') { |
|
6815
|
0
|
|
|
|
|
|
cur++; |
|
6816
|
0
|
|
|
|
|
|
goto arr_end; |
|
6817
|
|
|
|
|
|
|
} |
|
6818
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6819
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6820
|
0
|
|
|
|
|
|
goto arr_val_end; |
|
6821
|
|
|
|
|
|
|
} |
|
6822
|
0
|
|
|
|
|
|
goto fail_character_arr_end; |
|
6823
|
|
|
|
|
|
|
|
|
6824
|
0
|
|
|
|
|
|
arr_end: |
|
6825
|
|
|
|
|
|
|
/* get parent container */ |
|
6826
|
0
|
|
|
|
|
|
ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); |
|
6827
|
|
|
|
|
|
|
|
|
6828
|
|
|
|
|
|
|
/* save the next sibling value offset */ |
|
6829
|
0
|
|
|
|
|
|
ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); |
|
6830
|
0
|
|
|
|
|
|
ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; |
|
6831
|
0
|
0
|
|
|
|
|
if (unlikely(ctn == ctn_parent)) goto doc_end; |
|
6832
|
|
|
|
|
|
|
|
|
6833
|
|
|
|
|
|
|
/* pop parent as current container */ |
|
6834
|
0
|
|
|
|
|
|
ctn = ctn_parent; |
|
6835
|
0
|
|
|
|
|
|
ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); |
|
6836
|
0
|
0
|
|
|
|
|
if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { |
|
6837
|
0
|
|
|
|
|
|
goto obj_val_end; |
|
6838
|
|
|
|
|
|
|
} else { |
|
6839
|
0
|
|
|
|
|
|
goto arr_val_end; |
|
6840
|
|
|
|
|
|
|
} |
|
6841
|
|
|
|
|
|
|
|
|
6842
|
0
|
|
|
|
|
|
obj_begin: |
|
6843
|
|
|
|
|
|
|
/* push container */ |
|
6844
|
0
|
|
|
|
|
|
ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | |
|
6845
|
0
|
|
|
|
|
|
(ctn->tag & YYJSON_TAG_MASK); |
|
6846
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
6847
|
0
|
|
|
|
|
|
val->tag = YYJSON_TYPE_OBJ; |
|
6848
|
|
|
|
|
|
|
/* offset to the parent */ |
|
6849
|
0
|
|
|
|
|
|
val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); |
|
6850
|
0
|
|
|
|
|
|
ctn = val; |
|
6851
|
0
|
|
|
|
|
|
ctn_len = 0; |
|
6852
|
|
|
|
|
|
|
|
|
6853
|
0
|
|
|
|
|
|
obj_key_begin: |
|
6854
|
0
|
0
|
|
|
|
|
save_incr_state(obj_key_begin); |
|
6855
|
0
|
|
|
|
|
|
obj_key_continue: |
|
6856
|
0
|
0
|
|
|
|
|
if (likely(*cur == '"')) { |
|
6857
|
0
|
0
|
|
|
|
|
val_incr(); |
|
|
|
0
|
|
|
|
|
|
|
6858
|
0
|
0
|
|
|
|
|
ctn_len++; |
|
6859
|
0
|
0
|
|
|
|
|
if (likely(read_str_con(&cur, end, flg, val, &msg, con))) |
|
6860
|
0
|
|
|
|
|
|
goto obj_key_end; |
|
6861
|
0
|
|
|
|
|
|
goto fail_string; |
|
6862
|
|
|
|
|
|
|
} |
|
6863
|
0
|
0
|
|
|
|
|
if (likely(*cur == '}')) { |
|
6864
|
0
|
|
|
|
|
|
cur++; |
|
6865
|
0
|
0
|
|
|
|
|
if (likely(ctn_len == 0)) goto obj_end; |
|
6866
|
0
|
0
|
|
|
|
|
while (*cur != ',') cur--; |
|
6867
|
0
|
|
|
|
|
|
goto fail_trailing_comma; |
|
6868
|
|
|
|
|
|
|
} |
|
6869
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6870
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6871
|
0
|
|
|
|
|
|
goto obj_key_continue; |
|
6872
|
|
|
|
|
|
|
} |
|
6873
|
0
|
|
|
|
|
|
goto fail_character_obj_key; |
|
6874
|
|
|
|
|
|
|
|
|
6875
|
0
|
|
|
|
|
|
obj_key_end: |
|
6876
|
0
|
0
|
|
|
|
|
save_incr_state(obj_key_end); |
|
6877
|
0
|
0
|
|
|
|
|
if (*cur == ':') { |
|
6878
|
0
|
|
|
|
|
|
cur++; |
|
6879
|
0
|
|
|
|
|
|
goto obj_val_begin; |
|
6880
|
|
|
|
|
|
|
} |
|
6881
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6882
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6883
|
0
|
|
|
|
|
|
goto obj_key_end; |
|
6884
|
|
|
|
|
|
|
} |
|
6885
|
0
|
|
|
|
|
|
goto fail_character_obj_sep; |
|
6886
|
|
|
|
|
|
|
|
|
6887
|
0
|
|
|
|
|
|
obj_val_begin: |
|
6888
|
0
|
0
|
|
|
|
|
save_incr_state(obj_val_begin); |
|
6889
|
0
|
|
|
|
|
|
obj_val_continue: |
|
6890
|
0
|
0
|
|
|
|
|
if (*cur == '"') { |
|
6891
|
0
|
|
|
|
|
|
val++; |
|
6892
|
0
|
0
|
|
|
|
|
ctn_len++; |
|
6893
|
0
|
0
|
|
|
|
|
if (likely(read_str_con(&cur, end, flg, val, &msg, con))) |
|
6894
|
0
|
|
|
|
|
|
goto obj_val_end; |
|
6895
|
0
|
|
|
|
|
|
goto fail_string; |
|
6896
|
|
|
|
|
|
|
} |
|
6897
|
0
|
0
|
|
|
|
|
if (char_is_num(*cur)) { |
|
6898
|
0
|
|
|
|
|
|
val++; |
|
6899
|
0
|
|
|
|
|
|
ctn_len++; |
|
6900
|
0
|
0
|
|
|
|
|
if (likely(read_num(&cur, pre, flg, val, &msg))) goto obj_val_maybe_end; |
|
6901
|
0
|
|
|
|
|
|
goto fail_number; |
|
6902
|
|
|
|
|
|
|
} |
|
6903
|
0
|
0
|
|
|
|
|
if (*cur == '{') { |
|
6904
|
0
|
|
|
|
|
|
cur++; |
|
6905
|
0
|
|
|
|
|
|
goto obj_begin; |
|
6906
|
|
|
|
|
|
|
} |
|
6907
|
0
|
0
|
|
|
|
|
if (*cur == '[') { |
|
6908
|
0
|
|
|
|
|
|
cur++; |
|
6909
|
0
|
|
|
|
|
|
goto arr_begin; |
|
6910
|
|
|
|
|
|
|
} |
|
6911
|
0
|
0
|
|
|
|
|
if (*cur == 't') { |
|
6912
|
0
|
|
|
|
|
|
val++; |
|
6913
|
0
|
|
|
|
|
|
ctn_len++; |
|
6914
|
0
|
0
|
|
|
|
|
if (likely(read_true(&cur, val))) goto obj_val_end; |
|
6915
|
0
|
|
|
|
|
|
goto fail_literal_true; |
|
6916
|
|
|
|
|
|
|
} |
|
6917
|
0
|
0
|
|
|
|
|
if (*cur == 'f') { |
|
6918
|
0
|
|
|
|
|
|
val++; |
|
6919
|
0
|
|
|
|
|
|
ctn_len++; |
|
6920
|
0
|
0
|
|
|
|
|
if (likely(read_false(&cur, val))) goto obj_val_end; |
|
6921
|
0
|
|
|
|
|
|
goto fail_literal_false; |
|
6922
|
|
|
|
|
|
|
} |
|
6923
|
0
|
0
|
|
|
|
|
if (*cur == 'n') { |
|
6924
|
0
|
|
|
|
|
|
val++; |
|
6925
|
0
|
|
|
|
|
|
ctn_len++; |
|
6926
|
0
|
0
|
|
|
|
|
if (likely(read_null(&cur, val))) goto obj_val_end; |
|
6927
|
0
|
|
|
|
|
|
goto fail_literal_null; |
|
6928
|
|
|
|
|
|
|
} |
|
6929
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6930
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6931
|
0
|
|
|
|
|
|
goto obj_val_continue; |
|
6932
|
|
|
|
|
|
|
} |
|
6933
|
0
|
|
|
|
|
|
goto fail_character_val; |
|
6934
|
|
|
|
|
|
|
|
|
6935
|
0
|
|
|
|
|
|
obj_val_maybe_end: |
|
6936
|
|
|
|
|
|
|
/* if incremental parsing stops in the middle of a number, it may continue |
|
6937
|
|
|
|
|
|
|
with more digits, so obj val maybe didn't end yet */ |
|
6938
|
0
|
0
|
|
|
|
|
check_maybe_truncated_number(); |
|
|
|
0
|
|
|
|
|
|
|
6939
|
|
|
|
|
|
|
|
|
6940
|
0
|
|
|
|
|
|
obj_val_end: |
|
6941
|
0
|
0
|
|
|
|
|
save_incr_state(obj_val_end); |
|
6942
|
0
|
0
|
|
|
|
|
if (likely(*cur == ',')) { |
|
6943
|
0
|
|
|
|
|
|
cur++; |
|
6944
|
0
|
|
|
|
|
|
goto obj_key_begin; |
|
6945
|
|
|
|
|
|
|
} |
|
6946
|
0
|
0
|
|
|
|
|
if (likely(*cur == '}')) { |
|
6947
|
0
|
|
|
|
|
|
cur++; |
|
6948
|
0
|
|
|
|
|
|
goto obj_end; |
|
6949
|
|
|
|
|
|
|
} |
|
6950
|
0
|
0
|
|
|
|
|
if (char_is_space(*cur)) { |
|
6951
|
0
|
0
|
|
|
|
|
while (char_is_space(*++cur)); |
|
6952
|
0
|
|
|
|
|
|
goto obj_val_end; |
|
6953
|
|
|
|
|
|
|
} |
|
6954
|
0
|
|
|
|
|
|
goto fail_character_obj_end; |
|
6955
|
|
|
|
|
|
|
|
|
6956
|
0
|
|
|
|
|
|
obj_end: |
|
6957
|
|
|
|
|
|
|
/* pop container */ |
|
6958
|
0
|
|
|
|
|
|
ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); |
|
6959
|
|
|
|
|
|
|
/* point to the next value */ |
|
6960
|
0
|
|
|
|
|
|
ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); |
|
6961
|
0
|
|
|
|
|
|
ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ; |
|
6962
|
0
|
0
|
|
|
|
|
if (unlikely(ctn == ctn_parent)) goto doc_end; |
|
6963
|
0
|
|
|
|
|
|
ctn = ctn_parent; |
|
6964
|
0
|
|
|
|
|
|
ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); |
|
6965
|
0
|
0
|
|
|
|
|
if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { |
|
6966
|
0
|
|
|
|
|
|
goto obj_val_end; |
|
6967
|
|
|
|
|
|
|
} else { |
|
6968
|
0
|
|
|
|
|
|
goto arr_val_end; |
|
6969
|
|
|
|
|
|
|
} |
|
6970
|
|
|
|
|
|
|
|
|
6971
|
0
|
|
|
|
|
|
doc_end: |
|
6972
|
|
|
|
|
|
|
/* check invalid contents after json document */ |
|
6973
|
0
|
0
|
|
|
|
|
if (unlikely(cur < end) && !has_flg(STOP_WHEN_DONE)) { |
|
|
|
0
|
|
|
|
|
|
|
6974
|
0
|
0
|
|
|
|
|
save_incr_state(doc_end); |
|
6975
|
0
|
0
|
|
|
|
|
while (char_is_space(*cur)) cur++; |
|
6976
|
0
|
0
|
|
|
|
|
if (unlikely(cur < end)) goto fail_garbage; |
|
6977
|
|
|
|
|
|
|
} |
|
6978
|
|
|
|
|
|
|
|
|
6979
|
0
|
|
|
|
|
|
**pre = '\0'; |
|
6980
|
0
|
|
|
|
|
|
doc = (yyjson_doc *)val_hdr; |
|
6981
|
0
|
|
|
|
|
|
doc->root = val_hdr + hdr_len; |
|
6982
|
0
|
|
|
|
|
|
doc->alc = alc; |
|
6983
|
0
|
|
|
|
|
|
doc->dat_read = (usize)(cur - hdr); |
|
6984
|
0
|
|
|
|
|
|
doc->val_read = (usize)((val - doc->root) + 1); |
|
6985
|
0
|
0
|
|
|
|
|
doc->str_pool = has_flg(INSITU) ? NULL : (char *)hdr; |
|
6986
|
0
|
|
|
|
|
|
state->hdr = NULL; |
|
6987
|
0
|
|
|
|
|
|
state->val_hdr = NULL; |
|
6988
|
0
|
|
|
|
|
|
memset(err, 0, sizeof(yyjson_read_err)); |
|
6989
|
0
|
|
|
|
|
|
return doc; |
|
6990
|
|
|
|
|
|
|
|
|
6991
|
0
|
|
|
|
|
|
unexpected_end: |
|
6992
|
0
|
|
|
|
|
|
err->pos = len; |
|
6993
|
|
|
|
|
|
|
/* if no nore data, stop the incr read */ |
|
6994
|
0
|
0
|
|
|
|
|
if (unlikely(len >= state->buf_len)) { |
|
6995
|
0
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_UNEXPECTED_END; |
|
6996
|
0
|
|
|
|
|
|
err->msg = MSG_NOT_END; |
|
6997
|
0
|
|
|
|
|
|
return NULL; |
|
6998
|
|
|
|
|
|
|
} |
|
6999
|
|
|
|
|
|
|
/* save parser state in extended error struct, in addition to what was |
|
7000
|
|
|
|
|
|
|
* stored in the last save_incr_state */ |
|
7001
|
0
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_MORE; |
|
7002
|
0
|
|
|
|
|
|
err->msg = "need more data"; |
|
7003
|
0
|
|
|
|
|
|
state->val_end = val_end; |
|
7004
|
0
|
|
|
|
|
|
state->ctn = ctn; |
|
7005
|
0
|
|
|
|
|
|
state->alc_len = alc_len; |
|
7006
|
|
|
|
|
|
|
/* restore the end where we've inserted a null terminator */ |
|
7007
|
0
|
|
|
|
|
|
*end = saved_end; |
|
7008
|
0
|
|
|
|
|
|
return NULL; |
|
7009
|
|
|
|
|
|
|
|
|
7010
|
0
|
0
|
|
|
|
|
fail_string: return_err(cur, INVALID_STRING, msg); |
|
7011
|
0
|
0
|
|
|
|
|
fail_number: return_err(cur, INVALID_NUMBER, msg); |
|
7012
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(cur, MEMORY_ALLOCATION, MSG_MALLOC); |
|
7013
|
0
|
0
|
|
|
|
|
fail_trailing_comma: return_err(cur, JSON_STRUCTURE, MSG_COMMA); |
|
7014
|
0
|
0
|
|
|
|
|
fail_literal_true: return_err(cur, LITERAL, MSG_CHAR_T); |
|
7015
|
0
|
0
|
|
|
|
|
fail_literal_false: return_err(cur, LITERAL, MSG_CHAR_F); |
|
7016
|
0
|
0
|
|
|
|
|
fail_literal_null: return_err(cur, LITERAL, MSG_CHAR_N); |
|
7017
|
0
|
0
|
|
|
|
|
fail_character_val: return_err(cur, UNEXPECTED_CHARACTER, MSG_CHAR); |
|
7018
|
0
|
0
|
|
|
|
|
fail_character_arr_end: return_err(cur, UNEXPECTED_CHARACTER, MSG_ARR_END); |
|
7019
|
0
|
0
|
|
|
|
|
fail_character_obj_key: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_KEY); |
|
7020
|
0
|
0
|
|
|
|
|
fail_character_obj_sep: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_SEP); |
|
7021
|
0
|
0
|
|
|
|
|
fail_character_obj_end: return_err(cur, UNEXPECTED_CHARACTER, MSG_OBJ_END); |
|
7022
|
0
|
0
|
|
|
|
|
fail_garbage: return_err(cur, UNEXPECTED_CONTENT, MSG_GARBAGE); |
|
7023
|
|
|
|
|
|
|
|
|
7024
|
|
|
|
|
|
|
#undef val_incr |
|
7025
|
|
|
|
|
|
|
#undef return_err |
|
7026
|
|
|
|
|
|
|
#undef return_err_inv_param |
|
7027
|
|
|
|
|
|
|
#undef save_incr_state |
|
7028
|
|
|
|
|
|
|
#undef check_maybe_truncated_number |
|
7029
|
|
|
|
|
|
|
} |
|
7030
|
|
|
|
|
|
|
|
|
7031
|
|
|
|
|
|
|
#endif /* YYJSON_DISABLE_INCR_READER */ |
|
7032
|
|
|
|
|
|
|
|
|
7033
|
|
|
|
|
|
|
#undef has_flg |
|
7034
|
|
|
|
|
|
|
#undef has_allow |
|
7035
|
|
|
|
|
|
|
#endif /* YYJSON_DISABLE_READER */ |
|
7036
|
|
|
|
|
|
|
|
|
7037
|
|
|
|
|
|
|
|
|
7038
|
|
|
|
|
|
|
|
|
7039
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_WRITER /* writer begin */ |
|
7040
|
|
|
|
|
|
|
|
|
7041
|
|
|
|
|
|
|
/* Check write flag, avoids `always false` warning when disabled. */ |
|
7042
|
|
|
|
|
|
|
#define has_flg(_flg) unlikely(has_wflag(flg, YYJSON_WRITE_##_flg, 0)) |
|
7043
|
|
|
|
|
|
|
#define has_allow(_flg) unlikely(has_wflag(flg, YYJSON_WRITE_ALLOW_##_flg, 1)) |
|
7044
|
|
|
|
|
|
|
static_inline bool has_wflag(yyjson_write_flag flg, yyjson_write_flag chk, |
|
7045
|
|
|
|
|
|
|
bool non_standard) { |
|
7046
|
|
|
|
|
|
|
#if YYJSON_DISABLE_NON_STANDARD |
|
7047
|
|
|
|
|
|
|
if (non_standard) return false; |
|
7048
|
|
|
|
|
|
|
#endif |
|
7049
|
75239
|
|
|
|
|
|
return (flg & chk) != 0; |
|
7050
|
|
|
|
|
|
|
} |
|
7051
|
|
|
|
|
|
|
|
|
7052
|
|
|
|
|
|
|
/*============================================================================== |
|
7053
|
|
|
|
|
|
|
* MARK: - Integer Writer (Private) |
|
7054
|
|
|
|
|
|
|
* |
|
7055
|
|
|
|
|
|
|
* The maximum value of uint32_t is 4294967295 (10 digits), |
|
7056
|
|
|
|
|
|
|
* these digits are named as 'aabbccddee' here. |
|
7057
|
|
|
|
|
|
|
* |
|
7058
|
|
|
|
|
|
|
* Although most compilers may convert the "division by constant value" into |
|
7059
|
|
|
|
|
|
|
* "multiply and shift", manual conversion can still help some compilers |
|
7060
|
|
|
|
|
|
|
* generate fewer and better instructions. |
|
7061
|
|
|
|
|
|
|
* |
|
7062
|
|
|
|
|
|
|
* Reference: |
|
7063
|
|
|
|
|
|
|
* Division by Invariant Integers using Multiplication, 1994. |
|
7064
|
|
|
|
|
|
|
* https://gmplib.org/~tege/divcnst-pldi94.pdf |
|
7065
|
|
|
|
|
|
|
* Improved division by invariant integers, 2011. |
|
7066
|
|
|
|
|
|
|
* https://gmplib.org/~tege/division-paper.pdf |
|
7067
|
|
|
|
|
|
|
*============================================================================*/ |
|
7068
|
|
|
|
|
|
|
|
|
7069
|
|
|
|
|
|
|
/** Digit table from 00 to 99. */ |
|
7070
|
|
|
|
|
|
|
yyjson_align(2) |
|
7071
|
|
|
|
|
|
|
static const char digit_table[200] = { |
|
7072
|
|
|
|
|
|
|
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', |
|
7073
|
|
|
|
|
|
|
'0', '5', '0', '6', '0', '7', '0', '8', '0', '9', |
|
7074
|
|
|
|
|
|
|
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', |
|
7075
|
|
|
|
|
|
|
'1', '5', '1', '6', '1', '7', '1', '8', '1', '9', |
|
7076
|
|
|
|
|
|
|
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', |
|
7077
|
|
|
|
|
|
|
'2', '5', '2', '6', '2', '7', '2', '8', '2', '9', |
|
7078
|
|
|
|
|
|
|
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', |
|
7079
|
|
|
|
|
|
|
'3', '5', '3', '6', '3', '7', '3', '8', '3', '9', |
|
7080
|
|
|
|
|
|
|
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4', |
|
7081
|
|
|
|
|
|
|
'4', '5', '4', '6', '4', '7', '4', '8', '4', '9', |
|
7082
|
|
|
|
|
|
|
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4', |
|
7083
|
|
|
|
|
|
|
'5', '5', '5', '6', '5', '7', '5', '8', '5', '9', |
|
7084
|
|
|
|
|
|
|
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', |
|
7085
|
|
|
|
|
|
|
'6', '5', '6', '6', '6', '7', '6', '8', '6', '9', |
|
7086
|
|
|
|
|
|
|
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', |
|
7087
|
|
|
|
|
|
|
'7', '5', '7', '6', '7', '7', '7', '8', '7', '9', |
|
7088
|
|
|
|
|
|
|
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4', |
|
7089
|
|
|
|
|
|
|
'8', '5', '8', '6', '8', '7', '8', '8', '8', '9', |
|
7090
|
|
|
|
|
|
|
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', |
|
7091
|
|
|
|
|
|
|
'9', '5', '9', '6', '9', '7', '9', '8', '9', '9' |
|
7092
|
|
|
|
|
|
|
}; |
|
7093
|
|
|
|
|
|
|
|
|
7094
|
|
|
|
|
|
|
static_inline u8 *write_u32_len_8(u32 val, u8 *buf) { |
|
7095
|
|
|
|
|
|
|
u32 aa, bb, cc, dd, aabb, ccdd; /* 8 digits: aabbccdd */ |
|
7096
|
0
|
|
|
|
|
|
aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ |
|
7097
|
0
|
|
|
|
|
|
ccdd = val - aabb * 10000; /* (val % 10000) */ |
|
7098
|
0
|
|
|
|
|
|
aa = (aabb * 5243) >> 19; /* (aabb / 100) */ |
|
7099
|
0
|
|
|
|
|
|
cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ |
|
7100
|
0
|
|
|
|
|
|
bb = aabb - aa * 100; /* (aabb % 100) */ |
|
7101
|
0
|
|
|
|
|
|
dd = ccdd - cc * 100; /* (ccdd % 100) */ |
|
7102
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + aa * 2); |
|
7103
|
0
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + bb * 2); |
|
7104
|
0
|
|
|
|
|
|
byte_copy_2(buf + 4, digit_table + cc * 2); |
|
7105
|
0
|
|
|
|
|
|
byte_copy_2(buf + 6, digit_table + dd * 2); |
|
7106
|
0
|
|
|
|
|
|
return buf + 8; |
|
7107
|
|
|
|
|
|
|
} |
|
7108
|
|
|
|
|
|
|
|
|
7109
|
|
|
|
|
|
|
static_inline u8 *write_u32_len_4(u32 val, u8 *buf) { |
|
7110
|
|
|
|
|
|
|
u32 aa, bb; /* 4 digits: aabb */ |
|
7111
|
0
|
|
|
|
|
|
aa = (val * 5243) >> 19; /* (val / 100) */ |
|
7112
|
0
|
|
|
|
|
|
bb = val - aa * 100; /* (val % 100) */ |
|
7113
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + aa * 2); |
|
7114
|
0
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + bb * 2); |
|
7115
|
0
|
|
|
|
|
|
return buf + 4; |
|
7116
|
|
|
|
|
|
|
} |
|
7117
|
|
|
|
|
|
|
|
|
7118
|
|
|
|
|
|
|
static_inline u8 *write_u32_len_1_to_8(u32 val, u8 *buf) { |
|
7119
|
|
|
|
|
|
|
u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz; |
|
7120
|
|
|
|
|
|
|
|
|
7121
|
35053
|
|
|
|
|
|
if (val < 100) { /* 1-2 digits: aa */ |
|
7122
|
35053
|
|
|
|
|
|
lz = val < 10; /* leading zero: 0 or 1 */ |
|
7123
|
35053
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + val * 2 + lz); |
|
7124
|
35053
|
|
|
|
|
|
buf -= lz; |
|
7125
|
35053
|
|
|
|
|
|
return buf + 2; |
|
7126
|
|
|
|
|
|
|
|
|
7127
|
0
|
0
|
|
|
|
|
} else if (val < 10000) { /* 3-4 digits: aabb */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7128
|
0
|
|
|
|
|
|
aa = (val * 5243) >> 19; /* (val / 100) */ |
|
7129
|
0
|
|
|
|
|
|
bb = val - aa * 100; /* (val % 100) */ |
|
7130
|
0
|
|
|
|
|
|
lz = aa < 10; /* leading zero: 0 or 1 */ |
|
7131
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + aa * 2 + lz); |
|
7132
|
0
|
|
|
|
|
|
buf -= lz; |
|
7133
|
0
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + bb * 2); |
|
7134
|
0
|
|
|
|
|
|
return buf + 4; |
|
7135
|
|
|
|
|
|
|
|
|
7136
|
0
|
0
|
|
|
|
|
} else if (val < 1000000) { /* 5-6 digits: aabbcc */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7137
|
0
|
|
|
|
|
|
aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */ |
|
7138
|
0
|
|
|
|
|
|
bbcc = val - aa * 10000; /* (val % 10000) */ |
|
7139
|
0
|
|
|
|
|
|
bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */ |
|
7140
|
0
|
|
|
|
|
|
cc = bbcc - bb * 100; /* (bbcc % 100) */ |
|
7141
|
0
|
|
|
|
|
|
lz = aa < 10; /* leading zero: 0 or 1 */ |
|
7142
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + aa * 2 + lz); |
|
7143
|
0
|
|
|
|
|
|
buf -= lz; |
|
7144
|
0
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + bb * 2); |
|
7145
|
0
|
|
|
|
|
|
byte_copy_2(buf + 4, digit_table + cc * 2); |
|
7146
|
0
|
|
|
|
|
|
return buf + 6; |
|
7147
|
|
|
|
|
|
|
|
|
7148
|
|
|
|
|
|
|
} else { /* 7-8 digits: aabbccdd */ |
|
7149
|
0
|
|
|
|
|
|
aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ |
|
7150
|
0
|
|
|
|
|
|
ccdd = val - aabb * 10000; /* (val % 10000) */ |
|
7151
|
0
|
|
|
|
|
|
aa = (aabb * 5243) >> 19; /* (aabb / 100) */ |
|
7152
|
0
|
|
|
|
|
|
cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ |
|
7153
|
0
|
|
|
|
|
|
bb = aabb - aa * 100; /* (aabb % 100) */ |
|
7154
|
0
|
|
|
|
|
|
dd = ccdd - cc * 100; /* (ccdd % 100) */ |
|
7155
|
0
|
|
|
|
|
|
lz = aa < 10; /* leading zero: 0 or 1 */ |
|
7156
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + aa * 2 + lz); |
|
7157
|
0
|
|
|
|
|
|
buf -= lz; |
|
7158
|
0
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + bb * 2); |
|
7159
|
0
|
|
|
|
|
|
byte_copy_2(buf + 4, digit_table + cc * 2); |
|
7160
|
0
|
|
|
|
|
|
byte_copy_2(buf + 6, digit_table + dd * 2); |
|
7161
|
0
|
|
|
|
|
|
return buf + 8; |
|
7162
|
|
|
|
|
|
|
} |
|
7163
|
|
|
|
|
|
|
} |
|
7164
|
|
|
|
|
|
|
|
|
7165
|
|
|
|
|
|
|
static_inline u8 *write_u32_len_5_to_8(u32 val, u8 *buf) { |
|
7166
|
|
|
|
|
|
|
u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz; |
|
7167
|
|
|
|
|
|
|
|
|
7168
|
0
|
|
|
|
|
|
if (val < 1000000) { /* 5-6 digits: aabbcc */ |
|
7169
|
0
|
|
|
|
|
|
aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */ |
|
7170
|
0
|
|
|
|
|
|
bbcc = val - aa * 10000; /* (val % 10000) */ |
|
7171
|
0
|
|
|
|
|
|
bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */ |
|
7172
|
0
|
|
|
|
|
|
cc = bbcc - bb * 100; /* (bbcc % 100) */ |
|
7173
|
0
|
|
|
|
|
|
lz = aa < 10; /* leading zero: 0 or 1 */ |
|
7174
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + aa * 2 + lz); |
|
7175
|
0
|
|
|
|
|
|
buf -= lz; |
|
7176
|
0
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + bb * 2); |
|
7177
|
0
|
|
|
|
|
|
byte_copy_2(buf + 4, digit_table + cc * 2); |
|
7178
|
0
|
|
|
|
|
|
return buf + 6; |
|
7179
|
|
|
|
|
|
|
|
|
7180
|
|
|
|
|
|
|
} else { /* 7-8 digits: aabbccdd */ |
|
7181
|
0
|
|
|
|
|
|
aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ |
|
7182
|
0
|
|
|
|
|
|
ccdd = val - aabb * 10000; /* (val % 10000) */ |
|
7183
|
0
|
|
|
|
|
|
aa = (aabb * 5243) >> 19; /* (aabb / 100) */ |
|
7184
|
0
|
|
|
|
|
|
cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ |
|
7185
|
0
|
|
|
|
|
|
bb = aabb - aa * 100; /* (aabb % 100) */ |
|
7186
|
0
|
|
|
|
|
|
dd = ccdd - cc * 100; /* (ccdd % 100) */ |
|
7187
|
0
|
|
|
|
|
|
lz = aa < 10; /* leading zero: 0 or 1 */ |
|
7188
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + aa * 2 + lz); |
|
7189
|
0
|
|
|
|
|
|
buf -= lz; |
|
7190
|
0
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + bb * 2); |
|
7191
|
0
|
|
|
|
|
|
byte_copy_2(buf + 4, digit_table + cc * 2); |
|
7192
|
0
|
|
|
|
|
|
byte_copy_2(buf + 6, digit_table + dd * 2); |
|
7193
|
0
|
|
|
|
|
|
return buf + 8; |
|
7194
|
|
|
|
|
|
|
} |
|
7195
|
|
|
|
|
|
|
} |
|
7196
|
|
|
|
|
|
|
|
|
7197
|
|
|
|
|
|
|
static_inline u8 *write_u64(u64 val, u8 *buf) { |
|
7198
|
|
|
|
|
|
|
u64 tmp, hgh; |
|
7199
|
|
|
|
|
|
|
u32 mid, low; |
|
7200
|
|
|
|
|
|
|
|
|
7201
|
35053
|
50
|
|
|
|
|
if (val < 100000000) { /* 1-8 digits */ |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7202
|
35053
|
50
|
|
|
|
|
buf = write_u32_len_1_to_8((u32)val, buf); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7203
|
35053
|
|
|
|
|
|
return buf; |
|
7204
|
|
|
|
|
|
|
|
|
7205
|
0
|
0
|
|
|
|
|
} else if (val < (u64)100000000 * 100000000) { /* 9-16 digits */ |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7206
|
0
|
|
|
|
|
|
hgh = val / 100000000; /* (val / 100000000) */ |
|
7207
|
0
|
|
|
|
|
|
low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ |
|
7208
|
0
|
0
|
|
|
|
|
buf = write_u32_len_1_to_8((u32)hgh, buf); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7209
|
0
|
|
|
|
|
|
buf = write_u32_len_8(low, buf); |
|
7210
|
0
|
|
|
|
|
|
return buf; |
|
7211
|
|
|
|
|
|
|
|
|
7212
|
|
|
|
|
|
|
} else { /* 17-20 digits */ |
|
7213
|
0
|
|
|
|
|
|
tmp = val / 100000000; /* (val / 100000000) */ |
|
7214
|
0
|
|
|
|
|
|
low = (u32)(val - tmp * 100000000); /* (val % 100000000) */ |
|
7215
|
0
|
|
|
|
|
|
hgh = (u32)(tmp / 10000); /* (tmp / 10000) */ |
|
7216
|
0
|
|
|
|
|
|
mid = (u32)(tmp - hgh * 10000); /* (tmp % 10000) */ |
|
7217
|
0
|
0
|
|
|
|
|
buf = write_u32_len_5_to_8((u32)hgh, buf); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7218
|
0
|
|
|
|
|
|
buf = write_u32_len_4(mid, buf); |
|
7219
|
0
|
|
|
|
|
|
buf = write_u32_len_8(low, buf); |
|
7220
|
0
|
|
|
|
|
|
return buf; |
|
7221
|
|
|
|
|
|
|
} |
|
7222
|
|
|
|
|
|
|
} |
|
7223
|
|
|
|
|
|
|
|
|
7224
|
|
|
|
|
|
|
|
|
7225
|
|
|
|
|
|
|
|
|
7226
|
|
|
|
|
|
|
/*============================================================================== |
|
7227
|
|
|
|
|
|
|
* MARK: - Number Writer (Private) |
|
7228
|
|
|
|
|
|
|
*============================================================================*/ |
|
7229
|
|
|
|
|
|
|
|
|
7230
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_FAST_FP_CONV /* FP_WRITER */ |
|
7231
|
|
|
|
|
|
|
|
|
7232
|
|
|
|
|
|
|
/** Trailing zero count table for number 0 to 99. |
|
7233
|
|
|
|
|
|
|
(generate with misc/make_tables.c) */ |
|
7234
|
|
|
|
|
|
|
static const u8 dec_trailing_zero_table[] = { |
|
7235
|
|
|
|
|
|
|
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7236
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7237
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7238
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7239
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7240
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7241
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7242
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7243
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
7244
|
|
|
|
|
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
|
7245
|
|
|
|
|
|
|
}; |
|
7246
|
|
|
|
|
|
|
|
|
7247
|
|
|
|
|
|
|
static_inline u8 *write_u64_len_1_to_16(u64 val, u8 *buf) { |
|
7248
|
|
|
|
|
|
|
u64 hgh; |
|
7249
|
|
|
|
|
|
|
u32 low; |
|
7250
|
0
|
|
|
|
|
|
if (val < 100000000) { /* 1-8 digits */ |
|
7251
|
0
|
0
|
|
|
|
|
buf = write_u32_len_1_to_8((u32)val, buf); |
|
|
|
0
|
|
|
|
|
|
|
7252
|
0
|
|
|
|
|
|
return buf; |
|
7253
|
|
|
|
|
|
|
} else { /* 9-16 digits */ |
|
7254
|
0
|
|
|
|
|
|
hgh = val / 100000000; /* (val / 100000000) */ |
|
7255
|
0
|
|
|
|
|
|
low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ |
|
7256
|
0
|
0
|
|
|
|
|
buf = write_u32_len_1_to_8((u32)hgh, buf); |
|
|
|
0
|
|
|
|
|
|
|
7257
|
0
|
|
|
|
|
|
buf = write_u32_len_8(low, buf); |
|
7258
|
0
|
|
|
|
|
|
return buf; |
|
7259
|
|
|
|
|
|
|
} |
|
7260
|
|
|
|
|
|
|
} |
|
7261
|
|
|
|
|
|
|
|
|
7262
|
|
|
|
|
|
|
static_inline u8 *write_u64_len_1_to_17(u64 val, u8 *buf) { |
|
7263
|
|
|
|
|
|
|
u64 hgh; |
|
7264
|
|
|
|
|
|
|
u32 mid, low, one; |
|
7265
|
0
|
|
|
|
|
|
if (val >= (u64)100000000 * 10000000) { /* len: 16 to 17 */ |
|
7266
|
0
|
|
|
|
|
|
hgh = val / 100000000; /* (val / 100000000) */ |
|
7267
|
0
|
|
|
|
|
|
low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ |
|
7268
|
0
|
|
|
|
|
|
one = (u32)(hgh / 100000000); /* (hgh / 100000000) */ |
|
7269
|
0
|
|
|
|
|
|
mid = (u32)(hgh - (u64)one * 100000000); /* (hgh % 100000000) */ |
|
7270
|
0
|
|
|
|
|
|
*buf = (u8)((u8)one + (u8)'0'); |
|
7271
|
0
|
|
|
|
|
|
buf += one > 0; |
|
7272
|
0
|
|
|
|
|
|
buf = write_u32_len_8(mid, buf); |
|
7273
|
0
|
|
|
|
|
|
buf = write_u32_len_8(low, buf); |
|
7274
|
0
|
|
|
|
|
|
return buf; |
|
7275
|
0
|
0
|
|
|
|
|
} else if (val >= (u64)100000000){ /* len: 9 to 15 */ |
|
|
|
0
|
|
|
|
|
|
|
7276
|
0
|
|
|
|
|
|
hgh = val / 100000000; /* (val / 100000000) */ |
|
7277
|
0
|
|
|
|
|
|
low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ |
|
7278
|
0
|
0
|
|
|
|
|
buf = write_u32_len_1_to_8((u32)hgh, buf); |
|
|
|
0
|
|
|
|
|
|
|
7279
|
0
|
|
|
|
|
|
buf = write_u32_len_8(low, buf); |
|
7280
|
0
|
|
|
|
|
|
return buf; |
|
7281
|
|
|
|
|
|
|
} else { /* len: 1 to 8 */ |
|
7282
|
0
|
0
|
|
|
|
|
buf = write_u32_len_1_to_8((u32)val, buf); |
|
|
|
0
|
|
|
|
|
|
|
7283
|
0
|
|
|
|
|
|
return buf; |
|
7284
|
|
|
|
|
|
|
} |
|
7285
|
|
|
|
|
|
|
} |
|
7286
|
|
|
|
|
|
|
|
|
7287
|
|
|
|
|
|
|
/** |
|
7288
|
|
|
|
|
|
|
Write an unsigned integer with a length of 7 to 9 with trailing zero trimmed. |
|
7289
|
|
|
|
|
|
|
These digits are named as "abbccddee" here. |
|
7290
|
|
|
|
|
|
|
For example, input 123456000, output "123456". |
|
7291
|
|
|
|
|
|
|
*/ |
|
7292
|
|
|
|
|
|
|
static_inline u8 *write_u32_len_7_to_9_trim(u32 val, u8 *buf) { |
|
7293
|
|
|
|
|
|
|
bool lz; |
|
7294
|
|
|
|
|
|
|
u32 tz, tz1, tz2; |
|
7295
|
|
|
|
|
|
|
|
|
7296
|
0
|
|
|
|
|
|
u32 abbcc = val / 10000; /* (abbccddee / 10000) */ |
|
7297
|
0
|
|
|
|
|
|
u32 ddee = val - abbcc * 10000; /* (abbccddee % 10000) */ |
|
7298
|
0
|
|
|
|
|
|
u32 abb = (u32)(((u64)abbcc * 167773) >> 24); /* (abbcc / 100) */ |
|
7299
|
0
|
|
|
|
|
|
u32 a = (abb * 41) >> 12; /* (abb / 100) */ |
|
7300
|
0
|
|
|
|
|
|
u32 bb = abb - a * 100; /* (abb % 100) */ |
|
7301
|
0
|
|
|
|
|
|
u32 cc = abbcc - abb * 100; /* (abbcc % 100) */ |
|
7302
|
|
|
|
|
|
|
|
|
7303
|
|
|
|
|
|
|
/* write abbcc */ |
|
7304
|
0
|
|
|
|
|
|
buf[0] = (u8)(a + '0'); |
|
7305
|
0
|
|
|
|
|
|
buf += a > 0; |
|
7306
|
0
|
0
|
|
|
|
|
lz = bb < 10 && a == 0; |
|
|
|
0
|
|
|
|
|
|
|
7307
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + bb * 2 + lz); |
|
7308
|
0
|
|
|
|
|
|
buf -= lz; |
|
7309
|
0
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + cc * 2); |
|
7310
|
|
|
|
|
|
|
|
|
7311
|
0
|
0
|
|
|
|
|
if (ddee) { |
|
|
|
0
|
|
|
|
|
|
|
7312
|
0
|
|
|
|
|
|
u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ |
|
7313
|
0
|
|
|
|
|
|
u32 ee = ddee - dd * 100; /* (ddee % 100) */ |
|
7314
|
0
|
|
|
|
|
|
byte_copy_2(buf + 4, digit_table + dd * 2); |
|
7315
|
0
|
|
|
|
|
|
byte_copy_2(buf + 6, digit_table + ee * 2); |
|
7316
|
0
|
|
|
|
|
|
tz1 = dec_trailing_zero_table[dd]; |
|
7317
|
0
|
|
|
|
|
|
tz2 = dec_trailing_zero_table[ee]; |
|
7318
|
0
|
0
|
|
|
|
|
tz = ee ? tz2 : (tz1 + 2); |
|
|
|
0
|
|
|
|
|
|
|
7319
|
0
|
|
|
|
|
|
buf += 8 - tz; |
|
7320
|
0
|
|
|
|
|
|
return buf; |
|
7321
|
|
|
|
|
|
|
} else { |
|
7322
|
0
|
|
|
|
|
|
tz1 = dec_trailing_zero_table[bb]; |
|
7323
|
0
|
|
|
|
|
|
tz2 = dec_trailing_zero_table[cc]; |
|
7324
|
0
|
0
|
|
|
|
|
tz = cc ? tz2 : (tz1 + tz2); |
|
|
|
0
|
|
|
|
|
|
|
7325
|
0
|
|
|
|
|
|
buf += 4 - tz; |
|
7326
|
0
|
|
|
|
|
|
return buf; |
|
7327
|
|
|
|
|
|
|
} |
|
7328
|
|
|
|
|
|
|
} |
|
7329
|
|
|
|
|
|
|
|
|
7330
|
|
|
|
|
|
|
/** |
|
7331
|
|
|
|
|
|
|
Write an unsigned integer with a length of 16 or 17 with trailing zero trimmed. |
|
7332
|
|
|
|
|
|
|
These digits are named as "abbccddeeffgghhii" here. |
|
7333
|
|
|
|
|
|
|
For example, input 1234567890123000, output "1234567890123". |
|
7334
|
|
|
|
|
|
|
*/ |
|
7335
|
|
|
|
|
|
|
static_inline u8 *write_u64_len_16_to_17_trim(u64 val, u8 *buf) { |
|
7336
|
|
|
|
|
|
|
u32 tz, tz1, tz2; |
|
7337
|
|
|
|
|
|
|
|
|
7338
|
1
|
|
|
|
|
|
u32 abbccddee = (u32)(val / 100000000); |
|
7339
|
1
|
|
|
|
|
|
u32 ffgghhii = (u32)(val - (u64)abbccddee * 100000000); |
|
7340
|
1
|
|
|
|
|
|
u32 abbcc = abbccddee / 10000; |
|
7341
|
1
|
|
|
|
|
|
u32 ddee = abbccddee - abbcc * 10000; |
|
7342
|
1
|
|
|
|
|
|
u32 abb = (u32)(((u64)abbcc * 167773) >> 24); /* (abbcc / 100) */ |
|
7343
|
1
|
|
|
|
|
|
u32 a = (abb * 41) >> 12; /* (abb / 100) */ |
|
7344
|
1
|
|
|
|
|
|
u32 bb = abb - a * 100; /* (abb % 100) */ |
|
7345
|
1
|
|
|
|
|
|
u32 cc = abbcc - abb * 100; /* (abbcc % 100) */ |
|
7346
|
1
|
|
|
|
|
|
buf[0] = (u8)(a + '0'); |
|
7347
|
1
|
|
|
|
|
|
buf += a > 0; |
|
7348
|
1
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + bb * 2); |
|
7349
|
1
|
|
|
|
|
|
byte_copy_2(buf + 2, digit_table + cc * 2); |
|
7350
|
|
|
|
|
|
|
|
|
7351
|
1
|
0
|
|
|
|
|
if (ffgghhii) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7352
|
0
|
|
|
|
|
|
u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ |
|
7353
|
0
|
|
|
|
|
|
u32 ee = ddee - dd * 100; /* (ddee % 100) */ |
|
7354
|
0
|
|
|
|
|
|
u32 ffgg = (u32)(((u64)ffgghhii * 109951163) >> 40); /* (val / 10000) */ |
|
7355
|
0
|
|
|
|
|
|
u32 hhii = ffgghhii - ffgg * 10000; /* (val % 10000) */ |
|
7356
|
0
|
|
|
|
|
|
u32 ff = (ffgg * 5243) >> 19; /* (aabb / 100) */ |
|
7357
|
0
|
|
|
|
|
|
u32 gg = ffgg - ff * 100; /* (aabb % 100) */ |
|
7358
|
0
|
|
|
|
|
|
byte_copy_2(buf + 4, digit_table + dd * 2); |
|
7359
|
0
|
|
|
|
|
|
byte_copy_2(buf + 6, digit_table + ee * 2); |
|
7360
|
0
|
|
|
|
|
|
byte_copy_2(buf + 8, digit_table + ff * 2); |
|
7361
|
0
|
|
|
|
|
|
byte_copy_2(buf + 10, digit_table + gg * 2); |
|
7362
|
0
|
0
|
|
|
|
|
if (hhii) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7363
|
0
|
|
|
|
|
|
u32 hh = (hhii * 5243) >> 19; /* (ccdd / 100) */ |
|
7364
|
0
|
|
|
|
|
|
u32 ii = hhii - hh * 100; /* (ccdd % 100) */ |
|
7365
|
0
|
|
|
|
|
|
byte_copy_2(buf + 12, digit_table + hh * 2); |
|
7366
|
0
|
|
|
|
|
|
byte_copy_2(buf + 14, digit_table + ii * 2); |
|
7367
|
0
|
|
|
|
|
|
tz1 = dec_trailing_zero_table[hh]; |
|
7368
|
0
|
|
|
|
|
|
tz2 = dec_trailing_zero_table[ii]; |
|
7369
|
0
|
0
|
|
|
|
|
tz = ii ? tz2 : (tz1 + 2); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7370
|
0
|
|
|
|
|
|
return buf + 16 - tz; |
|
7371
|
|
|
|
|
|
|
} else { |
|
7372
|
0
|
|
|
|
|
|
tz1 = dec_trailing_zero_table[ff]; |
|
7373
|
0
|
|
|
|
|
|
tz2 = dec_trailing_zero_table[gg]; |
|
7374
|
0
|
0
|
|
|
|
|
tz = gg ? tz2 : (tz1 + 2); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7375
|
0
|
|
|
|
|
|
return buf + 12 - tz; |
|
7376
|
|
|
|
|
|
|
} |
|
7377
|
|
|
|
|
|
|
} else { |
|
7378
|
1
|
0
|
|
|
|
|
if (ddee) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7379
|
0
|
|
|
|
|
|
u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ |
|
7380
|
0
|
|
|
|
|
|
u32 ee = ddee - dd * 100; /* (ddee % 100) */ |
|
7381
|
0
|
|
|
|
|
|
byte_copy_2(buf + 4, digit_table + dd * 2); |
|
7382
|
0
|
|
|
|
|
|
byte_copy_2(buf + 6, digit_table + ee * 2); |
|
7383
|
0
|
|
|
|
|
|
tz1 = dec_trailing_zero_table[dd]; |
|
7384
|
0
|
|
|
|
|
|
tz2 = dec_trailing_zero_table[ee]; |
|
7385
|
0
|
0
|
|
|
|
|
tz = ee ? tz2 : (tz1 + 2); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7386
|
0
|
|
|
|
|
|
return buf + 8 - tz; |
|
7387
|
|
|
|
|
|
|
} else { |
|
7388
|
1
|
|
|
|
|
|
tz1 = dec_trailing_zero_table[bb]; |
|
7389
|
1
|
|
|
|
|
|
tz2 = dec_trailing_zero_table[cc]; |
|
7390
|
1
|
0
|
|
|
|
|
tz = cc ? tz2 : (tz1 + tz2); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7391
|
1
|
|
|
|
|
|
return buf + 4 - tz; |
|
7392
|
|
|
|
|
|
|
} |
|
7393
|
|
|
|
|
|
|
} |
|
7394
|
|
|
|
|
|
|
} |
|
7395
|
|
|
|
|
|
|
|
|
7396
|
|
|
|
|
|
|
/** Write exponent part in range `e-45` to `e38`. */ |
|
7397
|
|
|
|
|
|
|
static_inline u8 *write_f32_exp(i32 exp, u8 *buf) { |
|
7398
|
|
|
|
|
|
|
bool lz; |
|
7399
|
|
|
|
|
|
|
byte_copy_2(buf, "e-"); |
|
7400
|
0
|
0
|
|
|
|
|
buf += 2 - (exp >= 0); |
|
|
|
0
|
|
|
|
|
|
|
7401
|
0
|
|
|
|
|
|
exp = exp < 0 ? -exp : exp; |
|
7402
|
0
|
|
|
|
|
|
lz = exp < 10; |
|
7403
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + (u32)exp * 2 + lz); |
|
7404
|
0
|
|
|
|
|
|
return buf + 2 - lz; |
|
7405
|
|
|
|
|
|
|
} |
|
7406
|
|
|
|
|
|
|
|
|
7407
|
|
|
|
|
|
|
/** Write exponent part in range `e-324` to `e308`. */ |
|
7408
|
|
|
|
|
|
|
static_inline u8 *write_f64_exp(i32 exp, u8 *buf) { |
|
7409
|
|
|
|
|
|
|
byte_copy_2(buf, "e-"); |
|
7410
|
0
|
0
|
|
|
|
|
buf += 2 - (exp >= 0); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7411
|
0
|
|
|
|
|
|
exp = exp < 0 ? -exp : exp; |
|
7412
|
0
|
0
|
|
|
|
|
if (exp < 100) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7413
|
0
|
|
|
|
|
|
bool lz = exp < 10; |
|
7414
|
0
|
|
|
|
|
|
byte_copy_2(buf + 0, digit_table + (u32)exp * 2 + lz); |
|
7415
|
0
|
|
|
|
|
|
return buf + 2 - lz; |
|
7416
|
|
|
|
|
|
|
} else { |
|
7417
|
0
|
|
|
|
|
|
u32 hi = ((u32)exp * 656) >> 16; /* exp / 100 */ |
|
7418
|
0
|
|
|
|
|
|
u32 lo = (u32)exp - hi * 100; /* exp % 100 */ |
|
7419
|
0
|
|
|
|
|
|
buf[0] = (u8)((u8)hi + (u8)'0'); |
|
7420
|
0
|
|
|
|
|
|
byte_copy_2(buf + 1, digit_table + lo * 2); |
|
7421
|
0
|
|
|
|
|
|
return buf + 3; |
|
7422
|
|
|
|
|
|
|
} |
|
7423
|
|
|
|
|
|
|
} |
|
7424
|
|
|
|
|
|
|
|
|
7425
|
|
|
|
|
|
|
/** Magic number for fast `divide by power of 10`. */ |
|
7426
|
|
|
|
|
|
|
typedef struct { |
|
7427
|
|
|
|
|
|
|
u64 p10, mul; |
|
7428
|
|
|
|
|
|
|
u32 shr1, shr2; |
|
7429
|
|
|
|
|
|
|
} div_pow10_magic; |
|
7430
|
|
|
|
|
|
|
|
|
7431
|
|
|
|
|
|
|
/** Generated with llvm, see https://github.com/llvm/llvm-project/ |
|
7432
|
|
|
|
|
|
|
blob/main/llvm/lib/Support/DivisionByConstantInfo.cpp */ |
|
7433
|
|
|
|
|
|
|
static const div_pow10_magic div_pow10_table[] = { |
|
7434
|
|
|
|
|
|
|
{ U64(0x00000000, 0x00000001), U64(0x00000000, 0x00000000), 0, 0 }, |
|
7435
|
|
|
|
|
|
|
{ U64(0x00000000, 0x0000000A), U64(0xCCCCCCCC, 0xCCCCCCCD), 0, 3 }, |
|
7436
|
|
|
|
|
|
|
{ U64(0x00000000, 0x00000064), U64(0x28F5C28F, 0x5C28F5C3), 2, 2 }, |
|
7437
|
|
|
|
|
|
|
{ U64(0x00000000, 0x000003E8), U64(0x20C49BA5, 0xE353F7CF), 3, 4 }, |
|
7438
|
|
|
|
|
|
|
{ U64(0x00000000, 0x00002710), U64(0x346DC5D6, 0x3886594B), 0, 11 }, |
|
7439
|
|
|
|
|
|
|
{ U64(0x00000000, 0x000186A0), U64(0x0A7C5AC4, 0x71B47843), 5, 7 }, |
|
7440
|
|
|
|
|
|
|
{ U64(0x00000000, 0x000F4240), U64(0x431BDE82, 0xD7B634DB), 0, 18 }, |
|
7441
|
|
|
|
|
|
|
{ U64(0x00000000, 0x00989680), U64(0xD6BF94D5, 0xE57A42BD), 0, 23 }, |
|
7442
|
|
|
|
|
|
|
{ U64(0x00000000, 0x05F5E100), U64(0xABCC7711, 0x8461CEFD), 0, 26 }, |
|
7443
|
|
|
|
|
|
|
{ U64(0x00000000, 0x3B9ACA00), U64(0x0044B82F, 0xA09B5A53), 9, 11 }, |
|
7444
|
|
|
|
|
|
|
{ U64(0x00000002, 0x540BE400), U64(0xDBE6FECE, 0xBDEDD5BF), 0, 33 }, |
|
7445
|
|
|
|
|
|
|
{ U64(0x00000017, 0x4876E800), U64(0xAFEBFF0B, 0xCB24AAFF), 0, 36 }, |
|
7446
|
|
|
|
|
|
|
{ U64(0x000000E8, 0xD4A51000), U64(0x232F3302, 0x5BD42233), 0, 37 }, |
|
7447
|
|
|
|
|
|
|
{ U64(0x00000918, 0x4E72A000), U64(0x384B84D0, 0x92ED0385), 0, 41 }, |
|
7448
|
|
|
|
|
|
|
{ U64(0x00005AF3, 0x107A4000), U64(0x0B424DC3, 0x5095CD81), 0, 42 }, |
|
7449
|
|
|
|
|
|
|
{ U64(0x00038D7E, 0xA4C68000), U64(0x00024075, 0xF3DCEAC3), 15, 20 }, |
|
7450
|
|
|
|
|
|
|
{ U64(0x002386F2, 0x6FC10000), U64(0x39A5652F, 0xB1137857), 0, 51 }, |
|
7451
|
|
|
|
|
|
|
{ U64(0x01634578, 0x5D8A0000), U64(0x00005C3B, 0xD5191B53), 17, 22 }, |
|
7452
|
|
|
|
|
|
|
{ U64(0x0DE0B6B3, 0xA7640000), U64(0x000049C9, 0x7747490F), 18, 24 }, |
|
7453
|
|
|
|
|
|
|
{ U64(0x8AC72304, 0x89E80000), U64(0x760F253E, 0xDB4AB0d3), 0, 62 }, |
|
7454
|
|
|
|
|
|
|
}; |
|
7455
|
|
|
|
|
|
|
|
|
7456
|
|
|
|
|
|
|
/** Divide a number by power of 10. */ |
|
7457
|
|
|
|
|
|
|
static_inline void div_pow10(u64 num, u32 exp, u64 *div, u64 *mod, u64 *p10) { |
|
7458
|
|
|
|
|
|
|
u64 hi, lo; |
|
7459
|
0
|
|
|
|
|
|
div_pow10_magic m = div_pow10_table[exp]; |
|
7460
|
0
|
|
|
|
|
|
u128_mul(num >> m.shr1, m.mul, &hi, &lo); |
|
7461
|
0
|
|
|
|
|
|
*div = hi >> m.shr2; |
|
7462
|
0
|
|
|
|
|
|
*mod = num - (*div * m.p10); |
|
7463
|
0
|
|
|
|
|
|
*p10 = m.p10; |
|
7464
|
0
|
|
|
|
|
|
} |
|
7465
|
|
|
|
|
|
|
|
|
7466
|
|
|
|
|
|
|
/** Multiplies 64-bit integer and returns highest 64-bit rounded value. */ |
|
7467
|
|
|
|
|
|
|
static_inline u32 u64_round_to_odd(u64 u, u32 cp) { |
|
7468
|
|
|
|
|
|
|
u64 hi, lo; |
|
7469
|
|
|
|
|
|
|
u32 y_hi, y_lo; |
|
7470
|
0
|
|
|
|
|
|
u128_mul(cp, u, &hi, &lo); |
|
7471
|
0
|
|
|
|
|
|
y_hi = (u32)hi; |
|
7472
|
0
|
|
|
|
|
|
y_lo = (u32)(lo >> 32); |
|
7473
|
0
|
|
|
|
|
|
return y_hi | (y_lo > 1); |
|
7474
|
|
|
|
|
|
|
} |
|
7475
|
|
|
|
|
|
|
|
|
7476
|
|
|
|
|
|
|
/** Multiplies 128-bit integer and returns highest 64-bit rounded value. */ |
|
7477
|
|
|
|
|
|
|
static_inline u64 u128_round_to_odd(u64 hi, u64 lo, u64 cp) { |
|
7478
|
|
|
|
|
|
|
u64 x_hi, x_lo, y_hi, y_lo; |
|
7479
|
|
|
|
|
|
|
u128_mul(cp, lo, &x_hi, &x_lo); |
|
7480
|
0
|
|
|
|
|
|
u128_mul_add(cp, hi, x_hi, &y_hi, &y_lo); |
|
7481
|
0
|
|
|
|
|
|
return y_hi | (y_lo > 1); |
|
7482
|
|
|
|
|
|
|
} |
|
7483
|
|
|
|
|
|
|
|
|
7484
|
|
|
|
|
|
|
/** Convert f32 from binary to decimal (shortest but may have trailing zeros). |
|
7485
|
|
|
|
|
|
|
The input should not be 0, inf or nan. */ |
|
7486
|
|
|
|
|
|
|
static_inline void f32_bin_to_dec(u32 sig_raw, u32 exp_raw, |
|
7487
|
|
|
|
|
|
|
u32 sig_bin, i32 exp_bin, |
|
7488
|
|
|
|
|
|
|
u32 *sig_dec, i32 *exp_dec) { |
|
7489
|
|
|
|
|
|
|
|
|
7490
|
|
|
|
|
|
|
bool is_even, irregular, round_up, trim; |
|
7491
|
|
|
|
|
|
|
bool u0_inside, u1_inside, w0_inside, w1_inside; |
|
7492
|
|
|
|
|
|
|
u64 p10_hi, p10_lo, hi, lo; |
|
7493
|
|
|
|
|
|
|
u32 s, sp, cb, cbl, cbr, vb, vbl, vbr, upper, lower, mid; |
|
7494
|
|
|
|
|
|
|
i32 k, h; |
|
7495
|
|
|
|
|
|
|
|
|
7496
|
|
|
|
|
|
|
/* Fast path, see f64_bin_to_dec(). */ |
|
7497
|
0
|
0
|
|
|
|
|
while (likely(sig_raw)) { |
|
|
|
0
|
|
|
|
|
|
|
7498
|
|
|
|
|
|
|
u32 mod, dec, add_1, add_10, s_hi, s_lo; |
|
7499
|
|
|
|
|
|
|
u32 c, half_ulp, t0, t1; |
|
7500
|
|
|
|
|
|
|
|
|
7501
|
|
|
|
|
|
|
/* k = floor(exp_bin * log10(2)); */ |
|
7502
|
|
|
|
|
|
|
/* h = exp_bin + floor(log2(10) * -k); (h = 0/1/2/3) */ |
|
7503
|
0
|
|
|
|
|
|
k = (i32)(exp_bin * 315653) >> 20; |
|
7504
|
0
|
|
|
|
|
|
h = exp_bin + ((-k * 217707) >> 16); |
|
7505
|
0
|
|
|
|
|
|
pow10_table_get_sig(-k, &p10_hi, &p10_lo); |
|
7506
|
|
|
|
|
|
|
|
|
7507
|
|
|
|
|
|
|
/* sig_bin << (1/2/3/4) */ |
|
7508
|
0
|
|
|
|
|
|
cb = sig_bin << (h + 1); |
|
7509
|
0
|
|
|
|
|
|
u128_mul(cb, p10_hi, &hi, &lo); |
|
7510
|
0
|
|
|
|
|
|
s_hi = (u32)(hi); |
|
7511
|
0
|
|
|
|
|
|
s_lo = (u32)(lo >> 32); |
|
7512
|
0
|
|
|
|
|
|
mod = s_hi % 10; |
|
7513
|
0
|
|
|
|
|
|
dec = s_hi - mod; |
|
7514
|
|
|
|
|
|
|
|
|
7515
|
|
|
|
|
|
|
/* right shift 4 to fit in u32 */ |
|
7516
|
0
|
|
|
|
|
|
c = (mod << (32 - 4)) | (s_lo >> 4); |
|
7517
|
0
|
|
|
|
|
|
half_ulp = (u32)(p10_hi >> (32 + 4 - h)); |
|
7518
|
|
|
|
|
|
|
|
|
7519
|
|
|
|
|
|
|
/* check w1, u0, w0 range */ |
|
7520
|
0
|
|
|
|
|
|
w1_inside = (s_lo >= ((u32)1 << 31)); |
|
7521
|
0
|
0
|
|
|
|
|
if (unlikely(s_lo == ((u32)1 << 31))) break; |
|
|
|
0
|
|
|
|
|
|
|
7522
|
0
|
|
|
|
|
|
u0_inside = (half_ulp >= c); |
|
7523
|
0
|
0
|
|
|
|
|
if (unlikely(half_ulp == c)) break; |
|
|
|
0
|
|
|
|
|
|
|
7524
|
0
|
|
|
|
|
|
t0 = (u32)10 << (32 - 4); |
|
7525
|
0
|
|
|
|
|
|
t1 = c + half_ulp; |
|
7526
|
0
|
|
|
|
|
|
w0_inside = (t1 >= t0); |
|
7527
|
0
|
0
|
|
|
|
|
if (unlikely(t0 - t1 <= (u32)1)) break; |
|
|
|
0
|
|
|
|
|
|
|
7528
|
|
|
|
|
|
|
|
|
7529
|
0
|
|
|
|
|
|
trim = (u0_inside | w0_inside); |
|
7530
|
0
|
0
|
|
|
|
|
add_10 = (w0_inside ? 10 : 0); |
|
|
|
0
|
|
|
|
|
|
|
7531
|
0
|
|
|
|
|
|
add_1 = mod + w1_inside; |
|
7532
|
0
|
0
|
|
|
|
|
*sig_dec = dec + (trim ? add_10 : add_1); |
|
|
|
0
|
|
|
|
|
|
|
7533
|
0
|
|
|
|
|
|
*exp_dec = k; |
|
7534
|
0
|
|
|
|
|
|
return; |
|
7535
|
|
|
|
|
|
|
} |
|
7536
|
|
|
|
|
|
|
|
|
7537
|
|
|
|
|
|
|
/* Schubfach algorithm, see f64_bin_to_dec(). */ |
|
7538
|
0
|
0
|
|
|
|
|
irregular = (sig_raw == 0 && exp_raw > 1); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7539
|
0
|
|
|
|
|
|
is_even = !(sig_bin & 1); |
|
7540
|
0
|
|
|
|
|
|
cbl = 4 * sig_bin - 2 + irregular; |
|
7541
|
0
|
|
|
|
|
|
cb = 4 * sig_bin; |
|
7542
|
0
|
|
|
|
|
|
cbr = 4 * sig_bin + 2; |
|
7543
|
|
|
|
|
|
|
|
|
7544
|
|
|
|
|
|
|
/* k = floor(exp_bin * log10(2) + (irregular ? log10(3.0 / 4.0) : 0)); */ |
|
7545
|
|
|
|
|
|
|
/* h = exp_bin + floor(log2(10) * -k) + 1; (h = 1/2/3/4) */ |
|
7546
|
0
|
0
|
|
|
|
|
k = (i32)(exp_bin * 315653 - (irregular ? 131237 : 0)) >> 20; |
|
|
|
0
|
|
|
|
|
|
|
7547
|
0
|
|
|
|
|
|
h = exp_bin + ((-k * 217707) >> 16) + 1; |
|
7548
|
0
|
|
|
|
|
|
pow10_table_get_sig(-k, &p10_hi, &p10_lo); |
|
7549
|
0
|
|
|
|
|
|
p10_hi += 1; |
|
7550
|
|
|
|
|
|
|
|
|
7551
|
0
|
|
|
|
|
|
vbl = u64_round_to_odd(p10_hi, cbl << h); |
|
7552
|
0
|
|
|
|
|
|
vb = u64_round_to_odd(p10_hi, cb << h); |
|
7553
|
0
|
|
|
|
|
|
vbr = u64_round_to_odd(p10_hi, cbr << h); |
|
7554
|
0
|
|
|
|
|
|
lower = vbl + !is_even; |
|
7555
|
0
|
|
|
|
|
|
upper = vbr - !is_even; |
|
7556
|
|
|
|
|
|
|
|
|
7557
|
0
|
|
|
|
|
|
s = vb / 4; |
|
7558
|
0
|
0
|
|
|
|
|
if (s >= 10) { |
|
|
|
0
|
|
|
|
|
|
|
7559
|
0
|
|
|
|
|
|
sp = s / 10; |
|
7560
|
0
|
|
|
|
|
|
u0_inside = (lower <= 40 * sp); |
|
7561
|
0
|
|
|
|
|
|
w0_inside = (upper >= 40 * sp + 40); |
|
7562
|
0
|
0
|
|
|
|
|
if (u0_inside != w0_inside) { |
|
|
|
0
|
|
|
|
|
|
|
7563
|
0
|
0
|
|
|
|
|
*sig_dec = sp * 10 + (w0_inside ? 10 : 0); |
|
|
|
0
|
|
|
|
|
|
|
7564
|
0
|
|
|
|
|
|
*exp_dec = k; |
|
7565
|
0
|
|
|
|
|
|
return; |
|
7566
|
|
|
|
|
|
|
} |
|
7567
|
|
|
|
|
|
|
} |
|
7568
|
0
|
|
|
|
|
|
u1_inside = (lower <= 4 * s); |
|
7569
|
0
|
|
|
|
|
|
w1_inside = (upper >= 4 * s + 4); |
|
7570
|
0
|
|
|
|
|
|
mid = 4 * s + 2; |
|
7571
|
0
|
0
|
|
|
|
|
round_up = (vb > mid) || (vb == mid && (s & 1) != 0); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7572
|
0
|
0
|
|
|
|
|
*sig_dec = s + ((u1_inside != w1_inside) ? w1_inside : round_up); |
|
|
|
0
|
|
|
|
|
|
|
7573
|
0
|
|
|
|
|
|
*exp_dec = k; |
|
7574
|
|
|
|
|
|
|
} |
|
7575
|
|
|
|
|
|
|
|
|
7576
|
|
|
|
|
|
|
/** Convert f64 from binary to decimal (shortest but may have trailing zeros). |
|
7577
|
|
|
|
|
|
|
The input should not be 0, inf or nan. */ |
|
7578
|
|
|
|
|
|
|
static_inline void f64_bin_to_dec(u64 sig_raw, u32 exp_raw, |
|
7579
|
|
|
|
|
|
|
u64 sig_bin, i32 exp_bin, |
|
7580
|
|
|
|
|
|
|
u64 *sig_dec, i32 *exp_dec) { |
|
7581
|
|
|
|
|
|
|
|
|
7582
|
|
|
|
|
|
|
bool is_even, irregular, round_up, trim; |
|
7583
|
|
|
|
|
|
|
bool u0_inside, u1_inside, w0_inside, w1_inside; |
|
7584
|
|
|
|
|
|
|
u64 s, sp, cb, cbl, cbr, vb, vbl, vbr, p10_hi, p10_lo, upper, lower, mid; |
|
7585
|
|
|
|
|
|
|
i32 k, h; |
|
7586
|
|
|
|
|
|
|
|
|
7587
|
|
|
|
|
|
|
/* |
|
7588
|
|
|
|
|
|
|
Fast path: |
|
7589
|
|
|
|
|
|
|
For regular spacing significand 'c', there are 4 candidates: |
|
7590
|
|
|
|
|
|
|
|
|
7591
|
|
|
|
|
|
|
u0 u1 c w1 w0 |
|
7592
|
|
|
|
|
|
|
----|----|----|----|----|-*--|----|----|----|----|----|----|----|---- |
|
7593
|
|
|
|
|
|
|
9 0 1 2 3 4 5 6 7 8 9 0 1 |
|
7594
|
|
|
|
|
|
|
|___________________|___________________| |
|
7595
|
|
|
|
|
|
|
1ulp |
|
7596
|
|
|
|
|
|
|
|
|
7597
|
|
|
|
|
|
|
The `1ulp` is in the range [1.0, 10.0). |
|
7598
|
|
|
|
|
|
|
If (c - 0.5ulp < u0), trim the last digit and round down. |
|
7599
|
|
|
|
|
|
|
If (c + 0.5ulp > w0), trim the last digit and round up. |
|
7600
|
|
|
|
|
|
|
If (c - 0.5ulp < u1), round down. |
|
7601
|
|
|
|
|
|
|
If (c + 0.5ulp > w1), round up. |
|
7602
|
|
|
|
|
|
|
*/ |
|
7603
|
1
|
0
|
|
|
|
|
while (likely(sig_raw)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7604
|
|
|
|
|
|
|
u64 mod, dec, add_1, add_10, s_hi, s_lo; |
|
7605
|
|
|
|
|
|
|
u64 c, half_ulp, t0, t1; |
|
7606
|
|
|
|
|
|
|
|
|
7607
|
|
|
|
|
|
|
/* k = floor(exp_bin * log10(2)); */ |
|
7608
|
|
|
|
|
|
|
/* h = exp_bin + floor(log2(10) * -k); (h = 0/1/2/3) */ |
|
7609
|
1
|
|
|
|
|
|
k = (i32)(exp_bin * 315653) >> 20; |
|
7610
|
1
|
|
|
|
|
|
h = exp_bin + ((-k * 217707) >> 16); |
|
7611
|
1
|
|
|
|
|
|
pow10_table_get_sig(-k, &p10_hi, &p10_lo); |
|
7612
|
|
|
|
|
|
|
|
|
7613
|
|
|
|
|
|
|
/* sig_bin << (1/2/3/4) */ |
|
7614
|
1
|
|
|
|
|
|
cb = sig_bin << (h + 1); |
|
7615
|
1
|
|
|
|
|
|
u128_mul(cb, p10_lo, &s_hi, &s_lo); |
|
7616
|
1
|
|
|
|
|
|
u128_mul_add(cb, p10_hi, s_hi, &s_hi, &s_lo); |
|
7617
|
1
|
|
|
|
|
|
mod = s_hi % 10; |
|
7618
|
1
|
|
|
|
|
|
dec = s_hi - mod; |
|
7619
|
|
|
|
|
|
|
|
|
7620
|
|
|
|
|
|
|
/* right shift 4 to fit in u64 */ |
|
7621
|
1
|
|
|
|
|
|
c = (mod << (64 - 4)) | (s_lo >> 4); |
|
7622
|
1
|
|
|
|
|
|
half_ulp = p10_hi >> (4 - h); |
|
7623
|
|
|
|
|
|
|
|
|
7624
|
|
|
|
|
|
|
/* check w1, u0, w0 range */ |
|
7625
|
1
|
|
|
|
|
|
w1_inside = (s_lo >= ((u64)1 << 63)); |
|
7626
|
1
|
0
|
|
|
|
|
if (unlikely(s_lo == ((u64)1 << 63))) break; |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7627
|
1
|
|
|
|
|
|
u0_inside = (half_ulp >= c); |
|
7628
|
1
|
0
|
|
|
|
|
if (unlikely(half_ulp == c)) break; |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7629
|
1
|
|
|
|
|
|
t0 = ((u64)10 << (64 - 4)); |
|
7630
|
1
|
|
|
|
|
|
t1 = c + half_ulp; |
|
7631
|
1
|
|
|
|
|
|
w0_inside = (t1 >= t0); |
|
7632
|
1
|
0
|
|
|
|
|
if (unlikely(t0 - t1 <= (u64)1)) break; |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7633
|
|
|
|
|
|
|
|
|
7634
|
1
|
|
|
|
|
|
trim = (u0_inside | w0_inside); |
|
7635
|
1
|
0
|
|
|
|
|
add_10 = (w0_inside ? 10 : 0); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7636
|
1
|
|
|
|
|
|
add_1 = mod + w1_inside; |
|
7637
|
1
|
0
|
|
|
|
|
*sig_dec = dec + (trim ? add_10 : add_1); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7638
|
1
|
|
|
|
|
|
*exp_dec = k; |
|
7639
|
1
|
|
|
|
|
|
return; |
|
7640
|
|
|
|
|
|
|
} |
|
7641
|
|
|
|
|
|
|
|
|
7642
|
|
|
|
|
|
|
/* |
|
7643
|
|
|
|
|
|
|
Schubfach algorithm: |
|
7644
|
|
|
|
|
|
|
Raffaello Giulietti, The Schubfach way to render doubles, 2022. |
|
7645
|
|
|
|
|
|
|
https://drive.google.com/file/d/1gp5xv4CAa78SVgCeWfGqqI4FfYYYuNFb (Paper) |
|
7646
|
|
|
|
|
|
|
https://github.com/openjdk/jdk/pull/3402 (Java implementation) |
|
7647
|
|
|
|
|
|
|
https://github.com/abolz/Drachennest (C++ implementation) |
|
7648
|
|
|
|
|
|
|
*/ |
|
7649
|
0
|
0
|
|
|
|
|
irregular = (sig_raw == 0 && exp_raw > 1); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7650
|
0
|
|
|
|
|
|
is_even = !(sig_bin & 1); |
|
7651
|
0
|
|
|
|
|
|
cbl = 4 * sig_bin - 2 + irregular; |
|
7652
|
0
|
|
|
|
|
|
cb = 4 * sig_bin; |
|
7653
|
0
|
|
|
|
|
|
cbr = 4 * sig_bin + 2; |
|
7654
|
|
|
|
|
|
|
|
|
7655
|
|
|
|
|
|
|
/* k = floor(exp_bin * log10(2) + (irregular ? log10(3.0 / 4.0) : 0)); */ |
|
7656
|
|
|
|
|
|
|
/* h = exp_bin + floor(log2(10) * -k) + 1; (h = 1/2/3/4) */ |
|
7657
|
0
|
0
|
|
|
|
|
k = (i32)(exp_bin * 315653 - (irregular ? 131237 : 0)) >> 20; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7658
|
0
|
|
|
|
|
|
h = exp_bin + ((-k * 217707) >> 16) + 1; |
|
7659
|
0
|
|
|
|
|
|
pow10_table_get_sig(-k, &p10_hi, &p10_lo); |
|
7660
|
0
|
|
|
|
|
|
p10_lo += 1; |
|
7661
|
|
|
|
|
|
|
|
|
7662
|
0
|
|
|
|
|
|
vbl = u128_round_to_odd(p10_hi, p10_lo, cbl << h); |
|
7663
|
0
|
|
|
|
|
|
vb = u128_round_to_odd(p10_hi, p10_lo, cb << h); |
|
7664
|
0
|
|
|
|
|
|
vbr = u128_round_to_odd(p10_hi, p10_lo, cbr << h); |
|
7665
|
0
|
|
|
|
|
|
lower = vbl + !is_even; |
|
7666
|
0
|
|
|
|
|
|
upper = vbr - !is_even; |
|
7667
|
|
|
|
|
|
|
|
|
7668
|
0
|
|
|
|
|
|
s = vb / 4; |
|
7669
|
0
|
0
|
|
|
|
|
if (s >= 10) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7670
|
0
|
|
|
|
|
|
sp = s / 10; |
|
7671
|
0
|
|
|
|
|
|
u0_inside = (lower <= 40 * sp); |
|
7672
|
0
|
|
|
|
|
|
w0_inside = (upper >= 40 * sp + 40); |
|
7673
|
0
|
0
|
|
|
|
|
if (u0_inside != w0_inside) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7674
|
0
|
0
|
|
|
|
|
*sig_dec = sp * 10 + (w0_inside ? 10 : 0); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7675
|
0
|
|
|
|
|
|
*exp_dec = k; |
|
7676
|
0
|
|
|
|
|
|
return; |
|
7677
|
|
|
|
|
|
|
} |
|
7678
|
|
|
|
|
|
|
} |
|
7679
|
0
|
|
|
|
|
|
u1_inside = (lower <= 4 * s); |
|
7680
|
0
|
|
|
|
|
|
w1_inside = (upper >= 4 * s + 4); |
|
7681
|
0
|
|
|
|
|
|
mid = 4 * s + 2; |
|
7682
|
0
|
0
|
|
|
|
|
round_up = (vb > mid) || (vb == mid && (s & 1) != 0); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7683
|
0
|
0
|
|
|
|
|
*sig_dec = s + ((u1_inside != w1_inside) ? w1_inside : round_up); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7684
|
0
|
|
|
|
|
|
*exp_dec = k; |
|
7685
|
|
|
|
|
|
|
} |
|
7686
|
|
|
|
|
|
|
|
|
7687
|
|
|
|
|
|
|
/** Convert f64 from binary to decimal (fast but not the shortest). |
|
7688
|
|
|
|
|
|
|
The input should not be 0, inf, nan. */ |
|
7689
|
|
|
|
|
|
|
static_inline void f64_bin_to_dec_fast(u64 sig_raw, u32 exp_raw, |
|
7690
|
|
|
|
|
|
|
u64 sig_bin, i32 exp_bin, |
|
7691
|
|
|
|
|
|
|
u64 *sig_dec, i32 *exp_dec, |
|
7692
|
|
|
|
|
|
|
bool *round_up) { |
|
7693
|
|
|
|
|
|
|
u64 cb, p10_hi, p10_lo, s_hi, s_lo; |
|
7694
|
|
|
|
|
|
|
i32 k, h; |
|
7695
|
|
|
|
|
|
|
bool irregular, u; |
|
7696
|
|
|
|
|
|
|
|
|
7697
|
0
|
0
|
|
|
|
|
irregular = (sig_raw == 0 && exp_raw > 1); |
|
|
|
0
|
|
|
|
|
|
|
7698
|
|
|
|
|
|
|
|
|
7699
|
|
|
|
|
|
|
/* k = floor(exp_bin * log10(2) + (irregular ? log10(3.0 / 4.0) : 0)); */ |
|
7700
|
|
|
|
|
|
|
/* h = exp_bin + floor(log2(10) * -k) + 1; (h = 1/2/3/4) */ |
|
7701
|
0
|
0
|
|
|
|
|
k = (i32)(exp_bin * 315653 - (irregular ? 131237 : 0)) >> 20; |
|
7702
|
0
|
|
|
|
|
|
h = exp_bin + ((-k * 217707) >> 16); |
|
7703
|
0
|
|
|
|
|
|
pow10_table_get_sig(-k, &p10_hi, &p10_lo); |
|
7704
|
|
|
|
|
|
|
|
|
7705
|
|
|
|
|
|
|
/* sig_bin << (1/2/3/4) */ |
|
7706
|
0
|
|
|
|
|
|
cb = sig_bin << (h + 1); |
|
7707
|
0
|
|
|
|
|
|
u128_mul(cb, p10_lo, &s_hi, &s_lo); |
|
7708
|
0
|
|
|
|
|
|
u128_mul_add(cb, p10_hi, s_hi, &s_hi, &s_lo); |
|
7709
|
|
|
|
|
|
|
|
|
7710
|
|
|
|
|
|
|
/* round up */ |
|
7711
|
0
|
0
|
|
|
|
|
u = s_lo >= (irregular ? U64(0x55555555, 0x55555555) : ((u64)1 << 63)); |
|
7712
|
|
|
|
|
|
|
|
|
7713
|
0
|
|
|
|
|
|
*sig_dec = s_hi + u; |
|
7714
|
0
|
|
|
|
|
|
*exp_dec = k; |
|
7715
|
0
|
|
|
|
|
|
*round_up = u; |
|
7716
|
0
|
|
|
|
|
|
return; |
|
7717
|
|
|
|
|
|
|
} |
|
7718
|
|
|
|
|
|
|
|
|
7719
|
|
|
|
|
|
|
/** Write inf/nan if allowed. */ |
|
7720
|
|
|
|
|
|
|
static_inline u8 *write_inf_or_nan(u8 *buf, yyjson_write_flag flg, |
|
7721
|
|
|
|
|
|
|
u64 sig_raw, bool sign) { |
|
7722
|
0
|
0
|
|
|
|
|
if (has_flg(INF_AND_NAN_AS_NULL)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7723
|
|
|
|
|
|
|
byte_copy_4(buf, "null"); |
|
7724
|
0
|
|
|
|
|
|
return buf + 4; |
|
7725
|
|
|
|
|
|
|
} |
|
7726
|
0
|
0
|
|
|
|
|
if (has_allow(INF_AND_NAN)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7727
|
0
|
0
|
|
|
|
|
if (sig_raw == 0) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7728
|
0
|
|
|
|
|
|
buf[0] = '-'; |
|
7729
|
0
|
|
|
|
|
|
buf += sign; |
|
7730
|
|
|
|
|
|
|
byte_copy_8(buf, "Infinity"); |
|
7731
|
0
|
|
|
|
|
|
return buf + 8; |
|
7732
|
|
|
|
|
|
|
} else { |
|
7733
|
|
|
|
|
|
|
byte_copy_4(buf, "NaN"); |
|
7734
|
0
|
|
|
|
|
|
return buf + 3; |
|
7735
|
|
|
|
|
|
|
} |
|
7736
|
|
|
|
|
|
|
} |
|
7737
|
0
|
|
|
|
|
|
return NULL; |
|
7738
|
|
|
|
|
|
|
} |
|
7739
|
|
|
|
|
|
|
|
|
7740
|
|
|
|
|
|
|
/** |
|
7741
|
|
|
|
|
|
|
Write a float number (requires 40 bytes buffer). |
|
7742
|
|
|
|
|
|
|
We follow the ECMAScript specification for printing floating-point numbers, |
|
7743
|
|
|
|
|
|
|
similar to `Number.prototype.toString()`, but with the following changes: |
|
7744
|
|
|
|
|
|
|
1. Keep the negative sign of `-0.0` to preserve input information. |
|
7745
|
|
|
|
|
|
|
2. Keep decimal point to indicate the number is floating point. |
|
7746
|
|
|
|
|
|
|
3. Remove positive sign in the exponent part. |
|
7747
|
|
|
|
|
|
|
*/ |
|
7748
|
0
|
|
|
|
|
|
static_noinline u8 *write_f32_raw(u8 *buf, u64 raw_f64, |
|
7749
|
|
|
|
|
|
|
yyjson_write_flag flg) { |
|
7750
|
|
|
|
|
|
|
u32 sig_bin, sig_dec, sig_raw; |
|
7751
|
|
|
|
|
|
|
i32 exp_bin, exp_dec, sig_len, dot_ofs; |
|
7752
|
|
|
|
|
|
|
u32 exp_raw, raw; |
|
7753
|
|
|
|
|
|
|
u8 *end; |
|
7754
|
|
|
|
|
|
|
bool sign; |
|
7755
|
|
|
|
|
|
|
|
|
7756
|
|
|
|
|
|
|
/* cast double to float */ |
|
7757
|
0
|
|
|
|
|
|
raw = f32_to_bits(f64_to_f32(f64_from_bits(raw_f64))); |
|
7758
|
|
|
|
|
|
|
|
|
7759
|
|
|
|
|
|
|
/* decode raw bytes from IEEE-754 double format. */ |
|
7760
|
0
|
|
|
|
|
|
sign = (bool)(raw >> (F32_BITS - 1)); |
|
7761
|
0
|
|
|
|
|
|
sig_raw = raw & F32_SIG_MASK; |
|
7762
|
0
|
|
|
|
|
|
exp_raw = (raw & F32_EXP_MASK) >> F32_SIG_BITS; |
|
7763
|
|
|
|
|
|
|
|
|
7764
|
|
|
|
|
|
|
/* return inf or nan */ |
|
7765
|
0
|
0
|
|
|
|
|
if (unlikely(exp_raw == ((u32)1 << F32_EXP_BITS) - 1)) { |
|
7766
|
0
|
|
|
|
|
|
return write_inf_or_nan(buf, flg, sig_raw, sign); |
|
7767
|
|
|
|
|
|
|
} |
|
7768
|
|
|
|
|
|
|
|
|
7769
|
|
|
|
|
|
|
/* add sign for all finite number */ |
|
7770
|
0
|
|
|
|
|
|
buf[0] = '-'; |
|
7771
|
0
|
|
|
|
|
|
buf += sign; |
|
7772
|
|
|
|
|
|
|
|
|
7773
|
|
|
|
|
|
|
/* return zero */ |
|
7774
|
0
|
0
|
|
|
|
|
if ((raw << 1) == 0) { |
|
7775
|
|
|
|
|
|
|
byte_copy_4(buf, "0.0"); |
|
7776
|
0
|
|
|
|
|
|
return buf + 3; |
|
7777
|
|
|
|
|
|
|
} |
|
7778
|
|
|
|
|
|
|
|
|
7779
|
0
|
0
|
|
|
|
|
if (likely(exp_raw != 0)) { |
|
7780
|
|
|
|
|
|
|
/* normal number */ |
|
7781
|
0
|
|
|
|
|
|
sig_bin = sig_raw | ((u32)1 << F32_SIG_BITS); |
|
7782
|
0
|
|
|
|
|
|
exp_bin = (i32)exp_raw - F32_EXP_BIAS - F32_SIG_BITS; |
|
7783
|
|
|
|
|
|
|
|
|
7784
|
|
|
|
|
|
|
/* fast path for small integer number without fraction */ |
|
7785
|
0
|
0
|
|
|
|
|
if ((-F32_SIG_BITS <= exp_bin && exp_bin <= 0) && |
|
|
|
0
|
|
|
|
|
|
|
7786
|
0
|
0
|
|
|
|
|
(u64_tz_bits(sig_bin) >= (u32)-exp_bin)) { |
|
7787
|
0
|
|
|
|
|
|
sig_dec = sig_bin >> -exp_bin; /* range: [1, 0xFFFFFF] */ |
|
7788
|
0
|
0
|
|
|
|
|
buf = write_u32_len_1_to_8(sig_dec, buf); |
|
7789
|
|
|
|
|
|
|
byte_copy_2(buf, ".0"); |
|
7790
|
0
|
|
|
|
|
|
return buf + 2; |
|
7791
|
|
|
|
|
|
|
} |
|
7792
|
|
|
|
|
|
|
|
|
7793
|
|
|
|
|
|
|
/* binary to decimal */ |
|
7794
|
|
|
|
|
|
|
f32_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); |
|
7795
|
|
|
|
|
|
|
|
|
7796
|
|
|
|
|
|
|
/* the sig length is 7 or 9 */ |
|
7797
|
0
|
0
|
|
|
|
|
sig_len = 7 + (sig_dec >= (u32)10000000) + (sig_dec >= (u32)100000000); |
|
7798
|
|
|
|
|
|
|
|
|
7799
|
|
|
|
|
|
|
/* the decimal point offset relative to the first digit */ |
|
7800
|
0
|
|
|
|
|
|
dot_ofs = sig_len + exp_dec; |
|
7801
|
|
|
|
|
|
|
|
|
7802
|
0
|
0
|
|
|
|
|
if (-6 < dot_ofs && dot_ofs <= 21) { |
|
|
|
0
|
|
|
|
|
|
|
7803
|
|
|
|
|
|
|
i32 num_sep_pos, dot_set_pos, pre_ofs; |
|
7804
|
|
|
|
|
|
|
u8 *num_hdr, *num_end, *num_sep, *dot_end; |
|
7805
|
|
|
|
|
|
|
bool no_pre_zero; |
|
7806
|
|
|
|
|
|
|
|
|
7807
|
|
|
|
|
|
|
/* fill zeros */ |
|
7808
|
0
|
|
|
|
|
|
memset(buf, '0', 32); |
|
7809
|
|
|
|
|
|
|
|
|
7810
|
|
|
|
|
|
|
/* not prefixed with zero, e.g. 1.234, 1234.0 */ |
|
7811
|
0
|
|
|
|
|
|
no_pre_zero = (dot_ofs > 0); |
|
7812
|
|
|
|
|
|
|
|
|
7813
|
|
|
|
|
|
|
/* write the number as digits */ |
|
7814
|
0
|
0
|
|
|
|
|
pre_ofs = no_pre_zero ? 0 : (2 - dot_ofs); |
|
7815
|
0
|
|
|
|
|
|
num_hdr = buf + pre_ofs; |
|
7816
|
0
|
0
|
|
|
|
|
num_end = write_u32_len_7_to_9_trim(sig_dec, num_hdr); |
|
7817
|
|
|
|
|
|
|
|
|
7818
|
|
|
|
|
|
|
/* seperate these digits to leave a space for dot */ |
|
7819
|
0
|
0
|
|
|
|
|
num_sep_pos = no_pre_zero ? dot_ofs : 0; |
|
7820
|
0
|
|
|
|
|
|
num_sep = num_hdr + num_sep_pos; |
|
7821
|
0
|
|
|
|
|
|
byte_move_8(num_sep + no_pre_zero, num_sep); |
|
7822
|
0
|
|
|
|
|
|
num_end += no_pre_zero; |
|
7823
|
|
|
|
|
|
|
|
|
7824
|
|
|
|
|
|
|
/* write the dot */ |
|
7825
|
0
|
|
|
|
|
|
dot_set_pos = yyjson_max(dot_ofs, 1); |
|
7826
|
0
|
|
|
|
|
|
buf[dot_set_pos] = '.'; |
|
7827
|
|
|
|
|
|
|
|
|
7828
|
|
|
|
|
|
|
/* return the ending */ |
|
7829
|
0
|
|
|
|
|
|
dot_end = buf + dot_ofs + 2; |
|
7830
|
0
|
|
|
|
|
|
return yyjson_max(dot_end, num_end); |
|
7831
|
|
|
|
|
|
|
|
|
7832
|
|
|
|
|
|
|
} else { |
|
7833
|
|
|
|
|
|
|
/* write with scientific notation, e.g. 1.234e56 */ |
|
7834
|
0
|
0
|
|
|
|
|
end = write_u32_len_7_to_9_trim(sig_dec, buf + 1); |
|
7835
|
0
|
|
|
|
|
|
end -= (end == buf + 2); /* remove '.0', e.g. 2.0e34 -> 2e34 */ |
|
7836
|
0
|
|
|
|
|
|
exp_dec += sig_len - 1; |
|
7837
|
0
|
|
|
|
|
|
buf[0] = buf[1]; |
|
7838
|
0
|
|
|
|
|
|
buf[1] = '.'; |
|
7839
|
0
|
|
|
|
|
|
return write_f32_exp(exp_dec, end); |
|
7840
|
|
|
|
|
|
|
} |
|
7841
|
|
|
|
|
|
|
|
|
7842
|
|
|
|
|
|
|
} else { |
|
7843
|
|
|
|
|
|
|
/* subnormal number */ |
|
7844
|
0
|
|
|
|
|
|
sig_bin = sig_raw; |
|
7845
|
0
|
|
|
|
|
|
exp_bin = 1 - F32_EXP_BIAS - F32_SIG_BITS; |
|
7846
|
|
|
|
|
|
|
|
|
7847
|
|
|
|
|
|
|
/* binary to decimal */ |
|
7848
|
|
|
|
|
|
|
f32_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); |
|
7849
|
|
|
|
|
|
|
|
|
7850
|
|
|
|
|
|
|
/* write significand part */ |
|
7851
|
0
|
0
|
|
|
|
|
end = write_u32_len_1_to_8(sig_dec, buf + 1); |
|
7852
|
0
|
|
|
|
|
|
buf[0] = buf[1]; |
|
7853
|
0
|
|
|
|
|
|
buf[1] = '.'; |
|
7854
|
0
|
|
|
|
|
|
exp_dec += (i32)(end - buf) - 2; |
|
7855
|
|
|
|
|
|
|
|
|
7856
|
|
|
|
|
|
|
/* trim trailing zeros */ |
|
7857
|
0
|
|
|
|
|
|
end -= *(end - 1) == '0'; /* branchless for last zero */ |
|
7858
|
0
|
|
|
|
|
|
end -= *(end - 1) == '0'; /* branchless for second last zero */ |
|
7859
|
0
|
0
|
|
|
|
|
while (*(end - 1) == '0') end--; /* for unlikely more zeros */ |
|
7860
|
0
|
|
|
|
|
|
end -= *(end - 1) == '.'; /* remove dot, e.g. 2.e-321 -> 2e-321 */ |
|
7861
|
|
|
|
|
|
|
|
|
7862
|
|
|
|
|
|
|
/* write exponent part */ |
|
7863
|
0
|
|
|
|
|
|
return write_f32_exp(exp_dec, end); |
|
7864
|
|
|
|
|
|
|
} |
|
7865
|
|
|
|
|
|
|
} |
|
7866
|
|
|
|
|
|
|
|
|
7867
|
|
|
|
|
|
|
/** |
|
7868
|
|
|
|
|
|
|
Write a double number (requires 40 bytes buffer). |
|
7869
|
|
|
|
|
|
|
We follow the ECMAScript specification for printing floating-point numbers, |
|
7870
|
|
|
|
|
|
|
similar to `Number.prototype.toString()`, but with the following changes: |
|
7871
|
|
|
|
|
|
|
1. Keep the negative sign of `-0.0` to preserve input information. |
|
7872
|
|
|
|
|
|
|
2. Keep decimal point to indicate the number is floating point. |
|
7873
|
|
|
|
|
|
|
3. Remove positive sign in the exponent part. |
|
7874
|
|
|
|
|
|
|
*/ |
|
7875
|
1
|
|
|
|
|
|
static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { |
|
7876
|
|
|
|
|
|
|
u64 sig_bin, sig_dec, sig_raw; |
|
7877
|
|
|
|
|
|
|
i32 exp_bin, exp_dec, sig_len, dot_ofs; |
|
7878
|
|
|
|
|
|
|
u32 exp_raw; |
|
7879
|
|
|
|
|
|
|
u8 *end; |
|
7880
|
|
|
|
|
|
|
bool sign; |
|
7881
|
|
|
|
|
|
|
|
|
7882
|
|
|
|
|
|
|
/* decode raw bytes from IEEE-754 double format. */ |
|
7883
|
1
|
|
|
|
|
|
sign = (bool)(raw >> (F64_BITS - 1)); |
|
7884
|
1
|
|
|
|
|
|
sig_raw = raw & F64_SIG_MASK; |
|
7885
|
1
|
|
|
|
|
|
exp_raw = (u32)((raw & F64_EXP_MASK) >> F64_SIG_BITS); |
|
7886
|
|
|
|
|
|
|
|
|
7887
|
|
|
|
|
|
|
/* return inf or nan */ |
|
7888
|
1
|
50
|
|
|
|
|
if (unlikely(exp_raw == ((u32)1 << F64_EXP_BITS) - 1)) { |
|
7889
|
0
|
|
|
|
|
|
return write_inf_or_nan(buf, flg, sig_raw, sign); |
|
7890
|
|
|
|
|
|
|
} |
|
7891
|
|
|
|
|
|
|
|
|
7892
|
|
|
|
|
|
|
/* add sign for all finite number */ |
|
7893
|
1
|
|
|
|
|
|
buf[0] = '-'; |
|
7894
|
1
|
|
|
|
|
|
buf += sign; |
|
7895
|
|
|
|
|
|
|
|
|
7896
|
|
|
|
|
|
|
/* return zero */ |
|
7897
|
1
|
50
|
|
|
|
|
if ((raw << 1) == 0) { |
|
7898
|
|
|
|
|
|
|
byte_copy_4(buf, "0.0"); |
|
7899
|
0
|
|
|
|
|
|
return buf + 3; |
|
7900
|
|
|
|
|
|
|
} |
|
7901
|
|
|
|
|
|
|
|
|
7902
|
1
|
50
|
|
|
|
|
if (likely(exp_raw != 0)) { |
|
7903
|
|
|
|
|
|
|
/* normal number */ |
|
7904
|
1
|
|
|
|
|
|
sig_bin = sig_raw | ((u64)1 << F64_SIG_BITS); |
|
7905
|
1
|
|
|
|
|
|
exp_bin = (i32)exp_raw - F64_EXP_BIAS - F64_SIG_BITS; |
|
7906
|
|
|
|
|
|
|
|
|
7907
|
|
|
|
|
|
|
/* fast path for small integer number without fraction */ |
|
7908
|
1
|
50
|
|
|
|
|
if ((-F64_SIG_BITS <= exp_bin && exp_bin <= 0) && |
|
|
|
50
|
|
|
|
|
|
|
7909
|
1
|
50
|
|
|
|
|
(u64_tz_bits(sig_bin) >= (u32)-exp_bin)) { |
|
7910
|
0
|
|
|
|
|
|
sig_dec = sig_bin >> -exp_bin; /* range: [1, 0x1FFFFFFFFFFFFF] */ |
|
7911
|
0
|
0
|
|
|
|
|
buf = write_u64_len_1_to_16(sig_dec, buf); |
|
7912
|
|
|
|
|
|
|
byte_copy_2(buf, ".0"); |
|
7913
|
0
|
|
|
|
|
|
return buf + 2; |
|
7914
|
|
|
|
|
|
|
} |
|
7915
|
|
|
|
|
|
|
|
|
7916
|
|
|
|
|
|
|
/* binary to decimal */ |
|
7917
|
|
|
|
|
|
|
f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); |
|
7918
|
|
|
|
|
|
|
|
|
7919
|
|
|
|
|
|
|
/* the sig length is 16 or 17 */ |
|
7920
|
1
|
50
|
|
|
|
|
sig_len = 16 + (sig_dec >= (u64)100000000 * 100000000); |
|
7921
|
|
|
|
|
|
|
|
|
7922
|
|
|
|
|
|
|
/* the decimal point offset relative to the first digit */ |
|
7923
|
1
|
|
|
|
|
|
dot_ofs = sig_len + exp_dec; |
|
7924
|
|
|
|
|
|
|
|
|
7925
|
1
|
50
|
|
|
|
|
if (-6 < dot_ofs && dot_ofs <= 21) { |
|
|
|
50
|
|
|
|
|
|
|
7926
|
|
|
|
|
|
|
i32 num_sep_pos, dot_set_pos, pre_ofs; |
|
7927
|
|
|
|
|
|
|
u8 *num_hdr, *num_end, *num_sep, *dot_end; |
|
7928
|
|
|
|
|
|
|
bool no_pre_zero; |
|
7929
|
|
|
|
|
|
|
|
|
7930
|
|
|
|
|
|
|
/* fill zeros */ |
|
7931
|
1
|
|
|
|
|
|
memset(buf, '0', 32); |
|
7932
|
|
|
|
|
|
|
|
|
7933
|
|
|
|
|
|
|
/* not prefixed with zero, e.g. 1.234, 1234.0 */ |
|
7934
|
1
|
|
|
|
|
|
no_pre_zero = (dot_ofs > 0); |
|
7935
|
|
|
|
|
|
|
|
|
7936
|
|
|
|
|
|
|
/* write the number as digits */ |
|
7937
|
1
|
50
|
|
|
|
|
pre_ofs = no_pre_zero ? 0 : (2 - dot_ofs); |
|
7938
|
1
|
|
|
|
|
|
num_hdr = buf + pre_ofs; |
|
7939
|
1
|
|
|
|
|
|
num_end = write_u64_len_16_to_17_trim(sig_dec, num_hdr); |
|
7940
|
|
|
|
|
|
|
|
|
7941
|
|
|
|
|
|
|
/* seperate these digits to leave a space for dot */ |
|
7942
|
1
|
50
|
|
|
|
|
num_sep_pos = no_pre_zero ? dot_ofs : 0; |
|
7943
|
1
|
|
|
|
|
|
num_sep = num_hdr + num_sep_pos; |
|
7944
|
1
|
|
|
|
|
|
byte_move_16(num_sep + no_pre_zero, num_sep); |
|
7945
|
1
|
|
|
|
|
|
num_end += no_pre_zero; |
|
7946
|
|
|
|
|
|
|
|
|
7947
|
|
|
|
|
|
|
/* write the dot */ |
|
7948
|
1
|
|
|
|
|
|
dot_set_pos = yyjson_max(dot_ofs, 1); |
|
7949
|
1
|
|
|
|
|
|
buf[dot_set_pos] = '.'; |
|
7950
|
|
|
|
|
|
|
|
|
7951
|
|
|
|
|
|
|
/* return the ending */ |
|
7952
|
1
|
|
|
|
|
|
dot_end = buf + dot_ofs + 2; |
|
7953
|
1
|
|
|
|
|
|
return yyjson_max(dot_end, num_end); |
|
7954
|
|
|
|
|
|
|
|
|
7955
|
|
|
|
|
|
|
} else { |
|
7956
|
|
|
|
|
|
|
/* write with scientific notation, e.g. 1.234e56 */ |
|
7957
|
0
|
|
|
|
|
|
end = write_u64_len_16_to_17_trim(sig_dec, buf + 1); |
|
7958
|
0
|
|
|
|
|
|
end -= (end == buf + 2); /* remove '.0', e.g. 2.0e34 -> 2e34 */ |
|
7959
|
0
|
|
|
|
|
|
exp_dec += sig_len - 1; |
|
7960
|
0
|
|
|
|
|
|
buf[0] = buf[1]; |
|
7961
|
0
|
|
|
|
|
|
buf[1] = '.'; |
|
7962
|
0
|
|
|
|
|
|
return write_f64_exp(exp_dec, end); |
|
7963
|
|
|
|
|
|
|
} |
|
7964
|
|
|
|
|
|
|
|
|
7965
|
|
|
|
|
|
|
} else { |
|
7966
|
|
|
|
|
|
|
/* subnormal number */ |
|
7967
|
0
|
|
|
|
|
|
sig_bin = sig_raw; |
|
7968
|
0
|
|
|
|
|
|
exp_bin = 1 - F64_EXP_BIAS - F64_SIG_BITS; |
|
7969
|
|
|
|
|
|
|
|
|
7970
|
|
|
|
|
|
|
/* binary to decimal */ |
|
7971
|
|
|
|
|
|
|
f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); |
|
7972
|
|
|
|
|
|
|
|
|
7973
|
|
|
|
|
|
|
/* write significand part */ |
|
7974
|
0
|
0
|
|
|
|
|
end = write_u64_len_1_to_17(sig_dec, buf + 1); |
|
7975
|
0
|
|
|
|
|
|
buf[0] = buf[1]; |
|
7976
|
0
|
|
|
|
|
|
buf[1] = '.'; |
|
7977
|
0
|
|
|
|
|
|
exp_dec += (i32)(end - buf) - 2; |
|
7978
|
|
|
|
|
|
|
|
|
7979
|
|
|
|
|
|
|
/* trim trailing zeros */ |
|
7980
|
0
|
|
|
|
|
|
end -= *(end - 1) == '0'; /* branchless for last zero */ |
|
7981
|
0
|
|
|
|
|
|
end -= *(end - 1) == '0'; /* branchless for second last zero */ |
|
7982
|
0
|
0
|
|
|
|
|
while (*(end - 1) == '0') end--; /* for unlikely more zeros */ |
|
7983
|
0
|
|
|
|
|
|
end -= *(end - 1) == '.'; /* remove dot, e.g. 2.e-321 -> 2e-321 */ |
|
7984
|
|
|
|
|
|
|
|
|
7985
|
|
|
|
|
|
|
/* write exponent part */ |
|
7986
|
0
|
|
|
|
|
|
return write_f64_exp(exp_dec, end); |
|
7987
|
|
|
|
|
|
|
} |
|
7988
|
|
|
|
|
|
|
} |
|
7989
|
|
|
|
|
|
|
|
|
7990
|
|
|
|
|
|
|
/** |
|
7991
|
|
|
|
|
|
|
Write a double number using fixed-point notation (requires 40 bytes buffer). |
|
7992
|
|
|
|
|
|
|
|
|
7993
|
|
|
|
|
|
|
We follow the ECMAScript specification for printing floating-point numbers, |
|
7994
|
|
|
|
|
|
|
similar to `Number.prototype.toFixed(prec)`, but with the following changes: |
|
7995
|
|
|
|
|
|
|
1. Keep the negative sign of `-0.0` to preserve input information. |
|
7996
|
|
|
|
|
|
|
2. Keep decimal point to indicate the number is floating point. |
|
7997
|
|
|
|
|
|
|
3. Remove positive sign in the exponent part. |
|
7998
|
|
|
|
|
|
|
4. Remove trailing zeros and reduce unnecessary precision. |
|
7999
|
|
|
|
|
|
|
*/ |
|
8000
|
0
|
|
|
|
|
|
static_noinline u8 *write_f64_raw_fixed(u8 *buf, u64 raw, yyjson_write_flag flg, |
|
8001
|
|
|
|
|
|
|
u32 prec) { |
|
8002
|
|
|
|
|
|
|
u64 sig_bin, sig_dec, sig_raw; |
|
8003
|
|
|
|
|
|
|
i32 exp_bin, exp_dec, sig_len, dot_ofs; |
|
8004
|
|
|
|
|
|
|
u32 exp_raw; |
|
8005
|
|
|
|
|
|
|
u8 *end; |
|
8006
|
|
|
|
|
|
|
bool sign; |
|
8007
|
|
|
|
|
|
|
|
|
8008
|
|
|
|
|
|
|
/* decode raw bytes from IEEE-754 double format. */ |
|
8009
|
0
|
|
|
|
|
|
sign = (bool)(raw >> (F64_BITS - 1)); |
|
8010
|
0
|
|
|
|
|
|
sig_raw = raw & F64_SIG_MASK; |
|
8011
|
0
|
|
|
|
|
|
exp_raw = (u32)((raw & F64_EXP_MASK) >> F64_SIG_BITS); |
|
8012
|
|
|
|
|
|
|
|
|
8013
|
|
|
|
|
|
|
/* return inf or nan */ |
|
8014
|
0
|
0
|
|
|
|
|
if (unlikely(exp_raw == ((u32)1 << F64_EXP_BITS) - 1)) { |
|
8015
|
0
|
|
|
|
|
|
return write_inf_or_nan(buf, flg, sig_raw, sign); |
|
8016
|
|
|
|
|
|
|
} |
|
8017
|
|
|
|
|
|
|
|
|
8018
|
|
|
|
|
|
|
/* add sign for all finite number */ |
|
8019
|
0
|
|
|
|
|
|
buf[0] = '-'; |
|
8020
|
0
|
|
|
|
|
|
buf += sign; |
|
8021
|
|
|
|
|
|
|
|
|
8022
|
|
|
|
|
|
|
/* return zero */ |
|
8023
|
0
|
0
|
|
|
|
|
if ((raw << 1) == 0) { |
|
8024
|
|
|
|
|
|
|
byte_copy_4(buf, "0.0"); |
|
8025
|
0
|
|
|
|
|
|
return buf + 3; |
|
8026
|
|
|
|
|
|
|
} |
|
8027
|
|
|
|
|
|
|
|
|
8028
|
0
|
0
|
|
|
|
|
if (likely(exp_raw != 0)) { |
|
8029
|
|
|
|
|
|
|
/* normal number */ |
|
8030
|
0
|
|
|
|
|
|
sig_bin = sig_raw | ((u64)1 << F64_SIG_BITS); |
|
8031
|
0
|
|
|
|
|
|
exp_bin = (i32)exp_raw - F64_EXP_BIAS - F64_SIG_BITS; |
|
8032
|
|
|
|
|
|
|
|
|
8033
|
|
|
|
|
|
|
/* fast path for small integer number without fraction */ |
|
8034
|
0
|
0
|
|
|
|
|
if ((-F64_SIG_BITS <= exp_bin && exp_bin <= 0) && |
|
|
|
0
|
|
|
|
|
|
|
8035
|
0
|
0
|
|
|
|
|
(u64_tz_bits(sig_bin) >= (u32)-exp_bin)) { |
|
8036
|
0
|
|
|
|
|
|
sig_dec = sig_bin >> -exp_bin; /* range: [1, 0x1FFFFFFFFFFFFF] */ |
|
8037
|
0
|
0
|
|
|
|
|
buf = write_u64_len_1_to_16(sig_dec, buf); |
|
8038
|
|
|
|
|
|
|
byte_copy_2(buf, ".0"); |
|
8039
|
0
|
|
|
|
|
|
return buf + 2; |
|
8040
|
|
|
|
|
|
|
} |
|
8041
|
|
|
|
|
|
|
|
|
8042
|
|
|
|
|
|
|
/* only `fabs(num) < 1e21` are processed here. */ |
|
8043
|
0
|
0
|
|
|
|
|
if ((raw << 1) < (U64(0x444B1AE4, 0xD6E2EF50) << 1)) { |
|
8044
|
|
|
|
|
|
|
i32 num_sep_pos, dot_set_pos, pre_ofs; |
|
8045
|
|
|
|
|
|
|
u8 *num_hdr, *num_end, *num_sep; |
|
8046
|
|
|
|
|
|
|
bool round_up, no_pre_zero; |
|
8047
|
|
|
|
|
|
|
|
|
8048
|
|
|
|
|
|
|
/* binary to decimal */ |
|
8049
|
|
|
|
|
|
|
f64_bin_to_dec_fast(sig_raw, exp_raw, sig_bin, exp_bin, |
|
8050
|
|
|
|
|
|
|
&sig_dec, &exp_dec, &round_up); |
|
8051
|
|
|
|
|
|
|
|
|
8052
|
|
|
|
|
|
|
/* the sig length is 16 or 17 */ |
|
8053
|
0
|
0
|
|
|
|
|
sig_len = 16 + (sig_dec >= (u64)100000000 * 100000000); |
|
8054
|
|
|
|
|
|
|
|
|
8055
|
|
|
|
|
|
|
/* limit the length of digits after the decimal point */ |
|
8056
|
0
|
0
|
|
|
|
|
if (exp_dec < -1) { |
|
8057
|
0
|
|
|
|
|
|
i32 sig_len_cut = -exp_dec - (i32)prec; |
|
8058
|
0
|
0
|
|
|
|
|
if (sig_len_cut > sig_len) { |
|
8059
|
|
|
|
|
|
|
byte_copy_4(buf, "0.0"); |
|
8060
|
0
|
|
|
|
|
|
return buf + 3; |
|
8061
|
|
|
|
|
|
|
} |
|
8062
|
0
|
0
|
|
|
|
|
if (sig_len_cut > 0) { |
|
8063
|
|
|
|
|
|
|
u64 div, mod, p10; |
|
8064
|
|
|
|
|
|
|
|
|
8065
|
|
|
|
|
|
|
/* remove round up */ |
|
8066
|
0
|
|
|
|
|
|
sig_dec -= round_up; |
|
8067
|
0
|
0
|
|
|
|
|
sig_len = 16 + (sig_dec >= (u64)100000000 * 100000000); |
|
8068
|
|
|
|
|
|
|
|
|
8069
|
|
|
|
|
|
|
/* cut off some digits */ |
|
8070
|
0
|
|
|
|
|
|
div_pow10(sig_dec, (u32)sig_len_cut, &div, &mod, &p10); |
|
8071
|
|
|
|
|
|
|
|
|
8072
|
|
|
|
|
|
|
/* add round up */ |
|
8073
|
0
|
|
|
|
|
|
sig_dec = div + (mod >= p10 / 2); |
|
8074
|
|
|
|
|
|
|
|
|
8075
|
|
|
|
|
|
|
/* update exp and sig length */ |
|
8076
|
0
|
|
|
|
|
|
exp_dec += sig_len_cut; |
|
8077
|
0
|
|
|
|
|
|
sig_len -= sig_len_cut; |
|
8078
|
0
|
0
|
|
|
|
|
sig_len += (sig_len >= 0) && |
|
8079
|
0
|
0
|
|
|
|
|
(sig_dec >= div_pow10_table[sig_len].p10); |
|
8080
|
|
|
|
|
|
|
} |
|
8081
|
0
|
0
|
|
|
|
|
if (sig_len <= 0) { |
|
8082
|
|
|
|
|
|
|
byte_copy_4(buf, "0.0"); |
|
8083
|
0
|
|
|
|
|
|
return buf + 3; |
|
8084
|
|
|
|
|
|
|
} |
|
8085
|
|
|
|
|
|
|
} |
|
8086
|
|
|
|
|
|
|
|
|
8087
|
|
|
|
|
|
|
/* fill zeros */ |
|
8088
|
0
|
|
|
|
|
|
memset(buf, '0', 32); |
|
8089
|
|
|
|
|
|
|
|
|
8090
|
|
|
|
|
|
|
/* the decimal point offset relative to the first digit */ |
|
8091
|
0
|
|
|
|
|
|
dot_ofs = sig_len + exp_dec; |
|
8092
|
|
|
|
|
|
|
|
|
8093
|
|
|
|
|
|
|
/* not prefixed with zero, e.g. 1.234, 1234.0 */ |
|
8094
|
0
|
|
|
|
|
|
no_pre_zero = (dot_ofs > 0); |
|
8095
|
|
|
|
|
|
|
|
|
8096
|
|
|
|
|
|
|
/* write the number as digits */ |
|
8097
|
0
|
0
|
|
|
|
|
pre_ofs = no_pre_zero ? 0 : (1 - dot_ofs); |
|
8098
|
0
|
|
|
|
|
|
num_hdr = buf + pre_ofs; |
|
8099
|
0
|
0
|
|
|
|
|
num_end = write_u64_len_1_to_17(sig_dec, num_hdr); |
|
8100
|
|
|
|
|
|
|
|
|
8101
|
|
|
|
|
|
|
/* seperate these digits to leave a space for dot */ |
|
8102
|
0
|
0
|
|
|
|
|
num_sep_pos = no_pre_zero ? dot_ofs : -dot_ofs; |
|
8103
|
0
|
|
|
|
|
|
num_sep = buf + num_sep_pos; |
|
8104
|
0
|
|
|
|
|
|
byte_move_16(num_sep + 1, num_sep); |
|
8105
|
0
|
|
|
|
|
|
num_end += (exp_dec < 0); |
|
8106
|
|
|
|
|
|
|
|
|
8107
|
|
|
|
|
|
|
/* write the dot */ |
|
8108
|
0
|
|
|
|
|
|
dot_set_pos = yyjson_max(dot_ofs, 1); |
|
8109
|
0
|
|
|
|
|
|
buf[dot_set_pos] = '.'; |
|
8110
|
|
|
|
|
|
|
|
|
8111
|
|
|
|
|
|
|
/* remove trailing zeros */ |
|
8112
|
0
|
|
|
|
|
|
buf += dot_set_pos + 2; |
|
8113
|
0
|
|
|
|
|
|
buf = yyjson_max(buf, num_end); |
|
8114
|
0
|
|
|
|
|
|
buf -= *(buf - 1) == '0'; /* branchless for last zero */ |
|
8115
|
0
|
|
|
|
|
|
buf -= *(buf - 1) == '0'; /* branchless for second last zero */ |
|
8116
|
0
|
0
|
|
|
|
|
while (*(buf - 1) == '0') buf--; /* for unlikely more zeros */ |
|
8117
|
0
|
|
|
|
|
|
buf += *(buf - 1) == '.'; /* keep a zero after dot */ |
|
8118
|
0
|
|
|
|
|
|
return buf; |
|
8119
|
|
|
|
|
|
|
|
|
8120
|
|
|
|
|
|
|
} else { |
|
8121
|
|
|
|
|
|
|
/* binary to decimal */ |
|
8122
|
|
|
|
|
|
|
f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, |
|
8123
|
|
|
|
|
|
|
&sig_dec, &exp_dec); |
|
8124
|
|
|
|
|
|
|
|
|
8125
|
|
|
|
|
|
|
/* the sig length is 16 or 17 */ |
|
8126
|
0
|
0
|
|
|
|
|
sig_len = 16 + (sig_dec >= (u64)100000000 * 100000000); |
|
8127
|
|
|
|
|
|
|
|
|
8128
|
|
|
|
|
|
|
/* write with scientific notation, e.g. 1.234e56 */ |
|
8129
|
0
|
|
|
|
|
|
end = write_u64_len_16_to_17_trim(sig_dec, buf + 1); |
|
8130
|
0
|
|
|
|
|
|
end -= (end == buf + 2); /* remove '.0', e.g. 2.0e34 -> 2e34 */ |
|
8131
|
0
|
|
|
|
|
|
exp_dec += sig_len - 1; |
|
8132
|
0
|
|
|
|
|
|
buf[0] = buf[1]; |
|
8133
|
0
|
|
|
|
|
|
buf[1] = '.'; |
|
8134
|
0
|
|
|
|
|
|
return write_f64_exp(exp_dec, end); |
|
8135
|
|
|
|
|
|
|
} |
|
8136
|
|
|
|
|
|
|
} else { |
|
8137
|
|
|
|
|
|
|
/* subnormal number */ |
|
8138
|
|
|
|
|
|
|
byte_copy_4(buf, "0.0"); |
|
8139
|
0
|
|
|
|
|
|
return buf + 3; |
|
8140
|
|
|
|
|
|
|
} |
|
8141
|
|
|
|
|
|
|
} |
|
8142
|
|
|
|
|
|
|
|
|
8143
|
|
|
|
|
|
|
#else /* FP_WRITER */ |
|
8144
|
|
|
|
|
|
|
|
|
8145
|
|
|
|
|
|
|
#if YYJSON_MSC_VER >= 1400 |
|
8146
|
|
|
|
|
|
|
#define snprintf_num(buf, len, fmt, dig, val) \ |
|
8147
|
|
|
|
|
|
|
sprintf_s((char *)buf, len, fmt, dig, val) |
|
8148
|
|
|
|
|
|
|
#elif defined(snprintf) || (YYJSON_STDC_VER >= 199901L) |
|
8149
|
|
|
|
|
|
|
#define snprintf_num(buf, len, fmt, dig, val) \ |
|
8150
|
|
|
|
|
|
|
snprintf((char *)buf, len, fmt, dig, val) |
|
8151
|
|
|
|
|
|
|
#else |
|
8152
|
|
|
|
|
|
|
#define snprintf_num(buf, len, fmt, dig, val) \ |
|
8153
|
|
|
|
|
|
|
sprintf((char *)buf, fmt, dig, val) |
|
8154
|
|
|
|
|
|
|
#endif |
|
8155
|
|
|
|
|
|
|
|
|
8156
|
|
|
|
|
|
|
static_noinline u8 *write_fp_reformat(u8 *buf, int len, |
|
8157
|
|
|
|
|
|
|
yyjson_write_flag flg, bool fixed) { |
|
8158
|
|
|
|
|
|
|
u8 *cur = buf; |
|
8159
|
|
|
|
|
|
|
if (unlikely(len < 1)) return NULL; |
|
8160
|
|
|
|
|
|
|
cur += (*cur == '-'); |
|
8161
|
|
|
|
|
|
|
if (unlikely(!char_is_digit(*cur))) { |
|
8162
|
|
|
|
|
|
|
/* nan, inf, or bad output */ |
|
8163
|
|
|
|
|
|
|
if (has_flg(INF_AND_NAN_AS_NULL)) { |
|
8164
|
|
|
|
|
|
|
byte_copy_4(buf, "null"); |
|
8165
|
|
|
|
|
|
|
return buf + 4; |
|
8166
|
|
|
|
|
|
|
} else if (has_allow(INF_AND_NAN)) { |
|
8167
|
|
|
|
|
|
|
if (*cur == 'i') { |
|
8168
|
|
|
|
|
|
|
byte_copy_8(cur, "Infinity"); |
|
8169
|
|
|
|
|
|
|
return cur + 8; |
|
8170
|
|
|
|
|
|
|
} else if (*cur == 'n') { |
|
8171
|
|
|
|
|
|
|
byte_copy_4(buf, "NaN"); |
|
8172
|
|
|
|
|
|
|
return buf + 3; |
|
8173
|
|
|
|
|
|
|
} |
|
8174
|
|
|
|
|
|
|
} |
|
8175
|
|
|
|
|
|
|
return NULL; |
|
8176
|
|
|
|
|
|
|
} else { |
|
8177
|
|
|
|
|
|
|
/* finite number */ |
|
8178
|
|
|
|
|
|
|
u8 *end = buf + len, *dot = NULL, *exp = NULL; |
|
8179
|
|
|
|
|
|
|
|
|
8180
|
|
|
|
|
|
|
/* |
|
8181
|
|
|
|
|
|
|
The snprintf() function is locale-dependent. For currently known |
|
8182
|
|
|
|
|
|
|
locales, (en, zh, ja, ko, am, he, hi) use '.' as the decimal point, |
|
8183
|
|
|
|
|
|
|
while other locales use ',' as the decimal point. we need to replace |
|
8184
|
|
|
|
|
|
|
',' with '.' to avoid the locale setting. |
|
8185
|
|
|
|
|
|
|
*/ |
|
8186
|
|
|
|
|
|
|
for (; cur < end; cur++) { |
|
8187
|
|
|
|
|
|
|
switch (*cur) { |
|
8188
|
|
|
|
|
|
|
case ',': *cur = '.'; /* fallthrough */ |
|
8189
|
|
|
|
|
|
|
case '.': dot = cur; break; |
|
8190
|
|
|
|
|
|
|
case 'e': exp = cur; break; |
|
8191
|
|
|
|
|
|
|
default: break; |
|
8192
|
|
|
|
|
|
|
} |
|
8193
|
|
|
|
|
|
|
} |
|
8194
|
|
|
|
|
|
|
if (fixed) { |
|
8195
|
|
|
|
|
|
|
/* remove trailing zeros */ |
|
8196
|
|
|
|
|
|
|
while (*(end - 1) == '0') end--; |
|
8197
|
|
|
|
|
|
|
end += *(end - 1) == '.'; |
|
8198
|
|
|
|
|
|
|
} else { |
|
8199
|
|
|
|
|
|
|
if (!dot && !exp) { |
|
8200
|
|
|
|
|
|
|
/* add decimal point, e.g. 123 -> 123.0 */ |
|
8201
|
|
|
|
|
|
|
byte_copy_2(end, ".0"); |
|
8202
|
|
|
|
|
|
|
end += 2; |
|
8203
|
|
|
|
|
|
|
} else if (exp) { |
|
8204
|
|
|
|
|
|
|
cur = exp + 1; |
|
8205
|
|
|
|
|
|
|
/* remove positive sign in the exponent part */ |
|
8206
|
|
|
|
|
|
|
if (*cur == '+') { |
|
8207
|
|
|
|
|
|
|
memmove(cur, cur + 1, (usize)(end - cur - 1)); |
|
8208
|
|
|
|
|
|
|
end--; |
|
8209
|
|
|
|
|
|
|
} |
|
8210
|
|
|
|
|
|
|
cur += (*cur == '-'); |
|
8211
|
|
|
|
|
|
|
/* remove leading zeros in the exponent part */ |
|
8212
|
|
|
|
|
|
|
if (*cur == '0') { |
|
8213
|
|
|
|
|
|
|
u8 *hdr = cur++; |
|
8214
|
|
|
|
|
|
|
while (*cur == '0') cur++; |
|
8215
|
|
|
|
|
|
|
memmove(hdr, cur, (usize)(end - cur)); |
|
8216
|
|
|
|
|
|
|
end -= (usize)(cur - hdr); |
|
8217
|
|
|
|
|
|
|
} |
|
8218
|
|
|
|
|
|
|
} |
|
8219
|
|
|
|
|
|
|
} |
|
8220
|
|
|
|
|
|
|
return end; |
|
8221
|
|
|
|
|
|
|
} |
|
8222
|
|
|
|
|
|
|
} |
|
8223
|
|
|
|
|
|
|
|
|
8224
|
|
|
|
|
|
|
/** Write a double number (requires 40 bytes buffer). */ |
|
8225
|
|
|
|
|
|
|
static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { |
|
8226
|
|
|
|
|
|
|
#if defined(DBL_DECIMAL_DIG) && DBL_DECIMAL_DIG < F64_DEC_DIG |
|
8227
|
|
|
|
|
|
|
int dig = DBL_DECIMAL_DIG; |
|
8228
|
|
|
|
|
|
|
#else |
|
8229
|
|
|
|
|
|
|
int dig = F64_DEC_DIG; |
|
8230
|
|
|
|
|
|
|
#endif |
|
8231
|
|
|
|
|
|
|
f64 val = f64_from_bits(raw); |
|
8232
|
|
|
|
|
|
|
int len = snprintf_num(buf, FP_BUF_LEN, "%.*g", dig, val); |
|
8233
|
|
|
|
|
|
|
return write_fp_reformat(buf, len, flg, false); |
|
8234
|
|
|
|
|
|
|
} |
|
8235
|
|
|
|
|
|
|
|
|
8236
|
|
|
|
|
|
|
/** Write a double number (requires 40 bytes buffer). */ |
|
8237
|
|
|
|
|
|
|
static_noinline u8 *write_f32_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { |
|
8238
|
|
|
|
|
|
|
#if defined(FLT_DECIMAL_DIG) && FLT_DECIMAL_DIG < F32_DEC_DIG |
|
8239
|
|
|
|
|
|
|
int dig = FLT_DECIMAL_DIG; |
|
8240
|
|
|
|
|
|
|
#else |
|
8241
|
|
|
|
|
|
|
int dig = F32_DEC_DIG; |
|
8242
|
|
|
|
|
|
|
#endif |
|
8243
|
|
|
|
|
|
|
f64 val = (f64)f64_to_f32(f64_from_bits(raw)); |
|
8244
|
|
|
|
|
|
|
int len = snprintf_num(buf, FP_BUF_LEN, "%.*g", dig, val); |
|
8245
|
|
|
|
|
|
|
return write_fp_reformat(buf, len, flg, false); |
|
8246
|
|
|
|
|
|
|
} |
|
8247
|
|
|
|
|
|
|
|
|
8248
|
|
|
|
|
|
|
/** Write a double number (requires 40 bytes buffer). */ |
|
8249
|
|
|
|
|
|
|
static_noinline u8 *write_f64_raw_fixed(u8 *buf, u64 raw, |
|
8250
|
|
|
|
|
|
|
yyjson_write_flag flg, u32 prec) { |
|
8251
|
|
|
|
|
|
|
f64 val = (f64)f64_from_bits(raw); |
|
8252
|
|
|
|
|
|
|
if (-1e21 < val && val < 1e21) { |
|
8253
|
|
|
|
|
|
|
int len = snprintf_num(buf, FP_BUF_LEN, "%.*f", (int)prec, val); |
|
8254
|
|
|
|
|
|
|
return write_fp_reformat(buf, len, flg, true); |
|
8255
|
|
|
|
|
|
|
} else { |
|
8256
|
|
|
|
|
|
|
return write_f64_raw(buf, raw, flg); |
|
8257
|
|
|
|
|
|
|
} |
|
8258
|
|
|
|
|
|
|
} |
|
8259
|
|
|
|
|
|
|
|
|
8260
|
|
|
|
|
|
|
#endif /* FP_WRITER */ |
|
8261
|
|
|
|
|
|
|
|
|
8262
|
|
|
|
|
|
|
/** Write a JSON number (requires 40 bytes buffer). */ |
|
8263
|
|
|
|
|
|
|
static_inline u8 *write_num(u8 *cur, yyjson_val *val, yyjson_write_flag flg) { |
|
8264
|
35040
|
50
|
|
|
|
|
if (!(val->tag & YYJSON_SUBTYPE_REAL)) { |
|
|
|
0
|
|
|
|
|
|
|
8265
|
35053
|
|
|
|
|
|
u64 pos = val->uni.u64; |
|
8266
|
35053
|
|
|
|
|
|
u64 neg = ~pos + 1; |
|
8267
|
35053
|
|
|
|
|
|
usize sign = ((val->tag & YYJSON_SUBTYPE_SINT) > 0) & ((i64)pos < 0); |
|
8268
|
35053
|
|
|
|
|
|
*cur = '-'; |
|
8269
|
70106
|
50
|
|
|
|
|
return write_u64(sign ? neg : pos, cur + sign); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8270
|
|
|
|
|
|
|
} else { |
|
8271
|
1
|
|
|
|
|
|
u64 raw = val->uni.u64; |
|
8272
|
1
|
|
|
|
|
|
u32 val_fmt = (u32)(val->tag >> 32); |
|
8273
|
1
|
|
|
|
|
|
u32 all_fmt = flg; |
|
8274
|
1
|
|
|
|
|
|
u32 fmt = val_fmt | all_fmt; |
|
8275
|
1
|
50
|
|
|
|
|
if (likely(!(fmt >> (32 - YYJSON_WRITE_FP_FLAG_BITS)))) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8276
|
|
|
|
|
|
|
/* double to shortest */ |
|
8277
|
1
|
|
|
|
|
|
return write_f64_raw(cur, raw, flg); |
|
8278
|
0
|
0
|
|
|
|
|
} else if (fmt >> (32 - YYJSON_WRITE_FP_PREC_BITS)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8279
|
|
|
|
|
|
|
/* double to fixed */ |
|
8280
|
0
|
|
|
|
|
|
u32 val_prec = val_fmt >> (32 - YYJSON_WRITE_FP_PREC_BITS); |
|
8281
|
0
|
|
|
|
|
|
u32 all_prec = all_fmt >> (32 - YYJSON_WRITE_FP_PREC_BITS); |
|
8282
|
0
|
0
|
|
|
|
|
u32 prec = val_prec ? val_prec : all_prec; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8283
|
0
|
|
|
|
|
|
return write_f64_raw_fixed(cur, raw, flg, prec); |
|
8284
|
|
|
|
|
|
|
} else { |
|
8285
|
0
|
0
|
|
|
|
|
if (fmt & YYJSON_WRITE_FP_TO_FLOAT) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8286
|
|
|
|
|
|
|
/* float to shortest */ |
|
8287
|
0
|
|
|
|
|
|
return write_f32_raw(cur, raw, flg); |
|
8288
|
|
|
|
|
|
|
} else { |
|
8289
|
|
|
|
|
|
|
/* double to shortest */ |
|
8290
|
0
|
|
|
|
|
|
return write_f64_raw(cur, raw, flg); |
|
8291
|
|
|
|
|
|
|
} |
|
8292
|
|
|
|
|
|
|
} |
|
8293
|
|
|
|
|
|
|
} |
|
8294
|
|
|
|
|
|
|
} |
|
8295
|
|
|
|
|
|
|
|
|
8296
|
0
|
|
|
|
|
|
char *yyjson_write_number(const yyjson_val *val, char *buf) { |
|
8297
|
0
|
0
|
|
|
|
|
if (unlikely(!val || !buf)) return NULL; |
|
|
|
0
|
|
|
|
|
|
|
8298
|
0
|
|
|
|
|
|
switch (val->tag & YYJSON_TAG_MASK) { |
|
8299
|
0
|
|
|
|
|
|
case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT: { |
|
8300
|
0
|
0
|
|
|
|
|
buf = (char *)write_u64(val->uni.u64, (u8 *)buf); |
|
8301
|
0
|
|
|
|
|
|
*buf = '\0'; |
|
8302
|
0
|
|
|
|
|
|
return buf; |
|
8303
|
|
|
|
|
|
|
} |
|
8304
|
0
|
|
|
|
|
|
case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT: { |
|
8305
|
0
|
|
|
|
|
|
u64 pos = val->uni.u64; |
|
8306
|
0
|
|
|
|
|
|
u64 neg = ~pos + 1; |
|
8307
|
0
|
|
|
|
|
|
usize sign = ((i64)pos < 0); |
|
8308
|
0
|
|
|
|
|
|
*buf = '-'; |
|
8309
|
0
|
0
|
|
|
|
|
buf = (char *)write_u64(sign ? neg : pos, (u8 *)buf + sign); |
|
8310
|
0
|
|
|
|
|
|
*buf = '\0'; |
|
8311
|
0
|
|
|
|
|
|
return buf; |
|
8312
|
|
|
|
|
|
|
} |
|
8313
|
0
|
|
|
|
|
|
case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL: { |
|
8314
|
0
|
|
|
|
|
|
u64 raw = val->uni.u64; |
|
8315
|
0
|
|
|
|
|
|
u32 fmt = (u32)(val->tag >> 32); |
|
8316
|
0
|
|
|
|
|
|
u32 flg = YYJSON_WRITE_ALLOW_INF_AND_NAN; |
|
8317
|
0
|
0
|
|
|
|
|
if (likely(!(fmt >> (32 - YYJSON_WRITE_FP_FLAG_BITS)))) { |
|
8318
|
0
|
|
|
|
|
|
buf = (char *)write_f64_raw((u8 *)buf, raw, flg); |
|
8319
|
0
|
0
|
|
|
|
|
} else if (fmt >> (32 - YYJSON_WRITE_FP_PREC_BITS)) { |
|
8320
|
0
|
|
|
|
|
|
u32 prec = fmt >> (32 - YYJSON_WRITE_FP_PREC_BITS); |
|
8321
|
0
|
|
|
|
|
|
buf = (char *)write_f64_raw_fixed((u8 *)buf, raw, flg, prec); |
|
8322
|
|
|
|
|
|
|
} else { |
|
8323
|
0
|
0
|
|
|
|
|
if (fmt & YYJSON_WRITE_FP_TO_FLOAT) { |
|
8324
|
0
|
|
|
|
|
|
buf = (char *)write_f32_raw((u8 *)buf, raw, flg); |
|
8325
|
|
|
|
|
|
|
} else { |
|
8326
|
0
|
|
|
|
|
|
buf = (char *)write_f64_raw((u8 *)buf, raw, flg); |
|
8327
|
|
|
|
|
|
|
} |
|
8328
|
|
|
|
|
|
|
} |
|
8329
|
0
|
0
|
|
|
|
|
if (buf) *buf = '\0'; |
|
8330
|
0
|
|
|
|
|
|
return buf; |
|
8331
|
|
|
|
|
|
|
} |
|
8332
|
0
|
|
|
|
|
|
default: return NULL; |
|
8333
|
|
|
|
|
|
|
} |
|
8334
|
|
|
|
|
|
|
} |
|
8335
|
|
|
|
|
|
|
|
|
8336
|
|
|
|
|
|
|
|
|
8337
|
|
|
|
|
|
|
|
|
8338
|
|
|
|
|
|
|
/*============================================================================== |
|
8339
|
|
|
|
|
|
|
* MARK: - String Writer (Private) |
|
8340
|
|
|
|
|
|
|
*============================================================================*/ |
|
8341
|
|
|
|
|
|
|
|
|
8342
|
|
|
|
|
|
|
/** Character encode type, if (type > CHAR_ENC_ERR_1) bytes = type / 2; */ |
|
8343
|
|
|
|
|
|
|
typedef u8 char_enc_type; |
|
8344
|
|
|
|
|
|
|
#define CHAR_ENC_CPY_1 0 /* 1-byte UTF-8, copy. */ |
|
8345
|
|
|
|
|
|
|
#define CHAR_ENC_ERR_1 1 /* 1-byte UTF-8, error. */ |
|
8346
|
|
|
|
|
|
|
#define CHAR_ENC_ESC_A 2 /* 1-byte ASCII, escaped as '\x'. */ |
|
8347
|
|
|
|
|
|
|
#define CHAR_ENC_ESC_1 3 /* 1-byte UTF-8, escaped as '\uXXXX'. */ |
|
8348
|
|
|
|
|
|
|
#define CHAR_ENC_CPY_2 4 /* 2-byte UTF-8, copy. */ |
|
8349
|
|
|
|
|
|
|
#define CHAR_ENC_ESC_2 5 /* 2-byte UTF-8, escaped as '\uXXXX'. */ |
|
8350
|
|
|
|
|
|
|
#define CHAR_ENC_CPY_3 6 /* 3-byte UTF-8, copy. */ |
|
8351
|
|
|
|
|
|
|
#define CHAR_ENC_ESC_3 7 /* 3-byte UTF-8, escaped as '\uXXXX'. */ |
|
8352
|
|
|
|
|
|
|
#define CHAR_ENC_CPY_4 8 /* 4-byte UTF-8, copy. */ |
|
8353
|
|
|
|
|
|
|
#define CHAR_ENC_ESC_4 9 /* 4-byte UTF-8, escaped as '\uXXXX\uXXXX'. */ |
|
8354
|
|
|
|
|
|
|
|
|
8355
|
|
|
|
|
|
|
/** Character encode type table: don't escape unicode, don't escape '/'. |
|
8356
|
|
|
|
|
|
|
(generate with misc/make_tables.c) */ |
|
8357
|
|
|
|
|
|
|
static const char_enc_type enc_table_cpy[256] = { |
|
8358
|
|
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, |
|
8359
|
|
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
|
8360
|
|
|
|
|
|
|
0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8361
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8362
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8363
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, |
|
8364
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8365
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8366
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8367
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8368
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8369
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8370
|
|
|
|
|
|
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
|
8371
|
|
|
|
|
|
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
|
8372
|
|
|
|
|
|
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
|
8373
|
|
|
|
|
|
|
8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1 |
|
8374
|
|
|
|
|
|
|
}; |
|
8375
|
|
|
|
|
|
|
|
|
8376
|
|
|
|
|
|
|
/** Character encode type table: don't escape unicode, escape '/'. |
|
8377
|
|
|
|
|
|
|
(generate with misc/make_tables.c) */ |
|
8378
|
|
|
|
|
|
|
static const char_enc_type enc_table_cpy_slash[256] = { |
|
8379
|
|
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, |
|
8380
|
|
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
|
8381
|
|
|
|
|
|
|
0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, |
|
8382
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8383
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8384
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, |
|
8385
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8386
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8387
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8388
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8389
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8390
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8391
|
|
|
|
|
|
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
|
8392
|
|
|
|
|
|
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
|
8393
|
|
|
|
|
|
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
|
8394
|
|
|
|
|
|
|
8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1 |
|
8395
|
|
|
|
|
|
|
}; |
|
8396
|
|
|
|
|
|
|
|
|
8397
|
|
|
|
|
|
|
/** Character encode type table: escape unicode, don't escape '/'. |
|
8398
|
|
|
|
|
|
|
(generate with misc/make_tables.c) */ |
|
8399
|
|
|
|
|
|
|
static const char_enc_type enc_table_esc[256] = { |
|
8400
|
|
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, |
|
8401
|
|
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
|
8402
|
|
|
|
|
|
|
0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8403
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8404
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8405
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, |
|
8406
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8407
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8408
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8409
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8410
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8411
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8412
|
|
|
|
|
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
|
8413
|
|
|
|
|
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
|
8414
|
|
|
|
|
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
|
8415
|
|
|
|
|
|
|
9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1 |
|
8416
|
|
|
|
|
|
|
}; |
|
8417
|
|
|
|
|
|
|
|
|
8418
|
|
|
|
|
|
|
/** Character encode type table: escape unicode, escape '/'. |
|
8419
|
|
|
|
|
|
|
(generate with misc/make_tables.c) */ |
|
8420
|
|
|
|
|
|
|
static const char_enc_type enc_table_esc_slash[256] = { |
|
8421
|
|
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, |
|
8422
|
|
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
|
8423
|
|
|
|
|
|
|
0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, |
|
8424
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8425
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8426
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, |
|
8427
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8428
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
8429
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8430
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8431
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8432
|
|
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
|
8433
|
|
|
|
|
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
|
8434
|
|
|
|
|
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
|
8435
|
|
|
|
|
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
|
8436
|
|
|
|
|
|
|
9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1 |
|
8437
|
|
|
|
|
|
|
}; |
|
8438
|
|
|
|
|
|
|
|
|
8439
|
|
|
|
|
|
|
/** Escaped hex character table: ["00" "01" "02" ... "FD" "FE" "FF"]. |
|
8440
|
|
|
|
|
|
|
(generate with misc/make_tables.c) */ |
|
8441
|
|
|
|
|
|
|
yyjson_align(2) |
|
8442
|
|
|
|
|
|
|
static const u8 esc_hex_char_table[512] = { |
|
8443
|
|
|
|
|
|
|
'0', '0', '0', '1', '0', '2', '0', '3', |
|
8444
|
|
|
|
|
|
|
'0', '4', '0', '5', '0', '6', '0', '7', |
|
8445
|
|
|
|
|
|
|
'0', '8', '0', '9', '0', 'A', '0', 'B', |
|
8446
|
|
|
|
|
|
|
'0', 'C', '0', 'D', '0', 'E', '0', 'F', |
|
8447
|
|
|
|
|
|
|
'1', '0', '1', '1', '1', '2', '1', '3', |
|
8448
|
|
|
|
|
|
|
'1', '4', '1', '5', '1', '6', '1', '7', |
|
8449
|
|
|
|
|
|
|
'1', '8', '1', '9', '1', 'A', '1', 'B', |
|
8450
|
|
|
|
|
|
|
'1', 'C', '1', 'D', '1', 'E', '1', 'F', |
|
8451
|
|
|
|
|
|
|
'2', '0', '2', '1', '2', '2', '2', '3', |
|
8452
|
|
|
|
|
|
|
'2', '4', '2', '5', '2', '6', '2', '7', |
|
8453
|
|
|
|
|
|
|
'2', '8', '2', '9', '2', 'A', '2', 'B', |
|
8454
|
|
|
|
|
|
|
'2', 'C', '2', 'D', '2', 'E', '2', 'F', |
|
8455
|
|
|
|
|
|
|
'3', '0', '3', '1', '3', '2', '3', '3', |
|
8456
|
|
|
|
|
|
|
'3', '4', '3', '5', '3', '6', '3', '7', |
|
8457
|
|
|
|
|
|
|
'3', '8', '3', '9', '3', 'A', '3', 'B', |
|
8458
|
|
|
|
|
|
|
'3', 'C', '3', 'D', '3', 'E', '3', 'F', |
|
8459
|
|
|
|
|
|
|
'4', '0', '4', '1', '4', '2', '4', '3', |
|
8460
|
|
|
|
|
|
|
'4', '4', '4', '5', '4', '6', '4', '7', |
|
8461
|
|
|
|
|
|
|
'4', '8', '4', '9', '4', 'A', '4', 'B', |
|
8462
|
|
|
|
|
|
|
'4', 'C', '4', 'D', '4', 'E', '4', 'F', |
|
8463
|
|
|
|
|
|
|
'5', '0', '5', '1', '5', '2', '5', '3', |
|
8464
|
|
|
|
|
|
|
'5', '4', '5', '5', '5', '6', '5', '7', |
|
8465
|
|
|
|
|
|
|
'5', '8', '5', '9', '5', 'A', '5', 'B', |
|
8466
|
|
|
|
|
|
|
'5', 'C', '5', 'D', '5', 'E', '5', 'F', |
|
8467
|
|
|
|
|
|
|
'6', '0', '6', '1', '6', '2', '6', '3', |
|
8468
|
|
|
|
|
|
|
'6', '4', '6', '5', '6', '6', '6', '7', |
|
8469
|
|
|
|
|
|
|
'6', '8', '6', '9', '6', 'A', '6', 'B', |
|
8470
|
|
|
|
|
|
|
'6', 'C', '6', 'D', '6', 'E', '6', 'F', |
|
8471
|
|
|
|
|
|
|
'7', '0', '7', '1', '7', '2', '7', '3', |
|
8472
|
|
|
|
|
|
|
'7', '4', '7', '5', '7', '6', '7', '7', |
|
8473
|
|
|
|
|
|
|
'7', '8', '7', '9', '7', 'A', '7', 'B', |
|
8474
|
|
|
|
|
|
|
'7', 'C', '7', 'D', '7', 'E', '7', 'F', |
|
8475
|
|
|
|
|
|
|
'8', '0', '8', '1', '8', '2', '8', '3', |
|
8476
|
|
|
|
|
|
|
'8', '4', '8', '5', '8', '6', '8', '7', |
|
8477
|
|
|
|
|
|
|
'8', '8', '8', '9', '8', 'A', '8', 'B', |
|
8478
|
|
|
|
|
|
|
'8', 'C', '8', 'D', '8', 'E', '8', 'F', |
|
8479
|
|
|
|
|
|
|
'9', '0', '9', '1', '9', '2', '9', '3', |
|
8480
|
|
|
|
|
|
|
'9', '4', '9', '5', '9', '6', '9', '7', |
|
8481
|
|
|
|
|
|
|
'9', '8', '9', '9', '9', 'A', '9', 'B', |
|
8482
|
|
|
|
|
|
|
'9', 'C', '9', 'D', '9', 'E', '9', 'F', |
|
8483
|
|
|
|
|
|
|
'A', '0', 'A', '1', 'A', '2', 'A', '3', |
|
8484
|
|
|
|
|
|
|
'A', '4', 'A', '5', 'A', '6', 'A', '7', |
|
8485
|
|
|
|
|
|
|
'A', '8', 'A', '9', 'A', 'A', 'A', 'B', |
|
8486
|
|
|
|
|
|
|
'A', 'C', 'A', 'D', 'A', 'E', 'A', 'F', |
|
8487
|
|
|
|
|
|
|
'B', '0', 'B', '1', 'B', '2', 'B', '3', |
|
8488
|
|
|
|
|
|
|
'B', '4', 'B', '5', 'B', '6', 'B', '7', |
|
8489
|
|
|
|
|
|
|
'B', '8', 'B', '9', 'B', 'A', 'B', 'B', |
|
8490
|
|
|
|
|
|
|
'B', 'C', 'B', 'D', 'B', 'E', 'B', 'F', |
|
8491
|
|
|
|
|
|
|
'C', '0', 'C', '1', 'C', '2', 'C', '3', |
|
8492
|
|
|
|
|
|
|
'C', '4', 'C', '5', 'C', '6', 'C', '7', |
|
8493
|
|
|
|
|
|
|
'C', '8', 'C', '9', 'C', 'A', 'C', 'B', |
|
8494
|
|
|
|
|
|
|
'C', 'C', 'C', 'D', 'C', 'E', 'C', 'F', |
|
8495
|
|
|
|
|
|
|
'D', '0', 'D', '1', 'D', '2', 'D', '3', |
|
8496
|
|
|
|
|
|
|
'D', '4', 'D', '5', 'D', '6', 'D', '7', |
|
8497
|
|
|
|
|
|
|
'D', '8', 'D', '9', 'D', 'A', 'D', 'B', |
|
8498
|
|
|
|
|
|
|
'D', 'C', 'D', 'D', 'D', 'E', 'D', 'F', |
|
8499
|
|
|
|
|
|
|
'E', '0', 'E', '1', 'E', '2', 'E', '3', |
|
8500
|
|
|
|
|
|
|
'E', '4', 'E', '5', 'E', '6', 'E', '7', |
|
8501
|
|
|
|
|
|
|
'E', '8', 'E', '9', 'E', 'A', 'E', 'B', |
|
8502
|
|
|
|
|
|
|
'E', 'C', 'E', 'D', 'E', 'E', 'E', 'F', |
|
8503
|
|
|
|
|
|
|
'F', '0', 'F', '1', 'F', '2', 'F', '3', |
|
8504
|
|
|
|
|
|
|
'F', '4', 'F', '5', 'F', '6', 'F', '7', |
|
8505
|
|
|
|
|
|
|
'F', '8', 'F', '9', 'F', 'A', 'F', 'B', |
|
8506
|
|
|
|
|
|
|
'F', 'C', 'F', 'D', 'F', 'E', 'F', 'F' |
|
8507
|
|
|
|
|
|
|
}; |
|
8508
|
|
|
|
|
|
|
|
|
8509
|
|
|
|
|
|
|
/** Escaped single character table. (generate with misc/make_tables.c) */ |
|
8510
|
|
|
|
|
|
|
yyjson_align(2) |
|
8511
|
|
|
|
|
|
|
static const u8 esc_single_char_table[512] = { |
|
8512
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8513
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8514
|
|
|
|
|
|
|
'\\', 'b', '\\', 't', '\\', 'n', ' ', ' ', |
|
8515
|
|
|
|
|
|
|
'\\', 'f', '\\', 'r', ' ', ' ', ' ', ' ', |
|
8516
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8517
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8518
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8519
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8520
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', '\\', '"', ' ', ' ', |
|
8521
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8522
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8523
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', '\\', '/', |
|
8524
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8525
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8526
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8527
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8528
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8529
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8530
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8531
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8532
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8533
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8534
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8535
|
|
|
|
|
|
|
'\\', '\\', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8536
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8537
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8538
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8539
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8540
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8541
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8542
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8543
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8544
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8545
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8546
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8547
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8548
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8549
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8550
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8551
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8552
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8553
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8554
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8555
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8556
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8557
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8558
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8559
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8560
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8561
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8562
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8563
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8564
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8565
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8566
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8567
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8568
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8569
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8570
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8571
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8572
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8573
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8574
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', |
|
8575
|
|
|
|
|
|
|
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' |
|
8576
|
|
|
|
|
|
|
}; |
|
8577
|
|
|
|
|
|
|
|
|
8578
|
|
|
|
|
|
|
/** Returns the encode table with options. */ |
|
8579
|
|
|
|
|
|
|
static_inline const char_enc_type *get_enc_table_with_flag( |
|
8580
|
|
|
|
|
|
|
yyjson_write_flag flg) { |
|
8581
|
30076
|
50
|
|
|
|
|
if (has_flg(ESCAPE_UNICODE)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8582
|
0
|
0
|
|
|
|
|
if (has_flg(ESCAPE_SLASHES)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8583
|
0
|
|
|
|
|
|
return enc_table_esc_slash; |
|
8584
|
|
|
|
|
|
|
} else { |
|
8585
|
0
|
|
|
|
|
|
return enc_table_esc; |
|
8586
|
|
|
|
|
|
|
} |
|
8587
|
|
|
|
|
|
|
} else { |
|
8588
|
30092
|
50
|
|
|
|
|
if (has_flg(ESCAPE_SLASHES)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8589
|
0
|
|
|
|
|
|
return enc_table_cpy_slash; |
|
8590
|
|
|
|
|
|
|
} else { |
|
8591
|
15046
|
|
|
|
|
|
return enc_table_cpy; |
|
8592
|
|
|
|
|
|
|
} |
|
8593
|
|
|
|
|
|
|
} |
|
8594
|
|
|
|
|
|
|
} |
|
8595
|
|
|
|
|
|
|
|
|
8596
|
|
|
|
|
|
|
/** Write raw string. */ |
|
8597
|
|
|
|
|
|
|
static_inline u8 *write_raw(u8 *cur, const u8 *raw, usize raw_len) { |
|
8598
|
0
|
|
|
|
|
|
memcpy(cur, raw, raw_len); |
|
8599
|
0
|
|
|
|
|
|
return cur + raw_len; |
|
8600
|
|
|
|
|
|
|
} |
|
8601
|
|
|
|
|
|
|
|
|
8602
|
|
|
|
|
|
|
/** |
|
8603
|
|
|
|
|
|
|
Write string no-escape. |
|
8604
|
|
|
|
|
|
|
@param cur Buffer cursor. |
|
8605
|
|
|
|
|
|
|
@param str A UTF-8 string, null-terminator is not required. |
|
8606
|
|
|
|
|
|
|
@param str_len Length of string in bytes. |
|
8607
|
|
|
|
|
|
|
@return The buffer cursor after string. |
|
8608
|
|
|
|
|
|
|
*/ |
|
8609
|
|
|
|
|
|
|
static_inline u8 *write_str_noesc(u8 *cur, const u8 *str, usize str_len) { |
|
8610
|
10032
|
|
|
|
|
|
*cur++ = '"'; |
|
8611
|
10032
|
50
|
|
|
|
|
while (str_len >= 16) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8612
|
|
|
|
|
|
|
byte_copy_16(cur, str); |
|
8613
|
0
|
|
|
|
|
|
cur += 16; |
|
8614
|
0
|
|
|
|
|
|
str += 16; |
|
8615
|
0
|
|
|
|
|
|
str_len -= 16; |
|
8616
|
|
|
|
|
|
|
} |
|
8617
|
10037
|
50
|
|
|
|
|
while (str_len >= 4) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8618
|
|
|
|
|
|
|
byte_copy_4(cur, str); |
|
8619
|
5
|
|
|
|
|
|
cur += 4; |
|
8620
|
5
|
|
|
|
|
|
str += 4; |
|
8621
|
5
|
|
|
|
|
|
str_len -= 4; |
|
8622
|
|
|
|
|
|
|
} |
|
8623
|
20066
|
100
|
|
|
|
|
while (str_len) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8624
|
10034
|
|
|
|
|
|
*cur++ = *str++; |
|
8625
|
10034
|
|
|
|
|
|
str_len -= 1; |
|
8626
|
|
|
|
|
|
|
} |
|
8627
|
10032
|
|
|
|
|
|
*cur++ = '"'; |
|
8628
|
10032
|
|
|
|
|
|
return cur; |
|
8629
|
|
|
|
|
|
|
} |
|
8630
|
|
|
|
|
|
|
|
|
8631
|
|
|
|
|
|
|
/** |
|
8632
|
|
|
|
|
|
|
Write UTF-8 string (requires len * 6 + 2 bytes buffer). |
|
8633
|
|
|
|
|
|
|
@param cur Buffer cursor. |
|
8634
|
|
|
|
|
|
|
@param esc Escape unicode. |
|
8635
|
|
|
|
|
|
|
@param inv Allow invalid unicode. |
|
8636
|
|
|
|
|
|
|
@param str A UTF-8 string, null-terminator is not required. |
|
8637
|
|
|
|
|
|
|
@param str_len Length of string in bytes. |
|
8638
|
|
|
|
|
|
|
@param enc_table Encode type table for character. |
|
8639
|
|
|
|
|
|
|
@return The buffer cursor after string, or NULL on invalid unicode. |
|
8640
|
|
|
|
|
|
|
*/ |
|
8641
|
|
|
|
|
|
|
static_inline u8 *write_str(u8 *cur, bool esc, bool inv, |
|
8642
|
|
|
|
|
|
|
const u8 *str, usize str_len, |
|
8643
|
|
|
|
|
|
|
const char_enc_type *enc_table) { |
|
8644
|
|
|
|
|
|
|
/* The replacement character U+FFFD, used to indicate invalid character. */ |
|
8645
|
10018
|
|
|
|
|
|
const v32 rep = {{ 'F', 'F', 'F', 'D' }}; |
|
8646
|
10018
|
|
|
|
|
|
const v32 pre = {{ '\\', 'u', '0', '0' }}; |
|
8647
|
|
|
|
|
|
|
|
|
8648
|
10018
|
|
|
|
|
|
const u8 *src = str; |
|
8649
|
10018
|
|
|
|
|
|
const u8 *end = str + str_len; |
|
8650
|
10018
|
|
|
|
|
|
*cur++ = '"'; |
|
8651
|
|
|
|
|
|
|
|
|
8652
|
10018
|
|
|
|
|
|
copy_ascii: |
|
8653
|
|
|
|
|
|
|
/* |
|
8654
|
|
|
|
|
|
|
Copy continuous ASCII, loop unrolling, same as the following code: |
|
8655
|
|
|
|
|
|
|
|
|
8656
|
|
|
|
|
|
|
while (end > src) ( |
|
8657
|
|
|
|
|
|
|
if (unlikely(enc_table[*src])) break; |
|
8658
|
|
|
|
|
|
|
*cur++ = *src++; |
|
8659
|
|
|
|
|
|
|
); |
|
8660
|
|
|
|
|
|
|
*/ |
|
8661
|
|
|
|
|
|
|
#define expr_jump(i) \ |
|
8662
|
|
|
|
|
|
|
if (unlikely(enc_table[src[i]])) goto stop_char_##i; |
|
8663
|
|
|
|
|
|
|
|
|
8664
|
|
|
|
|
|
|
#define expr_stop(i) \ |
|
8665
|
|
|
|
|
|
|
stop_char_##i: \ |
|
8666
|
|
|
|
|
|
|
memcpy(cur, src, i); \ |
|
8667
|
|
|
|
|
|
|
cur += i; src += i; goto copy_utf8; |
|
8668
|
|
|
|
|
|
|
|
|
8669
|
10018
|
50
|
|
|
|
|
while (end - src >= 16) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8670
|
0
|
0
|
|
|
|
|
repeat16_incr(expr_jump) |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8671
|
|
|
|
|
|
|
byte_copy_16(cur, src); |
|
8672
|
0
|
|
|
|
|
|
cur += 16; src += 16; |
|
8673
|
|
|
|
|
|
|
} |
|
8674
|
|
|
|
|
|
|
|
|
8675
|
10022
|
100
|
|
|
|
|
while (end - src >= 4) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8676
|
4
|
50
|
|
|
|
|
repeat4_incr(expr_jump) |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8677
|
|
|
|
|
|
|
byte_copy_4(cur, src); |
|
8678
|
4
|
|
|
|
|
|
cur += 4; src += 4; |
|
8679
|
|
|
|
|
|
|
} |
|
8680
|
|
|
|
|
|
|
|
|
8681
|
20040
|
100
|
|
|
|
|
while (end > src) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8682
|
10022
|
50
|
|
|
|
|
expr_jump(0) |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8683
|
10022
|
|
|
|
|
|
*cur++ = *src++; |
|
8684
|
|
|
|
|
|
|
} |
|
8685
|
|
|
|
|
|
|
|
|
8686
|
10018
|
|
|
|
|
|
*cur++ = '"'; |
|
8687
|
10018
|
|
|
|
|
|
return cur; |
|
8688
|
|
|
|
|
|
|
|
|
8689
|
0
|
|
|
|
|
|
repeat16_incr(expr_stop) |
|
8690
|
|
|
|
|
|
|
|
|
8691
|
|
|
|
|
|
|
#undef expr_jump |
|
8692
|
|
|
|
|
|
|
#undef expr_stop |
|
8693
|
|
|
|
|
|
|
|
|
8694
|
0
|
|
|
|
|
|
copy_utf8: |
|
8695
|
0
|
0
|
|
|
|
|
if (unlikely(src + 4 > end)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8696
|
0
|
0
|
|
|
|
|
if (end == src) goto copy_end; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8697
|
0
|
0
|
|
|
|
|
if (end - src < enc_table[*src] / 2) goto err_one; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8698
|
|
|
|
|
|
|
} |
|
8699
|
0
|
|
|
|
|
|
switch (enc_table[*src]) { |
|
8700
|
0
|
|
|
|
|
|
case CHAR_ENC_CPY_1: { |
|
8701
|
0
|
|
|
|
|
|
*cur++ = *src++; |
|
8702
|
0
|
|
|
|
|
|
goto copy_ascii; |
|
8703
|
|
|
|
|
|
|
} |
|
8704
|
0
|
|
|
|
|
|
case CHAR_ENC_CPY_2: { |
|
8705
|
|
|
|
|
|
|
#if YYJSON_DISABLE_UTF8_VALIDATION |
|
8706
|
|
|
|
|
|
|
byte_copy_2(cur, src); |
|
8707
|
|
|
|
|
|
|
#else |
|
8708
|
0
|
|
|
|
|
|
u32 uni = 0; |
|
8709
|
|
|
|
|
|
|
byte_copy_2(&uni, src); |
|
8710
|
0
|
0
|
|
|
|
|
if (unlikely(!is_utf8_seq2(uni))) goto err_cpy; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8711
|
|
|
|
|
|
|
byte_copy_2(cur, &uni); |
|
8712
|
|
|
|
|
|
|
#endif |
|
8713
|
0
|
|
|
|
|
|
cur += 2; |
|
8714
|
0
|
|
|
|
|
|
src += 2; |
|
8715
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8716
|
|
|
|
|
|
|
} |
|
8717
|
0
|
|
|
|
|
|
case CHAR_ENC_CPY_3: { |
|
8718
|
|
|
|
|
|
|
#if YYJSON_DISABLE_UTF8_VALIDATION |
|
8719
|
|
|
|
|
|
|
if (likely(src + 4 <= end)) { |
|
8720
|
|
|
|
|
|
|
byte_copy_4(cur, src); |
|
8721
|
|
|
|
|
|
|
} else { |
|
8722
|
|
|
|
|
|
|
byte_copy_2(cur, src); |
|
8723
|
|
|
|
|
|
|
cur[2] = src[2]; |
|
8724
|
|
|
|
|
|
|
} |
|
8725
|
|
|
|
|
|
|
#else |
|
8726
|
|
|
|
|
|
|
u32 uni, tmp; |
|
8727
|
0
|
0
|
|
|
|
|
if (likely(src + 4 <= end)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8728
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
8729
|
0
|
0
|
|
|
|
|
if (unlikely(!is_utf8_seq3(uni))) goto err_cpy; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8730
|
|
|
|
|
|
|
byte_copy_4(cur, src); |
|
8731
|
|
|
|
|
|
|
} else { |
|
8732
|
0
|
|
|
|
|
|
uni = byte_load_3(src); |
|
8733
|
0
|
0
|
|
|
|
|
if (unlikely(!is_utf8_seq3(uni))) goto err_cpy; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8734
|
|
|
|
|
|
|
byte_copy_4(cur, &uni); |
|
8735
|
|
|
|
|
|
|
} |
|
8736
|
|
|
|
|
|
|
#endif |
|
8737
|
0
|
|
|
|
|
|
cur += 3; |
|
8738
|
0
|
|
|
|
|
|
src += 3; |
|
8739
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8740
|
|
|
|
|
|
|
} |
|
8741
|
0
|
|
|
|
|
|
case CHAR_ENC_CPY_4: { |
|
8742
|
|
|
|
|
|
|
#if YYJSON_DISABLE_UTF8_VALIDATION |
|
8743
|
|
|
|
|
|
|
byte_copy_4(cur, src); |
|
8744
|
|
|
|
|
|
|
#else |
|
8745
|
|
|
|
|
|
|
u32 uni, tmp; |
|
8746
|
0
|
|
|
|
|
|
uni = byte_load_4(src); |
|
8747
|
0
|
0
|
|
|
|
|
if (unlikely(!is_utf8_seq4(uni))) goto err_cpy; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8748
|
|
|
|
|
|
|
byte_copy_4(cur, src); |
|
8749
|
|
|
|
|
|
|
#endif |
|
8750
|
0
|
|
|
|
|
|
cur += 4; |
|
8751
|
0
|
|
|
|
|
|
src += 4; |
|
8752
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8753
|
|
|
|
|
|
|
} |
|
8754
|
0
|
|
|
|
|
|
case CHAR_ENC_ESC_A: { |
|
8755
|
0
|
|
|
|
|
|
byte_copy_2(cur, &esc_single_char_table[*src * 2]); |
|
8756
|
0
|
|
|
|
|
|
cur += 2; |
|
8757
|
0
|
|
|
|
|
|
src += 1; |
|
8758
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8759
|
|
|
|
|
|
|
} |
|
8760
|
0
|
|
|
|
|
|
case CHAR_ENC_ESC_1: { |
|
8761
|
|
|
|
|
|
|
byte_copy_4(cur + 0, &pre); |
|
8762
|
0
|
|
|
|
|
|
byte_copy_2(cur + 4, &esc_hex_char_table[*src * 2]); |
|
8763
|
0
|
|
|
|
|
|
cur += 6; |
|
8764
|
0
|
|
|
|
|
|
src += 1; |
|
8765
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8766
|
|
|
|
|
|
|
} |
|
8767
|
0
|
|
|
|
|
|
case CHAR_ENC_ESC_2: { |
|
8768
|
|
|
|
|
|
|
u16 u; |
|
8769
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UTF8_VALIDATION |
|
8770
|
0
|
|
|
|
|
|
u32 v4 = 0; |
|
8771
|
0
|
|
|
|
|
|
u16 v2 = byte_load_2(src); |
|
8772
|
|
|
|
|
|
|
byte_copy_2(&v4, &v2); |
|
8773
|
0
|
0
|
|
|
|
|
if (unlikely(!is_utf8_seq2(v4))) goto err_esc; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8774
|
|
|
|
|
|
|
#endif |
|
8775
|
0
|
|
|
|
|
|
u = (u16)(((u16)(src[0] & 0x1F) << 6) | |
|
8776
|
0
|
|
|
|
|
|
((u16)(src[1] & 0x3F) << 0)); |
|
8777
|
|
|
|
|
|
|
byte_copy_2(cur + 0, &pre); |
|
8778
|
0
|
|
|
|
|
|
byte_copy_2(cur + 2, &esc_hex_char_table[(u >> 8) * 2]); |
|
8779
|
0
|
|
|
|
|
|
byte_copy_2(cur + 4, &esc_hex_char_table[(u & 0xFF) * 2]); |
|
8780
|
0
|
|
|
|
|
|
cur += 6; |
|
8781
|
0
|
|
|
|
|
|
src += 2; |
|
8782
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8783
|
|
|
|
|
|
|
} |
|
8784
|
0
|
|
|
|
|
|
case CHAR_ENC_ESC_3: { |
|
8785
|
|
|
|
|
|
|
u16 u; |
|
8786
|
|
|
|
|
|
|
u32 v, tmp; |
|
8787
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UTF8_VALIDATION |
|
8788
|
0
|
|
|
|
|
|
v = byte_load_3(src); |
|
8789
|
0
|
0
|
|
|
|
|
if (unlikely(!is_utf8_seq3(v))) goto err_esc; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8790
|
|
|
|
|
|
|
#endif |
|
8791
|
0
|
|
|
|
|
|
u = (u16)(((u16)(src[0] & 0x0F) << 12) | |
|
8792
|
0
|
|
|
|
|
|
((u16)(src[1] & 0x3F) << 6) | |
|
8793
|
0
|
|
|
|
|
|
((u16)(src[2] & 0x3F) << 0)); |
|
8794
|
|
|
|
|
|
|
byte_copy_2(cur + 0, &pre); |
|
8795
|
0
|
|
|
|
|
|
byte_copy_2(cur + 2, &esc_hex_char_table[(u >> 8) * 2]); |
|
8796
|
0
|
|
|
|
|
|
byte_copy_2(cur + 4, &esc_hex_char_table[(u & 0xFF) * 2]); |
|
8797
|
0
|
|
|
|
|
|
cur += 6; |
|
8798
|
0
|
|
|
|
|
|
src += 3; |
|
8799
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8800
|
|
|
|
|
|
|
} |
|
8801
|
0
|
|
|
|
|
|
case CHAR_ENC_ESC_4: { |
|
8802
|
|
|
|
|
|
|
u32 hi, lo, u, v, tmp; |
|
8803
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UTF8_VALIDATION |
|
8804
|
0
|
|
|
|
|
|
v = byte_load_4(src); |
|
8805
|
0
|
0
|
|
|
|
|
if (unlikely(!is_utf8_seq4(v))) goto err_esc; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8806
|
|
|
|
|
|
|
#endif |
|
8807
|
0
|
|
|
|
|
|
u = ((u32)(src[0] & 0x07) << 18) | |
|
8808
|
0
|
|
|
|
|
|
((u32)(src[1] & 0x3F) << 12) | |
|
8809
|
0
|
|
|
|
|
|
((u32)(src[2] & 0x3F) << 6) | |
|
8810
|
0
|
|
|
|
|
|
((u32)(src[3] & 0x3F) << 0); |
|
8811
|
0
|
|
|
|
|
|
u -= 0x10000; |
|
8812
|
0
|
|
|
|
|
|
hi = (u >> 10) + 0xD800; |
|
8813
|
0
|
|
|
|
|
|
lo = (u & 0x3FF) + 0xDC00; |
|
8814
|
|
|
|
|
|
|
byte_copy_2(cur + 0, &pre); |
|
8815
|
0
|
|
|
|
|
|
byte_copy_2(cur + 2, &esc_hex_char_table[(hi >> 8) * 2]); |
|
8816
|
0
|
|
|
|
|
|
byte_copy_2(cur + 4, &esc_hex_char_table[(hi & 0xFF) * 2]); |
|
8817
|
0
|
|
|
|
|
|
byte_copy_2(cur + 6, &pre); |
|
8818
|
0
|
|
|
|
|
|
byte_copy_2(cur + 8, &esc_hex_char_table[(lo >> 8) * 2]); |
|
8819
|
0
|
|
|
|
|
|
byte_copy_2(cur + 10, &esc_hex_char_table[(lo & 0xFF) * 2]); |
|
8820
|
0
|
|
|
|
|
|
cur += 12; |
|
8821
|
0
|
|
|
|
|
|
src += 4; |
|
8822
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8823
|
|
|
|
|
|
|
} |
|
8824
|
0
|
|
|
|
|
|
case CHAR_ENC_ERR_1: { |
|
8825
|
0
|
|
|
|
|
|
goto err_one; |
|
8826
|
|
|
|
|
|
|
} |
|
8827
|
0
|
|
|
|
|
|
default: break; /* unreachable */ |
|
8828
|
|
|
|
|
|
|
} |
|
8829
|
|
|
|
|
|
|
|
|
8830
|
0
|
|
|
|
|
|
copy_end: |
|
8831
|
0
|
|
|
|
|
|
*cur++ = '"'; |
|
8832
|
0
|
|
|
|
|
|
return cur; |
|
8833
|
|
|
|
|
|
|
|
|
8834
|
0
|
|
|
|
|
|
err_one: |
|
8835
|
0
|
0
|
|
|
|
|
if (esc) goto err_esc; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8836
|
0
|
|
|
|
|
|
else goto err_cpy; |
|
8837
|
|
|
|
|
|
|
|
|
8838
|
0
|
|
|
|
|
|
err_cpy: |
|
8839
|
0
|
0
|
|
|
|
|
if (!inv) return NULL; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8840
|
0
|
|
|
|
|
|
*cur++ = *src++; |
|
8841
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8842
|
|
|
|
|
|
|
|
|
8843
|
0
|
|
|
|
|
|
err_esc: |
|
8844
|
0
|
0
|
|
|
|
|
if (!inv) return NULL; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8845
|
|
|
|
|
|
|
byte_copy_2(cur + 0, &pre); |
|
8846
|
0
|
|
|
|
|
|
byte_copy_4(cur + 2, &rep); |
|
8847
|
0
|
|
|
|
|
|
cur += 6; |
|
8848
|
0
|
|
|
|
|
|
src += 1; |
|
8849
|
0
|
|
|
|
|
|
goto copy_utf8; |
|
8850
|
|
|
|
|
|
|
} |
|
8851
|
|
|
|
|
|
|
|
|
8852
|
|
|
|
|
|
|
|
|
8853
|
|
|
|
|
|
|
|
|
8854
|
|
|
|
|
|
|
/*============================================================================== |
|
8855
|
|
|
|
|
|
|
* MARK: - JSON Writer Utilities (Private) |
|
8856
|
|
|
|
|
|
|
*============================================================================*/ |
|
8857
|
|
|
|
|
|
|
|
|
8858
|
|
|
|
|
|
|
/** Write null (requires 8 bytes buffer). */ |
|
8859
|
|
|
|
|
|
|
static_inline u8 *write_null(u8 *cur) { |
|
8860
|
1
|
|
|
|
|
|
v64 v = {{ 'n', 'u', 'l', 'l', ',', '\n', 0, 0 }}; |
|
8861
|
|
|
|
|
|
|
byte_copy_8(cur, &v); |
|
8862
|
3
|
|
|
|
|
|
return cur + 4; |
|
8863
|
|
|
|
|
|
|
} |
|
8864
|
|
|
|
|
|
|
|
|
8865
|
|
|
|
|
|
|
/** Write bool (requires 8 bytes buffer). */ |
|
8866
|
|
|
|
|
|
|
static_inline u8 *write_bool(u8 *cur, bool val) { |
|
8867
|
6
|
|
|
|
|
|
v64 v0 = {{ 'f', 'a', 'l', 's', 'e', ',', '\n', 0 }}; |
|
8868
|
6
|
|
|
|
|
|
v64 v1 = {{ 't', 'r', 'u', 'e', ',', '\n', 0, 0 }}; |
|
8869
|
6
|
|
|
|
|
|
if (val) { |
|
8870
|
|
|
|
|
|
|
byte_copy_8(cur, &v1); |
|
8871
|
|
|
|
|
|
|
} else { |
|
8872
|
|
|
|
|
|
|
byte_copy_8(cur, &v0); |
|
8873
|
|
|
|
|
|
|
} |
|
8874
|
6
|
|
|
|
|
|
return cur + 5 - val; |
|
8875
|
|
|
|
|
|
|
} |
|
8876
|
|
|
|
|
|
|
|
|
8877
|
|
|
|
|
|
|
/** Write indent (requires level x 4 bytes buffer). |
|
8878
|
|
|
|
|
|
|
Param spaces should not larger than 4. */ |
|
8879
|
|
|
|
|
|
|
static_inline u8 *write_indent(u8 *cur, usize level, usize spaces) { |
|
8880
|
47
|
100
|
|
|
|
|
while (level-- > 0) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8881
|
|
|
|
|
|
|
byte_copy_4(cur, " "); |
|
8882
|
15
|
|
|
|
|
|
cur += spaces; |
|
8883
|
|
|
|
|
|
|
} |
|
8884
|
32
|
|
|
|
|
|
return cur; |
|
8885
|
|
|
|
|
|
|
} |
|
8886
|
|
|
|
|
|
|
|
|
8887
|
|
|
|
|
|
|
/** Write data to file pointer. */ |
|
8888
|
0
|
|
|
|
|
|
static bool write_dat_to_fp(FILE *fp, u8 *dat, usize len, |
|
8889
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
8890
|
0
|
0
|
|
|
|
|
if (fwrite(dat, len, 1, fp) != 1) { |
|
8891
|
0
|
|
|
|
|
|
err->msg = "file writing failed"; |
|
8892
|
0
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_FILE_WRITE; |
|
8893
|
0
|
|
|
|
|
|
return false; |
|
8894
|
|
|
|
|
|
|
} |
|
8895
|
0
|
|
|
|
|
|
return true; |
|
8896
|
|
|
|
|
|
|
} |
|
8897
|
|
|
|
|
|
|
|
|
8898
|
|
|
|
|
|
|
/** Write data to file. */ |
|
8899
|
3
|
|
|
|
|
|
static bool write_dat_to_file(const char *path, u8 *dat, usize len, |
|
8900
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
8901
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
8902
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
8903
|
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_##_code; \ |
|
8904
|
|
|
|
|
|
|
if (file) fclose(file); \ |
|
8905
|
|
|
|
|
|
|
return false; \ |
|
8906
|
|
|
|
|
|
|
} while (false) |
|
8907
|
|
|
|
|
|
|
|
|
8908
|
3
|
|
|
|
|
|
FILE *file = fopen_writeonly(path); |
|
8909
|
3
|
50
|
|
|
|
|
if (file == NULL) { |
|
8910
|
0
|
0
|
|
|
|
|
return_err(FILE_OPEN, MSG_FOPEN); |
|
8911
|
|
|
|
|
|
|
} |
|
8912
|
3
|
50
|
|
|
|
|
if (fwrite(dat, len, 1, file) != 1) { |
|
8913
|
0
|
0
|
|
|
|
|
return_err(FILE_WRITE, MSG_FWRITE); |
|
8914
|
|
|
|
|
|
|
} |
|
8915
|
3
|
50
|
|
|
|
|
if (fclose(file) != 0) { |
|
8916
|
0
|
|
|
|
|
|
file = NULL; |
|
8917
|
0
|
0
|
|
|
|
|
return_err(FILE_WRITE, MSG_FCLOSE); |
|
8918
|
|
|
|
|
|
|
} |
|
8919
|
3
|
|
|
|
|
|
return true; |
|
8920
|
|
|
|
|
|
|
|
|
8921
|
|
|
|
|
|
|
#undef return_err |
|
8922
|
|
|
|
|
|
|
} |
|
8923
|
|
|
|
|
|
|
|
|
8924
|
|
|
|
|
|
|
|
|
8925
|
|
|
|
|
|
|
|
|
8926
|
|
|
|
|
|
|
/*============================================================================== |
|
8927
|
|
|
|
|
|
|
* MARK: - JSON Writer Implementation (Private) |
|
8928
|
|
|
|
|
|
|
*============================================================================*/ |
|
8929
|
|
|
|
|
|
|
|
|
8930
|
|
|
|
|
|
|
typedef struct yyjson_write_ctx { |
|
8931
|
|
|
|
|
|
|
usize tag; |
|
8932
|
|
|
|
|
|
|
} yyjson_write_ctx; |
|
8933
|
|
|
|
|
|
|
|
|
8934
|
|
|
|
|
|
|
static_inline void yyjson_write_ctx_set(yyjson_write_ctx *ctx, |
|
8935
|
|
|
|
|
|
|
usize size, bool is_obj) { |
|
8936
|
0
|
|
|
|
|
|
ctx->tag = (size << 1) | (usize)is_obj; |
|
8937
|
0
|
|
|
|
|
|
} |
|
8938
|
|
|
|
|
|
|
|
|
8939
|
|
|
|
|
|
|
static_inline void yyjson_write_ctx_get(yyjson_write_ctx *ctx, |
|
8940
|
|
|
|
|
|
|
usize *size, bool *is_obj) { |
|
8941
|
0
|
|
|
|
|
|
usize tag = ctx->tag; |
|
8942
|
0
|
|
|
|
|
|
*size = tag >> 1; |
|
8943
|
0
|
|
|
|
|
|
*is_obj = (bool)(tag & 1); |
|
8944
|
0
|
|
|
|
|
|
} |
|
8945
|
|
|
|
|
|
|
|
|
8946
|
|
|
|
|
|
|
/** Write single JSON value. */ |
|
8947
|
|
|
|
|
|
|
static_inline u8 *yyjson_write_single(yyjson_val *val, |
|
8948
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
8949
|
|
|
|
|
|
|
yyjson_alc alc, |
|
8950
|
|
|
|
|
|
|
usize *dat_len, |
|
8951
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
8952
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
8953
|
|
|
|
|
|
|
if (hdr) alc.free(alc.ctx, (void *)hdr); \ |
|
8954
|
|
|
|
|
|
|
*dat_len = 0; \ |
|
8955
|
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_##_code; \ |
|
8956
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
8957
|
|
|
|
|
|
|
return NULL; \ |
|
8958
|
|
|
|
|
|
|
} while (false) |
|
8959
|
|
|
|
|
|
|
|
|
8960
|
|
|
|
|
|
|
#define incr_len(_len) do { \ |
|
8961
|
|
|
|
|
|
|
hdr = (u8 *)alc.malloc(alc.ctx, _len); \ |
|
8962
|
|
|
|
|
|
|
if (!hdr) goto fail_alloc; \ |
|
8963
|
|
|
|
|
|
|
cur = hdr; \ |
|
8964
|
|
|
|
|
|
|
} while (false) |
|
8965
|
|
|
|
|
|
|
|
|
8966
|
|
|
|
|
|
|
#define check_str_len(_len) do { \ |
|
8967
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ |
|
8968
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
8969
|
|
|
|
|
|
|
} while (false) |
|
8970
|
|
|
|
|
|
|
|
|
8971
|
16
|
|
|
|
|
|
u8 *hdr = NULL, *cur; |
|
8972
|
|
|
|
|
|
|
usize str_len; |
|
8973
|
|
|
|
|
|
|
const u8 *str_ptr; |
|
8974
|
16
|
|
|
|
|
|
const char_enc_type *enc_table = get_enc_table_with_flag(flg); |
|
8975
|
16
|
|
|
|
|
|
bool cpy = (enc_table == enc_table_cpy); |
|
8976
|
16
|
|
|
|
|
|
bool esc = has_flg(ESCAPE_UNICODE) != 0; |
|
8977
|
16
|
|
|
|
|
|
bool inv = has_allow(INVALID_UNICODE) != 0; |
|
8978
|
16
|
|
|
|
|
|
bool newline = has_flg(NEWLINE_AT_END) != 0; |
|
8979
|
16
|
|
|
|
|
|
const usize end_len = 2; /* '\n' and '\0' */ |
|
8980
|
|
|
|
|
|
|
|
|
8981
|
16
|
|
|
|
|
|
switch (unsafe_yyjson_get_type(val)) { |
|
8982
|
0
|
|
|
|
|
|
case YYJSON_TYPE_RAW: |
|
8983
|
0
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
8984
|
0
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
8985
|
|
|
|
|
|
|
check_str_len(str_len); |
|
8986
|
0
|
0
|
|
|
|
|
incr_len(str_len + end_len); |
|
|
|
0
|
|
|
|
|
|
|
8987
|
0
|
|
|
|
|
|
cur = write_raw(cur, str_ptr, str_len); |
|
8988
|
0
|
|
|
|
|
|
break; |
|
8989
|
|
|
|
|
|
|
|
|
8990
|
4
|
|
|
|
|
|
case YYJSON_TYPE_STR: |
|
8991
|
4
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
8992
|
4
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
8993
|
|
|
|
|
|
|
check_str_len(str_len); |
|
8994
|
4
|
50
|
|
|
|
|
incr_len(str_len * 6 + 2 + end_len); |
|
|
|
0
|
|
|
|
|
|
|
8995
|
8
|
50
|
|
|
|
|
if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
8996
|
2
|
|
|
|
|
|
cur = write_str_noesc(cur, str_ptr, str_len); |
|
8997
|
|
|
|
|
|
|
} else { |
|
8998
|
2
|
|
|
|
|
|
cur = write_str(cur, esc, inv, str_ptr, str_len, enc_table); |
|
8999
|
2
|
50
|
|
|
|
|
if (unlikely(!cur)) goto fail_str; |
|
|
|
0
|
|
|
|
|
|
|
9000
|
|
|
|
|
|
|
} |
|
9001
|
4
|
|
|
|
|
|
break; |
|
9002
|
|
|
|
|
|
|
|
|
9003
|
6
|
|
|
|
|
|
case YYJSON_TYPE_NUM: |
|
9004
|
6
|
50
|
|
|
|
|
incr_len(FP_BUF_LEN + end_len); |
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9005
|
6
|
|
|
|
|
|
cur = write_num(cur, val, flg); |
|
9006
|
6
|
50
|
|
|
|
|
if (unlikely(!cur)) goto fail_num; |
|
|
|
0
|
|
|
|
|
|
|
9007
|
6
|
|
|
|
|
|
break; |
|
9008
|
|
|
|
|
|
|
|
|
9009
|
3
|
|
|
|
|
|
case YYJSON_TYPE_BOOL: |
|
9010
|
3
|
50
|
|
|
|
|
incr_len(8); |
|
|
|
0
|
|
|
|
|
|
|
9011
|
3
|
100
|
|
|
|
|
cur = write_bool(cur, unsafe_yyjson_get_bool(val)); |
|
|
|
0
|
|
|
|
|
|
|
9012
|
3
|
|
|
|
|
|
break; |
|
9013
|
|
|
|
|
|
|
|
|
9014
|
1
|
|
|
|
|
|
case YYJSON_TYPE_NULL: |
|
9015
|
1
|
50
|
|
|
|
|
incr_len(8); |
|
|
|
0
|
|
|
|
|
|
|
9016
|
1
|
|
|
|
|
|
cur = write_null(cur); |
|
9017
|
1
|
|
|
|
|
|
break; |
|
9018
|
|
|
|
|
|
|
|
|
9019
|
1
|
|
|
|
|
|
case YYJSON_TYPE_ARR: |
|
9020
|
1
|
50
|
|
|
|
|
incr_len(2 + end_len); |
|
|
|
0
|
|
|
|
|
|
|
9021
|
|
|
|
|
|
|
byte_copy_2(cur, "[]"); |
|
9022
|
1
|
|
|
|
|
|
cur += 2; |
|
9023
|
1
|
|
|
|
|
|
break; |
|
9024
|
|
|
|
|
|
|
|
|
9025
|
1
|
|
|
|
|
|
case YYJSON_TYPE_OBJ: |
|
9026
|
1
|
50
|
|
|
|
|
incr_len(2 + end_len); |
|
|
|
0
|
|
|
|
|
|
|
9027
|
|
|
|
|
|
|
byte_copy_2(cur, "{}"); |
|
9028
|
1
|
|
|
|
|
|
cur += 2; |
|
9029
|
1
|
|
|
|
|
|
break; |
|
9030
|
|
|
|
|
|
|
|
|
9031
|
0
|
|
|
|
|
|
default: |
|
9032
|
0
|
|
|
|
|
|
goto fail_type; |
|
9033
|
|
|
|
|
|
|
} |
|
9034
|
|
|
|
|
|
|
|
|
9035
|
16
|
50
|
|
|
|
|
if (newline) *cur++ = '\n'; |
|
|
|
0
|
|
|
|
|
|
|
9036
|
16
|
|
|
|
|
|
*cur = '\0'; |
|
9037
|
16
|
|
|
|
|
|
*dat_len = (usize)(cur - hdr); |
|
9038
|
16
|
|
|
|
|
|
memset(err, 0, sizeof(yyjson_write_err)); |
|
9039
|
16
|
|
|
|
|
|
return hdr; |
|
9040
|
|
|
|
|
|
|
|
|
9041
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
|
|
0
|
|
|
|
|
|
|
9042
|
0
|
0
|
|
|
|
|
fail_type: return_err(INVALID_VALUE_TYPE, MSG_ERR_TYPE); |
|
|
|
0
|
|
|
|
|
|
|
9043
|
0
|
0
|
|
|
|
|
fail_num: return_err(NAN_OR_INF, MSG_NAN_INF); |
|
|
|
0
|
|
|
|
|
|
|
9044
|
0
|
0
|
|
|
|
|
fail_str: return_err(INVALID_STRING, MSG_ERR_UTF8); |
|
|
|
0
|
|
|
|
|
|
|
9045
|
|
|
|
|
|
|
|
|
9046
|
|
|
|
|
|
|
#undef return_err |
|
9047
|
|
|
|
|
|
|
#undef check_str_len |
|
9048
|
|
|
|
|
|
|
#undef incr_len |
|
9049
|
|
|
|
|
|
|
} |
|
9050
|
|
|
|
|
|
|
|
|
9051
|
|
|
|
|
|
|
/** Write JSON document minify. |
|
9052
|
|
|
|
|
|
|
The root of this document should be a non-empty container. */ |
|
9053
|
|
|
|
|
|
|
static_inline u8 *yyjson_write_minify(const yyjson_val *root, |
|
9054
|
|
|
|
|
|
|
const yyjson_write_flag flg, |
|
9055
|
|
|
|
|
|
|
const yyjson_alc alc, |
|
9056
|
|
|
|
|
|
|
usize *dat_len, |
|
9057
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9058
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
9059
|
|
|
|
|
|
|
*dat_len = 0; \ |
|
9060
|
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_##_code; \ |
|
9061
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
9062
|
|
|
|
|
|
|
if (hdr) alc.free(alc.ctx, hdr); \ |
|
9063
|
|
|
|
|
|
|
return NULL; \ |
|
9064
|
|
|
|
|
|
|
} while (false) |
|
9065
|
|
|
|
|
|
|
|
|
9066
|
|
|
|
|
|
|
#define incr_len(_len) do { \ |
|
9067
|
|
|
|
|
|
|
ext_len = (usize)(_len); \ |
|
9068
|
|
|
|
|
|
|
if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ |
|
9069
|
|
|
|
|
|
|
usize ctx_pos = (usize)((u8 *)ctx - hdr); \ |
|
9070
|
|
|
|
|
|
|
usize cur_pos = (usize)(cur - hdr); \ |
|
9071
|
|
|
|
|
|
|
ctx_len = (usize)(end - (u8 *)ctx); \ |
|
9072
|
|
|
|
|
|
|
alc_inc = yyjson_max(alc_len / 2, ext_len); \ |
|
9073
|
|
|
|
|
|
|
alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \ |
|
9074
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \ |
|
9075
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
9076
|
|
|
|
|
|
|
alc_len += alc_inc; \ |
|
9077
|
|
|
|
|
|
|
tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ |
|
9078
|
|
|
|
|
|
|
if (unlikely(!tmp)) goto fail_alloc; \ |
|
9079
|
|
|
|
|
|
|
ctx_tmp = (yyjson_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ |
|
9080
|
|
|
|
|
|
|
memmove((void *)ctx_tmp, (void *)(tmp + ctx_pos), ctx_len); \ |
|
9081
|
|
|
|
|
|
|
ctx = ctx_tmp; \ |
|
9082
|
|
|
|
|
|
|
cur = tmp + cur_pos; \ |
|
9083
|
|
|
|
|
|
|
end = tmp + alc_len; \ |
|
9084
|
|
|
|
|
|
|
hdr = tmp; \ |
|
9085
|
|
|
|
|
|
|
} \ |
|
9086
|
|
|
|
|
|
|
} while (false) |
|
9087
|
|
|
|
|
|
|
|
|
9088
|
|
|
|
|
|
|
#define check_str_len(_len) do { \ |
|
9089
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ |
|
9090
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
9091
|
|
|
|
|
|
|
} while (false) |
|
9092
|
|
|
|
|
|
|
|
|
9093
|
|
|
|
|
|
|
yyjson_val *val; |
|
9094
|
|
|
|
|
|
|
yyjson_type val_type; |
|
9095
|
|
|
|
|
|
|
usize ctn_len, ctn_len_tmp; |
|
9096
|
|
|
|
|
|
|
bool ctn_obj, ctn_obj_tmp, is_key; |
|
9097
|
|
|
|
|
|
|
u8 *hdr, *cur, *end, *tmp; |
|
9098
|
|
|
|
|
|
|
yyjson_write_ctx *ctx, *ctx_tmp; |
|
9099
|
|
|
|
|
|
|
usize alc_len, alc_inc, ctx_len, ext_len, str_len; |
|
9100
|
|
|
|
|
|
|
const u8 *str_ptr; |
|
9101
|
0
|
|
|
|
|
|
const char_enc_type *enc_table = get_enc_table_with_flag(flg); |
|
9102
|
0
|
|
|
|
|
|
bool cpy = (enc_table == enc_table_cpy); |
|
9103
|
0
|
|
|
|
|
|
bool esc = has_flg(ESCAPE_UNICODE) != 0; |
|
9104
|
0
|
|
|
|
|
|
bool inv = has_allow(INVALID_UNICODE) != 0; |
|
9105
|
0
|
|
|
|
|
|
bool newline = has_flg(NEWLINE_AT_END) != 0; |
|
9106
|
|
|
|
|
|
|
|
|
9107
|
0
|
|
|
|
|
|
alc_len = root->uni.ofs / sizeof(yyjson_val); |
|
9108
|
0
|
|
|
|
|
|
alc_len = alc_len * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; |
|
9109
|
0
|
|
|
|
|
|
alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx)); |
|
9110
|
0
|
|
|
|
|
|
hdr = (u8 *)alc.malloc(alc.ctx, alc_len); |
|
9111
|
0
|
0
|
|
|
|
|
if (!hdr) goto fail_alloc; |
|
9112
|
0
|
|
|
|
|
|
cur = hdr; |
|
9113
|
0
|
|
|
|
|
|
end = hdr + alc_len; |
|
9114
|
0
|
|
|
|
|
|
ctx = (yyjson_write_ctx *)(void *)end; |
|
9115
|
|
|
|
|
|
|
|
|
9116
|
0
|
|
|
|
|
|
doc_begin: |
|
9117
|
0
|
|
|
|
|
|
val = constcast(yyjson_val *)root; |
|
9118
|
0
|
|
|
|
|
|
val_type = unsafe_yyjson_get_type(val); |
|
9119
|
0
|
|
|
|
|
|
ctn_obj = (val_type == YYJSON_TYPE_OBJ); |
|
9120
|
0
|
|
|
|
|
|
ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; |
|
9121
|
0
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj << 5)); |
|
9122
|
0
|
|
|
|
|
|
val++; |
|
9123
|
|
|
|
|
|
|
|
|
9124
|
0
|
|
|
|
|
|
val_begin: |
|
9125
|
0
|
|
|
|
|
|
val_type = unsafe_yyjson_get_type(val); |
|
9126
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_STR) { |
|
9127
|
0
|
|
|
|
|
|
is_key = ((u8)ctn_obj & (u8)~ctn_len); |
|
9128
|
0
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
9129
|
0
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
9130
|
|
|
|
|
|
|
check_str_len(str_len); |
|
9131
|
0
|
0
|
|
|
|
|
incr_len(str_len * 6 + 16); |
|
|
|
0
|
|
|
|
|
|
|
9132
|
0
|
0
|
|
|
|
|
if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { |
|
|
|
0
|
|
|
|
|
|
|
9133
|
0
|
|
|
|
|
|
cur = write_str_noesc(cur, str_ptr, str_len); |
|
9134
|
|
|
|
|
|
|
} else { |
|
9135
|
0
|
|
|
|
|
|
cur = write_str(cur, esc, inv, str_ptr, str_len, enc_table); |
|
9136
|
0
|
0
|
|
|
|
|
if (unlikely(!cur)) goto fail_str; |
|
9137
|
|
|
|
|
|
|
} |
|
9138
|
0
|
0
|
|
|
|
|
*cur++ = is_key ? ':' : ','; |
|
9139
|
0
|
|
|
|
|
|
goto val_end; |
|
9140
|
|
|
|
|
|
|
} |
|
9141
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_NUM) { |
|
9142
|
0
|
0
|
|
|
|
|
incr_len(FP_BUF_LEN); |
|
|
|
0
|
|
|
|
|
|
|
9143
|
0
|
|
|
|
|
|
cur = write_num(cur, val, flg); |
|
9144
|
0
|
0
|
|
|
|
|
if (unlikely(!cur)) goto fail_num; |
|
9145
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9146
|
0
|
|
|
|
|
|
goto val_end; |
|
9147
|
|
|
|
|
|
|
} |
|
9148
|
0
|
0
|
|
|
|
|
if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == |
|
9149
|
|
|
|
|
|
|
(YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { |
|
9150
|
0
|
|
|
|
|
|
ctn_len_tmp = unsafe_yyjson_get_len(val); |
|
9151
|
0
|
|
|
|
|
|
ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); |
|
9152
|
0
|
0
|
|
|
|
|
incr_len(16); |
|
|
|
0
|
|
|
|
|
|
|
9153
|
0
|
0
|
|
|
|
|
if (unlikely(ctn_len_tmp == 0)) { |
|
9154
|
|
|
|
|
|
|
/* write empty container */ |
|
9155
|
0
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); |
|
9156
|
0
|
|
|
|
|
|
*cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); |
|
9157
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9158
|
0
|
|
|
|
|
|
goto val_end; |
|
9159
|
|
|
|
|
|
|
} else { |
|
9160
|
|
|
|
|
|
|
/* push context, setup new container */ |
|
9161
|
0
|
|
|
|
|
|
yyjson_write_ctx_set(--ctx, ctn_len, ctn_obj); |
|
9162
|
0
|
|
|
|
|
|
ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; |
|
9163
|
0
|
|
|
|
|
|
ctn_obj = ctn_obj_tmp; |
|
9164
|
0
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj << 5)); |
|
9165
|
0
|
|
|
|
|
|
val++; |
|
9166
|
0
|
|
|
|
|
|
goto val_begin; |
|
9167
|
|
|
|
|
|
|
} |
|
9168
|
|
|
|
|
|
|
} |
|
9169
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_BOOL) { |
|
9170
|
0
|
0
|
|
|
|
|
incr_len(16); |
|
|
|
0
|
|
|
|
|
|
|
9171
|
0
|
0
|
|
|
|
|
cur = write_bool(cur, unsafe_yyjson_get_bool(val)); |
|
9172
|
0
|
|
|
|
|
|
cur++; |
|
9173
|
0
|
|
|
|
|
|
goto val_end; |
|
9174
|
|
|
|
|
|
|
} |
|
9175
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_NULL) { |
|
9176
|
0
|
0
|
|
|
|
|
incr_len(16); |
|
|
|
0
|
|
|
|
|
|
|
9177
|
0
|
|
|
|
|
|
cur = write_null(cur); |
|
9178
|
0
|
|
|
|
|
|
cur++; |
|
9179
|
0
|
|
|
|
|
|
goto val_end; |
|
9180
|
|
|
|
|
|
|
} |
|
9181
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_RAW) { |
|
9182
|
0
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
9183
|
0
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
9184
|
|
|
|
|
|
|
check_str_len(str_len); |
|
9185
|
0
|
0
|
|
|
|
|
incr_len(str_len + 2); |
|
|
|
0
|
|
|
|
|
|
|
9186
|
0
|
|
|
|
|
|
cur = write_raw(cur, str_ptr, str_len); |
|
9187
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9188
|
0
|
|
|
|
|
|
goto val_end; |
|
9189
|
|
|
|
|
|
|
} |
|
9190
|
0
|
|
|
|
|
|
goto fail_type; |
|
9191
|
|
|
|
|
|
|
|
|
9192
|
0
|
|
|
|
|
|
val_end: |
|
9193
|
0
|
|
|
|
|
|
val++; |
|
9194
|
0
|
|
|
|
|
|
ctn_len--; |
|
9195
|
0
|
0
|
|
|
|
|
if (unlikely(ctn_len == 0)) goto ctn_end; |
|
9196
|
0
|
|
|
|
|
|
goto val_begin; |
|
9197
|
|
|
|
|
|
|
|
|
9198
|
0
|
|
|
|
|
|
ctn_end: |
|
9199
|
0
|
|
|
|
|
|
cur--; |
|
9200
|
0
|
|
|
|
|
|
*cur++ = (u8)(']' | ((u8)ctn_obj << 5)); |
|
9201
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9202
|
0
|
0
|
|
|
|
|
if (unlikely((u8 *)ctx >= end)) goto doc_end; |
|
9203
|
0
|
|
|
|
|
|
yyjson_write_ctx_get(ctx++, &ctn_len, &ctn_obj); |
|
9204
|
0
|
|
|
|
|
|
ctn_len--; |
|
9205
|
0
|
0
|
|
|
|
|
if (likely(ctn_len > 0)) { |
|
9206
|
0
|
|
|
|
|
|
goto val_begin; |
|
9207
|
|
|
|
|
|
|
} else { |
|
9208
|
0
|
|
|
|
|
|
goto ctn_end; |
|
9209
|
|
|
|
|
|
|
} |
|
9210
|
|
|
|
|
|
|
|
|
9211
|
0
|
|
|
|
|
|
doc_end: |
|
9212
|
0
|
0
|
|
|
|
|
if (newline) { |
|
9213
|
0
|
0
|
|
|
|
|
incr_len(2); |
|
|
|
0
|
|
|
|
|
|
|
9214
|
0
|
|
|
|
|
|
*(cur - 1) = '\n'; |
|
9215
|
0
|
|
|
|
|
|
cur++; |
|
9216
|
|
|
|
|
|
|
} |
|
9217
|
0
|
|
|
|
|
|
*--cur = '\0'; |
|
9218
|
0
|
|
|
|
|
|
*dat_len = (usize)(cur - hdr); |
|
9219
|
0
|
|
|
|
|
|
memset(err, 0, sizeof(yyjson_write_err)); |
|
9220
|
0
|
|
|
|
|
|
return hdr; |
|
9221
|
|
|
|
|
|
|
|
|
9222
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
9223
|
0
|
0
|
|
|
|
|
fail_type: return_err(INVALID_VALUE_TYPE, MSG_ERR_TYPE); |
|
9224
|
0
|
0
|
|
|
|
|
fail_num: return_err(NAN_OR_INF, MSG_NAN_INF); |
|
9225
|
0
|
0
|
|
|
|
|
fail_str: return_err(INVALID_STRING, MSG_ERR_UTF8); |
|
9226
|
|
|
|
|
|
|
|
|
9227
|
|
|
|
|
|
|
#undef return_err |
|
9228
|
|
|
|
|
|
|
#undef incr_len |
|
9229
|
|
|
|
|
|
|
#undef check_str_len |
|
9230
|
|
|
|
|
|
|
} |
|
9231
|
|
|
|
|
|
|
|
|
9232
|
|
|
|
|
|
|
/** Write JSON document pretty. |
|
9233
|
|
|
|
|
|
|
The root of this document should be a non-empty container. */ |
|
9234
|
|
|
|
|
|
|
static_inline u8 *yyjson_write_pretty(const yyjson_val *root, |
|
9235
|
|
|
|
|
|
|
const yyjson_write_flag flg, |
|
9236
|
|
|
|
|
|
|
const yyjson_alc alc, |
|
9237
|
|
|
|
|
|
|
usize *dat_len, |
|
9238
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9239
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
9240
|
|
|
|
|
|
|
*dat_len = 0; \ |
|
9241
|
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_##_code; \ |
|
9242
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
9243
|
|
|
|
|
|
|
if (hdr) alc.free(alc.ctx, hdr); \ |
|
9244
|
|
|
|
|
|
|
return NULL; \ |
|
9245
|
|
|
|
|
|
|
} while (false) |
|
9246
|
|
|
|
|
|
|
|
|
9247
|
|
|
|
|
|
|
#define incr_len(_len) do { \ |
|
9248
|
|
|
|
|
|
|
ext_len = (usize)(_len); \ |
|
9249
|
|
|
|
|
|
|
if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ |
|
9250
|
|
|
|
|
|
|
usize ctx_pos = (usize)((u8 *)ctx - hdr); \ |
|
9251
|
|
|
|
|
|
|
usize cur_pos = (usize)(cur - hdr); \ |
|
9252
|
|
|
|
|
|
|
ctx_len = (usize)(end - (u8 *)ctx); \ |
|
9253
|
|
|
|
|
|
|
alc_inc = yyjson_max(alc_len / 2, ext_len); \ |
|
9254
|
|
|
|
|
|
|
alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \ |
|
9255
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \ |
|
9256
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
9257
|
|
|
|
|
|
|
alc_len += alc_inc; \ |
|
9258
|
|
|
|
|
|
|
tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ |
|
9259
|
|
|
|
|
|
|
if (unlikely(!tmp)) goto fail_alloc; \ |
|
9260
|
|
|
|
|
|
|
ctx_tmp = (yyjson_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ |
|
9261
|
|
|
|
|
|
|
memmove((void *)ctx_tmp, (void *)(tmp + ctx_pos), ctx_len); \ |
|
9262
|
|
|
|
|
|
|
ctx = ctx_tmp; \ |
|
9263
|
|
|
|
|
|
|
cur = tmp + cur_pos; \ |
|
9264
|
|
|
|
|
|
|
end = tmp + alc_len; \ |
|
9265
|
|
|
|
|
|
|
hdr = tmp; \ |
|
9266
|
|
|
|
|
|
|
} \ |
|
9267
|
|
|
|
|
|
|
} while (false) |
|
9268
|
|
|
|
|
|
|
|
|
9269
|
|
|
|
|
|
|
#define check_str_len(_len) do { \ |
|
9270
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ |
|
9271
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
9272
|
|
|
|
|
|
|
} while (false) |
|
9273
|
|
|
|
|
|
|
|
|
9274
|
|
|
|
|
|
|
yyjson_val *val; |
|
9275
|
|
|
|
|
|
|
yyjson_type val_type; |
|
9276
|
|
|
|
|
|
|
usize ctn_len, ctn_len_tmp; |
|
9277
|
|
|
|
|
|
|
bool ctn_obj, ctn_obj_tmp, is_key, no_indent; |
|
9278
|
|
|
|
|
|
|
u8 *hdr, *cur, *end, *tmp; |
|
9279
|
|
|
|
|
|
|
yyjson_write_ctx *ctx, *ctx_tmp; |
|
9280
|
|
|
|
|
|
|
usize alc_len, alc_inc, ctx_len, ext_len, str_len, level; |
|
9281
|
|
|
|
|
|
|
const u8 *str_ptr; |
|
9282
|
0
|
|
|
|
|
|
const char_enc_type *enc_table = get_enc_table_with_flag(flg); |
|
9283
|
0
|
|
|
|
|
|
bool cpy = (enc_table == enc_table_cpy); |
|
9284
|
0
|
|
|
|
|
|
bool esc = has_flg(ESCAPE_UNICODE) != 0; |
|
9285
|
0
|
|
|
|
|
|
bool inv = has_allow(INVALID_UNICODE) != 0; |
|
9286
|
0
|
0
|
|
|
|
|
usize spaces = has_flg(PRETTY_TWO_SPACES) ? 2 : 4; |
|
9287
|
0
|
|
|
|
|
|
bool newline = has_flg(NEWLINE_AT_END) != 0; |
|
9288
|
|
|
|
|
|
|
|
|
9289
|
0
|
|
|
|
|
|
alc_len = root->uni.ofs / sizeof(yyjson_val); |
|
9290
|
0
|
|
|
|
|
|
alc_len = alc_len * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; |
|
9291
|
0
|
|
|
|
|
|
alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx)); |
|
9292
|
0
|
|
|
|
|
|
hdr = (u8 *)alc.malloc(alc.ctx, alc_len); |
|
9293
|
0
|
0
|
|
|
|
|
if (!hdr) goto fail_alloc; |
|
9294
|
0
|
|
|
|
|
|
cur = hdr; |
|
9295
|
0
|
|
|
|
|
|
end = hdr + alc_len; |
|
9296
|
0
|
|
|
|
|
|
ctx = (yyjson_write_ctx *)(void *)end; |
|
9297
|
|
|
|
|
|
|
|
|
9298
|
0
|
|
|
|
|
|
doc_begin: |
|
9299
|
0
|
|
|
|
|
|
val = constcast(yyjson_val *)root; |
|
9300
|
0
|
|
|
|
|
|
val_type = unsafe_yyjson_get_type(val); |
|
9301
|
0
|
|
|
|
|
|
ctn_obj = (val_type == YYJSON_TYPE_OBJ); |
|
9302
|
0
|
|
|
|
|
|
ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; |
|
9303
|
0
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj << 5)); |
|
9304
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9305
|
0
|
|
|
|
|
|
val++; |
|
9306
|
0
|
|
|
|
|
|
level = 1; |
|
9307
|
|
|
|
|
|
|
|
|
9308
|
0
|
|
|
|
|
|
val_begin: |
|
9309
|
0
|
|
|
|
|
|
val_type = unsafe_yyjson_get_type(val); |
|
9310
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_STR) { |
|
9311
|
0
|
|
|
|
|
|
is_key = (bool)((u8)ctn_obj & (u8)~ctn_len); |
|
9312
|
0
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9313
|
0
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
9314
|
0
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
9315
|
|
|
|
|
|
|
check_str_len(str_len); |
|
9316
|
0
|
0
|
|
|
|
|
incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9317
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9318
|
0
|
0
|
|
|
|
|
if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { |
|
|
|
0
|
|
|
|
|
|
|
9319
|
0
|
|
|
|
|
|
cur = write_str_noesc(cur, str_ptr, str_len); |
|
9320
|
|
|
|
|
|
|
} else { |
|
9321
|
0
|
|
|
|
|
|
cur = write_str(cur, esc, inv, str_ptr, str_len, enc_table); |
|
9322
|
0
|
0
|
|
|
|
|
if (unlikely(!cur)) goto fail_str; |
|
9323
|
|
|
|
|
|
|
} |
|
9324
|
0
|
0
|
|
|
|
|
*cur++ = is_key ? ':' : ','; |
|
9325
|
0
|
0
|
|
|
|
|
*cur++ = is_key ? ' ' : '\n'; |
|
9326
|
0
|
|
|
|
|
|
goto val_end; |
|
9327
|
|
|
|
|
|
|
} |
|
9328
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_NUM) { |
|
9329
|
0
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9330
|
0
|
0
|
|
|
|
|
incr_len(FP_BUF_LEN + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9331
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
|
|
0
|
|
|
|
|
|
|
9332
|
0
|
|
|
|
|
|
cur = write_num(cur, val, flg); |
|
9333
|
0
|
0
|
|
|
|
|
if (unlikely(!cur)) goto fail_num; |
|
9334
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9335
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9336
|
0
|
|
|
|
|
|
goto val_end; |
|
9337
|
|
|
|
|
|
|
} |
|
9338
|
0
|
0
|
|
|
|
|
if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == |
|
9339
|
|
|
|
|
|
|
(YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { |
|
9340
|
0
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9341
|
0
|
|
|
|
|
|
ctn_len_tmp = unsafe_yyjson_get_len(val); |
|
9342
|
0
|
|
|
|
|
|
ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); |
|
9343
|
0
|
0
|
|
|
|
|
if (unlikely(ctn_len_tmp == 0)) { |
|
9344
|
|
|
|
|
|
|
/* write empty container */ |
|
9345
|
0
|
0
|
|
|
|
|
incr_len(16 + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9346
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9347
|
0
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); |
|
9348
|
0
|
|
|
|
|
|
*cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); |
|
9349
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9350
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9351
|
0
|
|
|
|
|
|
goto val_end; |
|
9352
|
|
|
|
|
|
|
} else { |
|
9353
|
|
|
|
|
|
|
/* push context, setup new container */ |
|
9354
|
0
|
0
|
|
|
|
|
incr_len(32 + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9355
|
0
|
|
|
|
|
|
yyjson_write_ctx_set(--ctx, ctn_len, ctn_obj); |
|
9356
|
0
|
|
|
|
|
|
ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; |
|
9357
|
0
|
|
|
|
|
|
ctn_obj = ctn_obj_tmp; |
|
9358
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9359
|
0
|
|
|
|
|
|
level++; |
|
9360
|
0
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj << 5)); |
|
9361
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9362
|
0
|
|
|
|
|
|
val++; |
|
9363
|
0
|
|
|
|
|
|
goto val_begin; |
|
9364
|
|
|
|
|
|
|
} |
|
9365
|
|
|
|
|
|
|
} |
|
9366
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_BOOL) { |
|
9367
|
0
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9368
|
0
|
0
|
|
|
|
|
incr_len(16 + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9369
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9370
|
0
|
0
|
|
|
|
|
cur = write_bool(cur, unsafe_yyjson_get_bool(val)); |
|
9371
|
0
|
|
|
|
|
|
cur += 2; |
|
9372
|
0
|
|
|
|
|
|
goto val_end; |
|
9373
|
|
|
|
|
|
|
} |
|
9374
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_NULL) { |
|
9375
|
0
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9376
|
0
|
0
|
|
|
|
|
incr_len(16 + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9377
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9378
|
0
|
|
|
|
|
|
cur = write_null(cur); |
|
9379
|
0
|
|
|
|
|
|
cur += 2; |
|
9380
|
0
|
|
|
|
|
|
goto val_end; |
|
9381
|
|
|
|
|
|
|
} |
|
9382
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_RAW) { |
|
9383
|
0
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9384
|
0
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
9385
|
0
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
9386
|
|
|
|
|
|
|
check_str_len(str_len); |
|
9387
|
0
|
0
|
|
|
|
|
incr_len(str_len + 3 + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9388
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9389
|
0
|
|
|
|
|
|
cur = write_raw(cur, str_ptr, str_len); |
|
9390
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9391
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9392
|
0
|
|
|
|
|
|
goto val_end; |
|
9393
|
|
|
|
|
|
|
} |
|
9394
|
0
|
|
|
|
|
|
goto fail_type; |
|
9395
|
|
|
|
|
|
|
|
|
9396
|
0
|
|
|
|
|
|
val_end: |
|
9397
|
0
|
|
|
|
|
|
val++; |
|
9398
|
0
|
|
|
|
|
|
ctn_len--; |
|
9399
|
0
|
0
|
|
|
|
|
if (unlikely(ctn_len == 0)) goto ctn_end; |
|
9400
|
0
|
|
|
|
|
|
goto val_begin; |
|
9401
|
|
|
|
|
|
|
|
|
9402
|
0
|
|
|
|
|
|
ctn_end: |
|
9403
|
0
|
|
|
|
|
|
cur -= 2; |
|
9404
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9405
|
0
|
0
|
|
|
|
|
incr_len(level * 4); |
|
|
|
0
|
|
|
|
|
|
|
9406
|
0
|
|
|
|
|
|
cur = write_indent(cur, --level, spaces); |
|
9407
|
0
|
|
|
|
|
|
*cur++ = (u8)(']' | ((u8)ctn_obj << 5)); |
|
9408
|
0
|
0
|
|
|
|
|
if (unlikely((u8 *)ctx >= end)) goto doc_end; |
|
9409
|
0
|
|
|
|
|
|
yyjson_write_ctx_get(ctx++, &ctn_len, &ctn_obj); |
|
9410
|
0
|
|
|
|
|
|
ctn_len--; |
|
9411
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9412
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9413
|
0
|
0
|
|
|
|
|
if (likely(ctn_len > 0)) { |
|
9414
|
0
|
|
|
|
|
|
goto val_begin; |
|
9415
|
|
|
|
|
|
|
} else { |
|
9416
|
0
|
|
|
|
|
|
goto ctn_end; |
|
9417
|
|
|
|
|
|
|
} |
|
9418
|
|
|
|
|
|
|
|
|
9419
|
0
|
|
|
|
|
|
doc_end: |
|
9420
|
0
|
0
|
|
|
|
|
if (newline) { |
|
9421
|
0
|
0
|
|
|
|
|
incr_len(2); |
|
|
|
0
|
|
|
|
|
|
|
9422
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9423
|
|
|
|
|
|
|
} |
|
9424
|
0
|
|
|
|
|
|
*cur = '\0'; |
|
9425
|
0
|
|
|
|
|
|
*dat_len = (usize)(cur - hdr); |
|
9426
|
0
|
|
|
|
|
|
memset(err, 0, sizeof(yyjson_write_err)); |
|
9427
|
0
|
|
|
|
|
|
return hdr; |
|
9428
|
|
|
|
|
|
|
|
|
9429
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
9430
|
0
|
0
|
|
|
|
|
fail_type: return_err(INVALID_VALUE_TYPE, MSG_ERR_TYPE); |
|
9431
|
0
|
0
|
|
|
|
|
fail_num: return_err(NAN_OR_INF, MSG_NAN_INF); |
|
9432
|
0
|
0
|
|
|
|
|
fail_str: return_err(INVALID_STRING, MSG_ERR_UTF8); |
|
9433
|
|
|
|
|
|
|
|
|
9434
|
|
|
|
|
|
|
#undef return_err |
|
9435
|
|
|
|
|
|
|
#undef incr_len |
|
9436
|
|
|
|
|
|
|
#undef check_str_len |
|
9437
|
|
|
|
|
|
|
} |
|
9438
|
|
|
|
|
|
|
|
|
9439
|
|
|
|
|
|
|
|
|
9440
|
|
|
|
|
|
|
|
|
9441
|
|
|
|
|
|
|
/*============================================================================== |
|
9442
|
|
|
|
|
|
|
* MARK: - JSON Writer (Public) |
|
9443
|
|
|
|
|
|
|
*============================================================================*/ |
|
9444
|
|
|
|
|
|
|
|
|
9445
|
0
|
|
|
|
|
|
char *yyjson_val_write_opts(const yyjson_val *val, |
|
9446
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9447
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
9448
|
|
|
|
|
|
|
usize *dat_len, |
|
9449
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9450
|
|
|
|
|
|
|
yyjson_write_err tmp_err; |
|
9451
|
|
|
|
|
|
|
usize tmp_dat_len; |
|
9452
|
0
|
0
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
9453
|
0
|
|
|
|
|
|
yyjson_val *root = constcast(yyjson_val *)val; |
|
9454
|
|
|
|
|
|
|
|
|
9455
|
0
|
0
|
|
|
|
|
if (!err) err = &tmp_err; |
|
9456
|
0
|
0
|
|
|
|
|
if (!dat_len) dat_len = &tmp_dat_len; |
|
9457
|
|
|
|
|
|
|
|
|
9458
|
0
|
0
|
|
|
|
|
if (unlikely(!root)) { |
|
9459
|
0
|
|
|
|
|
|
*dat_len = 0; |
|
9460
|
0
|
|
|
|
|
|
err->msg = "input JSON is NULL"; |
|
9461
|
0
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; |
|
9462
|
0
|
|
|
|
|
|
return NULL; |
|
9463
|
|
|
|
|
|
|
} |
|
9464
|
|
|
|
|
|
|
|
|
9465
|
0
|
0
|
|
|
|
|
if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) { |
|
|
|
0
|
|
|
|
|
|
|
9466
|
0
|
|
|
|
|
|
return (char *)yyjson_write_single(root, flg, alc, dat_len, err); |
|
9467
|
0
|
0
|
|
|
|
|
} else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) { |
|
9468
|
0
|
|
|
|
|
|
return (char *)yyjson_write_pretty(root, flg, alc, dat_len, err); |
|
9469
|
|
|
|
|
|
|
} else { |
|
9470
|
0
|
|
|
|
|
|
return (char *)yyjson_write_minify(root, flg, alc, dat_len, err); |
|
9471
|
|
|
|
|
|
|
} |
|
9472
|
|
|
|
|
|
|
} |
|
9473
|
|
|
|
|
|
|
|
|
9474
|
0
|
|
|
|
|
|
char *yyjson_write_opts(const yyjson_doc *doc, |
|
9475
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9476
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
9477
|
|
|
|
|
|
|
usize *dat_len, |
|
9478
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9479
|
0
|
0
|
|
|
|
|
yyjson_val *root = doc ? doc->root : NULL; |
|
9480
|
0
|
|
|
|
|
|
return yyjson_val_write_opts(root, flg, alc_ptr, dat_len, err); |
|
9481
|
|
|
|
|
|
|
} |
|
9482
|
|
|
|
|
|
|
|
|
9483
|
0
|
|
|
|
|
|
bool yyjson_val_write_file(const char *path, |
|
9484
|
|
|
|
|
|
|
const yyjson_val *val, |
|
9485
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9486
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
9487
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9488
|
|
|
|
|
|
|
yyjson_write_err tmp_err; |
|
9489
|
0
|
0
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
9490
|
|
|
|
|
|
|
u8 *dat; |
|
9491
|
0
|
|
|
|
|
|
usize dat_len = 0; |
|
9492
|
0
|
|
|
|
|
|
yyjson_val *root = constcast(yyjson_val *)val; |
|
9493
|
|
|
|
|
|
|
bool suc; |
|
9494
|
|
|
|
|
|
|
|
|
9495
|
0
|
0
|
|
|
|
|
if (!err) err = &tmp_err; |
|
9496
|
0
|
0
|
|
|
|
|
if (unlikely(!path || !*path)) { |
|
|
|
0
|
|
|
|
|
|
|
9497
|
0
|
|
|
|
|
|
err->msg = "input path is invalid"; |
|
9498
|
0
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; |
|
9499
|
0
|
|
|
|
|
|
return false; |
|
9500
|
|
|
|
|
|
|
} |
|
9501
|
|
|
|
|
|
|
|
|
9502
|
0
|
|
|
|
|
|
dat = (u8 *)yyjson_val_write_opts(root, flg, &alc, &dat_len, err); |
|
9503
|
0
|
0
|
|
|
|
|
if (unlikely(!dat)) return false; |
|
9504
|
0
|
|
|
|
|
|
suc = write_dat_to_file(path, dat, dat_len, err); |
|
9505
|
0
|
|
|
|
|
|
alc.free(alc.ctx, dat); |
|
9506
|
0
|
|
|
|
|
|
return suc; |
|
9507
|
|
|
|
|
|
|
} |
|
9508
|
|
|
|
|
|
|
|
|
9509
|
0
|
|
|
|
|
|
bool yyjson_val_write_fp(FILE *fp, |
|
9510
|
|
|
|
|
|
|
const yyjson_val *val, |
|
9511
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9512
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
9513
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9514
|
|
|
|
|
|
|
yyjson_write_err tmp_err; |
|
9515
|
0
|
0
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
9516
|
|
|
|
|
|
|
u8 *dat; |
|
9517
|
0
|
|
|
|
|
|
usize dat_len = 0; |
|
9518
|
0
|
|
|
|
|
|
yyjson_val *root = constcast(yyjson_val *)val; |
|
9519
|
|
|
|
|
|
|
bool suc; |
|
9520
|
|
|
|
|
|
|
|
|
9521
|
0
|
0
|
|
|
|
|
if (!err) err = &tmp_err; |
|
9522
|
0
|
0
|
|
|
|
|
if (unlikely(!fp)) { |
|
9523
|
0
|
|
|
|
|
|
err->msg = "input fp is invalid"; |
|
9524
|
0
|
|
|
|
|
|
err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; |
|
9525
|
0
|
|
|
|
|
|
return false; |
|
9526
|
|
|
|
|
|
|
} |
|
9527
|
|
|
|
|
|
|
|
|
9528
|
0
|
|
|
|
|
|
dat = (u8 *)yyjson_val_write_opts(root, flg, &alc, &dat_len, err); |
|
9529
|
0
|
0
|
|
|
|
|
if (unlikely(!dat)) return false; |
|
9530
|
0
|
|
|
|
|
|
suc = write_dat_to_fp(fp, dat, dat_len, err); |
|
9531
|
0
|
|
|
|
|
|
alc.free(alc.ctx, dat); |
|
9532
|
0
|
|
|
|
|
|
return suc; |
|
9533
|
|
|
|
|
|
|
} |
|
9534
|
|
|
|
|
|
|
|
|
9535
|
0
|
|
|
|
|
|
bool yyjson_write_file(const char *path, |
|
9536
|
|
|
|
|
|
|
const yyjson_doc *doc, |
|
9537
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9538
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
9539
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9540
|
0
|
0
|
|
|
|
|
yyjson_val *root = doc ? doc->root : NULL; |
|
9541
|
0
|
|
|
|
|
|
return yyjson_val_write_file(path, root, flg, alc_ptr, err); |
|
9542
|
|
|
|
|
|
|
} |
|
9543
|
|
|
|
|
|
|
|
|
9544
|
0
|
|
|
|
|
|
bool yyjson_write_fp(FILE *fp, |
|
9545
|
|
|
|
|
|
|
const yyjson_doc *doc, |
|
9546
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9547
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
9548
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9549
|
0
|
0
|
|
|
|
|
yyjson_val *root = doc ? doc->root : NULL; |
|
9550
|
0
|
|
|
|
|
|
return yyjson_val_write_fp(fp, root, flg, alc_ptr, err); |
|
9551
|
|
|
|
|
|
|
} |
|
9552
|
|
|
|
|
|
|
|
|
9553
|
|
|
|
|
|
|
|
|
9554
|
|
|
|
|
|
|
|
|
9555
|
|
|
|
|
|
|
/*============================================================================== |
|
9556
|
|
|
|
|
|
|
* MARK: - Mutable JSON Writer Implementation (Private) |
|
9557
|
|
|
|
|
|
|
*============================================================================*/ |
|
9558
|
|
|
|
|
|
|
|
|
9559
|
|
|
|
|
|
|
typedef struct yyjson_mut_write_ctx { |
|
9560
|
|
|
|
|
|
|
usize tag; |
|
9561
|
|
|
|
|
|
|
yyjson_mut_val *ctn; |
|
9562
|
|
|
|
|
|
|
} yyjson_mut_write_ctx; |
|
9563
|
|
|
|
|
|
|
|
|
9564
|
|
|
|
|
|
|
static_inline void yyjson_mut_write_ctx_set(yyjson_mut_write_ctx *ctx, |
|
9565
|
|
|
|
|
|
|
yyjson_mut_val *ctn, |
|
9566
|
|
|
|
|
|
|
usize size, bool is_obj) { |
|
9567
|
8
|
|
|
|
|
|
ctx->tag = (size << 1) | (usize)is_obj; |
|
9568
|
8
|
|
|
|
|
|
ctx->ctn = ctn; |
|
9569
|
8
|
|
|
|
|
|
} |
|
9570
|
|
|
|
|
|
|
|
|
9571
|
|
|
|
|
|
|
static_inline void yyjson_mut_write_ctx_get(yyjson_mut_write_ctx *ctx, |
|
9572
|
|
|
|
|
|
|
yyjson_mut_val **ctn, |
|
9573
|
|
|
|
|
|
|
usize *size, bool *is_obj) { |
|
9574
|
8
|
|
|
|
|
|
usize tag = ctx->tag; |
|
9575
|
8
|
|
|
|
|
|
*size = tag >> 1; |
|
9576
|
8
|
|
|
|
|
|
*is_obj = (bool)(tag & 1); |
|
9577
|
8
|
|
|
|
|
|
*ctn = ctx->ctn; |
|
9578
|
8
|
|
|
|
|
|
} |
|
9579
|
|
|
|
|
|
|
|
|
9580
|
|
|
|
|
|
|
/** Get the estimated number of values for the mutable JSON document. */ |
|
9581
|
|
|
|
|
|
|
static_inline usize yyjson_mut_doc_estimated_val_num( |
|
9582
|
|
|
|
|
|
|
const yyjson_mut_doc *doc) { |
|
9583
|
15026
|
|
|
|
|
|
usize sum = 0; |
|
9584
|
15026
|
|
|
|
|
|
yyjson_val_chunk *chunk = doc->val_pool.chunks; |
|
9585
|
30053
|
100
|
|
|
|
|
while (chunk) { |
|
9586
|
15027
|
|
|
|
|
|
sum += chunk->chunk_size / sizeof(yyjson_mut_val) - 1; |
|
9587
|
15027
|
100
|
|
|
|
|
if (chunk == doc->val_pool.chunks) { |
|
9588
|
15026
|
|
|
|
|
|
sum -= (usize)(doc->val_pool.end - doc->val_pool.cur); |
|
9589
|
|
|
|
|
|
|
} |
|
9590
|
15027
|
|
|
|
|
|
chunk = chunk->next; |
|
9591
|
|
|
|
|
|
|
} |
|
9592
|
15026
|
|
|
|
|
|
return sum; |
|
9593
|
|
|
|
|
|
|
} |
|
9594
|
|
|
|
|
|
|
|
|
9595
|
|
|
|
|
|
|
/** Write single JSON value. */ |
|
9596
|
|
|
|
|
|
|
static_inline u8 *yyjson_mut_write_single(yyjson_mut_val *val, |
|
9597
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9598
|
|
|
|
|
|
|
yyjson_alc alc, |
|
9599
|
|
|
|
|
|
|
usize *dat_len, |
|
9600
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9601
|
16
|
|
|
|
|
|
return yyjson_write_single((yyjson_val *)val, flg, alc, dat_len, err); |
|
9602
|
|
|
|
|
|
|
} |
|
9603
|
|
|
|
|
|
|
|
|
9604
|
|
|
|
|
|
|
/** Write JSON document minify. |
|
9605
|
|
|
|
|
|
|
The root of this document should be a non-empty container. */ |
|
9606
|
|
|
|
|
|
|
static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, |
|
9607
|
|
|
|
|
|
|
usize estimated_val_num, |
|
9608
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9609
|
|
|
|
|
|
|
yyjson_alc alc, |
|
9610
|
|
|
|
|
|
|
usize *dat_len, |
|
9611
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9612
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
9613
|
|
|
|
|
|
|
*dat_len = 0; \ |
|
9614
|
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_##_code; \ |
|
9615
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
9616
|
|
|
|
|
|
|
if (hdr) alc.free(alc.ctx, hdr); \ |
|
9617
|
|
|
|
|
|
|
return NULL; \ |
|
9618
|
|
|
|
|
|
|
} while (false) |
|
9619
|
|
|
|
|
|
|
|
|
9620
|
|
|
|
|
|
|
#define incr_len(_len) do { \ |
|
9621
|
|
|
|
|
|
|
ext_len = (usize)(_len); \ |
|
9622
|
|
|
|
|
|
|
if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ |
|
9623
|
|
|
|
|
|
|
usize ctx_pos = (usize)((u8 *)ctx - hdr); \ |
|
9624
|
|
|
|
|
|
|
usize cur_pos = (usize)(cur - hdr); \ |
|
9625
|
|
|
|
|
|
|
ctx_len = (usize)(end - (u8 *)ctx); \ |
|
9626
|
|
|
|
|
|
|
alc_inc = yyjson_max(alc_len / 2, ext_len); \ |
|
9627
|
|
|
|
|
|
|
alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \ |
|
9628
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \ |
|
9629
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
9630
|
|
|
|
|
|
|
alc_len += alc_inc; \ |
|
9631
|
|
|
|
|
|
|
tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ |
|
9632
|
|
|
|
|
|
|
if (unlikely(!tmp)) goto fail_alloc; \ |
|
9633
|
|
|
|
|
|
|
ctx_tmp = (yyjson_mut_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ |
|
9634
|
|
|
|
|
|
|
memmove((void *)ctx_tmp, (void *)(tmp + ctx_pos), ctx_len); \ |
|
9635
|
|
|
|
|
|
|
ctx = ctx_tmp; \ |
|
9636
|
|
|
|
|
|
|
cur = tmp + cur_pos; \ |
|
9637
|
|
|
|
|
|
|
end = tmp + alc_len; \ |
|
9638
|
|
|
|
|
|
|
hdr = tmp; \ |
|
9639
|
|
|
|
|
|
|
} \ |
|
9640
|
|
|
|
|
|
|
} while (false) |
|
9641
|
|
|
|
|
|
|
|
|
9642
|
|
|
|
|
|
|
#define check_str_len(_len) do { \ |
|
9643
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ |
|
9644
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
9645
|
|
|
|
|
|
|
} while (false) |
|
9646
|
|
|
|
|
|
|
|
|
9647
|
|
|
|
|
|
|
yyjson_mut_val *val, *ctn; |
|
9648
|
|
|
|
|
|
|
yyjson_type val_type; |
|
9649
|
|
|
|
|
|
|
usize ctn_len, ctn_len_tmp; |
|
9650
|
|
|
|
|
|
|
bool ctn_obj, ctn_obj_tmp, is_key; |
|
9651
|
|
|
|
|
|
|
u8 *hdr, *cur, *end, *tmp; |
|
9652
|
|
|
|
|
|
|
yyjson_mut_write_ctx *ctx, *ctx_tmp; |
|
9653
|
|
|
|
|
|
|
usize alc_len, alc_inc, ctx_len, ext_len, str_len; |
|
9654
|
|
|
|
|
|
|
const u8 *str_ptr; |
|
9655
|
15021
|
|
|
|
|
|
const char_enc_type *enc_table = get_enc_table_with_flag(flg); |
|
9656
|
15021
|
|
|
|
|
|
bool cpy = (enc_table == enc_table_cpy); |
|
9657
|
15021
|
|
|
|
|
|
bool esc = has_flg(ESCAPE_UNICODE) != 0; |
|
9658
|
15021
|
|
|
|
|
|
bool inv = has_allow(INVALID_UNICODE) != 0; |
|
9659
|
15021
|
|
|
|
|
|
bool newline = has_flg(NEWLINE_AT_END) != 0; |
|
9660
|
|
|
|
|
|
|
|
|
9661
|
15021
|
|
|
|
|
|
alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; |
|
9662
|
15021
|
|
|
|
|
|
alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx)); |
|
9663
|
15021
|
|
|
|
|
|
hdr = (u8 *)alc.malloc(alc.ctx, alc_len); |
|
9664
|
15021
|
50
|
|
|
|
|
if (!hdr) goto fail_alloc; |
|
9665
|
15021
|
|
|
|
|
|
cur = hdr; |
|
9666
|
15021
|
|
|
|
|
|
end = hdr + alc_len; |
|
9667
|
15021
|
|
|
|
|
|
ctx = (yyjson_mut_write_ctx *)(void *)end; |
|
9668
|
|
|
|
|
|
|
|
|
9669
|
15021
|
|
|
|
|
|
doc_begin: |
|
9670
|
15021
|
|
|
|
|
|
val = constcast(yyjson_mut_val *)root; |
|
9671
|
15021
|
|
|
|
|
|
val_type = unsafe_yyjson_get_type(val); |
|
9672
|
15021
|
|
|
|
|
|
ctn_obj = (val_type == YYJSON_TYPE_OBJ); |
|
9673
|
15021
|
|
|
|
|
|
ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; |
|
9674
|
15021
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj << 5)); |
|
9675
|
15021
|
|
|
|
|
|
ctn = val; |
|
9676
|
15021
|
|
|
|
|
|
val = (yyjson_mut_val *)val->uni.ptr; /* tail */ |
|
9677
|
15021
|
100
|
|
|
|
|
val = ctn_obj ? val->next->next : val->next; |
|
9678
|
|
|
|
|
|
|
|
|
9679
|
40066
|
|
|
|
|
|
val_begin: |
|
9680
|
55087
|
|
|
|
|
|
val_type = unsafe_yyjson_get_type(val); |
|
9681
|
55087
|
100
|
|
|
|
|
if (val_type == YYJSON_TYPE_STR) { |
|
9682
|
20035
|
|
|
|
|
|
is_key = ((u8)ctn_obj & (u8)~ctn_len); |
|
9683
|
20035
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
9684
|
20035
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
9685
|
|
|
|
|
|
|
check_str_len(str_len); |
|
9686
|
20035
|
50
|
|
|
|
|
incr_len(str_len * 6 + 16); |
|
|
|
0
|
|
|
|
|
|
|
9687
|
40070
|
50
|
|
|
|
|
if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { |
|
|
|
100
|
|
|
|
|
|
|
9688
|
10024
|
|
|
|
|
|
cur = write_str_noesc(cur, str_ptr, str_len); |
|
9689
|
|
|
|
|
|
|
} else { |
|
9690
|
10011
|
|
|
|
|
|
cur = write_str(cur, esc, inv, str_ptr, str_len, enc_table); |
|
9691
|
10011
|
50
|
|
|
|
|
if (unlikely(!cur)) goto fail_str; |
|
9692
|
|
|
|
|
|
|
} |
|
9693
|
20035
|
100
|
|
|
|
|
*cur++ = is_key ? ':' : ','; |
|
9694
|
20035
|
|
|
|
|
|
goto val_end; |
|
9695
|
|
|
|
|
|
|
} |
|
9696
|
35052
|
100
|
|
|
|
|
if (val_type == YYJSON_TYPE_NUM) { |
|
9697
|
35042
|
100
|
|
|
|
|
incr_len(FP_BUF_LEN); |
|
|
|
50
|
|
|
|
|
|
|
9698
|
35040
|
|
|
|
|
|
cur = write_num(cur, (yyjson_val *)val, flg); |
|
9699
|
35040
|
50
|
|
|
|
|
if (unlikely(!cur)) goto fail_num; |
|
9700
|
35040
|
|
|
|
|
|
*cur++ = ','; |
|
9701
|
35040
|
|
|
|
|
|
goto val_end; |
|
9702
|
|
|
|
|
|
|
} |
|
9703
|
12
|
100
|
|
|
|
|
if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == |
|
9704
|
|
|
|
|
|
|
(YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { |
|
9705
|
9
|
|
|
|
|
|
ctn_len_tmp = unsafe_yyjson_get_len(val); |
|
9706
|
9
|
|
|
|
|
|
ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); |
|
9707
|
9
|
50
|
|
|
|
|
incr_len(16); |
|
|
|
0
|
|
|
|
|
|
|
9708
|
9
|
100
|
|
|
|
|
if (unlikely(ctn_len_tmp == 0)) { |
|
9709
|
|
|
|
|
|
|
/* write empty container */ |
|
9710
|
2
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); |
|
9711
|
2
|
|
|
|
|
|
*cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); |
|
9712
|
2
|
|
|
|
|
|
*cur++ = ','; |
|
9713
|
2
|
|
|
|
|
|
goto val_end; |
|
9714
|
|
|
|
|
|
|
} else { |
|
9715
|
|
|
|
|
|
|
/* push context, setup new container */ |
|
9716
|
7
|
|
|
|
|
|
yyjson_mut_write_ctx_set(--ctx, ctn, ctn_len, ctn_obj); |
|
9717
|
7
|
|
|
|
|
|
ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; |
|
9718
|
7
|
|
|
|
|
|
ctn_obj = ctn_obj_tmp; |
|
9719
|
7
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj << 5)); |
|
9720
|
7
|
|
|
|
|
|
ctn = val; |
|
9721
|
7
|
|
|
|
|
|
val = (yyjson_mut_val *)ctn->uni.ptr; /* tail */ |
|
9722
|
7
|
100
|
|
|
|
|
val = ctn_obj ? val->next->next : val->next; |
|
9723
|
7
|
|
|
|
|
|
goto val_begin; |
|
9724
|
|
|
|
|
|
|
} |
|
9725
|
|
|
|
|
|
|
} |
|
9726
|
3
|
100
|
|
|
|
|
if (val_type == YYJSON_TYPE_BOOL) { |
|
9727
|
2
|
50
|
|
|
|
|
incr_len(16); |
|
|
|
0
|
|
|
|
|
|
|
9728
|
2
|
100
|
|
|
|
|
cur = write_bool(cur, unsafe_yyjson_get_bool(val)); |
|
9729
|
2
|
|
|
|
|
|
cur++; |
|
9730
|
2
|
|
|
|
|
|
goto val_end; |
|
9731
|
|
|
|
|
|
|
} |
|
9732
|
1
|
50
|
|
|
|
|
if (val_type == YYJSON_TYPE_NULL) { |
|
9733
|
1
|
50
|
|
|
|
|
incr_len(16); |
|
|
|
0
|
|
|
|
|
|
|
9734
|
1
|
|
|
|
|
|
cur = write_null(cur); |
|
9735
|
1
|
|
|
|
|
|
cur++; |
|
9736
|
1
|
|
|
|
|
|
goto val_end; |
|
9737
|
|
|
|
|
|
|
} |
|
9738
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_RAW) { |
|
9739
|
0
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
9740
|
0
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
9741
|
|
|
|
|
|
|
check_str_len(str_len); |
|
9742
|
0
|
0
|
|
|
|
|
incr_len(str_len + 2); |
|
|
|
0
|
|
|
|
|
|
|
9743
|
0
|
|
|
|
|
|
cur = write_raw(cur, str_ptr, str_len); |
|
9744
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9745
|
0
|
|
|
|
|
|
goto val_end; |
|
9746
|
|
|
|
|
|
|
} |
|
9747
|
0
|
|
|
|
|
|
goto fail_type; |
|
9748
|
|
|
|
|
|
|
|
|
9749
|
55080
|
|
|
|
|
|
val_end: |
|
9750
|
55080
|
|
|
|
|
|
ctn_len--; |
|
9751
|
55080
|
100
|
|
|
|
|
if (unlikely(ctn_len == 0)) goto ctn_end; |
|
9752
|
40059
|
|
|
|
|
|
val = val->next; |
|
9753
|
40059
|
|
|
|
|
|
goto val_begin; |
|
9754
|
|
|
|
|
|
|
|
|
9755
|
15028
|
|
|
|
|
|
ctn_end: |
|
9756
|
15028
|
|
|
|
|
|
cur--; |
|
9757
|
15028
|
|
|
|
|
|
*cur++ = (u8)(']' | ((u8)ctn_obj << 5)); |
|
9758
|
15028
|
|
|
|
|
|
*cur++ = ','; |
|
9759
|
15028
|
100
|
|
|
|
|
if (unlikely((u8 *)ctx >= end)) goto doc_end; |
|
9760
|
7
|
|
|
|
|
|
val = ctn->next; |
|
9761
|
7
|
|
|
|
|
|
yyjson_mut_write_ctx_get(ctx++, &ctn, &ctn_len, &ctn_obj); |
|
9762
|
7
|
|
|
|
|
|
ctn_len--; |
|
9763
|
7
|
50
|
|
|
|
|
if (likely(ctn_len > 0)) { |
|
9764
|
0
|
|
|
|
|
|
goto val_begin; |
|
9765
|
|
|
|
|
|
|
} else { |
|
9766
|
7
|
|
|
|
|
|
goto ctn_end; |
|
9767
|
|
|
|
|
|
|
} |
|
9768
|
|
|
|
|
|
|
|
|
9769
|
15021
|
|
|
|
|
|
doc_end: |
|
9770
|
15021
|
50
|
|
|
|
|
if (newline) { |
|
9771
|
0
|
0
|
|
|
|
|
incr_len(2); |
|
|
|
0
|
|
|
|
|
|
|
9772
|
0
|
|
|
|
|
|
*(cur - 1) = '\n'; |
|
9773
|
0
|
|
|
|
|
|
cur++; |
|
9774
|
|
|
|
|
|
|
} |
|
9775
|
15021
|
|
|
|
|
|
*--cur = '\0'; |
|
9776
|
15021
|
|
|
|
|
|
*dat_len = (usize)(cur - hdr); |
|
9777
|
15021
|
|
|
|
|
|
err->code = YYJSON_WRITE_SUCCESS; |
|
9778
|
15021
|
|
|
|
|
|
err->msg = NULL; |
|
9779
|
15021
|
|
|
|
|
|
return hdr; |
|
9780
|
|
|
|
|
|
|
|
|
9781
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
9782
|
0
|
0
|
|
|
|
|
fail_type: return_err(INVALID_VALUE_TYPE, MSG_ERR_TYPE); |
|
9783
|
0
|
0
|
|
|
|
|
fail_num: return_err(NAN_OR_INF, MSG_NAN_INF); |
|
9784
|
0
|
0
|
|
|
|
|
fail_str: return_err(INVALID_STRING, MSG_ERR_UTF8); |
|
9785
|
|
|
|
|
|
|
|
|
9786
|
|
|
|
|
|
|
#undef return_err |
|
9787
|
|
|
|
|
|
|
#undef incr_len |
|
9788
|
|
|
|
|
|
|
#undef check_str_len |
|
9789
|
|
|
|
|
|
|
} |
|
9790
|
|
|
|
|
|
|
|
|
9791
|
|
|
|
|
|
|
/** Write JSON document pretty. |
|
9792
|
|
|
|
|
|
|
The root of this document should be a non-empty container. */ |
|
9793
|
|
|
|
|
|
|
static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, |
|
9794
|
|
|
|
|
|
|
usize estimated_val_num, |
|
9795
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
9796
|
|
|
|
|
|
|
yyjson_alc alc, |
|
9797
|
|
|
|
|
|
|
usize *dat_len, |
|
9798
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
9799
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
9800
|
|
|
|
|
|
|
*dat_len = 0; \ |
|
9801
|
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_##_code; \ |
|
9802
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
9803
|
|
|
|
|
|
|
if (hdr) alc.free(alc.ctx, hdr); \ |
|
9804
|
|
|
|
|
|
|
return NULL; \ |
|
9805
|
|
|
|
|
|
|
} while (false) |
|
9806
|
|
|
|
|
|
|
|
|
9807
|
|
|
|
|
|
|
#define incr_len(_len) do { \ |
|
9808
|
|
|
|
|
|
|
ext_len = (usize)(_len); \ |
|
9809
|
|
|
|
|
|
|
if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ |
|
9810
|
|
|
|
|
|
|
usize ctx_pos = (usize)((u8 *)ctx - hdr); \ |
|
9811
|
|
|
|
|
|
|
usize cur_pos = (usize)(cur - hdr); \ |
|
9812
|
|
|
|
|
|
|
ctx_len = (usize)(end - (u8 *)ctx); \ |
|
9813
|
|
|
|
|
|
|
alc_inc = yyjson_max(alc_len / 2, ext_len); \ |
|
9814
|
|
|
|
|
|
|
alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \ |
|
9815
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \ |
|
9816
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
9817
|
|
|
|
|
|
|
alc_len += alc_inc; \ |
|
9818
|
|
|
|
|
|
|
tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ |
|
9819
|
|
|
|
|
|
|
if (unlikely(!tmp)) goto fail_alloc; \ |
|
9820
|
|
|
|
|
|
|
ctx_tmp = (yyjson_mut_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ |
|
9821
|
|
|
|
|
|
|
memmove((void *)ctx_tmp, (void *)(tmp + ctx_pos), ctx_len); \ |
|
9822
|
|
|
|
|
|
|
ctx = ctx_tmp; \ |
|
9823
|
|
|
|
|
|
|
cur = tmp + cur_pos; \ |
|
9824
|
|
|
|
|
|
|
end = tmp + alc_len; \ |
|
9825
|
|
|
|
|
|
|
hdr = tmp; \ |
|
9826
|
|
|
|
|
|
|
} \ |
|
9827
|
|
|
|
|
|
|
} while (false) |
|
9828
|
|
|
|
|
|
|
|
|
9829
|
|
|
|
|
|
|
#define check_str_len(_len) do { \ |
|
9830
|
|
|
|
|
|
|
if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ |
|
9831
|
|
|
|
|
|
|
goto fail_alloc; \ |
|
9832
|
|
|
|
|
|
|
} while (false) |
|
9833
|
|
|
|
|
|
|
|
|
9834
|
|
|
|
|
|
|
yyjson_mut_val *val, *ctn; |
|
9835
|
|
|
|
|
|
|
yyjson_type val_type; |
|
9836
|
|
|
|
|
|
|
usize ctn_len, ctn_len_tmp; |
|
9837
|
|
|
|
|
|
|
bool ctn_obj, ctn_obj_tmp, is_key, no_indent; |
|
9838
|
|
|
|
|
|
|
u8 *hdr, *cur, *end, *tmp; |
|
9839
|
|
|
|
|
|
|
yyjson_mut_write_ctx *ctx, *ctx_tmp; |
|
9840
|
|
|
|
|
|
|
usize alc_len, alc_inc, ctx_len, ext_len, str_len, level; |
|
9841
|
|
|
|
|
|
|
const u8 *str_ptr; |
|
9842
|
9
|
|
|
|
|
|
const char_enc_type *enc_table = get_enc_table_with_flag(flg); |
|
9843
|
9
|
|
|
|
|
|
bool cpy = (enc_table == enc_table_cpy); |
|
9844
|
9
|
|
|
|
|
|
bool esc = has_flg(ESCAPE_UNICODE) != 0; |
|
9845
|
9
|
|
|
|
|
|
bool inv = has_allow(INVALID_UNICODE) != 0; |
|
9846
|
18
|
50
|
|
|
|
|
usize spaces = has_flg(PRETTY_TWO_SPACES) ? 2 : 4; |
|
9847
|
9
|
|
|
|
|
|
bool newline = has_flg(NEWLINE_AT_END) != 0; |
|
9848
|
|
|
|
|
|
|
|
|
9849
|
9
|
|
|
|
|
|
alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; |
|
9850
|
9
|
|
|
|
|
|
alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx)); |
|
9851
|
9
|
|
|
|
|
|
hdr = (u8 *)alc.malloc(alc.ctx, alc_len); |
|
9852
|
9
|
50
|
|
|
|
|
if (!hdr) goto fail_alloc; |
|
9853
|
9
|
|
|
|
|
|
cur = hdr; |
|
9854
|
9
|
|
|
|
|
|
end = hdr + alc_len; |
|
9855
|
9
|
|
|
|
|
|
ctx = (yyjson_mut_write_ctx *)(void *)end; |
|
9856
|
|
|
|
|
|
|
|
|
9857
|
9
|
|
|
|
|
|
doc_begin: |
|
9858
|
9
|
|
|
|
|
|
val = constcast(yyjson_mut_val *)root; |
|
9859
|
9
|
|
|
|
|
|
val_type = unsafe_yyjson_get_type(val); |
|
9860
|
9
|
|
|
|
|
|
ctn_obj = (val_type == YYJSON_TYPE_OBJ); |
|
9861
|
9
|
|
|
|
|
|
ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; |
|
9862
|
9
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj << 5)); |
|
9863
|
9
|
|
|
|
|
|
*cur++ = '\n'; |
|
9864
|
9
|
|
|
|
|
|
ctn = val; |
|
9865
|
9
|
|
|
|
|
|
val = (yyjson_mut_val *)val->uni.ptr; /* tail */ |
|
9866
|
9
|
50
|
|
|
|
|
val = ctn_obj ? val->next->next : val->next; |
|
9867
|
9
|
|
|
|
|
|
level = 1; |
|
9868
|
|
|
|
|
|
|
|
|
9869
|
13
|
|
|
|
|
|
val_begin: |
|
9870
|
22
|
|
|
|
|
|
val_type = unsafe_yyjson_get_type(val); |
|
9871
|
22
|
100
|
|
|
|
|
if (val_type == YYJSON_TYPE_STR) { |
|
9872
|
11
|
|
|
|
|
|
is_key = (bool)((u8)ctn_obj & (u8)~ctn_len); |
|
9873
|
11
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9874
|
11
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
9875
|
11
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
9876
|
|
|
|
|
|
|
check_str_len(str_len); |
|
9877
|
11
|
100
|
|
|
|
|
incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4)); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9878
|
11
|
100
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9879
|
22
|
50
|
|
|
|
|
if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { |
|
|
|
100
|
|
|
|
|
|
|
9880
|
6
|
|
|
|
|
|
cur = write_str_noesc(cur, str_ptr, str_len); |
|
9881
|
|
|
|
|
|
|
} else { |
|
9882
|
5
|
|
|
|
|
|
cur = write_str(cur, esc, inv, str_ptr, str_len, enc_table); |
|
9883
|
5
|
50
|
|
|
|
|
if (unlikely(!cur)) goto fail_str; |
|
9884
|
|
|
|
|
|
|
} |
|
9885
|
11
|
100
|
|
|
|
|
*cur++ = is_key ? ':' : ','; |
|
9886
|
11
|
100
|
|
|
|
|
*cur++ = is_key ? ' ' : '\n'; |
|
9887
|
11
|
|
|
|
|
|
goto val_end; |
|
9888
|
|
|
|
|
|
|
} |
|
9889
|
11
|
100
|
|
|
|
|
if (val_type == YYJSON_TYPE_NUM) { |
|
9890
|
8
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9891
|
8
|
50
|
|
|
|
|
incr_len(FP_BUF_LEN + (no_indent ? 0 : level * 4)); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9892
|
16
|
50
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
|
|
50
|
|
|
|
|
|
|
9893
|
8
|
|
|
|
|
|
cur = write_num(cur, (yyjson_val *)val, flg); |
|
9894
|
8
|
50
|
|
|
|
|
if (unlikely(!cur)) goto fail_num; |
|
9895
|
8
|
|
|
|
|
|
*cur++ = ','; |
|
9896
|
8
|
|
|
|
|
|
*cur++ = '\n'; |
|
9897
|
8
|
|
|
|
|
|
goto val_end; |
|
9898
|
|
|
|
|
|
|
} |
|
9899
|
3
|
100
|
|
|
|
|
if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == |
|
9900
|
|
|
|
|
|
|
(YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { |
|
9901
|
1
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9902
|
1
|
|
|
|
|
|
ctn_len_tmp = unsafe_yyjson_get_len(val); |
|
9903
|
1
|
|
|
|
|
|
ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); |
|
9904
|
1
|
50
|
|
|
|
|
if (unlikely(ctn_len_tmp == 0)) { |
|
9905
|
|
|
|
|
|
|
/* write empty container */ |
|
9906
|
0
|
0
|
|
|
|
|
incr_len(16 + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9907
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9908
|
0
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); |
|
9909
|
0
|
|
|
|
|
|
*cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); |
|
9910
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9911
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9912
|
0
|
|
|
|
|
|
goto val_end; |
|
9913
|
|
|
|
|
|
|
} else { |
|
9914
|
|
|
|
|
|
|
/* push context, setup new container */ |
|
9915
|
1
|
50
|
|
|
|
|
incr_len(32 + (no_indent ? 0 : level * 4)); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9916
|
1
|
|
|
|
|
|
yyjson_mut_write_ctx_set(--ctx, ctn, ctn_len, ctn_obj); |
|
9917
|
1
|
|
|
|
|
|
ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; |
|
9918
|
1
|
|
|
|
|
|
ctn_obj = ctn_obj_tmp; |
|
9919
|
1
|
50
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9920
|
1
|
|
|
|
|
|
level++; |
|
9921
|
1
|
|
|
|
|
|
*cur++ = (u8)('[' | ((u8)ctn_obj << 5)); |
|
9922
|
1
|
|
|
|
|
|
*cur++ = '\n'; |
|
9923
|
1
|
|
|
|
|
|
ctn = val; |
|
9924
|
1
|
|
|
|
|
|
val = (yyjson_mut_val *)ctn->uni.ptr; /* tail */ |
|
9925
|
1
|
50
|
|
|
|
|
val = ctn_obj ? val->next->next : val->next; |
|
9926
|
1
|
|
|
|
|
|
goto val_begin; |
|
9927
|
|
|
|
|
|
|
} |
|
9928
|
|
|
|
|
|
|
} |
|
9929
|
2
|
100
|
|
|
|
|
if (val_type == YYJSON_TYPE_BOOL) { |
|
9930
|
1
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9931
|
2
|
50
|
|
|
|
|
incr_len(16 + (no_indent ? 0 : level * 4)); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
9932
|
2
|
50
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9933
|
1
|
50
|
|
|
|
|
cur = write_bool(cur, unsafe_yyjson_get_bool(val)); |
|
9934
|
1
|
|
|
|
|
|
cur += 2; |
|
9935
|
1
|
|
|
|
|
|
goto val_end; |
|
9936
|
|
|
|
|
|
|
} |
|
9937
|
1
|
50
|
|
|
|
|
if (val_type == YYJSON_TYPE_NULL) { |
|
9938
|
1
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9939
|
1
|
50
|
|
|
|
|
incr_len(16 + (no_indent ? 0 : level * 4)); |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9940
|
2
|
50
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9941
|
1
|
|
|
|
|
|
cur = write_null(cur); |
|
9942
|
1
|
|
|
|
|
|
cur += 2; |
|
9943
|
1
|
|
|
|
|
|
goto val_end; |
|
9944
|
|
|
|
|
|
|
} |
|
9945
|
0
|
0
|
|
|
|
|
if (val_type == YYJSON_TYPE_RAW) { |
|
9946
|
0
|
|
|
|
|
|
no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); |
|
9947
|
0
|
|
|
|
|
|
str_len = unsafe_yyjson_get_len(val); |
|
9948
|
0
|
|
|
|
|
|
str_ptr = (const u8 *)unsafe_yyjson_get_str(val); |
|
9949
|
|
|
|
|
|
|
check_str_len(str_len); |
|
9950
|
0
|
0
|
|
|
|
|
incr_len(str_len + 3 + (no_indent ? 0 : level * 4)); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
9951
|
0
|
0
|
|
|
|
|
cur = write_indent(cur, no_indent ? 0 : level, spaces); |
|
9952
|
0
|
|
|
|
|
|
cur = write_raw(cur, str_ptr, str_len); |
|
9953
|
0
|
|
|
|
|
|
*cur++ = ','; |
|
9954
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9955
|
0
|
|
|
|
|
|
goto val_end; |
|
9956
|
|
|
|
|
|
|
} |
|
9957
|
0
|
|
|
|
|
|
goto fail_type; |
|
9958
|
|
|
|
|
|
|
|
|
9959
|
21
|
|
|
|
|
|
val_end: |
|
9960
|
21
|
|
|
|
|
|
ctn_len--; |
|
9961
|
21
|
100
|
|
|
|
|
if (unlikely(ctn_len == 0)) goto ctn_end; |
|
9962
|
12
|
|
|
|
|
|
val = val->next; |
|
9963
|
12
|
|
|
|
|
|
goto val_begin; |
|
9964
|
|
|
|
|
|
|
|
|
9965
|
10
|
|
|
|
|
|
ctn_end: |
|
9966
|
10
|
|
|
|
|
|
cur -= 2; |
|
9967
|
10
|
|
|
|
|
|
*cur++ = '\n'; |
|
9968
|
10
|
50
|
|
|
|
|
incr_len(level * 4); |
|
|
|
0
|
|
|
|
|
|
|
9969
|
10
|
|
|
|
|
|
cur = write_indent(cur, --level, spaces); |
|
9970
|
10
|
|
|
|
|
|
*cur++ = (u8)(']' | ((u8)ctn_obj << 5)); |
|
9971
|
10
|
100
|
|
|
|
|
if (unlikely((u8 *)ctx >= end)) goto doc_end; |
|
9972
|
1
|
|
|
|
|
|
val = ctn->next; |
|
9973
|
1
|
|
|
|
|
|
yyjson_mut_write_ctx_get(ctx++, &ctn, &ctn_len, &ctn_obj); |
|
9974
|
1
|
|
|
|
|
|
ctn_len--; |
|
9975
|
1
|
|
|
|
|
|
*cur++ = ','; |
|
9976
|
1
|
|
|
|
|
|
*cur++ = '\n'; |
|
9977
|
1
|
50
|
|
|
|
|
if (likely(ctn_len > 0)) { |
|
9978
|
0
|
|
|
|
|
|
goto val_begin; |
|
9979
|
|
|
|
|
|
|
} else { |
|
9980
|
1
|
|
|
|
|
|
goto ctn_end; |
|
9981
|
|
|
|
|
|
|
} |
|
9982
|
|
|
|
|
|
|
|
|
9983
|
9
|
|
|
|
|
|
doc_end: |
|
9984
|
9
|
50
|
|
|
|
|
if (newline) { |
|
9985
|
0
|
0
|
|
|
|
|
incr_len(2); |
|
|
|
0
|
|
|
|
|
|
|
9986
|
0
|
|
|
|
|
|
*cur++ = '\n'; |
|
9987
|
|
|
|
|
|
|
} |
|
9988
|
9
|
|
|
|
|
|
*cur = '\0'; |
|
9989
|
9
|
|
|
|
|
|
*dat_len = (usize)(cur - hdr); |
|
9990
|
9
|
|
|
|
|
|
err->code = YYJSON_WRITE_SUCCESS; |
|
9991
|
9
|
|
|
|
|
|
err->msg = NULL; |
|
9992
|
9
|
|
|
|
|
|
return hdr; |
|
9993
|
|
|
|
|
|
|
|
|
9994
|
0
|
0
|
|
|
|
|
fail_alloc: return_err(MEMORY_ALLOCATION, MSG_MALLOC); |
|
9995
|
0
|
0
|
|
|
|
|
fail_type: return_err(INVALID_VALUE_TYPE, MSG_ERR_TYPE); |
|
9996
|
0
|
0
|
|
|
|
|
fail_num: return_err(NAN_OR_INF, MSG_NAN_INF); |
|
9997
|
0
|
0
|
|
|
|
|
fail_str: return_err(INVALID_STRING, MSG_ERR_UTF8); |
|
9998
|
|
|
|
|
|
|
|
|
9999
|
|
|
|
|
|
|
#undef return_err |
|
10000
|
|
|
|
|
|
|
#undef incr_len |
|
10001
|
|
|
|
|
|
|
#undef check_str_len |
|
10002
|
|
|
|
|
|
|
} |
|
10003
|
|
|
|
|
|
|
|
|
10004
|
15046
|
|
|
|
|
|
static char *yyjson_mut_write_opts_impl(const yyjson_mut_val *val, |
|
10005
|
|
|
|
|
|
|
usize estimated_val_num, |
|
10006
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
10007
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
10008
|
|
|
|
|
|
|
usize *dat_len, |
|
10009
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
10010
|
|
|
|
|
|
|
yyjson_write_err tmp_err; |
|
10011
|
|
|
|
|
|
|
usize tmp_dat_len; |
|
10012
|
15046
|
100
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
10013
|
15046
|
|
|
|
|
|
yyjson_mut_val *root = constcast(yyjson_mut_val *)val; |
|
10014
|
|
|
|
|
|
|
|
|
10015
|
15046
|
50
|
|
|
|
|
if (!err) err = &tmp_err; |
|
10016
|
15046
|
50
|
|
|
|
|
if (!dat_len) dat_len = &tmp_dat_len; |
|
10017
|
|
|
|
|
|
|
|
|
10018
|
15046
|
50
|
|
|
|
|
if (unlikely(!root)) { |
|
10019
|
0
|
|
|
|
|
|
*dat_len = 0; |
|
10020
|
0
|
|
|
|
|
|
err->msg = "input JSON is NULL"; |
|
10021
|
0
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; |
|
10022
|
0
|
|
|
|
|
|
return NULL; |
|
10023
|
|
|
|
|
|
|
} |
|
10024
|
|
|
|
|
|
|
|
|
10025
|
30078
|
100
|
|
|
|
|
if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) { |
|
|
|
100
|
|
|
|
|
|
|
10026
|
16
|
|
|
|
|
|
return (char *)yyjson_mut_write_single(root, flg, alc, dat_len, err); |
|
10027
|
15030
|
100
|
|
|
|
|
} else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) { |
|
10028
|
9
|
|
|
|
|
|
return (char *)yyjson_mut_write_pretty(root, estimated_val_num, |
|
10029
|
|
|
|
|
|
|
flg, alc, dat_len, err); |
|
10030
|
|
|
|
|
|
|
} else { |
|
10031
|
15021
|
|
|
|
|
|
return (char *)yyjson_mut_write_minify(root, estimated_val_num, |
|
10032
|
|
|
|
|
|
|
flg, alc, dat_len, err); |
|
10033
|
|
|
|
|
|
|
} |
|
10034
|
|
|
|
|
|
|
} |
|
10035
|
|
|
|
|
|
|
|
|
10036
|
|
|
|
|
|
|
|
|
10037
|
|
|
|
|
|
|
|
|
10038
|
|
|
|
|
|
|
/*============================================================================== |
|
10039
|
|
|
|
|
|
|
* MARK: - Mutable JSON Writer (Public) |
|
10040
|
|
|
|
|
|
|
*============================================================================*/ |
|
10041
|
|
|
|
|
|
|
|
|
10042
|
20
|
|
|
|
|
|
char *yyjson_mut_val_write_opts(const yyjson_mut_val *val, |
|
10043
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
10044
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
10045
|
|
|
|
|
|
|
usize *dat_len, |
|
10046
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
10047
|
20
|
|
|
|
|
|
return yyjson_mut_write_opts_impl(val, 0, flg, alc_ptr, dat_len, err); |
|
10048
|
|
|
|
|
|
|
} |
|
10049
|
|
|
|
|
|
|
|
|
10050
|
15026
|
|
|
|
|
|
char *yyjson_mut_write_opts(const yyjson_mut_doc *doc, |
|
10051
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
10052
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
10053
|
|
|
|
|
|
|
usize *dat_len, |
|
10054
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
10055
|
|
|
|
|
|
|
yyjson_mut_val *root; |
|
10056
|
|
|
|
|
|
|
usize estimated_val_num; |
|
10057
|
15026
|
50
|
|
|
|
|
if (likely(doc)) { |
|
10058
|
15026
|
|
|
|
|
|
root = doc->root; |
|
10059
|
15026
|
|
|
|
|
|
estimated_val_num = yyjson_mut_doc_estimated_val_num(doc); |
|
10060
|
|
|
|
|
|
|
} else { |
|
10061
|
0
|
|
|
|
|
|
root = NULL; |
|
10062
|
0
|
|
|
|
|
|
estimated_val_num = 0; |
|
10063
|
|
|
|
|
|
|
} |
|
10064
|
15026
|
|
|
|
|
|
return yyjson_mut_write_opts_impl(root, estimated_val_num, |
|
10065
|
|
|
|
|
|
|
flg, alc_ptr, dat_len, err); |
|
10066
|
|
|
|
|
|
|
} |
|
10067
|
|
|
|
|
|
|
|
|
10068
|
3
|
|
|
|
|
|
bool yyjson_mut_val_write_file(const char *path, |
|
10069
|
|
|
|
|
|
|
const yyjson_mut_val *val, |
|
10070
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
10071
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
10072
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
10073
|
|
|
|
|
|
|
yyjson_write_err tmp_err; |
|
10074
|
3
|
50
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
10075
|
|
|
|
|
|
|
u8 *dat; |
|
10076
|
3
|
|
|
|
|
|
usize dat_len = 0; |
|
10077
|
3
|
|
|
|
|
|
yyjson_mut_val *root = constcast(yyjson_mut_val *)val; |
|
10078
|
|
|
|
|
|
|
bool suc; |
|
10079
|
|
|
|
|
|
|
|
|
10080
|
3
|
50
|
|
|
|
|
if (!err) err = &tmp_err; |
|
10081
|
3
|
50
|
|
|
|
|
if (unlikely(!path || !*path)) { |
|
|
|
50
|
|
|
|
|
|
|
10082
|
0
|
|
|
|
|
|
err->msg = "input path is invalid"; |
|
10083
|
0
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; |
|
10084
|
0
|
|
|
|
|
|
return false; |
|
10085
|
|
|
|
|
|
|
} |
|
10086
|
|
|
|
|
|
|
|
|
10087
|
3
|
|
|
|
|
|
dat = (u8 *)yyjson_mut_val_write_opts(root, flg, &alc, &dat_len, err); |
|
10088
|
3
|
50
|
|
|
|
|
if (unlikely(!dat)) return false; |
|
10089
|
3
|
|
|
|
|
|
suc = write_dat_to_file(path, dat, dat_len, err); |
|
10090
|
3
|
|
|
|
|
|
alc.free(alc.ctx, dat); |
|
10091
|
3
|
|
|
|
|
|
return suc; |
|
10092
|
|
|
|
|
|
|
} |
|
10093
|
|
|
|
|
|
|
|
|
10094
|
0
|
|
|
|
|
|
bool yyjson_mut_val_write_fp(FILE *fp, |
|
10095
|
|
|
|
|
|
|
const yyjson_mut_val *val, |
|
10096
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
10097
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
10098
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
10099
|
|
|
|
|
|
|
yyjson_write_err tmp_err; |
|
10100
|
0
|
0
|
|
|
|
|
yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; |
|
10101
|
|
|
|
|
|
|
u8 *dat; |
|
10102
|
0
|
|
|
|
|
|
usize dat_len = 0; |
|
10103
|
0
|
|
|
|
|
|
yyjson_mut_val *root = constcast(yyjson_mut_val *)val; |
|
10104
|
|
|
|
|
|
|
bool suc; |
|
10105
|
|
|
|
|
|
|
|
|
10106
|
0
|
0
|
|
|
|
|
if (!err) err = &tmp_err; |
|
10107
|
0
|
0
|
|
|
|
|
if (unlikely(!fp)) { |
|
10108
|
0
|
|
|
|
|
|
err->msg = "input fp is invalid"; |
|
10109
|
0
|
|
|
|
|
|
err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; |
|
10110
|
0
|
|
|
|
|
|
return false; |
|
10111
|
|
|
|
|
|
|
} |
|
10112
|
|
|
|
|
|
|
|
|
10113
|
0
|
|
|
|
|
|
dat = (u8 *)yyjson_mut_val_write_opts(root, flg, &alc, &dat_len, err); |
|
10114
|
0
|
0
|
|
|
|
|
if (unlikely(!dat)) return false; |
|
10115
|
0
|
|
|
|
|
|
suc = write_dat_to_fp(fp, dat, dat_len, err); |
|
10116
|
0
|
|
|
|
|
|
alc.free(alc.ctx, dat); |
|
10117
|
0
|
|
|
|
|
|
return suc; |
|
10118
|
|
|
|
|
|
|
} |
|
10119
|
|
|
|
|
|
|
|
|
10120
|
3
|
|
|
|
|
|
bool yyjson_mut_write_file(const char *path, |
|
10121
|
|
|
|
|
|
|
const yyjson_mut_doc *doc, |
|
10122
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
10123
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
10124
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
10125
|
3
|
50
|
|
|
|
|
yyjson_mut_val *root = doc ? doc->root : NULL; |
|
10126
|
3
|
|
|
|
|
|
return yyjson_mut_val_write_file(path, root, flg, alc_ptr, err); |
|
10127
|
|
|
|
|
|
|
} |
|
10128
|
|
|
|
|
|
|
|
|
10129
|
0
|
|
|
|
|
|
bool yyjson_mut_write_fp(FILE *fp, |
|
10130
|
|
|
|
|
|
|
const yyjson_mut_doc *doc, |
|
10131
|
|
|
|
|
|
|
yyjson_write_flag flg, |
|
10132
|
|
|
|
|
|
|
const yyjson_alc *alc_ptr, |
|
10133
|
|
|
|
|
|
|
yyjson_write_err *err) { |
|
10134
|
0
|
0
|
|
|
|
|
yyjson_mut_val *root = doc ? doc->root : NULL; |
|
10135
|
0
|
|
|
|
|
|
return yyjson_mut_val_write_fp(fp, root, flg, alc_ptr, err); |
|
10136
|
|
|
|
|
|
|
} |
|
10137
|
|
|
|
|
|
|
|
|
10138
|
|
|
|
|
|
|
#undef has_flg |
|
10139
|
|
|
|
|
|
|
#undef has_allow |
|
10140
|
|
|
|
|
|
|
#endif /* YYJSON_DISABLE_WRITER */ |
|
10141
|
|
|
|
|
|
|
|
|
10142
|
|
|
|
|
|
|
|
|
10143
|
|
|
|
|
|
|
|
|
10144
|
|
|
|
|
|
|
#if !YYJSON_DISABLE_UTILS |
|
10145
|
|
|
|
|
|
|
|
|
10146
|
|
|
|
|
|
|
/*============================================================================== |
|
10147
|
|
|
|
|
|
|
* MARK: - JSON Pointer API (RFC 6901) (Public) |
|
10148
|
|
|
|
|
|
|
*============================================================================*/ |
|
10149
|
|
|
|
|
|
|
|
|
10150
|
|
|
|
|
|
|
/** |
|
10151
|
|
|
|
|
|
|
Get a token from JSON pointer string. |
|
10152
|
|
|
|
|
|
|
@param ptr [in] string that points to current token prefix `/` |
|
10153
|
|
|
|
|
|
|
[out] string that points to next token prefix `/`, or string end |
|
10154
|
|
|
|
|
|
|
@param end [in] end of the entire JSON Pointer string |
|
10155
|
|
|
|
|
|
|
@param len [out] unescaped token length |
|
10156
|
|
|
|
|
|
|
@param esc [out] number of escaped characters in this token |
|
10157
|
|
|
|
|
|
|
@return head of the token, or NULL if syntax error |
|
10158
|
|
|
|
|
|
|
*/ |
|
10159
|
|
|
|
|
|
|
static_inline const char *ptr_next_token(const char **ptr, const char *end, |
|
10160
|
|
|
|
|
|
|
usize *len, usize *esc) { |
|
10161
|
15294
|
|
|
|
|
|
const char *hdr = *ptr + 1; |
|
10162
|
15294
|
|
|
|
|
|
const char *cur = hdr; |
|
10163
|
|
|
|
|
|
|
/* skip unescaped characters */ |
|
10164
|
30821
|
100
|
|
|
|
|
while (cur < end && *cur != '/' && *cur != '~') cur++; |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10165
|
15294
|
100
|
|
|
|
|
if (likely(cur == end || *cur != '~')) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10166
|
|
|
|
|
|
|
/* no escaped characters, return */ |
|
10167
|
15294
|
|
|
|
|
|
*ptr = cur; |
|
10168
|
15294
|
|
|
|
|
|
*len = (usize)(cur - hdr); |
|
10169
|
15294
|
|
|
|
|
|
*esc = 0; |
|
10170
|
15294
|
|
|
|
|
|
return hdr; |
|
10171
|
|
|
|
|
|
|
} else { |
|
10172
|
|
|
|
|
|
|
/* handle escaped characters */ |
|
10173
|
0
|
|
|
|
|
|
usize esc_num = 0; |
|
10174
|
0
|
0
|
|
|
|
|
while (cur < end && *cur != '/') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10175
|
0
|
0
|
|
|
|
|
if (*cur++ == '~') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10176
|
0
|
0
|
|
|
|
|
if (cur == end || (*cur != '0' && *cur != '1')) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10177
|
0
|
|
|
|
|
|
*ptr = cur - 1; |
|
10178
|
0
|
|
|
|
|
|
return NULL; |
|
10179
|
|
|
|
|
|
|
} |
|
10180
|
0
|
|
|
|
|
|
esc_num++; |
|
10181
|
|
|
|
|
|
|
} |
|
10182
|
|
|
|
|
|
|
} |
|
10183
|
0
|
|
|
|
|
|
*ptr = cur; |
|
10184
|
0
|
|
|
|
|
|
*len = (usize)(cur - hdr) - esc_num; |
|
10185
|
0
|
|
|
|
|
|
*esc = esc_num; |
|
10186
|
0
|
|
|
|
|
|
return hdr; |
|
10187
|
|
|
|
|
|
|
} |
|
10188
|
|
|
|
|
|
|
} |
|
10189
|
|
|
|
|
|
|
|
|
10190
|
|
|
|
|
|
|
/** |
|
10191
|
|
|
|
|
|
|
Convert token string to index. |
|
10192
|
|
|
|
|
|
|
@param cur [in] token head |
|
10193
|
|
|
|
|
|
|
@param len [in] token length |
|
10194
|
|
|
|
|
|
|
@param idx [out] the index number, or USIZE_MAX if token is '-' |
|
10195
|
|
|
|
|
|
|
@return true if token is a valid array index |
|
10196
|
|
|
|
|
|
|
*/ |
|
10197
|
|
|
|
|
|
|
static_inline bool ptr_token_to_idx(const char *cur, usize len, usize *idx) { |
|
10198
|
118
|
|
|
|
|
|
const char *end = cur + len; |
|
10199
|
118
|
|
|
|
|
|
usize num = 0, add; |
|
10200
|
118
|
50
|
|
|
|
|
if (unlikely(len == 0 || len > USIZE_SAFE_DIG)) return false; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10201
|
118
|
100
|
|
|
|
|
if (*cur == '0') { |
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10202
|
104
|
50
|
|
|
|
|
if (unlikely(len > 1)) return false; |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10203
|
104
|
|
|
|
|
|
*idx = 0; |
|
10204
|
104
|
|
|
|
|
|
return true; |
|
10205
|
|
|
|
|
|
|
} |
|
10206
|
14
|
100
|
|
|
|
|
if (*cur == '-') { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10207
|
8
|
50
|
|
|
|
|
if (unlikely(len > 1)) return false; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10208
|
8
|
|
|
|
|
|
*idx = USIZE_MAX; |
|
10209
|
8
|
|
|
|
|
|
return true; |
|
10210
|
|
|
|
|
|
|
} |
|
10211
|
15
|
100
|
|
|
|
|
for (; cur < end && (add = (usize)((u8)*cur - (u8)'0')) <= 9; cur++) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10212
|
9
|
|
|
|
|
|
num = num * 10 + add; |
|
10213
|
|
|
|
|
|
|
} |
|
10214
|
6
|
50
|
|
|
|
|
if (unlikely(num == 0 || cur < end)) return false; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10215
|
6
|
|
|
|
|
|
*idx = num; |
|
10216
|
6
|
|
|
|
|
|
return true; |
|
10217
|
|
|
|
|
|
|
} |
|
10218
|
|
|
|
|
|
|
|
|
10219
|
|
|
|
|
|
|
/** |
|
10220
|
|
|
|
|
|
|
Compare JSON key with token. |
|
10221
|
|
|
|
|
|
|
@param key a string key (yyjson_val or yyjson_mut_val) |
|
10222
|
|
|
|
|
|
|
@param token a JSON pointer token |
|
10223
|
|
|
|
|
|
|
@param len unescaped token length |
|
10224
|
|
|
|
|
|
|
@param esc number of escaped characters in this token |
|
10225
|
|
|
|
|
|
|
@return true if `str` is equals to `token` |
|
10226
|
|
|
|
|
|
|
*/ |
|
10227
|
|
|
|
|
|
|
static_inline bool ptr_token_eq(void *key, |
|
10228
|
|
|
|
|
|
|
const char *token, usize len, usize esc) { |
|
10229
|
0
|
|
|
|
|
|
yyjson_val *val = (yyjson_val *)key; |
|
10230
|
18300
|
100
|
|
|
|
|
if (unsafe_yyjson_get_len(val) != len) return false; |
|
|
|
100
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10231
|
18130
|
50
|
|
|
|
|
if (likely(!esc)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10232
|
18130
|
|
|
|
|
|
return memcmp(val->uni.str, token, len) == 0; |
|
10233
|
|
|
|
|
|
|
} else { |
|
10234
|
0
|
|
|
|
|
|
const char *str = val->uni.str; |
|
10235
|
0
|
0
|
|
|
|
|
for (; len-- > 0; token++, str++) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10236
|
0
|
0
|
|
|
|
|
if (*token == '~') { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10237
|
0
|
0
|
|
|
|
|
if (*str != (*++token == '0' ? '~' : '/')) return false; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10238
|
|
|
|
|
|
|
} else { |
|
10239
|
0
|
0
|
|
|
|
|
if (*str != *token) return false; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10240
|
|
|
|
|
|
|
} |
|
10241
|
|
|
|
|
|
|
} |
|
10242
|
0
|
|
|
|
|
|
return true; |
|
10243
|
|
|
|
|
|
|
} |
|
10244
|
|
|
|
|
|
|
} |
|
10245
|
|
|
|
|
|
|
|
|
10246
|
|
|
|
|
|
|
/** |
|
10247
|
|
|
|
|
|
|
Get a value from array by token. |
|
10248
|
|
|
|
|
|
|
@param arr an array, should not be NULL or non-array type |
|
10249
|
|
|
|
|
|
|
@param token a JSON pointer token |
|
10250
|
|
|
|
|
|
|
@param len unescaped token length |
|
10251
|
|
|
|
|
|
|
@param esc number of escaped characters in this token |
|
10252
|
|
|
|
|
|
|
@return value at index, or NULL if token is not index or index is out of range |
|
10253
|
|
|
|
|
|
|
*/ |
|
10254
|
|
|
|
|
|
|
static_inline yyjson_val *ptr_arr_get(yyjson_val *arr, const char *token, |
|
10255
|
|
|
|
|
|
|
usize len, usize esc) { |
|
10256
|
0
|
|
|
|
|
|
yyjson_val *val = unsafe_yyjson_get_first(arr); |
|
10257
|
0
|
|
|
|
|
|
usize num = unsafe_yyjson_get_len(arr), idx = 0; |
|
10258
|
0
|
0
|
|
|
|
|
if (unlikely(num == 0)) return NULL; |
|
10259
|
0
|
0
|
|
|
|
|
if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL; |
|
10260
|
0
|
0
|
|
|
|
|
if (unlikely(idx >= num)) return NULL; |
|
10261
|
0
|
0
|
|
|
|
|
if (unsafe_yyjson_arr_is_flat(arr)) { |
|
10262
|
0
|
|
|
|
|
|
return val + idx; |
|
10263
|
|
|
|
|
|
|
} else { |
|
10264
|
0
|
0
|
|
|
|
|
while (idx-- > 0) val = unsafe_yyjson_get_next(val); |
|
10265
|
0
|
|
|
|
|
|
return val; |
|
10266
|
|
|
|
|
|
|
} |
|
10267
|
|
|
|
|
|
|
} |
|
10268
|
|
|
|
|
|
|
|
|
10269
|
|
|
|
|
|
|
/** |
|
10270
|
|
|
|
|
|
|
Get a value from object by token. |
|
10271
|
|
|
|
|
|
|
@param obj [in] an object, should not be NULL or non-object type |
|
10272
|
|
|
|
|
|
|
@param token [in] a JSON pointer token |
|
10273
|
|
|
|
|
|
|
@param len [in] unescaped token length |
|
10274
|
|
|
|
|
|
|
@param esc [in] number of escaped characters in this token |
|
10275
|
|
|
|
|
|
|
@return value associated with the token, or NULL if no value |
|
10276
|
|
|
|
|
|
|
*/ |
|
10277
|
|
|
|
|
|
|
static_inline yyjson_val *ptr_obj_get(yyjson_val *obj, const char *token, |
|
10278
|
|
|
|
|
|
|
usize len, usize esc) { |
|
10279
|
0
|
|
|
|
|
|
yyjson_val *key = unsafe_yyjson_get_first(obj); |
|
10280
|
0
|
|
|
|
|
|
usize num = unsafe_yyjson_get_len(obj); |
|
10281
|
0
|
0
|
|
|
|
|
if (unlikely(num == 0)) return NULL; |
|
10282
|
0
|
0
|
|
|
|
|
for (; num > 0; num--, key = unsafe_yyjson_get_next(key + 1)) { |
|
10283
|
0
|
0
|
|
|
|
|
if (ptr_token_eq(key, token, len, esc)) return key + 1; |
|
10284
|
|
|
|
|
|
|
} |
|
10285
|
0
|
|
|
|
|
|
return NULL; |
|
10286
|
|
|
|
|
|
|
} |
|
10287
|
|
|
|
|
|
|
|
|
10288
|
|
|
|
|
|
|
/** |
|
10289
|
|
|
|
|
|
|
Get a value from array by token. |
|
10290
|
|
|
|
|
|
|
@param arr [in] an array, should not be NULL or non-array type |
|
10291
|
|
|
|
|
|
|
@param token [in] a JSON pointer token |
|
10292
|
|
|
|
|
|
|
@param len [in] unescaped token length |
|
10293
|
|
|
|
|
|
|
@param esc [in] number of escaped characters in this token |
|
10294
|
|
|
|
|
|
|
@param pre [out] previous (sibling) value of the returned value |
|
10295
|
|
|
|
|
|
|
@param last [out] whether index is last |
|
10296
|
|
|
|
|
|
|
@return value at index, or NULL if token is not index or index is out of range |
|
10297
|
|
|
|
|
|
|
*/ |
|
10298
|
|
|
|
|
|
|
static_inline yyjson_mut_val *ptr_mut_arr_get(yyjson_mut_val *arr, |
|
10299
|
|
|
|
|
|
|
const char *token, |
|
10300
|
|
|
|
|
|
|
usize len, usize esc, |
|
10301
|
|
|
|
|
|
|
yyjson_mut_val **pre, |
|
10302
|
|
|
|
|
|
|
bool *last) { |
|
10303
|
120
|
|
|
|
|
|
yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; /* last (tail) */ |
|
10304
|
120
|
|
|
|
|
|
usize num = unsafe_yyjson_get_len(arr), idx; |
|
10305
|
120
|
50
|
|
|
|
|
if (last) *last = false; |
|
|
|
50
|
|
|
|
|
|
|
10306
|
120
|
50
|
|
|
|
|
if (pre) *pre = NULL; |
|
|
|
50
|
|
|
|
|
|
|
10307
|
120
|
100
|
|
|
|
|
if (unlikely(num == 0)) { |
|
|
|
50
|
|
|
|
|
|
|
10308
|
2
|
50
|
|
|
|
|
if (last && len == 1 && (*token == '0' || *token == '-')) *last = true; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10309
|
2
|
|
|
|
|
|
return NULL; |
|
10310
|
|
|
|
|
|
|
} |
|
10311
|
118
|
50
|
|
|
|
|
if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL; |
|
|
|
50
|
|
|
|
|
|
|
10312
|
118
|
50
|
|
|
|
|
if (last) *last = (idx == num || idx == USIZE_MAX); |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
10313
|
118
|
100
|
|
|
|
|
if (unlikely(idx >= num)) return NULL; |
|
|
|
50
|
|
|
|
|
|
|
10314
|
10115
|
100
|
|
|
|
|
while (idx-- > 0) val = val->next; |
|
|
|
100
|
|
|
|
|
|
|
10315
|
110
|
50
|
|
|
|
|
if (pre) *pre = val; |
|
|
|
50
|
|
|
|
|
|
|
10316
|
110
|
|
|
|
|
|
return val->next; |
|
10317
|
|
|
|
|
|
|
} |
|
10318
|
|
|
|
|
|
|
|
|
10319
|
|
|
|
|
|
|
/** |
|
10320
|
|
|
|
|
|
|
Get a value from object by token. |
|
10321
|
|
|
|
|
|
|
@param obj [in] an object, should not be NULL or non-object type |
|
10322
|
|
|
|
|
|
|
@param token [in] a JSON pointer token |
|
10323
|
|
|
|
|
|
|
@param len [in] unescaped token length |
|
10324
|
|
|
|
|
|
|
@param esc [in] number of escaped characters in this token |
|
10325
|
|
|
|
|
|
|
@param pre [out] previous (sibling) key of the returned value's key |
|
10326
|
|
|
|
|
|
|
@return value associated with the token, or NULL if no value |
|
10327
|
|
|
|
|
|
|
*/ |
|
10328
|
|
|
|
|
|
|
static_inline yyjson_mut_val *ptr_mut_obj_get(yyjson_mut_val *obj, |
|
10329
|
|
|
|
|
|
|
const char *token, |
|
10330
|
|
|
|
|
|
|
usize len, usize esc, |
|
10331
|
|
|
|
|
|
|
yyjson_mut_val **pre) { |
|
10332
|
15174
|
|
|
|
|
|
yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr, *key; |
|
10333
|
15174
|
|
|
|
|
|
usize num = unsafe_yyjson_get_len(obj); |
|
10334
|
15174
|
50
|
|
|
|
|
if (pre) *pre = NULL; |
|
|
|
50
|
|
|
|
|
|
|
10335
|
15174
|
100
|
|
|
|
|
if (unlikely(num == 0)) return NULL; |
|
|
|
100
|
|
|
|
|
|
|
10336
|
28327
|
100
|
|
|
|
|
for (; num > 0; num--, pre_key = key) { |
|
|
|
100
|
|
|
|
|
|
|
10337
|
18300
|
|
|
|
|
|
key = pre_key->next->next; |
|
10338
|
18300
|
100
|
|
|
|
|
if (ptr_token_eq(key, token, len, esc)) { |
|
|
|
100
|
|
|
|
|
|
|
10339
|
5143
|
50
|
|
|
|
|
if (pre) *pre = pre_key; |
|
|
|
50
|
|
|
|
|
|
|
10340
|
5143
|
|
|
|
|
|
return key->next; |
|
10341
|
|
|
|
|
|
|
} |
|
10342
|
|
|
|
|
|
|
} |
|
10343
|
10027
|
|
|
|
|
|
return NULL; |
|
10344
|
|
|
|
|
|
|
} |
|
10345
|
|
|
|
|
|
|
|
|
10346
|
|
|
|
|
|
|
/** |
|
10347
|
|
|
|
|
|
|
Create a string value with JSON pointer token. |
|
10348
|
|
|
|
|
|
|
@param token [in] a JSON pointer token |
|
10349
|
|
|
|
|
|
|
@param len [in] unescaped token length |
|
10350
|
|
|
|
|
|
|
@param esc [in] number of escaped characters in this token |
|
10351
|
|
|
|
|
|
|
@param doc [in] used for memory allocation when creating value |
|
10352
|
|
|
|
|
|
|
@return new string value, or NULL if memory allocation failed |
|
10353
|
|
|
|
|
|
|
*/ |
|
10354
|
|
|
|
|
|
|
static_inline yyjson_mut_val *ptr_new_key(const char *token, |
|
10355
|
|
|
|
|
|
|
usize len, usize esc, |
|
10356
|
|
|
|
|
|
|
yyjson_mut_doc *doc) { |
|
10357
|
10018
|
|
|
|
|
|
const char *src = token; |
|
10358
|
10018
|
|
|
|
|
|
if (likely(!esc)) { |
|
10359
|
10018
|
|
|
|
|
|
return yyjson_mut_strncpy(doc, src, len); |
|
10360
|
|
|
|
|
|
|
} else { |
|
10361
|
0
|
|
|
|
|
|
const char *end = src + len + esc; |
|
10362
|
0
|
0
|
|
|
|
|
char *dst = unsafe_yyjson_mut_str_alc(doc, len + esc); |
|
|
|
0
|
|
|
|
|
|
|
10363
|
0
|
|
|
|
|
|
char *str = dst; |
|
10364
|
0
|
0
|
|
|
|
|
if (unlikely(!dst)) return NULL; |
|
|
|
0
|
|
|
|
|
|
|
10365
|
0
|
0
|
|
|
|
|
for (; src < end; src++, dst++) { |
|
|
|
0
|
|
|
|
|
|
|
10366
|
0
|
0
|
|
|
|
|
if (*src != '~') *dst = *src; |
|
|
|
0
|
|
|
|
|
|
|
10367
|
0
|
0
|
|
|
|
|
else *dst = (*++src == '0' ? '~' : '/'); |
|
|
|
0
|
|
|
|
|
|
|
10368
|
|
|
|
|
|
|
} |
|
10369
|
0
|
0
|
|
|
|
|
*dst = '\0'; |
|
|
|
0
|
|
|
|
|
|
|
10370
|
0
|
|
|
|
|
|
return yyjson_mut_strn(doc, str, len); |
|
10371
|
|
|
|
|
|
|
} |
|
10372
|
|
|
|
|
|
|
} |
|
10373
|
|
|
|
|
|
|
|
|
10374
|
|
|
|
|
|
|
/* macros for yyjson_ptr */ |
|
10375
|
|
|
|
|
|
|
#define return_err(_ret, _code, _pos, _msg) do { \ |
|
10376
|
|
|
|
|
|
|
if (err) { \ |
|
10377
|
|
|
|
|
|
|
err->code = YYJSON_PTR_ERR_##_code; \ |
|
10378
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
10379
|
|
|
|
|
|
|
err->pos = (usize)(_pos); \ |
|
10380
|
|
|
|
|
|
|
} \ |
|
10381
|
|
|
|
|
|
|
return _ret; \ |
|
10382
|
|
|
|
|
|
|
} while (false) |
|
10383
|
|
|
|
|
|
|
|
|
10384
|
|
|
|
|
|
|
#define return_err_resolve(_ret, _pos) \ |
|
10385
|
|
|
|
|
|
|
return_err(_ret, RESOLVE, _pos, "JSON pointer cannot be resolved") |
|
10386
|
|
|
|
|
|
|
#define return_err_syntax(_ret, _pos) \ |
|
10387
|
|
|
|
|
|
|
return_err(_ret, SYNTAX, _pos, "invalid escaped character") |
|
10388
|
|
|
|
|
|
|
#define return_err_alloc(_ret) \ |
|
10389
|
|
|
|
|
|
|
return_err(_ret, MEMORY_ALLOCATION, 0, "failed to create value") |
|
10390
|
|
|
|
|
|
|
|
|
10391
|
0
|
|
|
|
|
|
yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val, |
|
10392
|
|
|
|
|
|
|
const char *ptr, size_t ptr_len, |
|
10393
|
|
|
|
|
|
|
yyjson_ptr_err *err) { |
|
10394
|
|
|
|
|
|
|
|
|
10395
|
0
|
|
|
|
|
|
const char *hdr = ptr, *end = ptr + ptr_len, *token; |
|
10396
|
|
|
|
|
|
|
usize len, esc; |
|
10397
|
|
|
|
|
|
|
yyjson_type type; |
|
10398
|
|
|
|
|
|
|
|
|
10399
|
|
|
|
|
|
|
while (true) { |
|
10400
|
0
|
|
|
|
|
|
token = ptr_next_token(&ptr, end, &len, &esc); |
|
10401
|
0
|
0
|
|
|
|
|
if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr); |
|
|
|
0
|
|
|
|
|
|
|
10402
|
0
|
|
|
|
|
|
type = unsafe_yyjson_get_type(val); |
|
10403
|
0
|
0
|
|
|
|
|
if (type == YYJSON_TYPE_OBJ) { |
|
10404
|
0
|
|
|
|
|
|
val = ptr_obj_get(val, token, len, esc); |
|
10405
|
0
|
0
|
|
|
|
|
} else if (type == YYJSON_TYPE_ARR) { |
|
10406
|
0
|
|
|
|
|
|
val = ptr_arr_get(val, token, len, esc); |
|
10407
|
|
|
|
|
|
|
} else { |
|
10408
|
0
|
|
|
|
|
|
val = NULL; |
|
10409
|
|
|
|
|
|
|
} |
|
10410
|
0
|
0
|
|
|
|
|
if (!val) return_err_resolve(NULL, token - hdr); |
|
|
|
0
|
|
|
|
|
|
|
10411
|
0
|
0
|
|
|
|
|
if (ptr == end) return val; |
|
10412
|
|
|
|
|
|
|
} |
|
10413
|
|
|
|
|
|
|
} |
|
10414
|
|
|
|
|
|
|
|
|
10415
|
5127
|
|
|
|
|
|
yyjson_mut_val *unsafe_yyjson_mut_ptr_getx( |
|
10416
|
|
|
|
|
|
|
yyjson_mut_val *val, const char *ptr, size_t ptr_len, |
|
10417
|
|
|
|
|
|
|
yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { |
|
10418
|
|
|
|
|
|
|
|
|
10419
|
5127
|
|
|
|
|
|
const char *hdr = ptr, *end = ptr + ptr_len, *token; |
|
10420
|
|
|
|
|
|
|
usize len, esc; |
|
10421
|
5127
|
|
|
|
|
|
yyjson_mut_val *ctn, *pre = NULL; |
|
10422
|
|
|
|
|
|
|
yyjson_type type; |
|
10423
|
5127
|
|
|
|
|
|
bool idx_is_last = false; |
|
10424
|
|
|
|
|
|
|
|
|
10425
|
|
|
|
|
|
|
while (true) { |
|
10426
|
123
|
|
|
|
|
|
token = ptr_next_token(&ptr, end, &len, &esc); |
|
10427
|
5250
|
50
|
|
|
|
|
if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr); |
|
|
|
0
|
|
|
|
|
|
|
10428
|
5250
|
|
|
|
|
|
ctn = val; |
|
10429
|
5250
|
|
|
|
|
|
type = unsafe_yyjson_get_type(val); |
|
10430
|
5250
|
100
|
|
|
|
|
if (type == YYJSON_TYPE_OBJ) { |
|
10431
|
10284
|
|
|
|
|
|
val = ptr_mut_obj_get(val, token, len, esc, &pre); |
|
10432
|
108
|
50
|
|
|
|
|
} else if (type == YYJSON_TYPE_ARR) { |
|
10433
|
216
|
|
|
|
|
|
val = ptr_mut_arr_get(val, token, len, esc, &pre, &idx_is_last); |
|
10434
|
|
|
|
|
|
|
} else { |
|
10435
|
0
|
|
|
|
|
|
val = NULL; |
|
10436
|
|
|
|
|
|
|
} |
|
10437
|
5250
|
100
|
|
|
|
|
if (ctx && (ptr == end)) { |
|
|
|
100
|
|
|
|
|
|
|
10438
|
7
|
50
|
|
|
|
|
if (type == YYJSON_TYPE_OBJ || |
|
|
|
0
|
|
|
|
|
|
|
10439
|
0
|
0
|
|
|
|
|
(type == YYJSON_TYPE_ARR && (val || idx_is_last))) { |
|
|
|
0
|
|
|
|
|
|
|
10440
|
7
|
|
|
|
|
|
ctx->ctn = ctn; |
|
10441
|
7
|
|
|
|
|
|
ctx->pre = pre; |
|
10442
|
|
|
|
|
|
|
} |
|
10443
|
|
|
|
|
|
|
} |
|
10444
|
5250
|
100
|
|
|
|
|
if (!val) return_err_resolve(NULL, token - hdr); |
|
|
|
100
|
|
|
|
|
|
|
10445
|
5237
|
100
|
|
|
|
|
if (ptr == end) return val; |
|
10446
|
|
|
|
|
|
|
} |
|
10447
|
|
|
|
|
|
|
} |
|
10448
|
|
|
|
|
|
|
|
|
10449
|
10031
|
|
|
|
|
|
bool unsafe_yyjson_mut_ptr_putx( |
|
10450
|
|
|
|
|
|
|
yyjson_mut_val *val, const char *ptr, size_t ptr_len, |
|
10451
|
|
|
|
|
|
|
yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, |
|
10452
|
|
|
|
|
|
|
bool insert_new, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { |
|
10453
|
|
|
|
|
|
|
|
|
10454
|
10031
|
|
|
|
|
|
const char *hdr = ptr, *end = ptr + ptr_len, *token; |
|
10455
|
|
|
|
|
|
|
usize token_len, esc, ctn_len; |
|
10456
|
10031
|
|
|
|
|
|
yyjson_mut_val *ctn, *key, *pre = NULL; |
|
10457
|
10031
|
|
|
|
|
|
yyjson_mut_val *sep_ctn = NULL, *sep_key = NULL, *sep_val = NULL; |
|
10458
|
|
|
|
|
|
|
yyjson_type ctn_type; |
|
10459
|
10031
|
|
|
|
|
|
bool idx_is_last = false; |
|
10460
|
|
|
|
|
|
|
|
|
10461
|
|
|
|
|
|
|
/* skip exist parent nodes */ |
|
10462
|
|
|
|
|
|
|
while (true) { |
|
10463
|
13
|
|
|
|
|
|
token = ptr_next_token(&ptr, end, &token_len, &esc); |
|
10464
|
10044
|
50
|
|
|
|
|
if (unlikely(!token)) return_err_syntax(false, ptr - hdr); |
|
|
|
0
|
|
|
|
|
|
|
10465
|
10044
|
|
|
|
|
|
ctn = val; |
|
10466
|
10044
|
|
|
|
|
|
ctn_type = unsafe_yyjson_get_type(ctn); |
|
10467
|
10044
|
100
|
|
|
|
|
if (ctn_type == YYJSON_TYPE_OBJ) { |
|
10468
|
20064
|
|
|
|
|
|
val = ptr_mut_obj_get(ctn, token, token_len, esc, &pre); |
|
10469
|
12
|
50
|
|
|
|
|
} else if (ctn_type == YYJSON_TYPE_ARR) { |
|
10470
|
24
|
|
|
|
|
|
val = ptr_mut_arr_get(ctn, token, token_len, esc, &pre, |
|
10471
|
|
|
|
|
|
|
&idx_is_last); |
|
10472
|
0
|
0
|
|
|
|
|
} else return_err_resolve(false, token - hdr); |
|
10473
|
10044
|
100
|
|
|
|
|
if (!val) break; |
|
10474
|
16
|
100
|
|
|
|
|
if (ptr == end) break; /* is last token */ |
|
10475
|
|
|
|
|
|
|
} |
|
10476
|
|
|
|
|
|
|
|
|
10477
|
|
|
|
|
|
|
/* create parent nodes if not exist */ |
|
10478
|
10031
|
50
|
|
|
|
|
if (unlikely(ptr != end)) { /* not last token */ |
|
10479
|
0
|
0
|
|
|
|
|
if (!create_parent) return_err_resolve(false, token - hdr); |
|
|
|
0
|
|
|
|
|
|
|
10480
|
|
|
|
|
|
|
|
|
10481
|
|
|
|
|
|
|
/* add value at last index if container is array */ |
|
10482
|
0
|
0
|
|
|
|
|
if (ctn_type == YYJSON_TYPE_ARR) { |
|
10483
|
0
|
0
|
|
|
|
|
if (!idx_is_last || !insert_new) { |
|
|
|
0
|
|
|
|
|
|
|
10484
|
0
|
0
|
|
|
|
|
return_err_resolve(false, token - hdr); |
|
10485
|
|
|
|
|
|
|
} |
|
10486
|
0
|
|
|
|
|
|
val = yyjson_mut_obj(doc); |
|
10487
|
0
|
0
|
|
|
|
|
if (!val) return_err_alloc(false); |
|
|
|
0
|
|
|
|
|
|
|
10488
|
|
|
|
|
|
|
|
|
10489
|
|
|
|
|
|
|
/* delay attaching until all operations are completed */ |
|
10490
|
0
|
|
|
|
|
|
sep_ctn = ctn; |
|
10491
|
0
|
|
|
|
|
|
sep_key = NULL; |
|
10492
|
0
|
|
|
|
|
|
sep_val = val; |
|
10493
|
|
|
|
|
|
|
|
|
10494
|
|
|
|
|
|
|
/* move to next token */ |
|
10495
|
0
|
|
|
|
|
|
ctn = val; |
|
10496
|
0
|
|
|
|
|
|
val = NULL; |
|
10497
|
0
|
|
|
|
|
|
ctn_type = YYJSON_TYPE_OBJ; |
|
10498
|
0
|
|
|
|
|
|
token = ptr_next_token(&ptr, end, &token_len, &esc); |
|
10499
|
0
|
0
|
|
|
|
|
if (unlikely(!token)) return_err_resolve(false, token - hdr); |
|
|
|
0
|
|
|
|
|
|
|
10500
|
|
|
|
|
|
|
} |
|
10501
|
|
|
|
|
|
|
|
|
10502
|
|
|
|
|
|
|
/* container is object, create parent nodes */ |
|
10503
|
0
|
0
|
|
|
|
|
while (ptr != end) { /* not last token */ |
|
10504
|
0
|
0
|
|
|
|
|
key = ptr_new_key(token, token_len, esc, doc); |
|
10505
|
0
|
0
|
|
|
|
|
if (!key) return_err_alloc(false); |
|
|
|
0
|
|
|
|
|
|
|
10506
|
0
|
|
|
|
|
|
val = yyjson_mut_obj(doc); |
|
10507
|
0
|
0
|
|
|
|
|
if (!val) return_err_alloc(false); |
|
|
|
0
|
|
|
|
|
|
|
10508
|
|
|
|
|
|
|
|
|
10509
|
|
|
|
|
|
|
/* delay attaching until all operations are completed */ |
|
10510
|
0
|
0
|
|
|
|
|
if (!sep_ctn) { |
|
10511
|
0
|
|
|
|
|
|
sep_ctn = ctn; |
|
10512
|
0
|
|
|
|
|
|
sep_key = key; |
|
10513
|
0
|
|
|
|
|
|
sep_val = val; |
|
10514
|
|
|
|
|
|
|
} else { |
|
10515
|
|
|
|
|
|
|
yyjson_mut_obj_add(ctn, key, val); |
|
10516
|
|
|
|
|
|
|
} |
|
10517
|
|
|
|
|
|
|
|
|
10518
|
|
|
|
|
|
|
/* move to next token */ |
|
10519
|
0
|
|
|
|
|
|
ctn = val; |
|
10520
|
0
|
|
|
|
|
|
val = NULL; |
|
10521
|
0
|
|
|
|
|
|
token = ptr_next_token(&ptr, end, &token_len, &esc); |
|
10522
|
0
|
0
|
|
|
|
|
if (unlikely(!token)) return_err_syntax(false, ptr - hdr); |
|
|
|
0
|
|
|
|
|
|
|
10523
|
|
|
|
|
|
|
} |
|
10524
|
|
|
|
|
|
|
} |
|
10525
|
|
|
|
|
|
|
|
|
10526
|
|
|
|
|
|
|
/* JSON pointer is resolved, insert or replace target value */ |
|
10527
|
10031
|
|
|
|
|
|
ctn_len = unsafe_yyjson_get_len(ctn); |
|
10528
|
10031
|
100
|
|
|
|
|
if (ctn_type == YYJSON_TYPE_OBJ) { |
|
10529
|
10019
|
50
|
|
|
|
|
if (ctx) ctx->ctn = ctn; |
|
10530
|
10019
|
100
|
|
|
|
|
if (!val || insert_new) { |
|
|
|
50
|
|
|
|
|
|
|
10531
|
|
|
|
|
|
|
/* insert new key-value pair */ |
|
10532
|
10018
|
50
|
|
|
|
|
key = ptr_new_key(token, token_len, esc, doc); |
|
10533
|
10018
|
50
|
|
|
|
|
if (unlikely(!key)) return_err_alloc(false); |
|
|
|
0
|
|
|
|
|
|
|
10534
|
10018
|
50
|
|
|
|
|
if (ctx) ctx->pre = ctn_len ? (yyjson_mut_val *)ctn->uni.ptr : key; |
|
|
|
0
|
|
|
|
|
|
|
10535
|
10018
|
|
|
|
|
|
unsafe_yyjson_mut_obj_add(ctn, key, new_val, ctn_len); |
|
10536
|
|
|
|
|
|
|
} else { |
|
10537
|
|
|
|
|
|
|
/* replace exist value */ |
|
10538
|
1
|
|
|
|
|
|
key = pre->next->next; |
|
10539
|
1
|
50
|
|
|
|
|
if (ctx) ctx->pre = pre; |
|
10540
|
1
|
50
|
|
|
|
|
if (ctx) ctx->old = val; |
|
10541
|
|
|
|
|
|
|
yyjson_mut_obj_put(ctn, key, new_val); |
|
10542
|
|
|
|
|
|
|
} |
|
10543
|
|
|
|
|
|
|
} else { |
|
10544
|
|
|
|
|
|
|
/* array */ |
|
10545
|
12
|
50
|
|
|
|
|
if (ctx && (val || idx_is_last)) ctx->ctn = ctn; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10546
|
12
|
100
|
|
|
|
|
if (insert_new) { |
|
10547
|
|
|
|
|
|
|
/* append new value */ |
|
10548
|
5
|
50
|
|
|
|
|
if (val) { |
|
10549
|
0
|
|
|
|
|
|
pre->next = new_val; |
|
10550
|
0
|
|
|
|
|
|
new_val->next = val; |
|
10551
|
0
|
0
|
|
|
|
|
if (ctx) ctx->pre = pre; |
|
10552
|
0
|
|
|
|
|
|
unsafe_yyjson_set_len(ctn, ctn_len + 1); |
|
10553
|
5
|
50
|
|
|
|
|
} else if (idx_is_last) { |
|
10554
|
5
|
50
|
|
|
|
|
if (ctx) ctx->pre = ctn_len ? |
|
10555
|
0
|
0
|
|
|
|
|
(yyjson_mut_val *)ctn->uni.ptr : new_val; |
|
10556
|
|
|
|
|
|
|
yyjson_mut_arr_append(ctn, new_val); |
|
10557
|
|
|
|
|
|
|
} else { |
|
10558
|
0
|
0
|
|
|
|
|
return_err_resolve(false, token - hdr); |
|
10559
|
|
|
|
|
|
|
} |
|
10560
|
|
|
|
|
|
|
} else { |
|
10561
|
|
|
|
|
|
|
/* replace exist value */ |
|
10562
|
7
|
100
|
|
|
|
|
if (!val) return_err_resolve(false, token - hdr); |
|
|
|
50
|
|
|
|
|
|
|
10563
|
2
|
50
|
|
|
|
|
if (ctn_len > 1) { |
|
10564
|
2
|
|
|
|
|
|
new_val->next = val->next; |
|
10565
|
2
|
|
|
|
|
|
pre->next = new_val; |
|
10566
|
2
|
50
|
|
|
|
|
if (ctn->uni.ptr == val) ctn->uni.ptr = new_val; |
|
10567
|
|
|
|
|
|
|
} else { |
|
10568
|
0
|
|
|
|
|
|
new_val->next = new_val; |
|
10569
|
0
|
|
|
|
|
|
ctn->uni.ptr = new_val; |
|
10570
|
0
|
|
|
|
|
|
pre = new_val; |
|
10571
|
|
|
|
|
|
|
} |
|
10572
|
2
|
50
|
|
|
|
|
if (ctx) ctx->pre = pre; |
|
10573
|
2
|
50
|
|
|
|
|
if (ctx) ctx->old = val; |
|
10574
|
|
|
|
|
|
|
} |
|
10575
|
|
|
|
|
|
|
} |
|
10576
|
|
|
|
|
|
|
|
|
10577
|
|
|
|
|
|
|
/* all operations are completed, attach the new components to the target */ |
|
10578
|
10026
|
50
|
|
|
|
|
if (unlikely(sep_ctn)) { |
|
10579
|
0
|
0
|
|
|
|
|
if (sep_key) yyjson_mut_obj_add(sep_ctn, sep_key, sep_val); |
|
10580
|
|
|
|
|
|
|
else yyjson_mut_arr_append(sep_ctn, sep_val); |
|
10581
|
|
|
|
|
|
|
} |
|
10582
|
10026
|
|
|
|
|
|
return true; |
|
10583
|
|
|
|
|
|
|
} |
|
10584
|
|
|
|
|
|
|
|
|
10585
|
1
|
|
|
|
|
|
yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex( |
|
10586
|
|
|
|
|
|
|
yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, |
|
10587
|
|
|
|
|
|
|
yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { |
|
10588
|
|
|
|
|
|
|
|
|
10589
|
|
|
|
|
|
|
yyjson_mut_val *cur_val; |
|
10590
|
|
|
|
|
|
|
yyjson_ptr_ctx cur_ctx; |
|
10591
|
1
|
|
|
|
|
|
memset(&cur_ctx, 0, sizeof(cur_ctx)); |
|
10592
|
1
|
50
|
|
|
|
|
if (!ctx) ctx = &cur_ctx; |
|
10593
|
1
|
|
|
|
|
|
cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); |
|
10594
|
1
|
50
|
|
|
|
|
if (!cur_val) return NULL; |
|
10595
|
|
|
|
|
|
|
|
|
10596
|
2
|
50
|
|
|
|
|
if (yyjson_mut_is_obj(ctx->ctn)) { |
|
|
|
50
|
|
|
|
|
|
|
10597
|
1
|
|
|
|
|
|
yyjson_mut_val *key = ctx->pre->next->next; |
|
10598
|
1
|
50
|
|
|
|
|
yyjson_mut_obj_put(ctx->ctn, key, new_val); |
|
10599
|
|
|
|
|
|
|
} else { |
|
10600
|
|
|
|
|
|
|
yyjson_ptr_ctx_replace(ctx, new_val); |
|
10601
|
|
|
|
|
|
|
} |
|
10602
|
1
|
|
|
|
|
|
ctx->old = cur_val; |
|
10603
|
1
|
|
|
|
|
|
return cur_val; |
|
10604
|
|
|
|
|
|
|
} |
|
10605
|
|
|
|
|
|
|
|
|
10606
|
6
|
|
|
|
|
|
yyjson_mut_val *unsafe_yyjson_mut_ptr_removex( |
|
10607
|
|
|
|
|
|
|
yyjson_mut_val *val, const char *ptr, size_t len, |
|
10608
|
|
|
|
|
|
|
yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { |
|
10609
|
|
|
|
|
|
|
|
|
10610
|
|
|
|
|
|
|
yyjson_mut_val *cur_val; |
|
10611
|
|
|
|
|
|
|
yyjson_ptr_ctx cur_ctx; |
|
10612
|
6
|
|
|
|
|
|
memset(&cur_ctx, 0, sizeof(cur_ctx)); |
|
10613
|
6
|
100
|
|
|
|
|
if (!ctx) ctx = &cur_ctx; |
|
10614
|
6
|
|
|
|
|
|
cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); |
|
10615
|
6
|
100
|
|
|
|
|
if (cur_val) { |
|
10616
|
8
|
50
|
|
|
|
|
if (yyjson_mut_is_obj(ctx->ctn)) { |
|
|
|
50
|
|
|
|
|
|
|
10617
|
4
|
|
|
|
|
|
yyjson_mut_val *key = ctx->pre->next->next; |
|
10618
|
4
|
50
|
|
|
|
|
yyjson_mut_obj_put(ctx->ctn, key, NULL); |
|
10619
|
|
|
|
|
|
|
} else { |
|
10620
|
|
|
|
|
|
|
yyjson_ptr_ctx_remove(ctx); |
|
10621
|
|
|
|
|
|
|
} |
|
10622
|
4
|
|
|
|
|
|
ctx->pre = NULL; |
|
10623
|
4
|
|
|
|
|
|
ctx->old = cur_val; |
|
10624
|
|
|
|
|
|
|
} |
|
10625
|
6
|
|
|
|
|
|
return cur_val; |
|
10626
|
|
|
|
|
|
|
} |
|
10627
|
|
|
|
|
|
|
|
|
10628
|
|
|
|
|
|
|
/* macros for yyjson_ptr */ |
|
10629
|
|
|
|
|
|
|
#undef return_err |
|
10630
|
|
|
|
|
|
|
#undef return_err_resolve |
|
10631
|
|
|
|
|
|
|
#undef return_err_syntax |
|
10632
|
|
|
|
|
|
|
#undef return_err_alloc |
|
10633
|
|
|
|
|
|
|
|
|
10634
|
|
|
|
|
|
|
|
|
10635
|
|
|
|
|
|
|
|
|
10636
|
|
|
|
|
|
|
/*============================================================================== |
|
10637
|
|
|
|
|
|
|
* MARK: - JSON Patch API (RFC 6902) (Public) |
|
10638
|
|
|
|
|
|
|
*============================================================================*/ |
|
10639
|
|
|
|
|
|
|
|
|
10640
|
|
|
|
|
|
|
/* JSON Patch operation */ |
|
10641
|
|
|
|
|
|
|
typedef enum patch_op { |
|
10642
|
|
|
|
|
|
|
PATCH_OP_ADD, /* path, value */ |
|
10643
|
|
|
|
|
|
|
PATCH_OP_REMOVE, /* path */ |
|
10644
|
|
|
|
|
|
|
PATCH_OP_REPLACE, /* path, value */ |
|
10645
|
|
|
|
|
|
|
PATCH_OP_MOVE, /* from, path */ |
|
10646
|
|
|
|
|
|
|
PATCH_OP_COPY, /* from, path */ |
|
10647
|
|
|
|
|
|
|
PATCH_OP_TEST, /* path, value */ |
|
10648
|
|
|
|
|
|
|
PATCH_OP_NONE /* invalid */ |
|
10649
|
|
|
|
|
|
|
} patch_op; |
|
10650
|
|
|
|
|
|
|
|
|
10651
|
7
|
|
|
|
|
|
static patch_op patch_op_get(yyjson_val *op) { |
|
10652
|
7
|
|
|
|
|
|
const char *str = op->uni.str; |
|
10653
|
7
|
|
|
|
|
|
switch (unsafe_yyjson_get_len(op)) { |
|
10654
|
1
|
|
|
|
|
|
case 3: |
|
10655
|
1
|
50
|
|
|
|
|
if (!memcmp(str, "add", 3)) return PATCH_OP_ADD; |
|
10656
|
0
|
|
|
|
|
|
return PATCH_OP_NONE; |
|
10657
|
4
|
|
|
|
|
|
case 4: |
|
10658
|
4
|
100
|
|
|
|
|
if (!memcmp(str, "move", 4)) return PATCH_OP_MOVE; |
|
10659
|
3
|
100
|
|
|
|
|
if (!memcmp(str, "copy", 4)) return PATCH_OP_COPY; |
|
10660
|
2
|
50
|
|
|
|
|
if (!memcmp(str, "test", 4)) return PATCH_OP_TEST; |
|
10661
|
0
|
|
|
|
|
|
return PATCH_OP_NONE; |
|
10662
|
1
|
|
|
|
|
|
case 6: |
|
10663
|
1
|
50
|
|
|
|
|
if (!memcmp(str, "remove", 6)) return PATCH_OP_REMOVE; |
|
10664
|
0
|
|
|
|
|
|
return PATCH_OP_NONE; |
|
10665
|
1
|
|
|
|
|
|
case 7: |
|
10666
|
1
|
50
|
|
|
|
|
if (!memcmp(str, "replace", 7)) return PATCH_OP_REPLACE; |
|
10667
|
0
|
|
|
|
|
|
return PATCH_OP_NONE; |
|
10668
|
0
|
|
|
|
|
|
default: |
|
10669
|
0
|
|
|
|
|
|
return PATCH_OP_NONE; |
|
10670
|
|
|
|
|
|
|
} |
|
10671
|
|
|
|
|
|
|
} |
|
10672
|
|
|
|
|
|
|
|
|
10673
|
|
|
|
|
|
|
/* macros for yyjson_patch */ |
|
10674
|
|
|
|
|
|
|
#define return_err(_code, _msg) do { \ |
|
10675
|
|
|
|
|
|
|
if (err->ptr.code == YYJSON_PTR_ERR_MEMORY_ALLOCATION) { \ |
|
10676
|
|
|
|
|
|
|
err->code = YYJSON_PATCH_ERROR_MEMORY_ALLOCATION; \ |
|
10677
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
10678
|
|
|
|
|
|
|
memset(&err->ptr, 0, sizeof(yyjson_ptr_err)); \ |
|
10679
|
|
|
|
|
|
|
} else { \ |
|
10680
|
|
|
|
|
|
|
err->code = YYJSON_PATCH_ERROR_##_code; \ |
|
10681
|
|
|
|
|
|
|
err->msg = _msg; \ |
|
10682
|
|
|
|
|
|
|
err->idx = iter.idx ? iter.idx - 1 : 0; \ |
|
10683
|
|
|
|
|
|
|
} \ |
|
10684
|
|
|
|
|
|
|
return NULL; \ |
|
10685
|
|
|
|
|
|
|
} while (false) |
|
10686
|
|
|
|
|
|
|
|
|
10687
|
|
|
|
|
|
|
#define return_err_copy() \ |
|
10688
|
|
|
|
|
|
|
return_err(MEMORY_ALLOCATION, "failed to copy value") |
|
10689
|
|
|
|
|
|
|
#define return_err_key(_key) \ |
|
10690
|
|
|
|
|
|
|
return_err(MISSING_KEY, "missing key " _key) |
|
10691
|
|
|
|
|
|
|
#define return_err_val(_key) \ |
|
10692
|
|
|
|
|
|
|
return_err(INVALID_MEMBER, "invalid member " _key) |
|
10693
|
|
|
|
|
|
|
|
|
10694
|
|
|
|
|
|
|
#define ptr_get(_ptr) yyjson_mut_ptr_getx( \ |
|
10695
|
|
|
|
|
|
|
root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr) |
|
10696
|
|
|
|
|
|
|
#define ptr_add(_ptr, _val) yyjson_mut_ptr_addx( \ |
|
10697
|
|
|
|
|
|
|
root, _ptr->uni.str, _ptr##_len, _val, doc, false, NULL, &err->ptr) |
|
10698
|
|
|
|
|
|
|
#define ptr_remove(_ptr) yyjson_mut_ptr_removex( \ |
|
10699
|
|
|
|
|
|
|
root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr) |
|
10700
|
|
|
|
|
|
|
#define ptr_replace(_ptr, _val)yyjson_mut_ptr_replacex( \ |
|
10701
|
|
|
|
|
|
|
root, _ptr->uni.str, _ptr##_len, _val, NULL, &err->ptr) |
|
10702
|
|
|
|
|
|
|
|
|
10703
|
0
|
|
|
|
|
|
yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc, |
|
10704
|
|
|
|
|
|
|
yyjson_val *orig, |
|
10705
|
|
|
|
|
|
|
yyjson_val *patch, |
|
10706
|
|
|
|
|
|
|
yyjson_patch_err *err) { |
|
10707
|
|
|
|
|
|
|
|
|
10708
|
|
|
|
|
|
|
yyjson_mut_val *root; |
|
10709
|
|
|
|
|
|
|
yyjson_val *obj; |
|
10710
|
|
|
|
|
|
|
yyjson_arr_iter iter; |
|
10711
|
|
|
|
|
|
|
yyjson_patch_err err_tmp; |
|
10712
|
0
|
0
|
|
|
|
|
if (!err) err = &err_tmp; |
|
10713
|
0
|
|
|
|
|
|
memset(err, 0, sizeof(*err)); |
|
10714
|
0
|
|
|
|
|
|
memset(&iter, 0, sizeof(iter)); |
|
10715
|
|
|
|
|
|
|
|
|
10716
|
0
|
0
|
|
|
|
|
if (unlikely(!doc || !orig || !patch)) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10717
|
0
|
0
|
|
|
|
|
return_err(INVALID_PARAMETER, "input parameter is NULL"); |
|
|
|
0
|
|
|
|
|
|
|
10718
|
|
|
|
|
|
|
} |
|
10719
|
0
|
0
|
|
|
|
|
if (unlikely(!yyjson_is_arr(patch))) { |
|
10720
|
0
|
0
|
|
|
|
|
return_err(INVALID_PARAMETER, "input patch is not array"); |
|
|
|
0
|
|
|
|
|
|
|
10721
|
|
|
|
|
|
|
} |
|
10722
|
0
|
|
|
|
|
|
root = yyjson_val_mut_copy(doc, orig); |
|
10723
|
0
|
0
|
|
|
|
|
if (unlikely(!root)) return_err_copy(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10724
|
|
|
|
|
|
|
|
|
10725
|
|
|
|
|
|
|
/* iterate through the patch array */ |
|
10726
|
|
|
|
|
|
|
yyjson_arr_iter_init(patch, &iter); |
|
10727
|
0
|
0
|
|
|
|
|
while ((obj = yyjson_arr_iter_next(&iter))) { |
|
10728
|
|
|
|
|
|
|
patch_op op_enum; |
|
10729
|
0
|
|
|
|
|
|
yyjson_val *op, *path, *from = NULL, *value; |
|
10730
|
0
|
|
|
|
|
|
yyjson_mut_val *val = NULL, *test; |
|
10731
|
0
|
|
|
|
|
|
usize path_len, from_len = 0; |
|
10732
|
0
|
0
|
|
|
|
|
if (unlikely(!unsafe_yyjson_is_obj(obj))) { |
|
10733
|
0
|
0
|
|
|
|
|
return_err(INVALID_OPERATION, "JSON patch operation is not object"); |
|
|
|
0
|
|
|
|
|
|
|
10734
|
|
|
|
|
|
|
} |
|
10735
|
|
|
|
|
|
|
|
|
10736
|
|
|
|
|
|
|
/* get required member: op */ |
|
10737
|
0
|
|
|
|
|
|
op = yyjson_obj_get(obj, "op"); |
|
10738
|
0
|
0
|
|
|
|
|
if (unlikely(!op)) return_err_key("`op`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10739
|
0
|
0
|
|
|
|
|
if (unlikely(!yyjson_is_str(op))) return_err_val("`op`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10740
|
0
|
|
|
|
|
|
op_enum = patch_op_get(op); |
|
10741
|
|
|
|
|
|
|
|
|
10742
|
|
|
|
|
|
|
/* get required member: path */ |
|
10743
|
0
|
|
|
|
|
|
path = yyjson_obj_get(obj, "path"); |
|
10744
|
0
|
0
|
|
|
|
|
if (unlikely(!path)) return_err_key("`path`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10745
|
0
|
0
|
|
|
|
|
if (unlikely(!yyjson_is_str(path))) return_err_val("`path`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10746
|
0
|
|
|
|
|
|
path_len = unsafe_yyjson_get_len(path); |
|
10747
|
|
|
|
|
|
|
|
|
10748
|
|
|
|
|
|
|
/* get required member: value, from */ |
|
10749
|
0
|
|
|
|
|
|
switch ((int)op_enum) { |
|
10750
|
0
|
0
|
|
|
|
|
case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST: |
|
10751
|
0
|
|
|
|
|
|
value = yyjson_obj_get(obj, "value"); |
|
10752
|
0
|
0
|
|
|
|
|
if (unlikely(!value)) return_err_key("`value`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10753
|
0
|
|
|
|
|
|
val = yyjson_val_mut_copy(doc, value); |
|
10754
|
0
|
0
|
|
|
|
|
if (unlikely(!val)) return_err_copy(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10755
|
0
|
|
|
|
|
|
break; |
|
10756
|
0
|
0
|
|
|
|
|
case PATCH_OP_MOVE: case PATCH_OP_COPY: |
|
10757
|
0
|
|
|
|
|
|
from = yyjson_obj_get(obj, "from"); |
|
10758
|
0
|
0
|
|
|
|
|
if (unlikely(!from)) return_err_key("`from`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10759
|
0
|
0
|
|
|
|
|
if (unlikely(!yyjson_is_str(from))) return_err_val("`from`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10760
|
0
|
|
|
|
|
|
from_len = unsafe_yyjson_get_len(from); |
|
10761
|
0
|
|
|
|
|
|
break; |
|
10762
|
0
|
|
|
|
|
|
default: |
|
10763
|
0
|
|
|
|
|
|
break; |
|
10764
|
|
|
|
|
|
|
} |
|
10765
|
|
|
|
|
|
|
|
|
10766
|
|
|
|
|
|
|
/* perform an operation */ |
|
10767
|
0
|
|
|
|
|
|
switch ((int)op_enum) { |
|
10768
|
0
|
|
|
|
|
|
case PATCH_OP_ADD: /* add(path, val) */ |
|
10769
|
0
|
0
|
|
|
|
|
if (unlikely(path_len == 0)) { root = val; break; } |
|
10770
|
0
|
0
|
|
|
|
|
if (unlikely(!ptr_add(path, val))) { |
|
|
|
0
|
|
|
|
|
|
|
10771
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to add `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10772
|
|
|
|
|
|
|
} |
|
10773
|
0
|
|
|
|
|
|
break; |
|
10774
|
0
|
|
|
|
|
|
case PATCH_OP_REMOVE: /* remove(path) */ |
|
10775
|
0
|
0
|
|
|
|
|
if (unlikely(!ptr_remove(path))) { |
|
|
|
0
|
|
|
|
|
|
|
10776
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to remove `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10777
|
|
|
|
|
|
|
} |
|
10778
|
0
|
|
|
|
|
|
break; |
|
10779
|
0
|
|
|
|
|
|
case PATCH_OP_REPLACE: /* replace(path, val) */ |
|
10780
|
0
|
0
|
|
|
|
|
if (unlikely(path_len == 0)) { root = val; break; } |
|
10781
|
0
|
0
|
|
|
|
|
if (unlikely(!ptr_replace(path, val))) { |
|
|
|
0
|
|
|
|
|
|
|
10782
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to replace `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10783
|
|
|
|
|
|
|
} |
|
10784
|
0
|
|
|
|
|
|
break; |
|
10785
|
0
|
|
|
|
|
|
case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */ |
|
10786
|
0
|
0
|
|
|
|
|
if (unlikely(from_len == 0 && path_len == 0)) break; |
|
|
|
0
|
|
|
|
|
|
|
10787
|
0
|
0
|
|
|
|
|
val = ptr_remove(from); |
|
10788
|
0
|
0
|
|
|
|
|
if (unlikely(!val)) { |
|
10789
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to remove `from`"); |
|
|
|
0
|
|
|
|
|
|
|
10790
|
|
|
|
|
|
|
} |
|
10791
|
0
|
0
|
|
|
|
|
if (unlikely(path_len == 0)) { root = val; break; } |
|
10792
|
0
|
0
|
|
|
|
|
if (unlikely(!ptr_add(path, val))) { |
|
|
|
0
|
|
|
|
|
|
|
10793
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to add `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10794
|
|
|
|
|
|
|
} |
|
10795
|
0
|
|
|
|
|
|
break; |
|
10796
|
0
|
|
|
|
|
|
case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */ |
|
10797
|
0
|
0
|
|
|
|
|
val = ptr_get(from); |
|
10798
|
0
|
0
|
|
|
|
|
if (unlikely(!val)) { |
|
10799
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to get `from`"); |
|
|
|
0
|
|
|
|
|
|
|
10800
|
|
|
|
|
|
|
} |
|
10801
|
0
|
0
|
|
|
|
|
if (unlikely(path_len == 0)) { root = val; break; } |
|
10802
|
0
|
|
|
|
|
|
val = yyjson_mut_val_mut_copy(doc, val); |
|
10803
|
0
|
0
|
|
|
|
|
if (unlikely(!val)) return_err_copy(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10804
|
0
|
0
|
|
|
|
|
if (unlikely(!ptr_add(path, val))) { |
|
|
|
0
|
|
|
|
|
|
|
10805
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to add `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10806
|
|
|
|
|
|
|
} |
|
10807
|
0
|
|
|
|
|
|
break; |
|
10808
|
0
|
|
|
|
|
|
case PATCH_OP_TEST: /* test = get(path), test.eq(val) */ |
|
10809
|
0
|
0
|
|
|
|
|
test = ptr_get(path); |
|
10810
|
0
|
0
|
|
|
|
|
if (unlikely(!test)) { |
|
10811
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to get `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10812
|
|
|
|
|
|
|
} |
|
10813
|
0
|
0
|
|
|
|
|
if (unlikely(!yyjson_mut_equals(val, test))) { |
|
10814
|
0
|
0
|
|
|
|
|
return_err(EQUAL, "failed to test equal"); |
|
|
|
0
|
|
|
|
|
|
|
10815
|
|
|
|
|
|
|
} |
|
10816
|
0
|
|
|
|
|
|
break; |
|
10817
|
0
|
|
|
|
|
|
default: |
|
10818
|
0
|
0
|
|
|
|
|
return_err(INVALID_MEMBER, "unsupported `op`"); |
|
|
|
0
|
|
|
|
|
|
|
10819
|
|
|
|
|
|
|
} |
|
10820
|
|
|
|
|
|
|
} |
|
10821
|
0
|
|
|
|
|
|
return root; |
|
10822
|
|
|
|
|
|
|
} |
|
10823
|
|
|
|
|
|
|
|
|
10824
|
5
|
|
|
|
|
|
yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc, |
|
10825
|
|
|
|
|
|
|
yyjson_mut_val *orig, |
|
10826
|
|
|
|
|
|
|
yyjson_mut_val *patch, |
|
10827
|
|
|
|
|
|
|
yyjson_patch_err *err) { |
|
10828
|
|
|
|
|
|
|
yyjson_mut_val *root, *obj; |
|
10829
|
|
|
|
|
|
|
yyjson_mut_arr_iter iter; |
|
10830
|
|
|
|
|
|
|
yyjson_patch_err err_tmp; |
|
10831
|
5
|
50
|
|
|
|
|
if (!err) err = &err_tmp; |
|
10832
|
5
|
|
|
|
|
|
memset(err, 0, sizeof(*err)); |
|
10833
|
5
|
|
|
|
|
|
memset(&iter, 0, sizeof(iter)); |
|
10834
|
|
|
|
|
|
|
|
|
10835
|
5
|
50
|
|
|
|
|
if (unlikely(!doc || !orig || !patch)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
10836
|
0
|
0
|
|
|
|
|
return_err(INVALID_PARAMETER, "input parameter is NULL"); |
|
|
|
0
|
|
|
|
|
|
|
10837
|
|
|
|
|
|
|
} |
|
10838
|
5
|
50
|
|
|
|
|
if (unlikely(!yyjson_mut_is_arr(patch))) { |
|
10839
|
0
|
0
|
|
|
|
|
return_err(INVALID_PARAMETER, "input patch is not array"); |
|
|
|
0
|
|
|
|
|
|
|
10840
|
|
|
|
|
|
|
} |
|
10841
|
5
|
|
|
|
|
|
root = yyjson_mut_val_mut_copy(doc, orig); |
|
10842
|
5
|
50
|
|
|
|
|
if (unlikely(!root)) return_err_copy(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10843
|
|
|
|
|
|
|
|
|
10844
|
|
|
|
|
|
|
/* iterate through the patch array */ |
|
10845
|
|
|
|
|
|
|
yyjson_mut_arr_iter_init(patch, &iter); |
|
10846
|
16
|
100
|
|
|
|
|
while ((obj = yyjson_mut_arr_iter_next(&iter))) { |
|
10847
|
|
|
|
|
|
|
patch_op op_enum; |
|
10848
|
7
|
|
|
|
|
|
yyjson_mut_val *op, *path, *from = NULL, *value; |
|
10849
|
7
|
|
|
|
|
|
yyjson_mut_val *val = NULL, *test; |
|
10850
|
7
|
|
|
|
|
|
usize path_len, from_len = 0; |
|
10851
|
7
|
50
|
|
|
|
|
if (!unsafe_yyjson_is_obj(obj)) { |
|
10852
|
0
|
0
|
|
|
|
|
return_err(INVALID_OPERATION, "JSON patch operation is not object"); |
|
|
|
0
|
|
|
|
|
|
|
10853
|
|
|
|
|
|
|
} |
|
10854
|
|
|
|
|
|
|
|
|
10855
|
|
|
|
|
|
|
/* get required member: op */ |
|
10856
|
7
|
|
|
|
|
|
op = yyjson_mut_obj_get(obj, "op"); |
|
10857
|
7
|
50
|
|
|
|
|
if (unlikely(!op)) return_err_key("`op`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10858
|
7
|
50
|
|
|
|
|
if (unlikely(!yyjson_mut_is_str(op))) return_err_val("`op`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10859
|
7
|
|
|
|
|
|
op_enum = patch_op_get((yyjson_val *)(void *)op); |
|
10860
|
|
|
|
|
|
|
|
|
10861
|
|
|
|
|
|
|
/* get required member: path */ |
|
10862
|
7
|
|
|
|
|
|
path = yyjson_mut_obj_get(obj, "path"); |
|
10863
|
7
|
50
|
|
|
|
|
if (unlikely(!path)) return_err_key("`path`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10864
|
7
|
50
|
|
|
|
|
if (unlikely(!yyjson_mut_is_str(path))) return_err_val("`path`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10865
|
7
|
|
|
|
|
|
path_len = unsafe_yyjson_get_len(path); |
|
10866
|
|
|
|
|
|
|
|
|
10867
|
|
|
|
|
|
|
/* get required member: value, from */ |
|
10868
|
7
|
|
|
|
|
|
switch ((int)op_enum) { |
|
10869
|
4
|
50
|
|
|
|
|
case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST: |
|
10870
|
4
|
|
|
|
|
|
value = yyjson_mut_obj_get(obj, "value"); |
|
10871
|
4
|
50
|
|
|
|
|
if (unlikely(!value)) return_err_key("`value`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10872
|
4
|
|
|
|
|
|
val = yyjson_mut_val_mut_copy(doc, value); |
|
10873
|
4
|
50
|
|
|
|
|
if (unlikely(!val)) return_err_copy(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10874
|
4
|
|
|
|
|
|
break; |
|
10875
|
2
|
50
|
|
|
|
|
case PATCH_OP_MOVE: case PATCH_OP_COPY: |
|
10876
|
2
|
|
|
|
|
|
from = yyjson_mut_obj_get(obj, "from"); |
|
10877
|
2
|
50
|
|
|
|
|
if (unlikely(!from)) return_err_key("`from`"); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10878
|
2
|
50
|
|
|
|
|
if (unlikely(!yyjson_mut_is_str(from))) { |
|
10879
|
0
|
0
|
|
|
|
|
return_err_val("`from`"); |
|
|
|
0
|
|
|
|
|
|
|
10880
|
|
|
|
|
|
|
} |
|
10881
|
2
|
|
|
|
|
|
from_len = unsafe_yyjson_get_len(from); |
|
10882
|
2
|
|
|
|
|
|
break; |
|
10883
|
1
|
|
|
|
|
|
default: |
|
10884
|
1
|
|
|
|
|
|
break; |
|
10885
|
|
|
|
|
|
|
} |
|
10886
|
|
|
|
|
|
|
|
|
10887
|
|
|
|
|
|
|
/* perform an operation */ |
|
10888
|
7
|
|
|
|
|
|
switch ((int)op_enum) { |
|
10889
|
1
|
|
|
|
|
|
case PATCH_OP_ADD: /* add(path, val) */ |
|
10890
|
1
|
50
|
|
|
|
|
if (unlikely(path_len == 0)) { root = val; break; } |
|
10891
|
2
|
50
|
|
|
|
|
if (unlikely(!ptr_add(path, val))) { |
|
|
|
50
|
|
|
|
|
|
|
10892
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to add `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10893
|
|
|
|
|
|
|
} |
|
10894
|
1
|
|
|
|
|
|
break; |
|
10895
|
1
|
|
|
|
|
|
case PATCH_OP_REMOVE: /* remove(path) */ |
|
10896
|
2
|
50
|
|
|
|
|
if (unlikely(!ptr_remove(path))) { |
|
|
|
50
|
|
|
|
|
|
|
10897
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to remove `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10898
|
|
|
|
|
|
|
} |
|
10899
|
1
|
|
|
|
|
|
break; |
|
10900
|
1
|
|
|
|
|
|
case PATCH_OP_REPLACE: /* replace(path, val) */ |
|
10901
|
1
|
50
|
|
|
|
|
if (unlikely(path_len == 0)) { root = val; break; } |
|
10902
|
2
|
50
|
|
|
|
|
if (unlikely(!ptr_replace(path, val))) { |
|
|
|
50
|
|
|
|
|
|
|
10903
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to replace `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10904
|
|
|
|
|
|
|
} |
|
10905
|
1
|
|
|
|
|
|
break; |
|
10906
|
1
|
|
|
|
|
|
case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */ |
|
10907
|
1
|
50
|
|
|
|
|
if (unlikely(from_len == 0 && path_len == 0)) break; |
|
|
|
0
|
|
|
|
|
|
|
10908
|
1
|
50
|
|
|
|
|
val = ptr_remove(from); |
|
10909
|
1
|
50
|
|
|
|
|
if (unlikely(!val)) { |
|
10910
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to remove `from`"); |
|
|
|
0
|
|
|
|
|
|
|
10911
|
|
|
|
|
|
|
} |
|
10912
|
1
|
50
|
|
|
|
|
if (unlikely(path_len == 0)) { root = val; break; } |
|
10913
|
2
|
50
|
|
|
|
|
if (unlikely(!ptr_add(path, val))) { |
|
|
|
50
|
|
|
|
|
|
|
10914
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to add `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10915
|
|
|
|
|
|
|
} |
|
10916
|
1
|
|
|
|
|
|
break; |
|
10917
|
1
|
|
|
|
|
|
case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */ |
|
10918
|
1
|
50
|
|
|
|
|
val = ptr_get(from); |
|
10919
|
1
|
50
|
|
|
|
|
if (unlikely(!val)) { |
|
10920
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to get `from`"); |
|
|
|
0
|
|
|
|
|
|
|
10921
|
|
|
|
|
|
|
} |
|
10922
|
1
|
50
|
|
|
|
|
if (unlikely(path_len == 0)) { root = val; break; } |
|
10923
|
1
|
|
|
|
|
|
val = yyjson_mut_val_mut_copy(doc, val); |
|
10924
|
1
|
50
|
|
|
|
|
if (unlikely(!val)) return_err_copy(); |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10925
|
2
|
50
|
|
|
|
|
if (unlikely(!ptr_add(path, val))) { |
|
|
|
50
|
|
|
|
|
|
|
10926
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to add `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10927
|
|
|
|
|
|
|
} |
|
10928
|
1
|
|
|
|
|
|
break; |
|
10929
|
2
|
|
|
|
|
|
case PATCH_OP_TEST: /* test = get(path), test.eq(val) */ |
|
10930
|
2
|
50
|
|
|
|
|
test = ptr_get(path); |
|
10931
|
2
|
50
|
|
|
|
|
if (unlikely(!test)) { |
|
10932
|
0
|
0
|
|
|
|
|
return_err(POINTER, "failed to get `path`"); |
|
|
|
0
|
|
|
|
|
|
|
10933
|
|
|
|
|
|
|
} |
|
10934
|
2
|
100
|
|
|
|
|
if (unlikely(!yyjson_mut_equals(val, test))) { |
|
10935
|
1
|
50
|
|
|
|
|
return_err(EQUAL, "failed to test equal"); |
|
|
|
50
|
|
|
|
|
|
|
10936
|
|
|
|
|
|
|
} |
|
10937
|
1
|
|
|
|
|
|
break; |
|
10938
|
0
|
|
|
|
|
|
default: |
|
10939
|
0
|
0
|
|
|
|
|
return_err(INVALID_MEMBER, "unsupported `op`"); |
|
|
|
0
|
|
|
|
|
|
|
10940
|
|
|
|
|
|
|
} |
|
10941
|
|
|
|
|
|
|
} |
|
10942
|
4
|
|
|
|
|
|
return root; |
|
10943
|
|
|
|
|
|
|
} |
|
10944
|
|
|
|
|
|
|
|
|
10945
|
|
|
|
|
|
|
/* macros for yyjson_patch */ |
|
10946
|
|
|
|
|
|
|
#undef return_err |
|
10947
|
|
|
|
|
|
|
#undef return_err_copy |
|
10948
|
|
|
|
|
|
|
#undef return_err_key |
|
10949
|
|
|
|
|
|
|
#undef return_err_val |
|
10950
|
|
|
|
|
|
|
#undef ptr_get |
|
10951
|
|
|
|
|
|
|
#undef ptr_add |
|
10952
|
|
|
|
|
|
|
#undef ptr_remove |
|
10953
|
|
|
|
|
|
|
#undef ptr_replace |
|
10954
|
|
|
|
|
|
|
|
|
10955
|
|
|
|
|
|
|
|
|
10956
|
|
|
|
|
|
|
|
|
10957
|
|
|
|
|
|
|
/*============================================================================== |
|
10958
|
|
|
|
|
|
|
* MARK: - JSON Merge-Patch API (RFC 7386) (Public) |
|
10959
|
|
|
|
|
|
|
*============================================================================*/ |
|
10960
|
|
|
|
|
|
|
|
|
10961
|
0
|
0
|
|
|
|
|
yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, |
|
10962
|
|
|
|
|
|
|
yyjson_val *orig, |
|
10963
|
|
|
|
|
|
|
yyjson_val *patch) { |
|
10964
|
|
|
|
|
|
|
usize idx, max; |
|
10965
|
|
|
|
|
|
|
yyjson_val *key, *orig_val, *patch_val, local_orig; |
|
10966
|
|
|
|
|
|
|
yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val; |
|
10967
|
|
|
|
|
|
|
|
|
10968
|
0
|
0
|
|
|
|
|
if (unlikely(!yyjson_is_obj(patch))) { |
|
10969
|
0
|
|
|
|
|
|
return yyjson_val_mut_copy(doc, patch); |
|
10970
|
|
|
|
|
|
|
} |
|
10971
|
|
|
|
|
|
|
|
|
10972
|
0
|
|
|
|
|
|
builder = yyjson_mut_obj(doc); |
|
10973
|
0
|
0
|
|
|
|
|
if (unlikely(!builder)) return NULL; |
|
10974
|
|
|
|
|
|
|
|
|
10975
|
0
|
0
|
|
|
|
|
memset(&local_orig, 0, sizeof(local_orig)); |
|
10976
|
0
|
0
|
|
|
|
|
if (!yyjson_is_obj(orig)) { |
|
10977
|
0
|
|
|
|
|
|
orig = &local_orig; |
|
10978
|
0
|
|
|
|
|
|
orig->tag = builder->tag; |
|
10979
|
0
|
|
|
|
|
|
orig->uni = builder->uni; |
|
10980
|
|
|
|
|
|
|
} |
|
10981
|
|
|
|
|
|
|
|
|
10982
|
|
|
|
|
|
|
/* If orig is contributing, copy any items not modified by the patch */ |
|
10983
|
0
|
0
|
|
|
|
|
if (orig != &local_orig) { |
|
10984
|
0
|
0
|
|
|
|
|
yyjson_obj_foreach(orig, idx, max, key, orig_val) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10985
|
0
|
0
|
|
|
|
|
patch_val = yyjson_obj_getn(patch, |
|
10986
|
|
|
|
|
|
|
unsafe_yyjson_get_str(key), |
|
10987
|
|
|
|
|
|
|
unsafe_yyjson_get_len(key)); |
|
10988
|
0
|
0
|
|
|
|
|
if (!patch_val) { |
|
10989
|
0
|
|
|
|
|
|
mut_key = yyjson_val_mut_copy(doc, key); |
|
10990
|
0
|
|
|
|
|
|
mut_val = yyjson_val_mut_copy(doc, orig_val); |
|
10991
|
0
|
0
|
|
|
|
|
if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; |
|
10992
|
|
|
|
|
|
|
} |
|
10993
|
|
|
|
|
|
|
} |
|
10994
|
|
|
|
|
|
|
} |
|
10995
|
|
|
|
|
|
|
|
|
10996
|
|
|
|
|
|
|
/* Merge items modified by the patch. */ |
|
10997
|
0
|
0
|
|
|
|
|
yyjson_obj_foreach(patch, idx, max, key, patch_val) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10998
|
|
|
|
|
|
|
/* null indicates the field is removed. */ |
|
10999
|
0
|
0
|
|
|
|
|
if (unsafe_yyjson_is_null(patch_val)) { |
|
11000
|
0
|
|
|
|
|
|
continue; |
|
11001
|
|
|
|
|
|
|
} |
|
11002
|
0
|
|
|
|
|
|
mut_key = yyjson_val_mut_copy(doc, key); |
|
11003
|
0
|
0
|
|
|
|
|
orig_val = yyjson_obj_getn(orig, |
|
11004
|
|
|
|
|
|
|
unsafe_yyjson_get_str(key), |
|
11005
|
|
|
|
|
|
|
unsafe_yyjson_get_len(key)); |
|
11006
|
0
|
|
|
|
|
|
merged_val = yyjson_merge_patch(doc, orig_val, patch_val); |
|
11007
|
0
|
0
|
|
|
|
|
if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL; |
|
11008
|
|
|
|
|
|
|
} |
|
11009
|
|
|
|
|
|
|
|
|
11010
|
0
|
|
|
|
|
|
return builder; |
|
11011
|
|
|
|
|
|
|
} |
|
11012
|
|
|
|
|
|
|
|
|
11013
|
5
|
50
|
|
|
|
|
yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, |
|
11014
|
|
|
|
|
|
|
yyjson_mut_val *orig, |
|
11015
|
|
|
|
|
|
|
yyjson_mut_val *patch) { |
|
11016
|
|
|
|
|
|
|
usize idx, max; |
|
11017
|
|
|
|
|
|
|
yyjson_mut_val *key, *orig_val, *patch_val, local_orig; |
|
11018
|
|
|
|
|
|
|
yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val; |
|
11019
|
|
|
|
|
|
|
|
|
11020
|
5
|
100
|
|
|
|
|
if (unlikely(!yyjson_mut_is_obj(patch))) { |
|
11021
|
3
|
|
|
|
|
|
return yyjson_mut_val_mut_copy(doc, patch); |
|
11022
|
|
|
|
|
|
|
} |
|
11023
|
|
|
|
|
|
|
|
|
11024
|
2
|
|
|
|
|
|
builder = yyjson_mut_obj(doc); |
|
11025
|
2
|
50
|
|
|
|
|
if (unlikely(!builder)) return NULL; |
|
11026
|
|
|
|
|
|
|
|
|
11027
|
2
|
50
|
|
|
|
|
memset(&local_orig, 0, sizeof(local_orig)); |
|
11028
|
2
|
50
|
|
|
|
|
if (!yyjson_mut_is_obj(orig)) { |
|
11029
|
0
|
|
|
|
|
|
orig = &local_orig; |
|
11030
|
0
|
|
|
|
|
|
orig->tag = builder->tag; |
|
11031
|
0
|
|
|
|
|
|
orig->uni = builder->uni; |
|
11032
|
|
|
|
|
|
|
} |
|
11033
|
|
|
|
|
|
|
|
|
11034
|
|
|
|
|
|
|
/* If orig is contributing, copy any items not modified by the patch */ |
|
11035
|
2
|
50
|
|
|
|
|
if (orig != &local_orig) { |
|
11036
|
8
|
50
|
|
|
|
|
yyjson_mut_obj_foreach(orig, idx, max, key, orig_val) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
11037
|
8
|
50
|
|
|
|
|
patch_val = yyjson_mut_obj_getn(patch, |
|
11038
|
|
|
|
|
|
|
unsafe_yyjson_get_str(key), |
|
11039
|
|
|
|
|
|
|
unsafe_yyjson_get_len(key)); |
|
11040
|
4
|
100
|
|
|
|
|
if (!patch_val) { |
|
11041
|
1
|
|
|
|
|
|
mut_key = yyjson_mut_val_mut_copy(doc, key); |
|
11042
|
1
|
|
|
|
|
|
mut_val = yyjson_mut_val_mut_copy(doc, orig_val); |
|
11043
|
1
|
50
|
|
|
|
|
if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; |
|
11044
|
|
|
|
|
|
|
} |
|
11045
|
|
|
|
|
|
|
} |
|
11046
|
|
|
|
|
|
|
} |
|
11047
|
|
|
|
|
|
|
|
|
11048
|
|
|
|
|
|
|
/* Merge items modified by the patch. */ |
|
11049
|
9
|
50
|
|
|
|
|
yyjson_mut_obj_foreach(patch, idx, max, key, patch_val) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
11050
|
|
|
|
|
|
|
/* null indicates the field is removed. */ |
|
11051
|
5
|
100
|
|
|
|
|
if (unsafe_yyjson_is_null(patch_val)) { |
|
11052
|
1
|
|
|
|
|
|
continue; |
|
11053
|
|
|
|
|
|
|
} |
|
11054
|
4
|
|
|
|
|
|
mut_key = yyjson_mut_val_mut_copy(doc, key); |
|
11055
|
8
|
50
|
|
|
|
|
orig_val = yyjson_mut_obj_getn(orig, |
|
11056
|
|
|
|
|
|
|
unsafe_yyjson_get_str(key), |
|
11057
|
|
|
|
|
|
|
unsafe_yyjson_get_len(key)); |
|
11058
|
4
|
|
|
|
|
|
merged_val = yyjson_mut_merge_patch(doc, orig_val, patch_val); |
|
11059
|
4
|
50
|
|
|
|
|
if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL; |
|
11060
|
|
|
|
|
|
|
} |
|
11061
|
|
|
|
|
|
|
|
|
11062
|
2
|
|
|
|
|
|
return builder; |
|
11063
|
|
|
|
|
|
|
} |
|
11064
|
|
|
|
|
|
|
|
|
11065
|
|
|
|
|
|
|
#endif /* YYJSON_DISABLE_UTILS */ |