koffi 2.14.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -1
- package/README.md +1 -1
- package/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_armhf/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_loong64/koffi.node +0 -0
- package/build/koffi/linux_riscv64d/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/musl_arm64/koffi.node +0 -0
- package/build/koffi/musl_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/doc/assets.ini +2 -1
- package/doc/build.sh +9 -0
- package/doc/pages/404.md +17 -0
- package/doc/pages/index.md +43 -4
- package/doc/pages/misc.md +16 -11
- package/doc/pages/platforms.md +8 -19
- package/doc/pages.ini +4 -7
- package/doc/static/highlight.js +2 -14
- package/doc/static/koffi.css +3 -15
- package/doc/static/perf_windows.png +0 -0
- package/doc/static/print.css +2 -14
- package/index.d.ts +29 -24
- package/index.js +10 -9
- package/indirect.js +10 -9
- package/{src/core → lib/native}/base/base.cc +1753 -1089
- package/{src/core → lib/native}/base/base.hh +868 -572
- package/{src/core → lib/native}/base/crc.inc +3 -21
- package/lib/native/base/crc_gen.py +72 -0
- package/{src/core → lib/native}/base/mimetypes.inc +2 -20
- package/{src/core → lib/native}/base/mimetypes_gen.py +2 -21
- package/lib/native/base/tower.cc +821 -0
- package/lib/native/base/tower.hh +81 -0
- package/{src/core → lib/native}/base/unicode.inc +3 -21
- package/{src/core → lib/native}/base/unicode_gen.py +5 -42
- package/package.json +3 -2
- package/src/cnoke/assets/FindCNoke.cmake +8 -20
- package/src/cnoke/assets/win_delay_hook.c +2 -20
- package/src/cnoke/cnoke.js +2 -21
- package/src/cnoke/src/builder.js +3 -22
- package/src/cnoke/src/index.js +2 -20
- package/src/cnoke/src/tools.js +2 -20
- package/src/koffi/CMakeLists.txt +19 -22
- package/src/koffi/cmake/raylib.cmake +5 -22
- package/src/koffi/cmake/sqlite3.cmake +2 -20
- package/src/koffi/src/abi_arm32.cc +31 -49
- package/src/koffi/src/abi_arm32_asm.S +2 -20
- package/src/koffi/src/abi_arm64.cc +36 -54
- package/src/koffi/src/abi_arm64_asm.S +2 -20
- package/src/koffi/src/abi_arm64_asm.asm +2 -20
- package/src/koffi/src/abi_loong64.cc +2 -20
- package/src/koffi/src/abi_loong64_asm.S +2 -20
- package/src/koffi/src/abi_riscv64.cc +34 -52
- package/src/koffi/src/abi_riscv64_asm.S +2 -20
- package/src/koffi/src/abi_x64_sysv.cc +36 -54
- package/src/koffi/src/abi_x64_sysv_asm.S +2 -20
- package/src/koffi/src/abi_x64_win.cc +32 -50
- package/src/koffi/src/abi_x64_win_asm.asm +2 -20
- package/src/koffi/src/abi_x86.cc +33 -51
- package/src/koffi/src/abi_x86_asm.S +2 -20
- package/src/koffi/src/abi_x86_asm.asm +2 -20
- package/src/koffi/src/call.cc +107 -281
- package/src/koffi/src/call.hh +9 -27
- package/src/koffi/src/errno.inc +2 -20
- package/src/koffi/src/ffi.cc +121 -121
- package/src/koffi/src/ffi.hh +23 -38
- package/src/koffi/src/init.js +2 -20
- package/src/koffi/src/parser.cc +15 -29
- package/src/koffi/src/parser.hh +4 -22
- package/src/koffi/src/trampolines/armasm.inc +0 -21
- package/src/koffi/src/trampolines/gnu.inc +0 -21
- package/src/koffi/src/trampolines/masm32.inc +0 -21
- package/src/koffi/src/trampolines/masm64.inc +0 -21
- package/src/koffi/src/trampolines/prototypes.inc +1 -22
- package/src/koffi/src/util.cc +87 -102
- package/src/koffi/src/util.hh +11 -29
- package/src/koffi/src/uv.cc +193 -0
- package/src/koffi/src/uv.def +10 -0
- package/src/koffi/src/uv.hh +40 -0
- package/src/koffi/src/win32.cc +7 -25
- package/src/koffi/src/win32.hh +4 -22
- package/vendor/node-api-headers/include/uv/aix.h +32 -0
- package/vendor/node-api-headers/include/uv/bsd.h +34 -0
- package/vendor/node-api-headers/include/uv/darwin.h +61 -0
- package/vendor/node-api-headers/include/uv/errno.h +483 -0
- package/vendor/node-api-headers/include/uv/linux.h +34 -0
- package/vendor/node-api-headers/include/uv/os390.h +33 -0
- package/vendor/node-api-headers/include/uv/posix.h +31 -0
- package/vendor/node-api-headers/include/uv/sunos.h +44 -0
- package/vendor/node-api-headers/include/uv/threadpool.h +37 -0
- package/vendor/node-api-headers/include/uv/tree.h +521 -0
- package/vendor/node-api-headers/include/uv/unix.h +512 -0
- package/vendor/node-api-headers/include/uv/version.h +43 -0
- package/vendor/node-api-headers/include/uv/win.h +698 -0
- package/vendor/node-api-headers/include/uv.h +1990 -0
- package/src/core/base/crc_gen.py +0 -109
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
-
// this software and associated documentation files (the “Software”), to deal in
|
|
5
|
-
// the Software without restriction, including without limitation the rights to use,
|
|
6
|
-
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
7
|
-
// Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
-
// subject to the following conditions:
|
|
9
|
-
|
|
10
|
-
// The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
// copies or substantial portions of the Software.
|
|
12
|
-
|
|
13
|
-
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
14
|
-
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
15
|
-
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
|
-
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
-
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
18
|
-
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
19
|
-
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
20
|
-
// OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
|
|
21
3
|
|
|
22
4
|
#pragma once
|
|
23
5
|
|
|
@@ -75,38 +57,40 @@
|
|
|
75
57
|
struct sigaction;
|
|
76
58
|
struct BrotliEncoderStateStruct;
|
|
77
59
|
|
|
78
|
-
namespace
|
|
60
|
+
namespace K {
|
|
79
61
|
|
|
80
62
|
// ------------------------------------------------------------------------
|
|
81
63
|
// Config
|
|
82
64
|
// ------------------------------------------------------------------------
|
|
83
65
|
|
|
84
66
|
#if !defined(NDEBUG)
|
|
85
|
-
#define
|
|
67
|
+
#define K_DEBUG
|
|
86
68
|
#endif
|
|
87
69
|
|
|
88
|
-
#define
|
|
89
|
-
#define
|
|
70
|
+
#define K_DEFAULT_ALLOCATOR MallocAllocator
|
|
71
|
+
#define K_BLOCK_ALLOCATOR_DEFAULT_SIZE Kibibytes(4)
|
|
90
72
|
|
|
91
|
-
#define
|
|
92
|
-
#define
|
|
73
|
+
#define K_HEAPARRAY_BASE_CAPACITY 8
|
|
74
|
+
#define K_HEAPARRAY_GROWTH_FACTOR 2.0
|
|
93
75
|
|
|
94
76
|
// Must be a power-of-two
|
|
95
|
-
#define
|
|
96
|
-
#define
|
|
77
|
+
#define K_HASHTABLE_BASE_CAPACITY 8
|
|
78
|
+
#define K_HASHTABLE_MAX_LOAD_FACTOR 0.5
|
|
97
79
|
|
|
98
|
-
#define
|
|
99
|
-
#define
|
|
80
|
+
#define K_FMT_STRING_BASE_CAPACITY 256
|
|
81
|
+
#define K_FMT_STRING_PRINT_BUFFER_SIZE 1024
|
|
100
82
|
|
|
101
|
-
#define
|
|
83
|
+
#define K_LINE_READER_STEP_SIZE 65536
|
|
102
84
|
|
|
103
|
-
#define
|
|
104
|
-
#define
|
|
105
|
-
#define
|
|
85
|
+
#define K_ASYNC_MAX_THREADS 2048
|
|
86
|
+
#define K_ASYNC_MAX_IDLE_TIME 10000
|
|
87
|
+
#define K_ASYNC_MAX_PENDING_TASKS 2048
|
|
106
88
|
|
|
107
|
-
#define
|
|
108
|
-
#define
|
|
109
|
-
#define
|
|
89
|
+
#define K_PROGRESS_MAX_NODES 400
|
|
90
|
+
#define K_PROGRESS_USED_NODES 100
|
|
91
|
+
#define K_PROGRESS_TEXT_SIZE 64
|
|
92
|
+
|
|
93
|
+
#define K_COMPLETE_PATH_LIMIT 256
|
|
110
94
|
|
|
111
95
|
// ------------------------------------------------------------------------
|
|
112
96
|
// Utility
|
|
@@ -125,13 +109,13 @@ extern StreamWriter *const StdErr;
|
|
|
125
109
|
|
|
126
110
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) || __riscv_xlen == 64 || defined(__loongarch64)
|
|
127
111
|
typedef int64_t Size;
|
|
128
|
-
#define
|
|
112
|
+
#define K_SIZE_MAX INT64_MAX
|
|
129
113
|
#elif defined(_WIN32) || defined(__APPLE__) || defined(__unix__)
|
|
130
114
|
typedef int32_t Size;
|
|
131
|
-
#define
|
|
115
|
+
#define K_SIZE_MAX INT32_MAX
|
|
132
116
|
#elif defined(__thumb__) || defined(__arm__) || defined(__wasm32__)
|
|
133
117
|
typedef int32_t Size;
|
|
134
|
-
#define
|
|
118
|
+
#define K_SIZE_MAX INT32_MAX
|
|
135
119
|
#else
|
|
136
120
|
#error Machine architecture not supported
|
|
137
121
|
#endif
|
|
@@ -139,7 +123,7 @@ extern StreamWriter *const StdErr;
|
|
|
139
123
|
#if defined(_MSC_VER) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
140
124
|
// Sane platform
|
|
141
125
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
142
|
-
#define
|
|
126
|
+
#define K_BIG_ENDIAN
|
|
143
127
|
#else
|
|
144
128
|
#error This code base is not designed to support platforms with crazy endianness
|
|
145
129
|
#endif
|
|
@@ -152,16 +136,16 @@ extern StreamWriter *const StdErr;
|
|
|
152
136
|
#endif
|
|
153
137
|
static_assert(sizeof(double) == 8, "This code base is not designed to support single-precision double floats");
|
|
154
138
|
|
|
155
|
-
#define
|
|
156
|
-
#define
|
|
157
|
-
#define
|
|
158
|
-
#define
|
|
159
|
-
#define
|
|
160
|
-
#define
|
|
161
|
-
#define
|
|
139
|
+
#define K_STRINGIFY_(a) #a
|
|
140
|
+
#define K_STRINGIFY(a) K_STRINGIFY_(a)
|
|
141
|
+
#define K_CONCAT_(a, b) a ## b
|
|
142
|
+
#define K_CONCAT(a, b) K_CONCAT_(a, b)
|
|
143
|
+
#define K_UNIQUE_NAME(prefix) K_CONCAT(prefix, __LINE__)
|
|
144
|
+
#define K_FORCE_EXPAND(x) x
|
|
145
|
+
#define K_IGNORE (void)!
|
|
162
146
|
|
|
163
147
|
#if defined(__GNUC__) || defined(__clang__)
|
|
164
|
-
#define
|
|
148
|
+
#define K_PUSH_NO_WARNINGS \
|
|
165
149
|
_Pragma("GCC diagnostic push") \
|
|
166
150
|
_Pragma("GCC diagnostic ignored \"-Wall\"") \
|
|
167
151
|
_Pragma("GCC diagnostic ignored \"-Wextra\"") \
|
|
@@ -173,7 +157,7 @@ static_assert(sizeof(double) == 8, "This code base is not designed to support si
|
|
|
173
157
|
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"") \
|
|
174
158
|
_Pragma("GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"") \
|
|
175
159
|
_Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
|
|
176
|
-
#define
|
|
160
|
+
#define K_POP_NO_WARNINGS \
|
|
177
161
|
_Pragma("GCC diagnostic pop")
|
|
178
162
|
|
|
179
163
|
#if !defined(SCNd8)
|
|
@@ -186,8 +170,8 @@ static_assert(sizeof(double) == 8, "This code base is not designed to support si
|
|
|
186
170
|
#define SCNu8 "hhu"
|
|
187
171
|
#endif
|
|
188
172
|
#elif defined(_MSC_VER)
|
|
189
|
-
#define
|
|
190
|
-
#define
|
|
173
|
+
#define K_PUSH_NO_WARNINGS __pragma(warning(push, 0))
|
|
174
|
+
#define K_POP_NO_WARNINGS __pragma(warning(pop))
|
|
191
175
|
|
|
192
176
|
#define __restrict__ __restrict
|
|
193
177
|
#else
|
|
@@ -209,73 +193,73 @@ static_assert(sizeof(double) == 8, "This code base is not designed to support si
|
|
|
209
193
|
extern "C" void AssertMessage(const char *filename, int line, const char *cond);
|
|
210
194
|
|
|
211
195
|
#if defined(_MSC_VER)
|
|
212
|
-
#define
|
|
196
|
+
#define K_DEBUG_BREAK() __debugbreak()
|
|
213
197
|
#elif defined(__clang__)
|
|
214
|
-
#define
|
|
198
|
+
#define K_DEBUG_BREAK() __builtin_debugtrap()
|
|
215
199
|
#elif defined(__i386__) || defined(__x86_64__)
|
|
216
|
-
#define
|
|
200
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__("int $0x03")
|
|
217
201
|
#elif defined(__thumb__)
|
|
218
|
-
#define
|
|
202
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__(".inst 0xde01")
|
|
219
203
|
#elif defined(__aarch64__)
|
|
220
|
-
#define
|
|
204
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__(".inst 0xd4200000")
|
|
221
205
|
#elif defined(__arm__)
|
|
222
|
-
#define
|
|
206
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__(".inst 0xe7f001f0")
|
|
223
207
|
#elif defined(__riscv)
|
|
224
|
-
#define
|
|
208
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__("ebreak")
|
|
225
209
|
#elif defined(__loongarch64)
|
|
226
|
-
#define
|
|
210
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__("break 1")
|
|
227
211
|
#endif
|
|
228
212
|
|
|
229
213
|
#if defined(_MSC_VER) || __EXCEPTIONS
|
|
230
|
-
#define
|
|
214
|
+
#define K_BAD_ALLOC() \
|
|
231
215
|
do { \
|
|
232
216
|
throw std::bad_alloc(); \
|
|
233
217
|
} while (false)
|
|
234
218
|
#else
|
|
235
|
-
#define
|
|
219
|
+
#define K_BAD_ALLOC() \
|
|
236
220
|
do { \
|
|
237
221
|
PrintLn(StdErr, "Memory allocation failed"); \
|
|
238
222
|
abort(); \
|
|
239
223
|
} while (false);
|
|
240
224
|
#endif
|
|
241
225
|
|
|
242
|
-
#define
|
|
226
|
+
#define K_CRITICAL(Cond, ...) \
|
|
243
227
|
do { \
|
|
244
228
|
if (!(Cond)) [[unlikely]] { \
|
|
245
229
|
PrintLn(StdErr, __VA_ARGS__); \
|
|
246
230
|
abort(); \
|
|
247
231
|
} \
|
|
248
232
|
} while (false)
|
|
249
|
-
#if defined(
|
|
250
|
-
#define
|
|
233
|
+
#if defined(K_DEBUG)
|
|
234
|
+
#define K_ASSERT(Cond) \
|
|
251
235
|
do { \
|
|
252
236
|
if (!(Cond)) [[unlikely]] { \
|
|
253
|
-
|
|
254
|
-
|
|
237
|
+
K::AssertMessage(__FILE__, __LINE__, K_STRINGIFY(Cond)); \
|
|
238
|
+
K_DEBUG_BREAK(); \
|
|
255
239
|
abort(); \
|
|
256
240
|
} \
|
|
257
241
|
} while (false)
|
|
258
242
|
#else
|
|
259
|
-
#define
|
|
243
|
+
#define K_ASSERT(Cond) \
|
|
260
244
|
do { \
|
|
261
245
|
(void)sizeof(Cond); \
|
|
262
246
|
} while (false)
|
|
263
247
|
#endif
|
|
264
248
|
|
|
265
|
-
#if defined(
|
|
266
|
-
#define
|
|
249
|
+
#if defined(K_DEBUG)
|
|
250
|
+
#define K_UNREACHABLE() \
|
|
267
251
|
do { \
|
|
268
|
-
|
|
269
|
-
|
|
252
|
+
K::AssertMessage(__FILE__, __LINE__, "Reached code marked as UNREACHABLE"); \
|
|
253
|
+
K_DEBUG_BREAK(); \
|
|
270
254
|
abort(); \
|
|
271
255
|
} while (false)
|
|
272
256
|
#elif defined(__GNUC__) || defined(__clang__)
|
|
273
|
-
#define
|
|
257
|
+
#define K_UNREACHABLE() __builtin_unreachable()
|
|
274
258
|
#else
|
|
275
|
-
#define
|
|
259
|
+
#define K_UNREACHABLE() __assume(0)
|
|
276
260
|
#endif
|
|
277
261
|
|
|
278
|
-
#define
|
|
262
|
+
#define K_DELETE_COPY(Cls) \
|
|
279
263
|
Cls(const Cls&) = delete; \
|
|
280
264
|
Cls &operator=(const Cls&) = delete;
|
|
281
265
|
|
|
@@ -289,11 +273,11 @@ constexpr Size Kibibytes(Size len) { return len * 1024; }
|
|
|
289
273
|
constexpr Size Megabytes(Size len) { return len * 1000 * 1000; }
|
|
290
274
|
constexpr Size Kilobytes(Size len) { return len * 1000; }
|
|
291
275
|
|
|
292
|
-
#define
|
|
276
|
+
#define K_SIZE(Type) ((K::Size)sizeof(Type))
|
|
293
277
|
template <typename T, unsigned N>
|
|
294
278
|
char (&ComputeArraySize(T const (&)[N]))[N];
|
|
295
|
-
#define
|
|
296
|
-
#define
|
|
279
|
+
#define K_BITS(Type) (8 * K_SIZE(Type))
|
|
280
|
+
#define K_LEN(Array) K_SIZE(K::ComputeArraySize(Array))
|
|
297
281
|
|
|
298
282
|
static constexpr inline uint16_t ReverseBytes(uint16_t u)
|
|
299
283
|
{
|
|
@@ -328,7 +312,7 @@ static constexpr inline int32_t ReverseBytes(int32_t i)
|
|
|
328
312
|
static constexpr inline int64_t ReverseBytes(int64_t i)
|
|
329
313
|
{ return (int64_t)ReverseBytes((uint64_t)i); }
|
|
330
314
|
|
|
331
|
-
#if defined(
|
|
315
|
+
#if defined(K_BIG_ENDIAN)
|
|
332
316
|
template <typename T>
|
|
333
317
|
constexpr T LittleEndian(T v) { return ReverseBytes(v); }
|
|
334
318
|
template <typename T>
|
|
@@ -478,9 +462,9 @@ constexpr T BigEndian(T v) { return ReverseBytes(v); }
|
|
|
478
462
|
#endif
|
|
479
463
|
|
|
480
464
|
#if __cplusplus >= 202002L && (defined(_MSC_VER) || defined(__clang__) || __GNUC__ >= 11)
|
|
481
|
-
#define
|
|
465
|
+
#define K_CONSTINIT constinit
|
|
482
466
|
#else
|
|
483
|
-
#define
|
|
467
|
+
#define K_CONSTINIT const
|
|
484
468
|
#endif
|
|
485
469
|
|
|
486
470
|
static inline Size AlignLen(Size len, Size align)
|
|
@@ -507,7 +491,7 @@ static inline T *AlignDown(T *ptr, Size align)
|
|
|
507
491
|
// even if length is 0. This is dumb, work around this.
|
|
508
492
|
static inline void *MemCpy(void *__restrict__ dest, const void *__restrict__ src, Size len)
|
|
509
493
|
{
|
|
510
|
-
|
|
494
|
+
K_ASSERT(len >= 0);
|
|
511
495
|
|
|
512
496
|
#if defined(__clang__)
|
|
513
497
|
// LLVM guarantees sane behavior
|
|
@@ -521,7 +505,7 @@ static inline void *MemCpy(void *__restrict__ dest, const void *__restrict__ src
|
|
|
521
505
|
}
|
|
522
506
|
static inline void *MemMove(void *dest, const void *src, Size len)
|
|
523
507
|
{
|
|
524
|
-
|
|
508
|
+
K_ASSERT(len >= 0);
|
|
525
509
|
|
|
526
510
|
#if defined(__clang__)
|
|
527
511
|
// LLVM guarantees sane behavior
|
|
@@ -535,7 +519,7 @@ static inline void *MemMove(void *dest, const void *src, Size len)
|
|
|
535
519
|
}
|
|
536
520
|
static inline void *MemSet(void *dest, int c, Size len)
|
|
537
521
|
{
|
|
538
|
-
|
|
522
|
+
K_ASSERT(len >= 0);
|
|
539
523
|
|
|
540
524
|
#if defined(__clang__)
|
|
541
525
|
// LLVM guarantees sane behavior
|
|
@@ -556,8 +540,8 @@ void *MemMem(const void *src, Size src_len, const void *needle, Size needle_len)
|
|
|
556
540
|
|
|
557
541
|
static inline void *MemMem(const void *src, Size src_len, const void *needle, Size needle_len)
|
|
558
542
|
{
|
|
559
|
-
|
|
560
|
-
|
|
543
|
+
K_ASSERT(src_len >= 0);
|
|
544
|
+
K_ASSERT(needle_len > 0);
|
|
561
545
|
|
|
562
546
|
void *ptr = memmem(src, (size_t)src_len, needle, (size_t)needle_len);
|
|
563
547
|
return ptr;
|
|
@@ -565,6 +549,9 @@ static inline void *MemMem(const void *src, Size src_len, const void *needle, Si
|
|
|
565
549
|
|
|
566
550
|
#endif
|
|
567
551
|
|
|
552
|
+
// Implemented for translations, but we need it before we get to this part
|
|
553
|
+
const char *T(const char *key);
|
|
554
|
+
|
|
568
555
|
template <typename T, typename = typename std::enable_if<std::is_enum<T>::value, T>>
|
|
569
556
|
typename std::underlying_type<T>::type MaskEnum(T value)
|
|
570
557
|
{
|
|
@@ -574,7 +561,7 @@ typename std::underlying_type<T>::type MaskEnum(T value)
|
|
|
574
561
|
|
|
575
562
|
template <typename Fun>
|
|
576
563
|
class DeferGuard {
|
|
577
|
-
|
|
564
|
+
K_DELETE_COPY(DeferGuard)
|
|
578
565
|
|
|
579
566
|
Fun f;
|
|
580
567
|
bool enabled;
|
|
@@ -610,14 +597,35 @@ DeferGuard<Fun> operator+(DeferGuardHelper, Fun &&f)
|
|
|
610
597
|
// Write 'DEFER { code };' to do something at the end of the current scope, you
|
|
611
598
|
// can use DEFER_N(Name) if you need to disable the guard for some reason, and
|
|
612
599
|
// DEFER_NC(Name, Captures) if you need to capture values.
|
|
613
|
-
#define
|
|
614
|
-
auto
|
|
615
|
-
#define
|
|
616
|
-
auto Name =
|
|
617
|
-
#define
|
|
618
|
-
auto
|
|
619
|
-
#define
|
|
620
|
-
auto Name =
|
|
600
|
+
#define K_DEFER \
|
|
601
|
+
auto K_UNIQUE_NAME(defer) = K::DeferGuardHelper() + [&]()
|
|
602
|
+
#define K_DEFER_N(Name) \
|
|
603
|
+
auto Name = K::DeferGuardHelper() + [&]()
|
|
604
|
+
#define K_DEFER_C(...) \
|
|
605
|
+
auto K_UNIQUE_NAME(defer) = K::DeferGuardHelper() + [&, __VA_ARGS__]()
|
|
606
|
+
#define K_DEFER_NC(Name, ...) \
|
|
607
|
+
auto Name = K::DeferGuardHelper() + [&, __VA_ARGS__]()
|
|
608
|
+
|
|
609
|
+
template <typename T>
|
|
610
|
+
class NoDestroy {
|
|
611
|
+
K_DELETE_COPY(NoDestroy);
|
|
612
|
+
|
|
613
|
+
alignas(T) uint8_t data[K_SIZE(T)];
|
|
614
|
+
|
|
615
|
+
public:
|
|
616
|
+
template <class... Args>
|
|
617
|
+
NoDestroy(Args&&... args) { new (data) T(std::forward<Args>(args)...); }
|
|
618
|
+
|
|
619
|
+
~NoDestroy() = default;
|
|
620
|
+
|
|
621
|
+
const T *Get() const { return (const T *)(data); }
|
|
622
|
+
T *Get() { return (T*)data; }
|
|
623
|
+
|
|
624
|
+
const T &operator*() const { return *Get(); }
|
|
625
|
+
T& operator*() { return *Get(); }
|
|
626
|
+
const T *operator->() const { return Get(); }
|
|
627
|
+
T *operator->() { return Get(); }
|
|
628
|
+
};
|
|
621
629
|
|
|
622
630
|
// Heavily inspired from FunctionRef in LLVM
|
|
623
631
|
template<typename Fn> class FunctionRef;
|
|
@@ -648,24 +656,6 @@ public:
|
|
|
648
656
|
bool IsValid() const { return callback; }
|
|
649
657
|
};
|
|
650
658
|
|
|
651
|
-
#define RG_INIT_(ClassName) \
|
|
652
|
-
class ClassName { \
|
|
653
|
-
public: \
|
|
654
|
-
ClassName(); \
|
|
655
|
-
}; \
|
|
656
|
-
static ClassName RG_UNIQUE_NAME(init); \
|
|
657
|
-
ClassName::ClassName()
|
|
658
|
-
#define RG_INIT(Name) RG_INIT_(RG_CONCAT(RG_UNIQUE_NAME(InitHelper), Name))
|
|
659
|
-
|
|
660
|
-
#define RG_EXIT_(ClassName) \
|
|
661
|
-
class ClassName { \
|
|
662
|
-
public: \
|
|
663
|
-
~ClassName(); \
|
|
664
|
-
}; \
|
|
665
|
-
static ClassName RG_UNIQUE_NAME(exit); \
|
|
666
|
-
ClassName::~ClassName()
|
|
667
|
-
#define RG_EXIT(Name) RG_EXIT_(RG_CONCAT(RG_UNIQUE_NAME(ExitHelper), Name))
|
|
668
|
-
|
|
669
659
|
template <typename T>
|
|
670
660
|
T MultiCmp()
|
|
671
661
|
{
|
|
@@ -730,19 +720,19 @@ public:
|
|
|
730
720
|
|
|
731
721
|
Size operator*() const
|
|
732
722
|
{
|
|
733
|
-
|
|
723
|
+
K_ASSERT(offset <= K_LEN(bitset->data));
|
|
734
724
|
|
|
735
|
-
if (offset ==
|
|
725
|
+
if (offset == K_LEN(bitset->data))
|
|
736
726
|
return -1;
|
|
737
|
-
return offset *
|
|
727
|
+
return offset * K_SIZE(size_t) * 8 + ctz;
|
|
738
728
|
}
|
|
739
729
|
|
|
740
730
|
Iterator &operator++()
|
|
741
731
|
{
|
|
742
|
-
|
|
732
|
+
K_ASSERT(offset <= K_LEN(bitset->data));
|
|
743
733
|
|
|
744
734
|
while (!bits) {
|
|
745
|
-
if (offset ==
|
|
735
|
+
if (offset == K_LEN(bitset->data) - 1)
|
|
746
736
|
return *this;
|
|
747
737
|
bits = bitset->data[++offset];
|
|
748
738
|
}
|
|
@@ -769,14 +759,14 @@ public:
|
|
|
769
759
|
typedef Iterator<Bitset> iterator_type;
|
|
770
760
|
|
|
771
761
|
static constexpr Size Bits = N;
|
|
772
|
-
size_t data[(N +
|
|
762
|
+
size_t data[(N + K_BITS(size_t) - 1) / K_BITS(size_t)] = {};
|
|
773
763
|
|
|
774
764
|
constexpr Bitset() = default;
|
|
775
765
|
constexpr Bitset(std::initializer_list<Size> bits)
|
|
776
766
|
{
|
|
777
767
|
for (Size idx: bits) {
|
|
778
|
-
Size offset = idx / (
|
|
779
|
-
size_t mask = (size_t)1 << (idx % (
|
|
768
|
+
Size offset = idx / (K_SIZE(size_t) * 8);
|
|
769
|
+
size_t mask = (size_t)1 << (idx % (K_SIZE(size_t) * 8));
|
|
780
770
|
|
|
781
771
|
data[offset] |= mask;
|
|
782
772
|
}
|
|
@@ -784,22 +774,22 @@ public:
|
|
|
784
774
|
|
|
785
775
|
void Clear()
|
|
786
776
|
{
|
|
787
|
-
MemSet(data, 0,
|
|
777
|
+
MemSet(data, 0, K_SIZE(data));
|
|
788
778
|
}
|
|
789
779
|
|
|
790
780
|
Iterator<Bitset> begin() { return Iterator<Bitset>(this, 0); }
|
|
791
781
|
Iterator<const Bitset> begin() const { return Iterator<const Bitset>(this, 0); }
|
|
792
|
-
Iterator<Bitset> end() { return Iterator<Bitset>(this,
|
|
793
|
-
Iterator<const Bitset> end() const { return Iterator<const Bitset>(this,
|
|
782
|
+
Iterator<Bitset> end() { return Iterator<Bitset>(this, K_LEN(data)); }
|
|
783
|
+
Iterator<const Bitset> end() const { return Iterator<const Bitset>(this, K_LEN(data)); }
|
|
794
784
|
|
|
795
785
|
Size PopCount() const
|
|
796
786
|
{
|
|
797
787
|
Size count = 0;
|
|
798
788
|
for (size_t bits: data) {
|
|
799
|
-
#if
|
|
800
|
-
count +=
|
|
789
|
+
#if K_SIZE_MAX == INT64_MAX
|
|
790
|
+
count += K::PopCount((uint64_t)bits);
|
|
801
791
|
#else
|
|
802
|
-
count +=
|
|
792
|
+
count += K::PopCount((uint32_t)bits);
|
|
803
793
|
#endif
|
|
804
794
|
}
|
|
805
795
|
return count;
|
|
@@ -807,28 +797,28 @@ public:
|
|
|
807
797
|
|
|
808
798
|
inline bool Test(Size idx) const
|
|
809
799
|
{
|
|
810
|
-
|
|
800
|
+
K_ASSERT(idx >= 0 && idx < N);
|
|
811
801
|
|
|
812
|
-
Size offset = idx / (
|
|
813
|
-
size_t mask = (size_t)1 << (idx % (
|
|
802
|
+
Size offset = idx / (K_SIZE(size_t) * 8);
|
|
803
|
+
size_t mask = (size_t)1 << (idx % (K_SIZE(size_t) * 8));
|
|
814
804
|
|
|
815
805
|
return data[offset] & mask;
|
|
816
806
|
}
|
|
817
807
|
inline void Set(Size idx, bool value = true)
|
|
818
808
|
{
|
|
819
|
-
|
|
809
|
+
K_ASSERT(idx >= 0 && idx < N);
|
|
820
810
|
|
|
821
|
-
Size offset = idx / (
|
|
822
|
-
size_t mask = (size_t)1 << (idx % (
|
|
811
|
+
Size offset = idx / (K_SIZE(size_t) * 8);
|
|
812
|
+
size_t mask = (size_t)1 << (idx % (K_SIZE(size_t) * 8));
|
|
823
813
|
|
|
824
814
|
data[offset] = ApplyMask(data[offset], mask, value);
|
|
825
815
|
}
|
|
826
816
|
inline bool TestAndSet(Size idx, bool value = true)
|
|
827
817
|
{
|
|
828
|
-
|
|
818
|
+
K_ASSERT(idx >= 0 && idx < N);
|
|
829
819
|
|
|
830
|
-
Size offset = idx / (
|
|
831
|
-
size_t mask = (size_t)1 << (idx % (
|
|
820
|
+
Size offset = idx / (K_SIZE(size_t) * 8);
|
|
821
|
+
size_t mask = (size_t)1 << (idx % (K_SIZE(size_t) * 8));
|
|
832
822
|
|
|
833
823
|
bool ret = data[offset] & mask;
|
|
834
824
|
data[offset] = ApplyMask(data[offset], mask, value);
|
|
@@ -838,7 +828,7 @@ public:
|
|
|
838
828
|
|
|
839
829
|
Bitset &operator&=(const Bitset &other)
|
|
840
830
|
{
|
|
841
|
-
for (Size i = 0; i <
|
|
831
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
842
832
|
data[i] &= other.data[i];
|
|
843
833
|
}
|
|
844
834
|
return *this;
|
|
@@ -846,7 +836,7 @@ public:
|
|
|
846
836
|
Bitset operator&(const Bitset &other)
|
|
847
837
|
{
|
|
848
838
|
Bitset ret;
|
|
849
|
-
for (Size i = 0; i <
|
|
839
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
850
840
|
ret.data[i] = data[i] & other.data[i];
|
|
851
841
|
}
|
|
852
842
|
return ret;
|
|
@@ -854,7 +844,7 @@ public:
|
|
|
854
844
|
|
|
855
845
|
Bitset &operator|=(const Bitset &other)
|
|
856
846
|
{
|
|
857
|
-
for (Size i = 0; i <
|
|
847
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
858
848
|
data[i] |= other.data[i];
|
|
859
849
|
}
|
|
860
850
|
return *this;
|
|
@@ -862,7 +852,7 @@ public:
|
|
|
862
852
|
Bitset operator|(const Bitset &other)
|
|
863
853
|
{
|
|
864
854
|
Bitset ret;
|
|
865
|
-
for (Size i = 0; i <
|
|
855
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
866
856
|
ret.data[i] = data[i] | other.data[i];
|
|
867
857
|
}
|
|
868
858
|
return ret;
|
|
@@ -870,7 +860,7 @@ public:
|
|
|
870
860
|
|
|
871
861
|
Bitset &operator^=(const Bitset &other)
|
|
872
862
|
{
|
|
873
|
-
for (Size i = 0; i <
|
|
863
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
874
864
|
data[i] ^= other.data[i];
|
|
875
865
|
}
|
|
876
866
|
return *this;
|
|
@@ -878,7 +868,7 @@ public:
|
|
|
878
868
|
Bitset operator^(const Bitset &other)
|
|
879
869
|
{
|
|
880
870
|
Bitset ret;
|
|
881
|
-
for (Size i = 0; i <
|
|
871
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
882
872
|
ret.data[i] = data[i] ^ other.data[i];
|
|
883
873
|
}
|
|
884
874
|
return ret;
|
|
@@ -886,7 +876,7 @@ public:
|
|
|
886
876
|
|
|
887
877
|
Bitset &Flip()
|
|
888
878
|
{
|
|
889
|
-
for (Size i = 0; i <
|
|
879
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
890
880
|
data[i] = ~data[i];
|
|
891
881
|
}
|
|
892
882
|
return *this;
|
|
@@ -894,7 +884,7 @@ public:
|
|
|
894
884
|
Bitset operator~()
|
|
895
885
|
{
|
|
896
886
|
Bitset ret;
|
|
897
|
-
for (Size i = 0; i <
|
|
887
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
898
888
|
ret.data[i] = ~data[i];
|
|
899
889
|
}
|
|
900
890
|
return ret;
|
|
@@ -936,12 +926,12 @@ struct Span {
|
|
|
936
926
|
|
|
937
927
|
constexpr T &operator[](Size idx)
|
|
938
928
|
{
|
|
939
|
-
|
|
929
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
940
930
|
return ptr[idx];
|
|
941
931
|
}
|
|
942
932
|
constexpr const T &operator[](Size idx) const
|
|
943
933
|
{
|
|
944
|
-
|
|
934
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
945
935
|
return ptr[idx];
|
|
946
936
|
}
|
|
947
937
|
|
|
@@ -963,8 +953,8 @@ struct Span {
|
|
|
963
953
|
|
|
964
954
|
constexpr Span Take(Size offset, Size sub_len) const
|
|
965
955
|
{
|
|
966
|
-
|
|
967
|
-
|
|
956
|
+
K_ASSERT(sub_len >= 0 && sub_len <= len);
|
|
957
|
+
K_ASSERT(offset >= 0 && offset <= len - sub_len);
|
|
968
958
|
|
|
969
959
|
Span<T> sub = { ptr + offset, sub_len };
|
|
970
960
|
return sub;
|
|
@@ -1005,7 +995,7 @@ struct Span<const char> {
|
|
|
1005
995
|
|
|
1006
996
|
constexpr char operator[](Size idx) const
|
|
1007
997
|
{
|
|
1008
|
-
|
|
998
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
1009
999
|
return ptr[idx];
|
|
1010
1000
|
}
|
|
1011
1001
|
|
|
@@ -1017,8 +1007,8 @@ struct Span<const char> {
|
|
|
1017
1007
|
|
|
1018
1008
|
constexpr Span Take(Size offset, Size sub_len) const
|
|
1019
1009
|
{
|
|
1020
|
-
|
|
1021
|
-
|
|
1010
|
+
K_ASSERT(sub_len >= 0 && sub_len <= len);
|
|
1011
|
+
K_ASSERT(offset >= 0 && offset <= len - sub_len);
|
|
1022
1012
|
|
|
1023
1013
|
Span<const char> sub = { ptr + offset, sub_len };
|
|
1024
1014
|
return sub;
|
|
@@ -1051,14 +1041,14 @@ public:
|
|
|
1051
1041
|
Size stride;
|
|
1052
1042
|
|
|
1053
1043
|
Strider() = default;
|
|
1054
|
-
constexpr Strider(T *ptr_) : ptr(ptr_), stride(
|
|
1044
|
+
constexpr Strider(T *ptr_) : ptr(ptr_), stride(K_SIZE(T)) {}
|
|
1055
1045
|
constexpr Strider(T *ptr_, Size stride_) : ptr(ptr_), stride(stride_) {}
|
|
1056
1046
|
|
|
1057
1047
|
constexpr bool IsValid() const { return ptr; }
|
|
1058
1048
|
|
|
1059
1049
|
constexpr T &operator[](Size idx) const
|
|
1060
1050
|
{
|
|
1061
|
-
|
|
1051
|
+
K_ASSERT(idx >= 0);
|
|
1062
1052
|
return *(T *)((uint8_t *)ptr + (idx * stride));
|
|
1063
1053
|
}
|
|
1064
1054
|
};
|
|
@@ -1066,7 +1056,7 @@ public:
|
|
|
1066
1056
|
template <typename T>
|
|
1067
1057
|
static constexpr inline Strider<T> MakeStrider(T *ptr)
|
|
1068
1058
|
{
|
|
1069
|
-
return Strider<T>(ptr,
|
|
1059
|
+
return Strider<T>(ptr, K_SIZE(T));
|
|
1070
1060
|
}
|
|
1071
1061
|
template <typename T>
|
|
1072
1062
|
static constexpr inline Strider<T> MakeStrider(T *ptr, Size stride)
|
|
@@ -1076,7 +1066,7 @@ static constexpr inline Strider<T> MakeStrider(T *ptr, Size stride)
|
|
|
1076
1066
|
template <typename T, Size N>
|
|
1077
1067
|
static constexpr inline Strider<T> MakeStrider(T (&arr)[N])
|
|
1078
1068
|
{
|
|
1079
|
-
return Strider<T>(arr,
|
|
1069
|
+
return Strider<T>(arr, K_SIZE(T));
|
|
1080
1070
|
}
|
|
1081
1071
|
|
|
1082
1072
|
enum class AllocFlag {
|
|
@@ -1085,7 +1075,7 @@ enum class AllocFlag {
|
|
|
1085
1075
|
};
|
|
1086
1076
|
|
|
1087
1077
|
class Allocator {
|
|
1088
|
-
|
|
1078
|
+
K_DELETE_COPY(Allocator)
|
|
1089
1079
|
|
|
1090
1080
|
public:
|
|
1091
1081
|
Allocator() = default;
|
|
@@ -1101,7 +1091,7 @@ Allocator *GetNullAllocator();
|
|
|
1101
1091
|
|
|
1102
1092
|
static inline void *AllocateRaw(Allocator *alloc, Size size, unsigned int flags = 0)
|
|
1103
1093
|
{
|
|
1104
|
-
|
|
1094
|
+
K_ASSERT(size >= 0);
|
|
1105
1095
|
|
|
1106
1096
|
if (!alloc) {
|
|
1107
1097
|
alloc = GetDefaultAllocator();
|
|
@@ -1118,7 +1108,7 @@ T *AllocateOne(Allocator *alloc, unsigned int flags = 0)
|
|
|
1118
1108
|
alloc = GetDefaultAllocator();
|
|
1119
1109
|
}
|
|
1120
1110
|
|
|
1121
|
-
Size size =
|
|
1111
|
+
Size size = K_SIZE(T);
|
|
1122
1112
|
|
|
1123
1113
|
T *ptr = (T *)alloc->Allocate(size, flags);
|
|
1124
1114
|
return ptr;
|
|
@@ -1127,13 +1117,13 @@ T *AllocateOne(Allocator *alloc, unsigned int flags = 0)
|
|
|
1127
1117
|
template <typename T>
|
|
1128
1118
|
Span<T> AllocateSpan(Allocator *alloc, Size len, unsigned int flags = 0)
|
|
1129
1119
|
{
|
|
1130
|
-
|
|
1120
|
+
K_ASSERT(len >= 0);
|
|
1131
1121
|
|
|
1132
1122
|
if (!alloc) {
|
|
1133
1123
|
alloc = GetDefaultAllocator();
|
|
1134
1124
|
}
|
|
1135
1125
|
|
|
1136
|
-
Size size = len *
|
|
1126
|
+
Size size = len * K_SIZE(T);
|
|
1137
1127
|
|
|
1138
1128
|
T *ptr = (T *)alloc->Allocate(size, flags);
|
|
1139
1129
|
return MakeSpan(ptr, len);
|
|
@@ -1142,7 +1132,7 @@ Span<T> AllocateSpan(Allocator *alloc, Size len, unsigned int flags = 0)
|
|
|
1142
1132
|
static inline void *ResizeRaw(Allocator *alloc, void *ptr, Size old_size, Size new_size,
|
|
1143
1133
|
unsigned int flags = 0)
|
|
1144
1134
|
{
|
|
1145
|
-
|
|
1135
|
+
K_ASSERT(new_size >= 0);
|
|
1146
1136
|
|
|
1147
1137
|
if (!alloc) {
|
|
1148
1138
|
alloc = GetDefaultAllocator();
|
|
@@ -1156,14 +1146,14 @@ template <typename T>
|
|
|
1156
1146
|
Span<T> ResizeSpan(Allocator *alloc, Span<T> mem, Size new_len,
|
|
1157
1147
|
unsigned int flags = 0)
|
|
1158
1148
|
{
|
|
1159
|
-
|
|
1149
|
+
K_ASSERT(new_len >= 0);
|
|
1160
1150
|
|
|
1161
1151
|
if (!alloc) {
|
|
1162
1152
|
alloc = GetDefaultAllocator();
|
|
1163
1153
|
}
|
|
1164
1154
|
|
|
1165
|
-
Size old_size = mem.len *
|
|
1166
|
-
Size new_size = new_len *
|
|
1155
|
+
Size old_size = mem.len * K_SIZE(T);
|
|
1156
|
+
Size new_size = new_len * K_SIZE(T);
|
|
1167
1157
|
|
|
1168
1158
|
mem.ptr = (T *)alloc->Resize(mem.ptr, old_size, new_size, flags);
|
|
1169
1159
|
return MakeSpan(mem.ptr, new_len);
|
|
@@ -1185,7 +1175,7 @@ void ReleaseOne(Allocator *alloc, T *ptr)
|
|
|
1185
1175
|
alloc = GetDefaultAllocator();
|
|
1186
1176
|
}
|
|
1187
1177
|
|
|
1188
|
-
alloc->Release((void *)ptr,
|
|
1178
|
+
alloc->Release((void *)ptr, K_SIZE(T));
|
|
1189
1179
|
}
|
|
1190
1180
|
|
|
1191
1181
|
template<typename T>
|
|
@@ -1195,7 +1185,7 @@ void ReleaseSpan(Allocator *alloc, Span<T> mem)
|
|
|
1195
1185
|
alloc = GetDefaultAllocator();
|
|
1196
1186
|
}
|
|
1197
1187
|
|
|
1198
|
-
Size size = mem.len *
|
|
1188
|
+
Size size = mem.len * K_SIZE(T);
|
|
1199
1189
|
|
|
1200
1190
|
alloc->Release((void *)mem.ptr, size);
|
|
1201
1191
|
}
|
|
@@ -1246,10 +1236,10 @@ class BlockAllocator: public Allocator {
|
|
|
1246
1236
|
uint8_t *last_alloc = nullptr;
|
|
1247
1237
|
|
|
1248
1238
|
public:
|
|
1249
|
-
BlockAllocator(Size block_size =
|
|
1239
|
+
BlockAllocator(Size block_size = K_BLOCK_ALLOCATOR_DEFAULT_SIZE)
|
|
1250
1240
|
: block_size(block_size)
|
|
1251
1241
|
{
|
|
1252
|
-
|
|
1242
|
+
K_ASSERT(block_size > 0);
|
|
1253
1243
|
}
|
|
1254
1244
|
|
|
1255
1245
|
BlockAllocator(BlockAllocator &&other) { *this = std::move(other); }
|
|
@@ -1288,9 +1278,9 @@ public:
|
|
|
1288
1278
|
RetainPtr(T *p, void (*delete_func)(std::remove_const_t<T> *))
|
|
1289
1279
|
: p(p)
|
|
1290
1280
|
{
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1281
|
+
K_ASSERT(p);
|
|
1282
|
+
K_ASSERT(delete_func);
|
|
1283
|
+
K_ASSERT(!p->delete_func || delete_func == p->delete_func);
|
|
1294
1284
|
|
|
1295
1285
|
p->Ref();
|
|
1296
1286
|
p->delete_func = delete_func;
|
|
@@ -1299,7 +1289,7 @@ public:
|
|
|
1299
1289
|
: p(p)
|
|
1300
1290
|
{
|
|
1301
1291
|
if (p) {
|
|
1302
|
-
|
|
1292
|
+
K_ASSERT(p->delete_func);
|
|
1303
1293
|
|
|
1304
1294
|
if (ref) {
|
|
1305
1295
|
p->Ref();
|
|
@@ -1346,7 +1336,7 @@ public:
|
|
|
1346
1336
|
|
|
1347
1337
|
T &operator*() const
|
|
1348
1338
|
{
|
|
1349
|
-
|
|
1339
|
+
K_ASSERT(p);
|
|
1350
1340
|
return *p;
|
|
1351
1341
|
}
|
|
1352
1342
|
T *operator->() const { return p; }
|
|
@@ -1363,7 +1353,7 @@ public:
|
|
|
1363
1353
|
bool Unref() const
|
|
1364
1354
|
{
|
|
1365
1355
|
int new_count = --refcount;
|
|
1366
|
-
|
|
1356
|
+
K_ASSERT(new_count >= 0);
|
|
1367
1357
|
return new_count;
|
|
1368
1358
|
}
|
|
1369
1359
|
|
|
@@ -1545,7 +1535,6 @@ static inline bool StartsWith(Span<const char> str, Span<const char> prefix)
|
|
|
1545
1535
|
return false;
|
|
1546
1536
|
i++;
|
|
1547
1537
|
}
|
|
1548
|
-
|
|
1549
1538
|
return (i == prefix.len);
|
|
1550
1539
|
}
|
|
1551
1540
|
static inline bool StartsWith(Span<const char> str, const char *prefix)
|
|
@@ -1556,9 +1545,18 @@ static inline bool StartsWith(Span<const char> str, const char *prefix)
|
|
|
1556
1545
|
return false;
|
|
1557
1546
|
i++;
|
|
1558
1547
|
}
|
|
1559
|
-
|
|
1560
1548
|
return !prefix[i];
|
|
1561
1549
|
}
|
|
1550
|
+
static inline bool StartsWith(const char *str, Span<const char> prefix)
|
|
1551
|
+
{
|
|
1552
|
+
Size i = 0;
|
|
1553
|
+
while (str[i] && i < prefix.len) {
|
|
1554
|
+
if (str[i] != prefix[i])
|
|
1555
|
+
return false;
|
|
1556
|
+
i++;
|
|
1557
|
+
}
|
|
1558
|
+
return (i == prefix.len);
|
|
1559
|
+
}
|
|
1562
1560
|
static inline bool StartsWith(const char *str, const char *prefix)
|
|
1563
1561
|
{
|
|
1564
1562
|
Size i = 0;
|
|
@@ -1567,14 +1565,55 @@ static inline bool StartsWith(const char *str, const char *prefix)
|
|
|
1567
1565
|
return false;
|
|
1568
1566
|
i++;
|
|
1569
1567
|
}
|
|
1568
|
+
return !prefix[i];
|
|
1569
|
+
}
|
|
1570
1570
|
|
|
1571
|
+
static inline bool StartsWithI(Span<const char> str, Span<const char> prefix)
|
|
1572
|
+
{
|
|
1573
|
+
Size i = 0;
|
|
1574
|
+
while (i < str.len && i < prefix.len) {
|
|
1575
|
+
if (LowerAscii(str[i]) != LowerAscii(prefix[i]))
|
|
1576
|
+
return false;
|
|
1577
|
+
i++;
|
|
1578
|
+
}
|
|
1579
|
+
return (i == prefix.len);
|
|
1580
|
+
}
|
|
1581
|
+
static inline bool StartsWithI(Span<const char> str, const char *prefix)
|
|
1582
|
+
{
|
|
1583
|
+
Size i = 0;
|
|
1584
|
+
while (i < str.len && prefix[i]) {
|
|
1585
|
+
if (LowerAscii(str[i]) != LowerAscii(prefix[i]))
|
|
1586
|
+
return false;
|
|
1587
|
+
i++;
|
|
1588
|
+
}
|
|
1589
|
+
return !prefix[i];
|
|
1590
|
+
}
|
|
1591
|
+
static inline bool StartsWithI(const char *str, Span<const char> prefix)
|
|
1592
|
+
{
|
|
1593
|
+
Size i = 0;
|
|
1594
|
+
while (str[i] && i < prefix.len) {
|
|
1595
|
+
if (LowerAscii(str[i]) != LowerAscii(prefix[i]))
|
|
1596
|
+
return false;
|
|
1597
|
+
i++;
|
|
1598
|
+
}
|
|
1599
|
+
return (i == prefix.len);
|
|
1600
|
+
}
|
|
1601
|
+
static inline bool StartsWithI(const char *str, const char *prefix)
|
|
1602
|
+
{
|
|
1603
|
+
Size i = 0;
|
|
1604
|
+
while (str[i] && prefix[i]) {
|
|
1605
|
+
if (LowerAscii(str[i]) != LowerAscii(prefix[i]))
|
|
1606
|
+
return false;
|
|
1607
|
+
i++;
|
|
1608
|
+
}
|
|
1571
1609
|
return !prefix[i];
|
|
1572
1610
|
}
|
|
1573
1611
|
|
|
1574
|
-
static inline bool EndsWith(Span<const char> str, const char
|
|
1612
|
+
static inline bool EndsWith(Span<const char> str, Span<const char> suffix)
|
|
1575
1613
|
{
|
|
1576
1614
|
Size i = str.len - 1;
|
|
1577
|
-
Size j =
|
|
1615
|
+
Size j = suffix.len - 1;
|
|
1616
|
+
|
|
1578
1617
|
while (i >= 0 && j >= 0) {
|
|
1579
1618
|
if (str[i] != suffix[j])
|
|
1580
1619
|
return false;
|
|
@@ -1585,6 +1624,21 @@ static inline bool EndsWith(Span<const char> str, const char *suffix)
|
|
|
1585
1624
|
|
|
1586
1625
|
return j < 0;
|
|
1587
1626
|
}
|
|
1627
|
+
static inline bool EndsWithI(Span<const char> str, Span<const char> suffix)
|
|
1628
|
+
{
|
|
1629
|
+
Size i = str.len - 1;
|
|
1630
|
+
Size j = suffix.len - 1;
|
|
1631
|
+
|
|
1632
|
+
while (i >= 0 && j >= 0) {
|
|
1633
|
+
if (LowerAscii(str[i]) != LowerAscii(suffix[j]))
|
|
1634
|
+
return false;
|
|
1635
|
+
|
|
1636
|
+
i--;
|
|
1637
|
+
j--;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
return j < 0;
|
|
1641
|
+
}
|
|
1588
1642
|
|
|
1589
1643
|
static inline Size FindStr(Span<const char> str, Span<const char> needle)
|
|
1590
1644
|
{
|
|
@@ -1649,16 +1703,15 @@ static inline Span<const char> SplitStr(Span<const char> str, char split_char, S
|
|
|
1649
1703
|
static inline Span<const char> SplitStr(const char *str, char split_char, const char **out_remainder = nullptr)
|
|
1650
1704
|
{ return SplitStr((char *)str, split_char, (char **)out_remainder); }
|
|
1651
1705
|
|
|
1652
|
-
static inline Span<char> SplitStr(Span<char> str, const char
|
|
1706
|
+
static inline Span<char> SplitStr(Span<char> str, Span<const char> split, Span<char> *out_remainder = nullptr)
|
|
1653
1707
|
{
|
|
1654
|
-
|
|
1708
|
+
K_ASSERT(split.len);
|
|
1655
1709
|
|
|
1656
1710
|
Size part_len = 0;
|
|
1657
1711
|
while (part_len < str.len) {
|
|
1658
|
-
if (StartsWith(str.Take(part_len, str.len - part_len),
|
|
1712
|
+
if (StartsWith(str.Take(part_len, str.len - part_len), split)) {
|
|
1659
1713
|
if (out_remainder) {
|
|
1660
|
-
|
|
1661
|
-
*out_remainder = str.Take(part_len + split_len, str.len - part_len - split_len);
|
|
1714
|
+
*out_remainder = str.Take(part_len + split.len, str.len - part_len - split.len);
|
|
1662
1715
|
}
|
|
1663
1716
|
return str.Take(0, part_len);
|
|
1664
1717
|
}
|
|
@@ -1670,16 +1723,15 @@ static inline Span<char> SplitStr(Span<char> str, const char *split_str, Span<ch
|
|
|
1670
1723
|
}
|
|
1671
1724
|
return str;
|
|
1672
1725
|
}
|
|
1673
|
-
static inline Span<char> SplitStr(char *str, const char
|
|
1726
|
+
static inline Span<char> SplitStr(char *str, Span<const char> split, char **out_remainder = nullptr)
|
|
1674
1727
|
{
|
|
1675
|
-
|
|
1728
|
+
K_ASSERT(split.len);
|
|
1676
1729
|
|
|
1677
1730
|
Size part_len = 0;
|
|
1678
1731
|
while (str[part_len]) {
|
|
1679
|
-
if (StartsWith(str + part_len,
|
|
1732
|
+
if (StartsWith(str + part_len, split)) {
|
|
1680
1733
|
if (out_remainder) {
|
|
1681
|
-
|
|
1682
|
-
*out_remainder = str + part_len + split_len;
|
|
1734
|
+
*out_remainder = str + part_len + split.len;
|
|
1683
1735
|
}
|
|
1684
1736
|
return MakeSpan(str, part_len);
|
|
1685
1737
|
}
|
|
@@ -1691,10 +1743,10 @@ static inline Span<char> SplitStr(char *str, const char *split_str, char **out_r
|
|
|
1691
1743
|
}
|
|
1692
1744
|
return MakeSpan(str, part_len);
|
|
1693
1745
|
}
|
|
1694
|
-
static inline Span<const char> SplitStr(Span<const char> str, const char
|
|
1695
|
-
{ return SplitStr(MakeSpan((char *)str.ptr, str.len),
|
|
1696
|
-
static inline Span<const char> SplitStr(const char *str, const char
|
|
1697
|
-
{ return SplitStr((char *)str,
|
|
1746
|
+
static inline Span<const char> SplitStr(Span<const char> str, Span<const char> split, Span<const char> *out_remainder = nullptr)
|
|
1747
|
+
{ return SplitStr(MakeSpan((char *)str.ptr, str.len), split, (Span<char> *)out_remainder); }
|
|
1748
|
+
static inline Span<const char> SplitStr(const char *str, Span<const char> split, const char **out_remainder = nullptr)
|
|
1749
|
+
{ return SplitStr((char *)str, split, (char **)out_remainder); }
|
|
1698
1750
|
|
|
1699
1751
|
static inline Span<char> SplitStrLine(Span<char> str, Span<char> *out_remainder = nullptr)
|
|
1700
1752
|
{
|
|
@@ -1890,116 +1942,8 @@ static inline Span<const char> TrimStrRight(Span<const char> str, const char *tr
|
|
|
1890
1942
|
static inline Span<const char> TrimStr(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
1891
1943
|
{ return TrimStr(MakeSpan((char *)str.ptr, str.len), trim_chars); }
|
|
1892
1944
|
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
int ones = CountLeadingZeros((uint32_t)~c << 24);
|
|
1896
|
-
return std::min(std::max(ones, 1), 4);
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
static constexpr inline Size DecodeUtf8(const char *str, int32_t *out_c)
|
|
1900
|
-
{
|
|
1901
|
-
RG_ASSERT(str[0]);
|
|
1902
|
-
|
|
1903
|
-
#define BYTE(Idx) ((uint8_t)str[Idx])
|
|
1904
|
-
|
|
1905
|
-
if (BYTE(0) < 0x80) {
|
|
1906
|
-
*out_c = BYTE(0);
|
|
1907
|
-
return 1;
|
|
1908
|
-
} else if (BYTE(0) - 0xC2 > 0xF4 - 0xC2) [[unlikely]] {
|
|
1909
|
-
return 0;
|
|
1910
|
-
} else if (BYTE(1)) [[likely]] {
|
|
1911
|
-
if (BYTE(0) < 0xE0 && (BYTE(1) & 0xC0) == 0x80) {
|
|
1912
|
-
*out_c = ((BYTE(0) & 0x1F) << 6) | (BYTE(1) & 0x3F);
|
|
1913
|
-
return 2;
|
|
1914
|
-
} else if (BYTE(2)) [[likely]] {
|
|
1915
|
-
if (BYTE(0) < 0xF0 &&
|
|
1916
|
-
(BYTE(1) & 0xC0) == 0x80 &&
|
|
1917
|
-
(BYTE(2) & 0xC0) == 0x80) {
|
|
1918
|
-
*out_c = ((BYTE(0) & 0xF) << 12) | ((BYTE(1) & 0x3F) << 6) | (BYTE(2) & 0x3F);
|
|
1919
|
-
return 3;
|
|
1920
|
-
} else if (BYTE(3)) [[likely]] {
|
|
1921
|
-
if ((BYTE(1) & 0xC0) == 0x80 &&
|
|
1922
|
-
(BYTE(2) & 0xC0) == 0x80 &&
|
|
1923
|
-
(BYTE(3) & 0xC0) == 0x80) {
|
|
1924
|
-
*out_c = ((BYTE(0) & 0x7) << 18) | ((BYTE(1) & 0x3F) << 12) | ((BYTE(2) & 0x3F) << 6) | (BYTE(3) & 0x3F);
|
|
1925
|
-
return 4;
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
|
|
1931
|
-
#undef BYTE
|
|
1932
|
-
|
|
1933
|
-
return 0;
|
|
1934
|
-
}
|
|
1935
|
-
|
|
1936
|
-
static constexpr inline Size DecodeUtf8(Span<const char> str, Size offset, int32_t *out_c)
|
|
1937
|
-
{
|
|
1938
|
-
RG_ASSERT(offset < str.len);
|
|
1939
|
-
|
|
1940
|
-
str = str.Take(offset, str.len - offset);
|
|
1941
|
-
|
|
1942
|
-
#define BYTE(Idx) ((uint8_t)str[Idx])
|
|
1943
|
-
|
|
1944
|
-
if (BYTE(0) < 0x80) {
|
|
1945
|
-
*out_c = BYTE(0);
|
|
1946
|
-
return 1;
|
|
1947
|
-
} else if (BYTE(0) - 0xC2 > 0xF4 - 0xC2) [[unlikely]] {
|
|
1948
|
-
return 0;
|
|
1949
|
-
} else if (BYTE(0) < 0xE0 && str.len >= 2 && (BYTE(1) & 0xC0) == 0x80) {
|
|
1950
|
-
*out_c = ((BYTE(0) & 0x1F) << 6) | (BYTE(1) & 0x3F);
|
|
1951
|
-
return 2;
|
|
1952
|
-
} else if (BYTE(0) < 0xF0 && str.len >= 3 && (BYTE(1) & 0xC0) == 0x80 &&
|
|
1953
|
-
(BYTE(2) & 0xC0) == 0x80) {
|
|
1954
|
-
*out_c = ((BYTE(0) & 0xF) << 12) | ((BYTE(1) & 0x3F) << 6) | (BYTE(2) & 0x3F);
|
|
1955
|
-
return 3;
|
|
1956
|
-
} else if (str.len >= 4 && (BYTE(1) & 0xC0) == 0x80 &&
|
|
1957
|
-
(BYTE(2) & 0xC0) == 0x80 &&
|
|
1958
|
-
(BYTE(3) & 0xC0) == 0x80) {
|
|
1959
|
-
*out_c = ((BYTE(0) & 0x7) << 18) | ((BYTE(1) & 0x3F) << 12) | ((BYTE(2) & 0x3F) << 6) | (BYTE(3) & 0x3F);
|
|
1960
|
-
return 4;
|
|
1961
|
-
} else {
|
|
1962
|
-
return 0;
|
|
1963
|
-
}
|
|
1964
|
-
|
|
1965
|
-
#undef BYTE
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
static constexpr inline int32_t DecodeUtf8(const char *str)
|
|
1969
|
-
{
|
|
1970
|
-
int32_t uc = -1;
|
|
1971
|
-
DecodeUtf8(str, &uc);
|
|
1972
|
-
return uc;
|
|
1973
|
-
}
|
|
1974
|
-
|
|
1975
|
-
static inline Size EncodeUtf8(int32_t c, char out_buf[4])
|
|
1976
|
-
{
|
|
1977
|
-
if (c < 0x80) {
|
|
1978
|
-
out_buf[0] = (char)c;
|
|
1979
|
-
return 1;
|
|
1980
|
-
} else if (c < 0x800) {
|
|
1981
|
-
out_buf[0] = (char)(0xC0 | (c >> 6));
|
|
1982
|
-
out_buf[1] = (char)(0x80 | (c & 0x3F));
|
|
1983
|
-
return 2;
|
|
1984
|
-
} else if (c >= 0xD800 && c < 0xE000) {
|
|
1985
|
-
return 0;
|
|
1986
|
-
} else if (c < 0x10000) {
|
|
1987
|
-
out_buf[0] = (char)(0xE0 | (c >> 12));
|
|
1988
|
-
out_buf[1] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
1989
|
-
out_buf[2] = (char)(0x80 | (c & 0x3F));
|
|
1990
|
-
return 3;
|
|
1991
|
-
} else if (c < 0x110000) {
|
|
1992
|
-
out_buf[0] = (char)(0xF0 | (c >> 18));
|
|
1993
|
-
out_buf[1] = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
1994
|
-
out_buf[2] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
1995
|
-
out_buf[3] = (char)(0x80 | (c & 0x3F));
|
|
1996
|
-
return 4;
|
|
1997
|
-
} else {
|
|
1998
|
-
return 0;
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
bool IsValidUtf8(Span<const char> str);
|
|
1945
|
+
int CmpNatural(Span<const char> str1, Span<const char> str2);
|
|
1946
|
+
int CmpNaturalI(Span<const char> str1, Span<const char> str2);
|
|
2003
1947
|
|
|
2004
1948
|
// ------------------------------------------------------------------------
|
|
2005
1949
|
// Collections
|
|
@@ -2017,7 +1961,7 @@ public:
|
|
|
2017
1961
|
constexpr LocalArray() = default;
|
|
2018
1962
|
constexpr LocalArray(std::initializer_list<T> l)
|
|
2019
1963
|
{
|
|
2020
|
-
|
|
1964
|
+
K_ASSERT(l.size() <= N);
|
|
2021
1965
|
for (const T &it: l) {
|
|
2022
1966
|
data[len++] = it;
|
|
2023
1967
|
}
|
|
@@ -2040,16 +1984,16 @@ public:
|
|
|
2040
1984
|
T *end() { return data + len; }
|
|
2041
1985
|
const T *end() const { return data + len; }
|
|
2042
1986
|
|
|
2043
|
-
Size Available() const { return
|
|
1987
|
+
Size Available() const { return K_LEN(data) - len; }
|
|
2044
1988
|
|
|
2045
1989
|
T &operator[](Size idx)
|
|
2046
1990
|
{
|
|
2047
|
-
|
|
1991
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
2048
1992
|
return data[idx];
|
|
2049
1993
|
}
|
|
2050
1994
|
const T &operator[](Size idx) const
|
|
2051
1995
|
{
|
|
2052
|
-
|
|
1996
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
2053
1997
|
return data[idx];
|
|
2054
1998
|
}
|
|
2055
1999
|
|
|
@@ -2069,7 +2013,7 @@ public:
|
|
|
2069
2013
|
|
|
2070
2014
|
T *AppendDefault(Size count = 1)
|
|
2071
2015
|
{
|
|
2072
|
-
|
|
2016
|
+
K_ASSERT(len <= N - count);
|
|
2073
2017
|
|
|
2074
2018
|
T *first = data + len;
|
|
2075
2019
|
if constexpr(!std::is_trivial<T>::value) {
|
|
@@ -2078,7 +2022,7 @@ public:
|
|
|
2078
2022
|
len++;
|
|
2079
2023
|
}
|
|
2080
2024
|
} else {
|
|
2081
|
-
MemSet(first, 0, count *
|
|
2025
|
+
MemSet(first, 0, count * K_SIZE(T));
|
|
2082
2026
|
len += count;
|
|
2083
2027
|
}
|
|
2084
2028
|
|
|
@@ -2087,7 +2031,7 @@ public:
|
|
|
2087
2031
|
|
|
2088
2032
|
T *Append(const T &value)
|
|
2089
2033
|
{
|
|
2090
|
-
|
|
2034
|
+
K_ASSERT(len < N);
|
|
2091
2035
|
|
|
2092
2036
|
T *it = data + len;
|
|
2093
2037
|
*it = value;
|
|
@@ -2097,7 +2041,7 @@ public:
|
|
|
2097
2041
|
}
|
|
2098
2042
|
T *Append(T &&value)
|
|
2099
2043
|
{
|
|
2100
|
-
|
|
2044
|
+
K_ASSERT(len < N);
|
|
2101
2045
|
|
|
2102
2046
|
T *it = data + len;
|
|
2103
2047
|
*it = std::move(value);
|
|
@@ -2107,7 +2051,7 @@ public:
|
|
|
2107
2051
|
}
|
|
2108
2052
|
T *Append(Span<const T> values)
|
|
2109
2053
|
{
|
|
2110
|
-
|
|
2054
|
+
K_ASSERT(values.len <= N - len);
|
|
2111
2055
|
|
|
2112
2056
|
T *it = data + len;
|
|
2113
2057
|
for (Size i = 0; i < values.len; i++) {
|
|
@@ -2120,7 +2064,7 @@ public:
|
|
|
2120
2064
|
|
|
2121
2065
|
void RemoveFrom(Size first)
|
|
2122
2066
|
{
|
|
2123
|
-
|
|
2067
|
+
K_ASSERT(first >= 0 && first <= len);
|
|
2124
2068
|
|
|
2125
2069
|
for (Size i = first; i < len; i++) {
|
|
2126
2070
|
data[i] = T();
|
|
@@ -2129,7 +2073,7 @@ public:
|
|
|
2129
2073
|
}
|
|
2130
2074
|
void RemoveLast(Size count = 1)
|
|
2131
2075
|
{
|
|
2132
|
-
|
|
2076
|
+
K_ASSERT(count >= 0 && count <= len);
|
|
2133
2077
|
RemoveFrom(len - count);
|
|
2134
2078
|
}
|
|
2135
2079
|
|
|
@@ -2171,8 +2115,8 @@ public:
|
|
|
2171
2115
|
HeapArray &operator=(HeapArray &&other)
|
|
2172
2116
|
{
|
|
2173
2117
|
Clear();
|
|
2174
|
-
MemMove(this, &other,
|
|
2175
|
-
MemSet(&other, 0,
|
|
2118
|
+
MemMove(this, &other, K_SIZE(other));
|
|
2119
|
+
MemSet(&other, 0, K_SIZE(other));
|
|
2176
2120
|
return *this;
|
|
2177
2121
|
}
|
|
2178
2122
|
HeapArray(const HeapArray &other) { *this = other; }
|
|
@@ -2185,7 +2129,7 @@ public:
|
|
|
2185
2129
|
ptr[i] = other.ptr[i];
|
|
2186
2130
|
}
|
|
2187
2131
|
} else {
|
|
2188
|
-
MemCpy(ptr, other.ptr, other.len *
|
|
2132
|
+
MemCpy(ptr, other.ptr, other.len * K_SIZE(*ptr));
|
|
2189
2133
|
}
|
|
2190
2134
|
len = other.len;
|
|
2191
2135
|
return *this;
|
|
@@ -2209,12 +2153,12 @@ public:
|
|
|
2209
2153
|
|
|
2210
2154
|
T &operator[](Size idx)
|
|
2211
2155
|
{
|
|
2212
|
-
|
|
2156
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
2213
2157
|
return ptr[idx];
|
|
2214
2158
|
}
|
|
2215
2159
|
const T &operator[](Size idx) const
|
|
2216
2160
|
{
|
|
2217
|
-
|
|
2161
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
2218
2162
|
return ptr[idx];
|
|
2219
2163
|
}
|
|
2220
2164
|
|
|
@@ -2234,7 +2178,7 @@ public:
|
|
|
2234
2178
|
|
|
2235
2179
|
void SetCapacity(Size new_capacity)
|
|
2236
2180
|
{
|
|
2237
|
-
|
|
2181
|
+
K_ASSERT(new_capacity >= 0);
|
|
2238
2182
|
|
|
2239
2183
|
if (new_capacity != capacity) {
|
|
2240
2184
|
if (len > new_capacity) {
|
|
@@ -2244,7 +2188,7 @@ public:
|
|
|
2244
2188
|
len = new_capacity;
|
|
2245
2189
|
}
|
|
2246
2190
|
|
|
2247
|
-
ptr = (T *)ResizeRaw(allocator, ptr, capacity *
|
|
2191
|
+
ptr = (T *)ResizeRaw(allocator, ptr, capacity * K_SIZE(T), new_capacity * K_SIZE(T));
|
|
2248
2192
|
capacity = new_capacity;
|
|
2249
2193
|
}
|
|
2250
2194
|
}
|
|
@@ -2258,18 +2202,18 @@ public:
|
|
|
2258
2202
|
|
|
2259
2203
|
T *Grow(Size reserve_capacity = 1)
|
|
2260
2204
|
{
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2205
|
+
K_ASSERT(capacity >= 0);
|
|
2206
|
+
K_ASSERT(reserve_capacity >= 0);
|
|
2207
|
+
K_ASSERT((size_t)capacity + (size_t)reserve_capacity <= K_SIZE_MAX);
|
|
2264
2208
|
|
|
2265
2209
|
if (reserve_capacity > capacity - len) {
|
|
2266
2210
|
Size needed = capacity + reserve_capacity;
|
|
2267
2211
|
|
|
2268
2212
|
Size new_capacity;
|
|
2269
|
-
if (needed <=
|
|
2270
|
-
new_capacity =
|
|
2213
|
+
if (needed <= K_HEAPARRAY_BASE_CAPACITY) {
|
|
2214
|
+
new_capacity = K_HEAPARRAY_BASE_CAPACITY;
|
|
2271
2215
|
} else {
|
|
2272
|
-
new_capacity = (Size)((double)(needed - 1) *
|
|
2216
|
+
new_capacity = (Size)((double)(needed - 1) * K_HEAPARRAY_GROWTH_FACTOR);
|
|
2273
2217
|
}
|
|
2274
2218
|
|
|
2275
2219
|
SetCapacity(new_capacity);
|
|
@@ -2291,7 +2235,7 @@ public:
|
|
|
2291
2235
|
len++;
|
|
2292
2236
|
}
|
|
2293
2237
|
} else {
|
|
2294
|
-
MemSet(first, 0, count *
|
|
2238
|
+
MemSet(first, 0, count * K_SIZE(T));
|
|
2295
2239
|
len += count;
|
|
2296
2240
|
}
|
|
2297
2241
|
|
|
@@ -2336,7 +2280,7 @@ public:
|
|
|
2336
2280
|
|
|
2337
2281
|
void RemoveFrom(Size first)
|
|
2338
2282
|
{
|
|
2339
|
-
|
|
2283
|
+
K_ASSERT(first >= 0 && first <= len);
|
|
2340
2284
|
|
|
2341
2285
|
if constexpr(!std::is_trivial<T>::value) {
|
|
2342
2286
|
for (Size i = first; i < len; i++) {
|
|
@@ -2347,7 +2291,7 @@ public:
|
|
|
2347
2291
|
}
|
|
2348
2292
|
void RemoveLast(Size count = 1)
|
|
2349
2293
|
{
|
|
2350
|
-
|
|
2294
|
+
K_ASSERT(count >= 0 && count <= len);
|
|
2351
2295
|
RemoveFrom(len - count);
|
|
2352
2296
|
}
|
|
2353
2297
|
|
|
@@ -2377,7 +2321,7 @@ public:
|
|
|
2377
2321
|
|
|
2378
2322
|
template <typename T, Size BucketSize = 64, typename AllocatorType = BlockAllocator>
|
|
2379
2323
|
class BucketArray {
|
|
2380
|
-
|
|
2324
|
+
K_DELETE_COPY(BucketArray)
|
|
2381
2325
|
|
|
2382
2326
|
public:
|
|
2383
2327
|
struct Bucket {
|
|
@@ -2495,8 +2439,8 @@ public:
|
|
|
2495
2439
|
BucketArray &operator=(BucketArray &&other)
|
|
2496
2440
|
{
|
|
2497
2441
|
ClearBucketsAndValues();
|
|
2498
|
-
MemMove(this, &other,
|
|
2499
|
-
MemSet(&other, 0,
|
|
2442
|
+
MemMove(this, &other, K_SIZE(other));
|
|
2443
|
+
MemSet(&other, 0, K_SIZE(other));
|
|
2500
2444
|
return *this;
|
|
2501
2445
|
}
|
|
2502
2446
|
|
|
@@ -2529,7 +2473,7 @@ public:
|
|
|
2529
2473
|
|
|
2530
2474
|
const T &operator[](Size idx) const
|
|
2531
2475
|
{
|
|
2532
|
-
|
|
2476
|
+
K_ASSERT(idx >= 0 && idx < count);
|
|
2533
2477
|
|
|
2534
2478
|
idx += offset;
|
|
2535
2479
|
Size bucket_idx = idx / BucketSize;
|
|
@@ -2547,7 +2491,7 @@ public:
|
|
|
2547
2491
|
if (bucket_idx >= buckets.len) {
|
|
2548
2492
|
Bucket *new_bucket = AllocateOne<Bucket>(buckets.allocator);
|
|
2549
2493
|
new (&new_bucket->allocator) AllocatorType();
|
|
2550
|
-
new_bucket->values = (T *)AllocateRaw(&new_bucket->allocator, BucketSize *
|
|
2494
|
+
new_bucket->values = (T *)AllocateRaw(&new_bucket->allocator, BucketSize * K_SIZE(T));
|
|
2551
2495
|
|
|
2552
2496
|
buckets.Append(new_bucket);
|
|
2553
2497
|
}
|
|
@@ -2572,7 +2516,7 @@ public:
|
|
|
2572
2516
|
|
|
2573
2517
|
void RemoveFrom(Size from)
|
|
2574
2518
|
{
|
|
2575
|
-
|
|
2519
|
+
K_ASSERT(from >= 0 && from <= count);
|
|
2576
2520
|
|
|
2577
2521
|
if (from == count)
|
|
2578
2522
|
return;
|
|
@@ -2598,13 +2542,13 @@ public:
|
|
|
2598
2542
|
}
|
|
2599
2543
|
void RemoveLast(Size n = 1)
|
|
2600
2544
|
{
|
|
2601
|
-
|
|
2545
|
+
K_ASSERT(n >= 0 && n <= count);
|
|
2602
2546
|
RemoveFrom(count - n);
|
|
2603
2547
|
}
|
|
2604
2548
|
|
|
2605
2549
|
void RemoveFirst(Size n = 1)
|
|
2606
2550
|
{
|
|
2607
|
-
|
|
2551
|
+
K_ASSERT(n >= 0 && n <= count);
|
|
2608
2552
|
|
|
2609
2553
|
if (n == count) {
|
|
2610
2554
|
Clear();
|
|
@@ -2623,7 +2567,7 @@ public:
|
|
|
2623
2567
|
DeleteBucket(buckets[i]);
|
|
2624
2568
|
}
|
|
2625
2569
|
MemMove(&buckets[0], &buckets[end_bucket_idx],
|
|
2626
|
-
(buckets.len - end_bucket_idx) *
|
|
2570
|
+
(buckets.len - end_bucket_idx) * K_SIZE(Bucket *));
|
|
2627
2571
|
buckets.RemoveLast(end_bucket_idx);
|
|
2628
2572
|
}
|
|
2629
2573
|
|
|
@@ -2650,7 +2594,7 @@ public:
|
|
|
2650
2594
|
|
|
2651
2595
|
count = (it.bucket_idx * BucketSize) + it.bucket_offset - offset;
|
|
2652
2596
|
|
|
2653
|
-
|
|
2597
|
+
K_ASSERT(it == end());
|
|
2654
2598
|
}
|
|
2655
2599
|
void RemoveFrom(const Iterator<const BucketArray<T, BucketSize>> &it) { return RemoveFrom((iterator_type)it); }
|
|
2656
2600
|
|
|
@@ -2670,7 +2614,7 @@ public:
|
|
|
2670
2614
|
DeleteBucket(buckets[i]);
|
|
2671
2615
|
}
|
|
2672
2616
|
MemMove(&buckets[0], &buckets[it.bucket_idx],
|
|
2673
|
-
(buckets.len - it.bucket_idx) *
|
|
2617
|
+
(buckets.len - it.bucket_idx) * K_SIZE(Bucket *));
|
|
2674
2618
|
buckets.RemoveLast(it.bucket_idx);
|
|
2675
2619
|
}
|
|
2676
2620
|
|
|
@@ -2736,18 +2680,18 @@ public:
|
|
|
2736
2680
|
|
|
2737
2681
|
ValueType &operator*()
|
|
2738
2682
|
{
|
|
2739
|
-
|
|
2683
|
+
K_ASSERT(!table->IsEmpty(offset));
|
|
2740
2684
|
return table->data[offset];
|
|
2741
2685
|
}
|
|
2742
2686
|
const ValueType &operator*() const
|
|
2743
2687
|
{
|
|
2744
|
-
|
|
2688
|
+
K_ASSERT(!table->IsEmpty(offset));
|
|
2745
2689
|
return table->data[offset];
|
|
2746
2690
|
}
|
|
2747
2691
|
|
|
2748
2692
|
Iterator &operator++()
|
|
2749
2693
|
{
|
|
2750
|
-
|
|
2694
|
+
K_ASSERT(offset < table->capacity);
|
|
2751
2695
|
while (++offset < table->capacity && table->IsEmpty(offset));
|
|
2752
2696
|
return *this;
|
|
2753
2697
|
}
|
|
@@ -2793,8 +2737,8 @@ public:
|
|
|
2793
2737
|
HashTable &operator=(HashTable &&other)
|
|
2794
2738
|
{
|
|
2795
2739
|
Clear();
|
|
2796
|
-
MemMove(this, &other,
|
|
2797
|
-
MemSet(&other, 0,
|
|
2740
|
+
MemMove(this, &other, K_SIZE(other));
|
|
2741
|
+
MemSet(&other, 0, K_SIZE(other));
|
|
2798
2742
|
return *this;
|
|
2799
2743
|
}
|
|
2800
2744
|
HashTable(const HashTable &other) { *this = other; }
|
|
@@ -2829,7 +2773,7 @@ public:
|
|
|
2829
2773
|
|
|
2830
2774
|
count = 0;
|
|
2831
2775
|
if (used) {
|
|
2832
|
-
size_t len = (size_t)(capacity + (
|
|
2776
|
+
size_t len = (size_t)(capacity + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t);
|
|
2833
2777
|
MemSet(used, 0, len);
|
|
2834
2778
|
}
|
|
2835
2779
|
}
|
|
@@ -2886,7 +2830,7 @@ public:
|
|
|
2886
2830
|
return ptr;
|
|
2887
2831
|
}
|
|
2888
2832
|
|
|
2889
|
-
ValueType *
|
|
2833
|
+
ValueType *InsertOrGet(const ValueType &value, bool *out_inserted = nullptr)
|
|
2890
2834
|
{
|
|
2891
2835
|
const KeyType &key = Handler::GetKey(value);
|
|
2892
2836
|
|
|
@@ -2902,7 +2846,7 @@ public:
|
|
|
2902
2846
|
}
|
|
2903
2847
|
return ptr;
|
|
2904
2848
|
}
|
|
2905
|
-
ValueType *
|
|
2849
|
+
ValueType *InsertOrGetDefault(const KeyType &key, bool *out_inserted = nullptr)
|
|
2906
2850
|
{
|
|
2907
2851
|
bool inserted;
|
|
2908
2852
|
ValueType *ptr = Insert(key, &inserted);
|
|
@@ -2923,7 +2867,7 @@ public:
|
|
|
2923
2867
|
return;
|
|
2924
2868
|
|
|
2925
2869
|
Size clear_idx = it - data;
|
|
2926
|
-
|
|
2870
|
+
K_ASSERT(!IsEmpty(clear_idx));
|
|
2927
2871
|
|
|
2928
2872
|
it->~ValueType();
|
|
2929
2873
|
count--;
|
|
@@ -2943,7 +2887,7 @@ public:
|
|
|
2943
2887
|
|
|
2944
2888
|
MarkUsed(clear_idx);
|
|
2945
2889
|
MarkEmpty(idx);
|
|
2946
|
-
MemMove(&data[clear_idx], &data[idx],
|
|
2890
|
+
MemMove(&data[clear_idx], &data[idx], K_SIZE(*data));
|
|
2947
2891
|
|
|
2948
2892
|
clear_idx = idx;
|
|
2949
2893
|
}
|
|
@@ -2958,9 +2902,9 @@ public:
|
|
|
2958
2902
|
if (count) {
|
|
2959
2903
|
Size new_capacity = (Size)1 << (64 - CountLeadingZeros((uint64_t)count));
|
|
2960
2904
|
|
|
2961
|
-
if (new_capacity <
|
|
2962
|
-
new_capacity =
|
|
2963
|
-
} else if (count > (double)new_capacity *
|
|
2905
|
+
if (new_capacity < K_HASHTABLE_BASE_CAPACITY) {
|
|
2906
|
+
new_capacity = K_HASHTABLE_BASE_CAPACITY;
|
|
2907
|
+
} else if (count > (double)new_capacity * K_HASHTABLE_MAX_LOAD_FACTOR) {
|
|
2964
2908
|
new_capacity *= 2;
|
|
2965
2909
|
}
|
|
2966
2910
|
|
|
@@ -3004,7 +2948,7 @@ private:
|
|
|
3004
2948
|
Size idx = HashToIndex(hash);
|
|
3005
2949
|
ValueType *it = Find(&idx, key);
|
|
3006
2950
|
if (!it) {
|
|
3007
|
-
if (count >= (Size)((double)capacity *
|
|
2951
|
+
if (count >= (Size)((double)capacity * K_HASHTABLE_MAX_LOAD_FACTOR)) {
|
|
3008
2952
|
Rehash(capacity << 1);
|
|
3009
2953
|
idx = HashToIndex(hash);
|
|
3010
2954
|
while (!IsEmpty(idx)) {
|
|
@@ -3021,7 +2965,7 @@ private:
|
|
|
3021
2965
|
return it;
|
|
3022
2966
|
}
|
|
3023
2967
|
} else {
|
|
3024
|
-
Rehash(
|
|
2968
|
+
Rehash(K_HASHTABLE_BASE_CAPACITY);
|
|
3025
2969
|
|
|
3026
2970
|
Size idx = HashToIndex(hash);
|
|
3027
2971
|
count++;
|
|
@@ -3036,7 +2980,7 @@ private:
|
|
|
3036
2980
|
{
|
|
3037
2981
|
if (new_capacity == capacity)
|
|
3038
2982
|
return;
|
|
3039
|
-
|
|
2983
|
+
K_ASSERT(count <= new_capacity);
|
|
3040
2984
|
|
|
3041
2985
|
size_t *old_used = used;
|
|
3042
2986
|
ValueType *old_data = data;
|
|
@@ -3044,9 +2988,9 @@ private:
|
|
|
3044
2988
|
|
|
3045
2989
|
if (new_capacity) {
|
|
3046
2990
|
used = (size_t *)AllocateRaw(allocator,
|
|
3047
|
-
(new_capacity + (
|
|
2991
|
+
(new_capacity + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t),
|
|
3048
2992
|
(int)AllocFlag::Zero);
|
|
3049
|
-
data = (ValueType *)AllocateRaw(allocator, new_capacity *
|
|
2993
|
+
data = (ValueType *)AllocateRaw(allocator, new_capacity * K_SIZE(ValueType));
|
|
3050
2994
|
for (Size i = 0; i < new_capacity; i++) {
|
|
3051
2995
|
new (&data[i]) ValueType();
|
|
3052
2996
|
}
|
|
@@ -3068,22 +3012,22 @@ private:
|
|
|
3068
3012
|
capacity = 0;
|
|
3069
3013
|
}
|
|
3070
3014
|
|
|
3071
|
-
ReleaseRaw(allocator, old_used, (old_capacity + (
|
|
3072
|
-
ReleaseRaw(allocator, old_data, old_capacity *
|
|
3015
|
+
ReleaseRaw(allocator, old_used, (old_capacity + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t));
|
|
3016
|
+
ReleaseRaw(allocator, old_data, old_capacity * K_SIZE(ValueType));
|
|
3073
3017
|
}
|
|
3074
3018
|
|
|
3075
3019
|
inline void MarkUsed(Size idx)
|
|
3076
3020
|
{
|
|
3077
|
-
used[idx / (
|
|
3021
|
+
used[idx / (K_SIZE(size_t) * 8)] |= (1ull << (idx % (K_SIZE(size_t) * 8)));
|
|
3078
3022
|
}
|
|
3079
3023
|
inline void MarkEmpty(Size idx)
|
|
3080
3024
|
{
|
|
3081
|
-
used[idx / (
|
|
3025
|
+
used[idx / (K_SIZE(size_t) * 8)] &= ~(1ull << (idx % (K_SIZE(size_t) * 8)));
|
|
3082
3026
|
}
|
|
3083
3027
|
|
|
3084
3028
|
inline bool IsEmpty(size_t *used, Size idx) const
|
|
3085
3029
|
{
|
|
3086
|
-
bool empty = !(used[idx / (
|
|
3030
|
+
bool empty = !(used[idx / (K_SIZE(size_t) * 8)] & (1ull << (idx % (K_SIZE(size_t) * 8))));
|
|
3087
3031
|
return empty;
|
|
3088
3032
|
}
|
|
3089
3033
|
inline bool IsEmpty(Size idx) const { return IsEmpty(used, idx); }
|
|
@@ -3167,7 +3111,7 @@ DEFINE_INTEGER_HASH_TRAITS_32(unsigned int, constexpr);
|
|
|
3167
3111
|
#endif
|
|
3168
3112
|
DEFINE_INTEGER_HASH_TRAITS_64(long long, constexpr);
|
|
3169
3113
|
DEFINE_INTEGER_HASH_TRAITS_64(unsigned long long, constexpr);
|
|
3170
|
-
#if
|
|
3114
|
+
#if K_SIZE_MAX == INT64_MAX
|
|
3171
3115
|
DEFINE_INTEGER_HASH_TRAITS_64(void *);
|
|
3172
3116
|
DEFINE_INTEGER_HASH_TRAITS_64(const void *);
|
|
3173
3117
|
#else
|
|
@@ -3194,7 +3138,7 @@ static constexpr inline uint64_t HashStr(Span<const char> str)
|
|
|
3194
3138
|
} :
|
|
3195
3139
|
#endif
|
|
3196
3140
|
[](const char *p) {
|
|
3197
|
-
#if defined(
|
|
3141
|
+
#if defined(K_BIG_ENDIAN)
|
|
3198
3142
|
uint64_t result = ((uint64_t)p[0] << 56) |
|
|
3199
3143
|
((uint64_t)p[1] << 48) |
|
|
3200
3144
|
((uint64_t)p[2] << 40) |
|
|
@@ -3275,7 +3219,7 @@ public:
|
|
|
3275
3219
|
static constexpr bool Test(Span<const char> key1, const char * key2) { return key1 == key2; }
|
|
3276
3220
|
};
|
|
3277
3221
|
|
|
3278
|
-
#define
|
|
3222
|
+
#define K_HASHTABLE_HANDLER_EX_N(Name, ValueType, KeyType, KeyMember, HashFunc, TestFunc) \
|
|
3279
3223
|
class Name { \
|
|
3280
3224
|
public: \
|
|
3281
3225
|
static constexpr KeyType GetKey(const ValueType &value) \
|
|
@@ -3289,16 +3233,16 @@ public:
|
|
|
3289
3233
|
static constexpr bool TestKeys(KeyType key1, TestKey key2) \
|
|
3290
3234
|
{ return TestFunc((key1), (key2)); } \
|
|
3291
3235
|
}
|
|
3292
|
-
#define
|
|
3293
|
-
|
|
3294
|
-
#define
|
|
3295
|
-
|
|
3296
|
-
#define
|
|
3297
|
-
|
|
3298
|
-
#define
|
|
3299
|
-
|
|
3300
|
-
#define
|
|
3301
|
-
|
|
3236
|
+
#define K_HASHTABLE_HANDLER_EX(ValueType, KeyType, KeyMember, HashFunc, TestFunc) \
|
|
3237
|
+
K_HASHTABLE_HANDLER_EX_N(HashHandler, ValueType, KeyType, KeyMember, HashFunc, TestFunc)
|
|
3238
|
+
#define K_HASHTABLE_HANDLER(ValueType, KeyMember) \
|
|
3239
|
+
K_HASHTABLE_HANDLER_EX(ValueType, decltype(ValueType::KeyMember), KeyMember, HashTraits<decltype(ValueType::KeyMember)>::Hash, HashTraits<decltype(ValueType::KeyMember)>::Test)
|
|
3240
|
+
#define K_HASHTABLE_HANDLER_N(Name, ValueType, KeyMember) \
|
|
3241
|
+
K_HASHTABLE_HANDLER_EX_N(Name, ValueType, decltype(ValueType::KeyMember), KeyMember, HashTraits<decltype(ValueType::KeyMember)>::Hash, HashTraits<decltype(ValueType::KeyMember)>::Test)
|
|
3242
|
+
#define K_HASHTABLE_HANDLER_T(ValueType, KeyType, KeyMember) \
|
|
3243
|
+
K_HASHTABLE_HANDLER_EX(ValueType, KeyType, KeyMember, HashTraits<KeyType>::Hash, HashTraits<KeyType>::Test)
|
|
3244
|
+
#define K_HASHTABLE_HANDLER_NT(Name, ValueType, KeyType, KeyMember) \
|
|
3245
|
+
K_HASHTABLE_HANDLER_EX_N(Name, ValueType, KeyType, KeyMember, HashTraits<KeyType>::Hash, HashTraits<KeyType>::Test)
|
|
3302
3246
|
|
|
3303
3247
|
template <typename KeyType, typename ValueType>
|
|
3304
3248
|
class HashMap {
|
|
@@ -3307,7 +3251,7 @@ public:
|
|
|
3307
3251
|
KeyType key;
|
|
3308
3252
|
ValueType value;
|
|
3309
3253
|
|
|
3310
|
-
|
|
3254
|
+
K_HASHTABLE_HANDLER(Bucket, key);
|
|
3311
3255
|
};
|
|
3312
3256
|
|
|
3313
3257
|
HashTable<KeyType, Bucket> table;
|
|
@@ -3346,15 +3290,15 @@ public:
|
|
|
3346
3290
|
return table_it;
|
|
3347
3291
|
}
|
|
3348
3292
|
|
|
3349
|
-
ValueType *
|
|
3293
|
+
ValueType *InsertOrGet(const KeyType &key, const ValueType &value, bool *out_inserted = nullptr)
|
|
3350
3294
|
{
|
|
3351
|
-
Bucket *ptr = table.
|
|
3295
|
+
Bucket *ptr = table.InsertOrGet({ key, value }, out_inserted);
|
|
3352
3296
|
return &ptr->value;
|
|
3353
3297
|
}
|
|
3354
|
-
Bucket *
|
|
3298
|
+
Bucket *InsertOrGetDefault(const KeyType &key, bool *out_inserted = nullptr)
|
|
3355
3299
|
{
|
|
3356
3300
|
bool inserted;
|
|
3357
|
-
Bucket *ptr = table.
|
|
3301
|
+
Bucket *ptr = table.InsertOrGetDefault(key, &inserted);
|
|
3358
3302
|
|
|
3359
3303
|
if (inserted) {
|
|
3360
3304
|
ptr->key = key;
|
|
@@ -3417,14 +3361,23 @@ public:
|
|
|
3417
3361
|
{ return table.FindValue(value, default_value); }
|
|
3418
3362
|
|
|
3419
3363
|
ValueType *Set(const ValueType &value) { return table.Set(value); }
|
|
3420
|
-
|
|
3421
|
-
|
|
3364
|
+
|
|
3365
|
+
ValueType *InsertOrGet(const ValueType &value, bool *out_inserted = nullptr)
|
|
3366
|
+
{ return table.InsertOrGet(value, out_inserted); }
|
|
3367
|
+
bool InsertOrFail(const ValueType &value)
|
|
3368
|
+
{
|
|
3369
|
+
bool inserted;
|
|
3370
|
+
InsertOrGet(value, &inserted);
|
|
3371
|
+
return inserted;
|
|
3372
|
+
}
|
|
3422
3373
|
|
|
3423
3374
|
void Remove(ValueType *it) { table.Remove(it); }
|
|
3424
3375
|
template <typename T = ValueType>
|
|
3425
3376
|
void Remove(const T &value) { Remove(Find(value)); }
|
|
3426
3377
|
|
|
3427
3378
|
void Trim() { table.Trim(); }
|
|
3379
|
+
|
|
3380
|
+
private:
|
|
3428
3381
|
};
|
|
3429
3382
|
|
|
3430
3383
|
// XXX: Switch to perfect hashing later on
|
|
@@ -3436,13 +3389,13 @@ public:
|
|
|
3436
3389
|
ValueType value;
|
|
3437
3390
|
};
|
|
3438
3391
|
|
|
3439
|
-
size_t used[(N + (
|
|
3392
|
+
size_t used[(N + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t)] = {};
|
|
3440
3393
|
Bucket data[N] = {};
|
|
3441
3394
|
Size count = 0;
|
|
3442
3395
|
|
|
3443
3396
|
constexpr ConstMap(std::initializer_list<Bucket> l)
|
|
3444
3397
|
{
|
|
3445
|
-
|
|
3398
|
+
K_CRITICAL(l.size() <= N, "ConstMap<%1> cannot be store %2 values", N, l.size());
|
|
3446
3399
|
|
|
3447
3400
|
for (const Bucket &it: l) {
|
|
3448
3401
|
Bucket *bucket = Insert(it.key);
|
|
@@ -3516,11 +3469,11 @@ private:
|
|
|
3516
3469
|
|
|
3517
3470
|
constexpr void MarkUsed(Size idx)
|
|
3518
3471
|
{
|
|
3519
|
-
used[idx / (
|
|
3472
|
+
used[idx / (K_SIZE(size_t) * 8)] |= (1ull << (idx % (K_SIZE(size_t) * 8)));
|
|
3520
3473
|
}
|
|
3521
3474
|
constexpr bool IsEmpty(Size idx) const
|
|
3522
3475
|
{
|
|
3523
|
-
bool empty = !(used[idx / (
|
|
3476
|
+
bool empty = !(used[idx / (K_SIZE(size_t) * 8)] & (1ull << (idx % (K_SIZE(size_t) * 8))));
|
|
3524
3477
|
return empty;
|
|
3525
3478
|
}
|
|
3526
3479
|
|
|
@@ -3537,7 +3490,7 @@ private:
|
|
|
3537
3490
|
union LocalDate {
|
|
3538
3491
|
int32_t value;
|
|
3539
3492
|
struct {
|
|
3540
|
-
#if defined(
|
|
3493
|
+
#if defined(K_BIG_ENDIAN)
|
|
3541
3494
|
int16_t year;
|
|
3542
3495
|
int8_t month;
|
|
3543
3496
|
int8_t day;
|
|
@@ -3549,12 +3502,12 @@ union LocalDate {
|
|
|
3549
3502
|
} st;
|
|
3550
3503
|
|
|
3551
3504
|
LocalDate() = default;
|
|
3552
|
-
#if defined(
|
|
3505
|
+
#if defined(K_BIG_ENDIAN)
|
|
3553
3506
|
LocalDate(int16_t year, int8_t month, int8_t day)
|
|
3554
|
-
: st({ year, month, day }) {
|
|
3507
|
+
: st({ year, month, day }) { K_ASSERT(IsValid()); }
|
|
3555
3508
|
#else
|
|
3556
3509
|
LocalDate(int16_t year, int8_t month, int8_t day)
|
|
3557
|
-
: st({ day, month, year }) {
|
|
3510
|
+
: st({ day, month, year }) { K_ASSERT(IsValid()); }
|
|
3558
3511
|
#endif
|
|
3559
3512
|
|
|
3560
3513
|
static inline bool IsLeapYear(int16_t year)
|
|
@@ -3651,6 +3604,13 @@ static inline int64_t GetClockCounter()
|
|
|
3651
3604
|
int64_t counter = ((int64_t)counter_high << 32) | counter_low;
|
|
3652
3605
|
return counter;
|
|
3653
3606
|
}
|
|
3607
|
+
#elif defined(__aarch64__)
|
|
3608
|
+
static inline int64_t GetClockCounter()
|
|
3609
|
+
{
|
|
3610
|
+
uint64_t counter;
|
|
3611
|
+
__asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (counter));
|
|
3612
|
+
return counter;
|
|
3613
|
+
}
|
|
3654
3614
|
#endif
|
|
3655
3615
|
|
|
3656
3616
|
struct TimeSpec {
|
|
@@ -3676,10 +3636,11 @@ int64_t ComposeTimeUTC(const TimeSpec &spec);
|
|
|
3676
3636
|
// ------------------------------------------------------------------------
|
|
3677
3637
|
|
|
3678
3638
|
enum class FmtType {
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3639
|
+
Str,
|
|
3640
|
+
PadStr,
|
|
3641
|
+
RepeatStr,
|
|
3682
3642
|
Char,
|
|
3643
|
+
Buffer,
|
|
3683
3644
|
Custom,
|
|
3684
3645
|
Bool,
|
|
3685
3646
|
Integer,
|
|
@@ -3690,15 +3651,19 @@ enum class FmtType {
|
|
|
3690
3651
|
Octal,
|
|
3691
3652
|
BigHex,
|
|
3692
3653
|
SmallHex,
|
|
3654
|
+
BigBytes,
|
|
3655
|
+
SmallBytes,
|
|
3693
3656
|
MemorySize,
|
|
3694
3657
|
DiskSize,
|
|
3695
3658
|
Date,
|
|
3696
3659
|
TimeISO,
|
|
3697
3660
|
TimeNice,
|
|
3698
|
-
|
|
3661
|
+
List,
|
|
3699
3662
|
FlagNames,
|
|
3700
3663
|
FlagOptions,
|
|
3701
|
-
|
|
3664
|
+
Random,
|
|
3665
|
+
SafeStr,
|
|
3666
|
+
SafeChar
|
|
3702
3667
|
};
|
|
3703
3668
|
|
|
3704
3669
|
template <typename T>
|
|
@@ -3733,7 +3698,7 @@ public:
|
|
|
3733
3698
|
template <typename T>
|
|
3734
3699
|
explicit FmtCustom(const T &obj)
|
|
3735
3700
|
{
|
|
3736
|
-
static_assert(
|
|
3701
|
+
static_assert(K_SIZE(*this) <= K_SIZE(raw));
|
|
3737
3702
|
new (raw) Concrete<T>(&obj, &FmtTraits<T>::Format);
|
|
3738
3703
|
}
|
|
3739
3704
|
|
|
@@ -3748,14 +3713,18 @@ class FmtArg {
|
|
|
3748
3713
|
public:
|
|
3749
3714
|
FmtType type;
|
|
3750
3715
|
union {
|
|
3751
|
-
const char
|
|
3752
|
-
|
|
3716
|
+
Span<const char> str;
|
|
3717
|
+
struct {
|
|
3718
|
+
const char *str;
|
|
3719
|
+
int count;
|
|
3720
|
+
} repeat;
|
|
3753
3721
|
char buf[32];
|
|
3754
3722
|
char ch;
|
|
3755
3723
|
FmtCustom custom;
|
|
3756
3724
|
bool b;
|
|
3757
3725
|
int64_t i;
|
|
3758
3726
|
uint64_t u;
|
|
3727
|
+
Span<const uint8_t> hex;
|
|
3759
3728
|
struct {
|
|
3760
3729
|
float value;
|
|
3761
3730
|
int min_prec;
|
|
@@ -3783,68 +3752,123 @@ public:
|
|
|
3783
3752
|
Span<const struct OptionDesc> options;
|
|
3784
3753
|
} u;
|
|
3785
3754
|
const char *separator;
|
|
3786
|
-
}
|
|
3787
|
-
|
|
3788
|
-
struct {
|
|
3789
|
-
FmtType type;
|
|
3790
|
-
int type_len;
|
|
3791
|
-
const void *ptr;
|
|
3792
|
-
Size len;
|
|
3793
|
-
const char *separator;
|
|
3794
|
-
} span;
|
|
3755
|
+
} list;
|
|
3795
3756
|
} u;
|
|
3796
3757
|
|
|
3797
|
-
int
|
|
3798
|
-
|
|
3799
|
-
char pad_char = 0;
|
|
3758
|
+
int pad = 0;
|
|
3759
|
+
char padding = 0;
|
|
3800
3760
|
|
|
3801
3761
|
FmtArg() = default;
|
|
3802
|
-
FmtArg(
|
|
3803
|
-
FmtArg(
|
|
3804
|
-
FmtArg(
|
|
3805
|
-
FmtArg(char
|
|
3806
|
-
FmtArg(
|
|
3807
|
-
FmtArg(
|
|
3808
|
-
FmtArg(
|
|
3809
|
-
FmtArg(
|
|
3810
|
-
FmtArg(
|
|
3811
|
-
FmtArg(
|
|
3812
|
-
FmtArg(
|
|
3813
|
-
FmtArg(
|
|
3814
|
-
FmtArg(
|
|
3815
|
-
FmtArg(
|
|
3816
|
-
FmtArg(
|
|
3817
|
-
FmtArg(
|
|
3818
|
-
FmtArg(
|
|
3819
|
-
FmtArg(
|
|
3820
|
-
FmtArg(const
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
FmtArg
|
|
3762
|
+
FmtArg(const FmtArg &other) = default;
|
|
3763
|
+
FmtArg(std::nullptr_t) : FmtArg(FmtType::Str) { u.str = "(null)"; }
|
|
3764
|
+
FmtArg(const char *str) : FmtArg(FmtType::Str) { u.str = str ? str : "(null)"; }
|
|
3765
|
+
FmtArg(Span<const char> str) : FmtArg(FmtType::Str) { u.str = str; }
|
|
3766
|
+
FmtArg(char c) : FmtArg(FmtType::Char) { u.ch = c; }
|
|
3767
|
+
FmtArg(const FmtCustom &custom) : FmtArg(FmtType::Custom) { u.custom = custom; }
|
|
3768
|
+
FmtArg(bool b) : FmtArg(FmtType::Bool) { u.b = b; }
|
|
3769
|
+
FmtArg(unsigned char i) : FmtArg(FmtType::Unsigned) { u.u = i; }
|
|
3770
|
+
FmtArg(short i) : FmtArg(FmtType::Integer) { u.i = i; }
|
|
3771
|
+
FmtArg(unsigned short i) : FmtArg(FmtType::Unsigned) { u.u = i; }
|
|
3772
|
+
FmtArg(int i) : FmtArg(FmtType::Integer) { u.i = i; }
|
|
3773
|
+
FmtArg(unsigned int i) : FmtArg(FmtType::Unsigned) { u.u = i; }
|
|
3774
|
+
FmtArg(long i) : FmtArg(FmtType::Integer) { u.i = i; }
|
|
3775
|
+
FmtArg(unsigned long i) : FmtArg(FmtType::Unsigned) { u.u = i; }
|
|
3776
|
+
FmtArg(long long i) : FmtArg(FmtType::Integer) { u.i = i; }
|
|
3777
|
+
FmtArg(unsigned long long i) : FmtArg(FmtType::Unsigned) { u.u = i; }
|
|
3778
|
+
FmtArg(float f) : FmtArg(FmtType::Float) { u.f = { f, 0, INT_MAX }; }
|
|
3779
|
+
FmtArg(double d) : FmtArg(FmtType::Double) { u.d = { d, 0, INT_MAX }; }
|
|
3780
|
+
FmtArg(const void *ptr) : FmtArg(FmtType::BigHex) { u.u = (uint64_t)ptr; }
|
|
3781
|
+
FmtArg(const LocalDate &date) : FmtArg(FmtType::Date) { u.date = date; }
|
|
3782
|
+
|
|
3783
|
+
protected:
|
|
3784
|
+
FmtArg(FmtType type) : type(type) {}
|
|
3785
|
+
};
|
|
3786
|
+
|
|
3787
|
+
class FmtSafe: public FmtArg {
|
|
3788
|
+
public:
|
|
3789
|
+
FmtSafe() = default;
|
|
3790
|
+
FmtSafe(FmtArg arg) : FmtArg(arg) {}
|
|
3791
|
+
FmtSafe(std::nullptr_t) : FmtArg(FmtType::Str) { u.str = "(null)"; }
|
|
3792
|
+
FmtSafe(const char *str) : FmtArg(FmtType::SafeStr) { u.str = str ? str : "(null)"; } // safe
|
|
3793
|
+
FmtSafe(Span<const char> str) : FmtArg(FmtType::SafeStr) { u.str = str; } // safe
|
|
3794
|
+
FmtSafe(char c) : FmtArg(FmtType::SafeChar) { u.ch = c; } // safe
|
|
3795
|
+
FmtSafe(const FmtCustom &custom) : FmtArg(custom) {}
|
|
3796
|
+
FmtSafe(bool b) : FmtArg(b) {}
|
|
3797
|
+
FmtSafe(unsigned char i) : FmtArg(i) {}
|
|
3798
|
+
FmtSafe(short i) : FmtArg(i) {}
|
|
3799
|
+
FmtSafe(unsigned short i) : FmtArg(i) {}
|
|
3800
|
+
FmtSafe(int i) : FmtArg(i) {}
|
|
3801
|
+
FmtSafe(unsigned int i) : FmtArg(i) {}
|
|
3802
|
+
FmtSafe(long i) : FmtArg(i) {}
|
|
3803
|
+
FmtSafe(unsigned long i) : FmtArg(i) {}
|
|
3804
|
+
FmtSafe(long long i) : FmtArg(i) {}
|
|
3805
|
+
FmtSafe(unsigned long long i) : FmtArg(i) {}
|
|
3806
|
+
FmtSafe(float f) : FmtArg(f) {}
|
|
3807
|
+
FmtSafe(double d) : FmtArg(d) {}
|
|
3808
|
+
FmtSafe(const void *ptr) : FmtArg(ptr) {}
|
|
3809
|
+
FmtSafe(const LocalDate &date) : FmtArg(date) {}
|
|
3825
3810
|
};
|
|
3826
3811
|
|
|
3827
|
-
static inline FmtArg
|
|
3812
|
+
static inline FmtArg FmtInt(long long i, int pad = 0, char padding = '0')
|
|
3813
|
+
{
|
|
3814
|
+
FmtArg arg;
|
|
3815
|
+
arg.type = FmtType::Integer;
|
|
3816
|
+
arg.u.i = i;
|
|
3817
|
+
arg.pad = pad;
|
|
3818
|
+
arg.padding = padding;
|
|
3819
|
+
return arg;
|
|
3820
|
+
}
|
|
3821
|
+
static inline FmtArg FmtInt(unsigned long long u, int pad = 0, char padding = '0')
|
|
3822
|
+
{
|
|
3823
|
+
FmtArg arg;
|
|
3824
|
+
arg.type = FmtType::Unsigned;
|
|
3825
|
+
arg.u.u = u;
|
|
3826
|
+
arg.pad = pad;
|
|
3827
|
+
arg.padding = padding;
|
|
3828
|
+
return arg;
|
|
3829
|
+
}
|
|
3830
|
+
static inline FmtArg FmtInt(unsigned char u, int pad = 0, char padding = '0') { return FmtInt((unsigned long long)u, pad, padding); }
|
|
3831
|
+
static inline FmtArg FmtInt(short i, int pad = 0, char padding = '0') { return FmtInt((long long)i, pad, padding); }
|
|
3832
|
+
static inline FmtArg FmtInt(unsigned short u, int pad = 0, char padding = '0') { return FmtInt((unsigned long long)u, pad, padding); }
|
|
3833
|
+
static inline FmtArg FmtInt(int i, int pad = 0, char padding = '0') { return FmtInt((long long)i, pad, padding); }
|
|
3834
|
+
static inline FmtArg FmtInt(unsigned int u, int pad = 0, char padding = '0') { return FmtInt((unsigned long long)u, pad, padding); }
|
|
3835
|
+
static inline FmtArg FmtInt(long i, int pad = 0, char padding = '0') { return FmtInt((long long)i, pad, padding); }
|
|
3836
|
+
static inline FmtArg FmtInt(unsigned long u, int pad = 0, char padding = '0') { return FmtInt((unsigned long long)u, pad, padding); }
|
|
3837
|
+
|
|
3838
|
+
static inline FmtArg FmtBin(uint64_t u, int pad = 0, char padding = '0')
|
|
3828
3839
|
{
|
|
3829
3840
|
FmtArg arg;
|
|
3830
3841
|
arg.type = FmtType::Binary;
|
|
3831
3842
|
arg.u.u = u;
|
|
3843
|
+
arg.pad = pad;
|
|
3844
|
+
arg.padding = padding;
|
|
3832
3845
|
return arg;
|
|
3833
3846
|
}
|
|
3834
|
-
static inline FmtArg FmtOctal(uint64_t u)
|
|
3847
|
+
static inline FmtArg FmtOctal(uint64_t u, int pad = 0, char padding = '0')
|
|
3835
3848
|
{
|
|
3836
3849
|
FmtArg arg;
|
|
3837
3850
|
arg.type = FmtType::Octal;
|
|
3838
3851
|
arg.u.u = u;
|
|
3852
|
+
arg.pad = pad;
|
|
3853
|
+
arg.padding = padding;
|
|
3839
3854
|
return arg;
|
|
3840
3855
|
}
|
|
3841
|
-
static inline FmtArg FmtHex(uint64_t u,
|
|
3856
|
+
static inline FmtArg FmtHex(uint64_t u, int pad = 0, char padding = '0')
|
|
3842
3857
|
{
|
|
3843
|
-
RG_ASSERT(type == FmtType::BigHex || type == FmtType::SmallHex);
|
|
3844
|
-
|
|
3845
3858
|
FmtArg arg;
|
|
3846
|
-
arg.type =
|
|
3859
|
+
arg.type = FmtType::BigHex;
|
|
3847
3860
|
arg.u.u = u;
|
|
3861
|
+
arg.pad = pad;
|
|
3862
|
+
arg.padding = padding;
|
|
3863
|
+
return arg;
|
|
3864
|
+
}
|
|
3865
|
+
static inline FmtArg FmtHexSmall(uint64_t u, int pad = 0, char padding = '0')
|
|
3866
|
+
{
|
|
3867
|
+
FmtArg arg;
|
|
3868
|
+
arg.type = FmtType::SmallHex;
|
|
3869
|
+
arg.u.u = u;
|
|
3870
|
+
arg.pad = pad;
|
|
3871
|
+
arg.padding = padding;
|
|
3848
3872
|
return arg;
|
|
3849
3873
|
}
|
|
3850
3874
|
|
|
@@ -3905,56 +3929,77 @@ static inline FmtArg FmtTimeNice(TimeSpec spec, bool ms = false)
|
|
|
3905
3929
|
return arg;
|
|
3906
3930
|
}
|
|
3907
3931
|
|
|
3908
|
-
static inline FmtArg
|
|
3932
|
+
static inline FmtArg FmtList(Span<const char *const> names, const char *sep = ", ")
|
|
3909
3933
|
{
|
|
3910
|
-
RG_ASSERT(len < 256);
|
|
3911
|
-
len = std::min(len, (Size)256);
|
|
3912
|
-
|
|
3913
3934
|
FmtArg arg;
|
|
3914
|
-
arg.type = FmtType::
|
|
3915
|
-
arg.u.
|
|
3916
|
-
arg.u.
|
|
3935
|
+
arg.type = FmtType::List;
|
|
3936
|
+
arg.u.list.u.names = names;
|
|
3937
|
+
arg.u.list.separator = sep;
|
|
3917
3938
|
return arg;
|
|
3918
3939
|
}
|
|
3919
|
-
|
|
3920
3940
|
static inline FmtArg FmtFlags(uint64_t flags, Span<const char *const> names, const char *sep = ", ")
|
|
3921
3941
|
{
|
|
3922
3942
|
FmtArg arg;
|
|
3923
3943
|
arg.type = FmtType::FlagNames;
|
|
3924
|
-
arg.u.
|
|
3925
|
-
arg.u.
|
|
3926
|
-
arg.u.
|
|
3944
|
+
arg.u.list.flags = flags & ((1ull << names.len) - 1);
|
|
3945
|
+
arg.u.list.u.names = names;
|
|
3946
|
+
arg.u.list.separator = sep;
|
|
3927
3947
|
return arg;
|
|
3928
3948
|
}
|
|
3929
|
-
|
|
3930
3949
|
static inline FmtArg FmtFlags(uint64_t flags, Span<const struct OptionDesc> options, const char *sep = ", ")
|
|
3931
3950
|
{
|
|
3932
3951
|
FmtArg arg;
|
|
3933
3952
|
arg.type = FmtType::FlagOptions;
|
|
3934
|
-
arg.u.
|
|
3935
|
-
arg.u.
|
|
3936
|
-
arg.u.
|
|
3953
|
+
arg.u.list.flags = flags & ((1ull << options.len) - 1);
|
|
3954
|
+
arg.u.list.u.options = options;
|
|
3955
|
+
arg.u.list.separator = sep;
|
|
3937
3956
|
return arg;
|
|
3938
3957
|
}
|
|
3939
3958
|
|
|
3940
|
-
|
|
3941
|
-
FmtArg FmtSpan(Span<T> arr, FmtType type, const char *sep = ", ")
|
|
3959
|
+
static inline FmtArg FmtPad(Span<const char> str, int pad, char padding = ' ')
|
|
3942
3960
|
{
|
|
3943
3961
|
FmtArg arg;
|
|
3944
|
-
arg.type = FmtType::
|
|
3945
|
-
arg.u.
|
|
3946
|
-
arg.
|
|
3947
|
-
arg.
|
|
3948
|
-
arg
|
|
3949
|
-
|
|
3962
|
+
arg.type = FmtType::PadStr;
|
|
3963
|
+
arg.u.str = str;
|
|
3964
|
+
arg.pad = pad;
|
|
3965
|
+
arg.padding = padding;
|
|
3966
|
+
return arg;
|
|
3967
|
+
}
|
|
3968
|
+
static inline FmtArg FmtRepeat(const char *str, int count)
|
|
3969
|
+
{
|
|
3970
|
+
FmtArg arg;
|
|
3971
|
+
arg.type = FmtType::RepeatStr;
|
|
3972
|
+
arg.u.repeat.str = str;
|
|
3973
|
+
arg.u.repeat.count = count;
|
|
3974
|
+
return arg;
|
|
3975
|
+
}
|
|
3976
|
+
|
|
3977
|
+
static inline FmtArg FmtHex(Span<const uint8_t> buf)
|
|
3978
|
+
{
|
|
3979
|
+
FmtArg arg;
|
|
3980
|
+
arg.type = FmtType::BigBytes;
|
|
3981
|
+
arg.u.hex = buf;
|
|
3982
|
+
return arg;
|
|
3983
|
+
}
|
|
3984
|
+
static inline FmtArg FmtHexSmall(Span<const uint8_t> buf)
|
|
3985
|
+
{
|
|
3986
|
+
FmtArg arg;
|
|
3987
|
+
arg.type = FmtType::SmallBytes;
|
|
3988
|
+
arg.u.hex = buf;
|
|
3989
|
+
return arg;
|
|
3990
|
+
}
|
|
3991
|
+
|
|
3992
|
+
static inline FmtArg FmtRandom(Size len, const char *chars = nullptr)
|
|
3993
|
+
{
|
|
3994
|
+
K_ASSERT(len < 256);
|
|
3995
|
+
len = std::min(len, (Size)256);
|
|
3996
|
+
|
|
3997
|
+
FmtArg arg;
|
|
3998
|
+
arg.type = FmtType::Random;
|
|
3999
|
+
arg.u.random.len = len;
|
|
4000
|
+
arg.u.random.chars = chars;
|
|
3950
4001
|
return arg;
|
|
3951
4002
|
}
|
|
3952
|
-
template <typename T>
|
|
3953
|
-
FmtArg FmtSpan(Span<T> arr, const char *sep = ", ") { return FmtSpan(arr, FmtArg(T()).type, sep); }
|
|
3954
|
-
template <typename T, Size N>
|
|
3955
|
-
FmtArg FmtSpan(T (&arr)[N], FmtType type, const char *sep = ", ") { return FmtSpan(MakeSpan(arr), type, sep); }
|
|
3956
|
-
template <typename T, Size N>
|
|
3957
|
-
FmtArg FmtSpan(T (&arr)[N], const char *sep = ", ") { return FmtSpan(MakeSpan(arr), sep); }
|
|
3958
4003
|
|
|
3959
4004
|
class FmtUpperAscii {
|
|
3960
4005
|
Span<const char> str;
|
|
@@ -3976,23 +4021,34 @@ public:
|
|
|
3976
4021
|
operator FmtArg() const { return FmtCustom(*this); }
|
|
3977
4022
|
};
|
|
3978
4023
|
|
|
3979
|
-
class
|
|
4024
|
+
class FmtUrlSafe {
|
|
4025
|
+
Span<const char> str;
|
|
4026
|
+
const char *passthrough;
|
|
4027
|
+
|
|
4028
|
+
public:
|
|
4029
|
+
FmtUrlSafe(Span<const char> str, const char *passthrough)
|
|
4030
|
+
: str(str), passthrough(passthrough) {}
|
|
4031
|
+
|
|
4032
|
+
void Format(FunctionRef<void(Span<const char>)> append) const;
|
|
4033
|
+
operator FmtArg() const { return FmtCustom(*this); }
|
|
4034
|
+
};
|
|
4035
|
+
|
|
4036
|
+
class FmtHtmlSafe {
|
|
3980
4037
|
Span<const char> str;
|
|
3981
4038
|
|
|
3982
4039
|
public:
|
|
3983
|
-
|
|
4040
|
+
FmtHtmlSafe(Span<const char> str) : str(str) {}
|
|
3984
4041
|
|
|
3985
4042
|
void Format(FunctionRef<void(Span<const char>)> append) const;
|
|
3986
4043
|
operator FmtArg() const { return FmtCustom(*this); }
|
|
3987
4044
|
};
|
|
3988
4045
|
|
|
3989
|
-
class
|
|
4046
|
+
class FmtEscape {
|
|
3990
4047
|
Span<const char> str;
|
|
3991
|
-
|
|
4048
|
+
char quote;
|
|
3992
4049
|
|
|
3993
4050
|
public:
|
|
3994
|
-
|
|
3995
|
-
: str(str), passthrough(passthrough) {}
|
|
4051
|
+
FmtEscape(Span<const char> str, char quote) : str(str), quote(quote) {}
|
|
3996
4052
|
|
|
3997
4053
|
void Format(FunctionRef<void(Span<const char>)> append) const;
|
|
3998
4054
|
operator FmtArg() const { return FmtCustom(*this); }
|
|
@@ -4097,11 +4153,11 @@ static inline void Log(LogLevel level, const char *ctx, const char *fmt)
|
|
|
4097
4153
|
template <typename... Args>
|
|
4098
4154
|
static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args... args)
|
|
4099
4155
|
{
|
|
4100
|
-
const FmtArg fmt_args[] = {
|
|
4156
|
+
const FmtArg fmt_args[] = { FmtSafe(args)... };
|
|
4101
4157
|
LogFmt(level, ctx, fmt, fmt_args);
|
|
4102
4158
|
}
|
|
4103
4159
|
|
|
4104
|
-
#if defined(
|
|
4160
|
+
#if defined(K_DEBUG) && __cplusplus >= 202002L && __has_include(<source_location>)
|
|
4105
4161
|
struct LogContext {
|
|
4106
4162
|
const char *fmt;
|
|
4107
4163
|
char str[56] = {};
|
|
@@ -4157,7 +4213,7 @@ static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args...
|
|
|
4157
4213
|
template <typename... Args>
|
|
4158
4214
|
static inline void LogError(LogContext ctx, Args... args) { Log(LogLevel::Error, ctx.str, ctx.fmt, args...); }
|
|
4159
4215
|
#else
|
|
4160
|
-
#if defined(
|
|
4216
|
+
#if defined(K_DEBUG)
|
|
4161
4217
|
template <typename... Args>
|
|
4162
4218
|
static inline void LogDebug(Args... args) { Log(LogLevel::Debug, "Debug: ", args...); }
|
|
4163
4219
|
#else
|
|
@@ -4167,9 +4223,9 @@ static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args...
|
|
|
4167
4223
|
template <typename... Args>
|
|
4168
4224
|
static inline void LogInfo(Args... args) { Log(LogLevel::Info, nullptr, args...); }
|
|
4169
4225
|
template <typename... Args>
|
|
4170
|
-
static inline void LogWarning(Args... args) { Log(LogLevel::Warning, "Warning: ", args...); }
|
|
4226
|
+
static inline void LogWarning(Args... args) { Log(LogLevel::Warning, T("Warning: "), args...); }
|
|
4171
4227
|
template <typename... Args>
|
|
4172
|
-
static inline void LogError(Args... args) { Log(LogLevel::Error, "Error: ", args...); }
|
|
4228
|
+
static inline void LogError(Args... args) { Log(LogLevel::Error, T("Error: "), args...); }
|
|
4173
4229
|
#endif
|
|
4174
4230
|
|
|
4175
4231
|
void SetLogHandler(const std::function<LogFunc> &func, bool vt100);
|
|
@@ -4202,7 +4258,7 @@ struct ProgressInfo {
|
|
|
4202
4258
|
typedef void ProgressFunc(Span<const ProgressInfo> states);
|
|
4203
4259
|
|
|
4204
4260
|
class ProgressHandle {
|
|
4205
|
-
char text[
|
|
4261
|
+
char text[K_PROGRESS_TEXT_SIZE] = {};
|
|
4206
4262
|
|
|
4207
4263
|
std::atomic<ProgressNode *> node = nullptr;
|
|
4208
4264
|
|
|
@@ -4222,7 +4278,7 @@ public:
|
|
|
4222
4278
|
template<typename... Args>
|
|
4223
4279
|
void SetFmt(int64_t value, int64_t min, int64_t max, const char *fmt, Args... args)
|
|
4224
4280
|
{
|
|
4225
|
-
char buf[
|
|
4281
|
+
char buf[K_PROGRESS_TEXT_SIZE];
|
|
4226
4282
|
Fmt(buf, fmt, args...);
|
|
4227
4283
|
|
|
4228
4284
|
Set(value, min, max, (const char *)buf);
|
|
@@ -4240,7 +4296,7 @@ public:
|
|
|
4240
4296
|
|
|
4241
4297
|
private:
|
|
4242
4298
|
ProgressNode *AcquireNode();
|
|
4243
|
-
void CopyText(Span<const char> text, char out[
|
|
4299
|
+
void CopyText(Span<const char> text, char out[K_PROGRESS_TEXT_SIZE]);
|
|
4244
4300
|
};
|
|
4245
4301
|
|
|
4246
4302
|
void SetProgressHandler(const std::function<ProgressFunc> &func);
|
|
@@ -4253,15 +4309,15 @@ void DefaultProgressHandler(Span<const ProgressInfo> bars);
|
|
|
4253
4309
|
// ------------------------------------------------------------------------
|
|
4254
4310
|
|
|
4255
4311
|
#if defined(_WIN32)
|
|
4256
|
-
#define
|
|
4257
|
-
#define
|
|
4258
|
-
#define
|
|
4259
|
-
#define
|
|
4312
|
+
#define K_PATH_SEPARATORS "\\/"
|
|
4313
|
+
#define K_PATH_DELIMITER ';'
|
|
4314
|
+
#define K_EXECUTABLE_EXTENSION ".exe"
|
|
4315
|
+
#define K_SHARED_LIBRARY_EXTENSION ".dll"
|
|
4260
4316
|
#else
|
|
4261
|
-
#define
|
|
4262
|
-
#define
|
|
4263
|
-
#define
|
|
4264
|
-
#define
|
|
4317
|
+
#define K_PATH_SEPARATORS "/"
|
|
4318
|
+
#define K_PATH_DELIMITER ':'
|
|
4319
|
+
#define K_EXECUTABLE_EXTENSION ""
|
|
4320
|
+
#define K_SHARED_LIBRARY_EXTENSION ".so"
|
|
4265
4321
|
#endif
|
|
4266
4322
|
|
|
4267
4323
|
#if defined(_WIN32)
|
|
@@ -4308,11 +4364,11 @@ static const char *const CompressionTypeExtensions[] = {
|
|
|
4308
4364
|
Span<const char> GetPathDirectory(Span<const char> filename);
|
|
4309
4365
|
Span<const char> GetPathExtension(Span<const char> filename,
|
|
4310
4366
|
CompressionType *out_compression_type = nullptr);
|
|
4311
|
-
CompressionType GetPathCompression(Span<const char> filename);
|
|
4312
4367
|
|
|
4313
4368
|
enum class NormalizeFlag {
|
|
4314
4369
|
EndWithSeparator = 1 << 0,
|
|
4315
|
-
ForceSlash = 1 << 1
|
|
4370
|
+
ForceSlash = 1 << 1,
|
|
4371
|
+
NoExpansion = 1 << 2
|
|
4316
4372
|
};
|
|
4317
4373
|
|
|
4318
4374
|
Span<char> NormalizePath(Span<const char> path, Span<const char> root_directory, unsigned int flags, Allocator *alloc);
|
|
@@ -4326,6 +4382,7 @@ static inline Span<char> NormalizePath(Span<const char> path, Allocator *alloc)
|
|
|
4326
4382
|
bool PathIsAbsolute(const char *path);
|
|
4327
4383
|
bool PathIsAbsolute(Span<const char> path);
|
|
4328
4384
|
bool PathContainsDotDot(const char *path);
|
|
4385
|
+
bool PathContainsDotDot(Span<const char> path);
|
|
4329
4386
|
|
|
4330
4387
|
enum class StatFlag {
|
|
4331
4388
|
SilentMissing = 1 << 0,
|
|
@@ -4398,7 +4455,20 @@ static inline RenameResult RenameFile(const char *src_filename, const char *dest
|
|
|
4398
4455
|
{ return RenameFile(src_filename, dest_filename, 0, flags); }
|
|
4399
4456
|
|
|
4400
4457
|
bool ResizeFile(int fd, const char *filename, int64_t len);
|
|
4401
|
-
|
|
4458
|
+
|
|
4459
|
+
#if !defined(_WIN32)
|
|
4460
|
+
bool SetFileMode(int fd, const char *filename, uint32_t mode);
|
|
4461
|
+
static inline bool SetFileMode(const char *filename, uint32_t mode)
|
|
4462
|
+
{ return SetFileMode(-1, filename, mode); }
|
|
4463
|
+
|
|
4464
|
+
bool SetFileOwner(int fd, const char *filename, uint32_t uid, uint32_t gid);
|
|
4465
|
+
static inline bool SetFileOwner(const char *filename, uint32_t uid, uint32_t gid)
|
|
4466
|
+
{ return SetFileOwner(-1, filename, uid, gid); }
|
|
4467
|
+
#endif
|
|
4468
|
+
|
|
4469
|
+
bool SetFileTimes(int fd, const char *filename, int64_t mtime, int64_t ctime);
|
|
4470
|
+
static inline bool SetFileTimes(const char *filename, int64_t mtime, int64_t ctime)
|
|
4471
|
+
{ return SetFileTimes(-1, filename, mtime, ctime); }
|
|
4402
4472
|
|
|
4403
4473
|
struct VolumeInfo {
|
|
4404
4474
|
int64_t total;
|
|
@@ -4523,7 +4593,7 @@ void CloseHandleSafe(void **handle_ptr); // HANDLE
|
|
|
4523
4593
|
#else
|
|
4524
4594
|
void SetSignalHandler(int signal, void (*func)(int), struct sigaction *prev = nullptr);
|
|
4525
4595
|
|
|
4526
|
-
bool CreatePipe(int
|
|
4596
|
+
bool CreatePipe(bool block, int out_pfd[2]);
|
|
4527
4597
|
void CloseDescriptorSafe(int *fd_ptr);
|
|
4528
4598
|
#endif
|
|
4529
4599
|
|
|
@@ -4547,7 +4617,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
|
4547
4617
|
HeapArray<uint8_t> *out_buf, int *out_code);
|
|
4548
4618
|
|
|
4549
4619
|
// Simple variants
|
|
4550
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,int *out_code)
|
|
4620
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info, int *out_code)
|
|
4551
4621
|
{ return ExecuteCommandLine(cmd_line, info, {}, {}, out_code); }
|
|
4552
4622
|
static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
4553
4623
|
Span<const uint8_t> in_buf,
|
|
@@ -4587,18 +4657,34 @@ void WaitDelay(int64_t delay);
|
|
|
4587
4657
|
|
|
4588
4658
|
#if !defined(__wasi__)
|
|
4589
4659
|
|
|
4590
|
-
enum class
|
|
4591
|
-
|
|
4660
|
+
enum class WaitResult {
|
|
4661
|
+
Ready,
|
|
4662
|
+
Timeout,
|
|
4592
4663
|
Interrupt,
|
|
4593
4664
|
Message,
|
|
4594
|
-
|
|
4665
|
+
Exit
|
|
4666
|
+
};
|
|
4667
|
+
|
|
4668
|
+
struct WaitSource {
|
|
4669
|
+
#if defined(_WIN32)
|
|
4670
|
+
// Special-cased on Windows: set to NULL to wait for the Win32 message pump too
|
|
4671
|
+
void *handle; // HANDLE
|
|
4672
|
+
int timeout;
|
|
4673
|
+
#else
|
|
4674
|
+
int fd;
|
|
4675
|
+
int timeout;
|
|
4676
|
+
int events = 0;
|
|
4677
|
+
#endif
|
|
4595
4678
|
};
|
|
4596
4679
|
|
|
4597
|
-
// After
|
|
4598
|
-
//
|
|
4599
|
-
//
|
|
4600
|
-
|
|
4601
|
-
|
|
4680
|
+
// After WaitEvents() has been called once (even with timeout 0), a few signals (such as SIGINT, SIGHUP)
|
|
4681
|
+
// and their Windows equivalent will be permanently ignored.
|
|
4682
|
+
// Only the main thread (running main) will get WaitResult::Message events (and SIGUSR1).
|
|
4683
|
+
WaitResult WaitEvents(Span<const WaitSource> sources, int64_t timeout, uint64_t *out_ready = nullptr);
|
|
4684
|
+
WaitResult WaitEvents(int64_t timeout);
|
|
4685
|
+
|
|
4686
|
+
void PostWaitMessage();
|
|
4687
|
+
void PostTerminate();
|
|
4602
4688
|
|
|
4603
4689
|
#endif
|
|
4604
4690
|
|
|
@@ -4613,19 +4699,72 @@ bool DropRootIdentity();
|
|
|
4613
4699
|
bool NotifySystemd();
|
|
4614
4700
|
#endif
|
|
4615
4701
|
|
|
4616
|
-
#define
|
|
4702
|
+
#define K_RESTART_EINTR(CallCode, ErrorCond) \
|
|
4617
4703
|
([&]() { \
|
|
4618
4704
|
decltype(CallCode) ret; \
|
|
4619
4705
|
while ((ret = (CallCode)) ErrorCond && errno == EINTR); \
|
|
4620
4706
|
return ret; \
|
|
4621
4707
|
})()
|
|
4622
4708
|
|
|
4709
|
+
class InitHelper {
|
|
4710
|
+
public:
|
|
4711
|
+
const char *name;
|
|
4712
|
+
InitHelper *next = nullptr;
|
|
4713
|
+
|
|
4714
|
+
InitHelper(const char *name);
|
|
4715
|
+
virtual void Run() = 0;
|
|
4716
|
+
};
|
|
4717
|
+
|
|
4718
|
+
class FinalizeHelper {
|
|
4719
|
+
public:
|
|
4720
|
+
const char *name;
|
|
4721
|
+
FinalizeHelper *next = nullptr;
|
|
4722
|
+
|
|
4723
|
+
FinalizeHelper(const char *name);
|
|
4724
|
+
virtual void Run() = 0;
|
|
4725
|
+
};
|
|
4726
|
+
|
|
4727
|
+
#define K_INIT_(ClassName, Name) \
|
|
4728
|
+
class ClassName: public InitHelper { \
|
|
4729
|
+
public: \
|
|
4730
|
+
ClassName(): InitHelper(Name) {} \
|
|
4731
|
+
void Run() override; \
|
|
4732
|
+
}; \
|
|
4733
|
+
static ClassName K_UNIQUE_NAME(init); \
|
|
4734
|
+
void ClassName::Run()
|
|
4735
|
+
#define K_INIT(Name) K_INIT_(K_CONCAT(K_UNIQUE_NAME(InitHelper), Name), K_STRINGIFY(Name))
|
|
4736
|
+
|
|
4737
|
+
#define K_FINALIZE_(ClassName, Name) \
|
|
4738
|
+
class ClassName: public FinalizeHelper { \
|
|
4739
|
+
public: \
|
|
4740
|
+
ClassName(): FinalizeHelper(Name) {} \
|
|
4741
|
+
void Run() override; \
|
|
4742
|
+
}; \
|
|
4743
|
+
static ClassName K_UNIQUE_NAME(finalize); \
|
|
4744
|
+
void ClassName::Run()
|
|
4745
|
+
#define K_FINALIZE(Name) K_FINALIZE_(K_CONCAT(K_UNIQUE_NAME(FinalizeHelper), Name), K_STRINGIFY(Name))
|
|
4746
|
+
|
|
4747
|
+
#define K_EXIT_(ClassName) \
|
|
4748
|
+
class ClassName { \
|
|
4749
|
+
public: \
|
|
4750
|
+
~ClassName(); \
|
|
4751
|
+
}; \
|
|
4752
|
+
static ClassName K_UNIQUE_NAME(exit); \
|
|
4753
|
+
ClassName::~ClassName()
|
|
4754
|
+
#define K_EXIT(Name) K_EXIT_(K_CONCAT(K_UNIQUE_NAME(ExitHelper), Name))
|
|
4755
|
+
|
|
4623
4756
|
void InitApp();
|
|
4757
|
+
void ExitApp();
|
|
4758
|
+
|
|
4624
4759
|
int Main(int argc, char **argv);
|
|
4625
4760
|
|
|
4626
4761
|
static inline int RunApp(int argc, char **argv)
|
|
4627
4762
|
{
|
|
4763
|
+
K_CRITICAL(argc >= 1, "First argument is missing");
|
|
4764
|
+
|
|
4628
4765
|
InitApp();
|
|
4766
|
+
K_DEFER { ExitApp(); };
|
|
4767
|
+
|
|
4629
4768
|
return Main(argc, argv);
|
|
4630
4769
|
}
|
|
4631
4770
|
|
|
@@ -4661,10 +4800,10 @@ enum class ParseFlag {
|
|
|
4661
4800
|
Validate = 1 << 1,
|
|
4662
4801
|
End = 1 << 2
|
|
4663
4802
|
};
|
|
4664
|
-
#define
|
|
4803
|
+
#define K_DEFAULT_PARSE_FLAGS ((int)ParseFlag::Log | (int)ParseFlag::Validate | (int)ParseFlag::End)
|
|
4665
4804
|
|
|
4666
4805
|
template <typename T>
|
|
4667
|
-
bool ParseInt(Span<const char> str, T *out_value, unsigned int flags =
|
|
4806
|
+
bool ParseInt(Span<const char> str, T *out_value, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4668
4807
|
Span<const char> *out_remaining = nullptr)
|
|
4669
4808
|
{
|
|
4670
4809
|
if (!str.len) [[unlikely]] {
|
|
@@ -4723,20 +4862,20 @@ overflow:
|
|
|
4723
4862
|
return false;
|
|
4724
4863
|
}
|
|
4725
4864
|
|
|
4726
|
-
bool ParseBool(Span<const char> str, bool *out_value, unsigned int flags =
|
|
4865
|
+
bool ParseBool(Span<const char> str, bool *out_value, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4727
4866
|
Span<const char> *out_remaining = nullptr);
|
|
4728
4867
|
|
|
4729
|
-
bool ParseSize(Span<const char> str, int64_t *out_size, unsigned int flags =
|
|
4868
|
+
bool ParseSize(Span<const char> str, int64_t *out_size, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4730
4869
|
Span<const char> *out_remaining = nullptr);
|
|
4731
|
-
#if
|
|
4870
|
+
#if K_SIZE_MAX < INT64_MAX
|
|
4732
4871
|
static inline bool ParseSize(Span<const char> str, Size *out_size,
|
|
4733
|
-
unsigned int flags =
|
|
4872
|
+
unsigned int flags = K_DEFAULT_PARSE_FLAGS, Span<const char> *out_remaining = nullptr)
|
|
4734
4873
|
{
|
|
4735
4874
|
int64_t size = 0;
|
|
4736
4875
|
if (!ParseSize(str, &size, flags, out_remaining))
|
|
4737
4876
|
return false;
|
|
4738
4877
|
|
|
4739
|
-
if (size >
|
|
4878
|
+
if (size > K_SIZE_MAX) [[unlikely]] {
|
|
4740
4879
|
if (flags & (int)ParseFlag::Log) {
|
|
4741
4880
|
LogError("Size value is too high");
|
|
4742
4881
|
}
|
|
@@ -4748,13 +4887,13 @@ static inline bool ParseSize(Span<const char> str, Size *out_size,
|
|
|
4748
4887
|
}
|
|
4749
4888
|
#endif
|
|
4750
4889
|
|
|
4751
|
-
bool ParseDate(Span<const char> date_str, LocalDate *out_date, unsigned int flags =
|
|
4890
|
+
bool ParseDate(Span<const char> date_str, LocalDate *out_date, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4752
4891
|
Span<const char> *out_remaining = nullptr);
|
|
4753
4892
|
|
|
4754
|
-
bool ParseDuration(Span<const char> str, int64_t *out_duration, unsigned int flags =
|
|
4893
|
+
bool ParseDuration(Span<const char> str, int64_t *out_duration, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4755
4894
|
Span<const char> *out_remaining = nullptr);
|
|
4756
4895
|
static inline bool ParseDuration(Span<const char> str, int *out_duration,
|
|
4757
|
-
unsigned int flags =
|
|
4896
|
+
unsigned int flags = K_DEFAULT_PARSE_FLAGS, Span<const char> *out_remaining = nullptr)
|
|
4758
4897
|
{
|
|
4759
4898
|
int64_t duration = 0;
|
|
4760
4899
|
if (!ParseDuration(str, &duration, flags, out_remaining))
|
|
@@ -4772,12 +4911,15 @@ static inline bool ParseDuration(Span<const char> str, int *out_duration,
|
|
|
4772
4911
|
}
|
|
4773
4912
|
|
|
4774
4913
|
bool ParseVersion(Span<const char> str, int parts, int multiplier, int64_t *out_duration,
|
|
4775
|
-
unsigned int flags =
|
|
4914
|
+
unsigned int flags = K_DEFAULT_PARSE_FLAGS, Span<const char> *out_remaining = nullptr);
|
|
4776
4915
|
|
|
4777
4916
|
// ------------------------------------------------------------------------
|
|
4778
4917
|
// Random
|
|
4779
4918
|
// ------------------------------------------------------------------------
|
|
4780
4919
|
|
|
4920
|
+
void InitChaCha20(uint32_t state[16], const uint8_t key[32], const uint8_t iv[8], const uint8_t counter[8] = nullptr);
|
|
4921
|
+
void RunChaCha20(uint32_t state[16], uint8_t out_buf[64]);
|
|
4922
|
+
|
|
4781
4923
|
void FillRandomSafe(void *buf, Size len);
|
|
4782
4924
|
static inline void FillRandomSafe(Span<uint8_t> buf) { FillRandomSafe(buf.ptr, buf.len); }
|
|
4783
4925
|
|
|
@@ -4788,14 +4930,13 @@ public:
|
|
|
4788
4930
|
FastRandom();
|
|
4789
4931
|
FastRandom(uint64_t seed);
|
|
4790
4932
|
|
|
4933
|
+
uint64_t Next();
|
|
4934
|
+
|
|
4791
4935
|
void Fill(void *buf, Size len);
|
|
4792
4936
|
void Fill(Span<uint8_t> buf) { Fill(buf.ptr, buf.len); }
|
|
4793
4937
|
|
|
4794
4938
|
int GetInt(int min, int max);
|
|
4795
4939
|
int64_t GetInt64(int64_t min, int64_t max);
|
|
4796
|
-
|
|
4797
|
-
private:
|
|
4798
|
-
uint64_t Next();
|
|
4799
4940
|
};
|
|
4800
4941
|
|
|
4801
4942
|
template <typename T>
|
|
@@ -4811,11 +4952,12 @@ public:
|
|
|
4811
4952
|
T operator()()
|
|
4812
4953
|
{
|
|
4813
4954
|
T value;
|
|
4814
|
-
rng.Fill(&value,
|
|
4955
|
+
rng.Fill(&value, K_SIZE(value));
|
|
4815
4956
|
return value;
|
|
4816
4957
|
}
|
|
4817
4958
|
};
|
|
4818
4959
|
|
|
4960
|
+
uint64_t GetRandom();
|
|
4819
4961
|
int GetRandomInt(int min, int max);
|
|
4820
4962
|
int64_t GetRandomInt64(int64_t min, int64_t max);
|
|
4821
4963
|
|
|
@@ -4848,12 +4990,10 @@ bool InitWinsock();
|
|
|
4848
4990
|
|
|
4849
4991
|
int CreateSocket(SocketType type, int flags);
|
|
4850
4992
|
|
|
4851
|
-
bool BindIPSocket(int sock, SocketType type, int port);
|
|
4993
|
+
bool BindIPSocket(int sock, SocketType type, const char *addr, int port);
|
|
4852
4994
|
bool BindUnixSocket(int sock, const char *path);
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
int OpenUnixSocket(const char *path, int flags);
|
|
4856
|
-
int ConnectToUnixSocket(const char *path, int flags);
|
|
4995
|
+
bool ConnectIPSocket(int sock, const char *addr, int port);
|
|
4996
|
+
bool ConnectUnixSocket(int sock, const char *path);
|
|
4857
4997
|
|
|
4858
4998
|
// Only for sockets on Windows
|
|
4859
4999
|
void SetDescriptorNonBlock(int fd, bool enable);
|
|
@@ -4868,7 +5008,7 @@ void CloseSocket(int fd);
|
|
|
4868
5008
|
// ------------------------------------------------------------------------
|
|
4869
5009
|
|
|
4870
5010
|
class Async {
|
|
4871
|
-
|
|
5011
|
+
K_DELETE_COPY(Async)
|
|
4872
5012
|
|
|
4873
5013
|
#if !defined(__wasi__)
|
|
4874
5014
|
std::atomic_bool success { true };
|
|
@@ -4914,7 +5054,7 @@ class StreamDecoder;
|
|
|
4914
5054
|
class StreamEncoder;
|
|
4915
5055
|
|
|
4916
5056
|
class StreamReader {
|
|
4917
|
-
|
|
5057
|
+
K_DELETE_COPY(StreamReader)
|
|
4918
5058
|
|
|
4919
5059
|
enum class SourceType {
|
|
4920
5060
|
Memory,
|
|
@@ -4962,16 +5102,13 @@ class StreamReader {
|
|
|
4962
5102
|
|
|
4963
5103
|
public:
|
|
4964
5104
|
StreamReader() { Close(true); }
|
|
4965
|
-
StreamReader(Span<const uint8_t> buf, const char *filename =
|
|
4966
|
-
CompressionType compression_type = CompressionType::None)
|
|
5105
|
+
StreamReader(Span<const uint8_t> buf, const char *filename, CompressionType compression_type = CompressionType::None)
|
|
4967
5106
|
: StreamReader() { Open(buf, filename, compression_type); }
|
|
4968
|
-
StreamReader(int fd, const char *filename,
|
|
4969
|
-
CompressionType compression_type = CompressionType::None)
|
|
5107
|
+
StreamReader(int fd, const char *filename, CompressionType compression_type = CompressionType::None)
|
|
4970
5108
|
: StreamReader() { Open(fd, filename, compression_type); }
|
|
4971
|
-
StreamReader(const char *filename,
|
|
4972
|
-
CompressionType compression_type = CompressionType::None)
|
|
5109
|
+
StreamReader(const char *filename, CompressionType compression_type = CompressionType::None)
|
|
4973
5110
|
: StreamReader() { Open(filename, compression_type); }
|
|
4974
|
-
StreamReader(const std::function<Size(Span<uint8_t>)> &func, const char *filename
|
|
5111
|
+
StreamReader(const std::function<Size(Span<uint8_t>)> &func, const char *filename,
|
|
4975
5112
|
CompressionType compression_type = CompressionType::None)
|
|
4976
5113
|
: StreamReader() { Open(func, filename, compression_type); }
|
|
4977
5114
|
~StreamReader() { Close(true); }
|
|
@@ -4979,12 +5116,10 @@ public:
|
|
|
4979
5116
|
// Call before Open. Takes ownership and deletes the decoder at the end.
|
|
4980
5117
|
void SetDecoder(StreamDecoder *decoder);
|
|
4981
5118
|
|
|
4982
|
-
bool Open(Span<const uint8_t> buf, const char *filename =
|
|
4983
|
-
|
|
4984
|
-
bool Open(int fd, const char *filename,
|
|
4985
|
-
CompressionType compression_type = CompressionType::None);
|
|
5119
|
+
bool Open(Span<const uint8_t> buf, const char *filename, CompressionType compression_type = CompressionType::None);
|
|
5120
|
+
bool Open(int fd, const char *filename, CompressionType compression_type = CompressionType::None);
|
|
4986
5121
|
OpenResult Open(const char *filename, CompressionType compression_type = CompressionType::None);
|
|
4987
|
-
bool Open(const std::function<Size(Span<uint8_t>)> &func, const char *filename
|
|
5122
|
+
bool Open(const std::function<Size(Span<uint8_t>)> &func, const char *filename,
|
|
4988
5123
|
CompressionType compression_type = CompressionType::None);
|
|
4989
5124
|
bool Close() { return Close(false); }
|
|
4990
5125
|
|
|
@@ -5004,7 +5139,11 @@ public:
|
|
|
5004
5139
|
// Thread safe methods
|
|
5005
5140
|
Size Read(Span<uint8_t> out_buf);
|
|
5006
5141
|
Size Read(Span<char> out_buf) { return Read(out_buf.As<uint8_t>()); }
|
|
5007
|
-
|
|
5142
|
+
|
|
5143
|
+
// Thread safe methods
|
|
5144
|
+
Size ReadFill(Span<uint8_t> out_buf);
|
|
5145
|
+
Size ReadFill(Span<char> out_buf) { return ReadFill(out_buf.As<uint8_t>()); }
|
|
5146
|
+
Size ReadFill(Size buf_len, void *out_buf) { return ReadFill(MakeSpan((uint8_t *)out_buf, buf_len)); }
|
|
5008
5147
|
|
|
5009
5148
|
Size ReadAll(Size max_len, HeapArray<uint8_t> *out_buf);
|
|
5010
5149
|
Size ReadAll(Size max_len, HeapArray<char> *out_buf)
|
|
@@ -5026,12 +5165,12 @@ private:
|
|
|
5026
5165
|
static inline Size ReadFile(const char *filename, Span<uint8_t> out_buf)
|
|
5027
5166
|
{
|
|
5028
5167
|
StreamReader st(filename);
|
|
5029
|
-
return st.
|
|
5168
|
+
return st.ReadFill(out_buf);
|
|
5030
5169
|
}
|
|
5031
5170
|
static inline Size ReadFile(const char *filename, Span<char> out_buf)
|
|
5032
5171
|
{
|
|
5033
5172
|
StreamReader st(filename);
|
|
5034
|
-
return st.
|
|
5173
|
+
return st.ReadFill(out_buf);
|
|
5035
5174
|
}
|
|
5036
5175
|
static inline Size ReadFile(const char *filename, Size max_len, HeapArray<uint8_t> *out_buf)
|
|
5037
5176
|
{
|
|
@@ -5071,16 +5210,16 @@ public:
|
|
|
5071
5210
|
StreamDecompressorHelper(CompressionType type, CreateDecompressorFunc *func);
|
|
5072
5211
|
};
|
|
5073
5212
|
|
|
5074
|
-
#define
|
|
5075
|
-
static StreamDecoder *
|
|
5213
|
+
#define K_REGISTER_DECOMPRESSOR(Type, Cls) \
|
|
5214
|
+
static StreamDecoder *K_UNIQUE_NAME(CreateDecompressor)(StreamReader *reader, CompressionType type) \
|
|
5076
5215
|
{ \
|
|
5077
5216
|
StreamDecoder *decompressor = new Cls(reader, type); \
|
|
5078
5217
|
return decompressor; \
|
|
5079
5218
|
} \
|
|
5080
|
-
static StreamDecompressorHelper
|
|
5219
|
+
static StreamDecompressorHelper K_UNIQUE_NAME(CreateDecompressorHelper)((Type), K_UNIQUE_NAME(CreateDecompressor))
|
|
5081
5220
|
|
|
5082
5221
|
class LineReader {
|
|
5083
|
-
|
|
5222
|
+
K_DELETE_COPY(LineReader)
|
|
5084
5223
|
|
|
5085
5224
|
HeapArray<char> buf;
|
|
5086
5225
|
Span<char> view = {};
|
|
@@ -5107,14 +5246,14 @@ public:
|
|
|
5107
5246
|
};
|
|
5108
5247
|
|
|
5109
5248
|
enum class StreamWriterFlag {
|
|
5110
|
-
Exclusive = 1 << 0,
|
|
5111
|
-
Atomic = 1 << 1,
|
|
5112
|
-
NoBuffer = 1 << 2,
|
|
5113
|
-
LineBuffer = 1 << 3
|
|
5249
|
+
Exclusive = 1 << 0, // Only for files
|
|
5250
|
+
Atomic = 1 << 1, // Only for files
|
|
5251
|
+
NoBuffer = 1 << 2, // Only for files and descriptors
|
|
5252
|
+
LineBuffer = 1 << 3 // Only for files and descriptors
|
|
5114
5253
|
};
|
|
5115
5254
|
|
|
5116
5255
|
class StreamWriter {
|
|
5117
|
-
|
|
5256
|
+
K_DELETE_COPY(StreamWriter)
|
|
5118
5257
|
|
|
5119
5258
|
enum class DestinationType {
|
|
5120
5259
|
Memory,
|
|
@@ -5167,14 +5306,14 @@ class StreamWriter {
|
|
|
5167
5306
|
|
|
5168
5307
|
public:
|
|
5169
5308
|
StreamWriter() { Close(true); }
|
|
5170
|
-
StreamWriter(HeapArray<uint8_t> *mem, const char *filename =
|
|
5309
|
+
StreamWriter(HeapArray<uint8_t> *mem, const char *filename, unsigned int flags = 0,
|
|
5171
5310
|
CompressionType compression_type = CompressionType::None,
|
|
5172
5311
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5173
|
-
: StreamWriter() { Open(mem, filename, compression_type, compression_speed); }
|
|
5174
|
-
StreamWriter(HeapArray<char> *mem, const char *filename =
|
|
5312
|
+
: StreamWriter() { Open(mem, filename, flags, compression_type, compression_speed); }
|
|
5313
|
+
StreamWriter(HeapArray<char> *mem, const char *filename, unsigned int flags = 0,
|
|
5175
5314
|
CompressionType compression_type = CompressionType::None,
|
|
5176
5315
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5177
|
-
: StreamWriter() { Open(mem, filename, compression_type, compression_speed); }
|
|
5316
|
+
: StreamWriter() { Open(mem, filename, flags, compression_type, compression_speed); }
|
|
5178
5317
|
StreamWriter(int fd, const char *filename, unsigned int flags = 0,
|
|
5179
5318
|
CompressionType compression_type = CompressionType::None,
|
|
5180
5319
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
@@ -5183,29 +5322,29 @@ public:
|
|
|
5183
5322
|
CompressionType compression_type = CompressionType::None,
|
|
5184
5323
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5185
5324
|
: StreamWriter() { Open(filename, flags, compression_type, compression_speed); }
|
|
5186
|
-
StreamWriter(const std::function<bool(Span<const uint8_t>)> &func, const char *filename =
|
|
5325
|
+
StreamWriter(const std::function<bool(Span<const uint8_t>)> &func, const char *filename, unsigned int flags = 0,
|
|
5187
5326
|
CompressionType compression_type = CompressionType::None,
|
|
5188
5327
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5189
|
-
: StreamWriter() { Open(func, filename, compression_type, compression_speed); }
|
|
5328
|
+
: StreamWriter() { Open(func, filename, flags, compression_type, compression_speed); }
|
|
5190
5329
|
~StreamWriter() { Close(true); }
|
|
5191
5330
|
|
|
5192
5331
|
// Call before Open. Takes ownership and deletes the encoder at the end.
|
|
5193
5332
|
void SetEncoder(StreamEncoder *encoder);
|
|
5194
5333
|
|
|
5195
|
-
bool Open(HeapArray<uint8_t> *mem, const char *filename =
|
|
5334
|
+
bool Open(HeapArray<uint8_t> *mem, const char *filename, unsigned int flags = 0,
|
|
5196
5335
|
CompressionType compression_type = CompressionType::None,
|
|
5197
5336
|
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
5198
|
-
bool Open(HeapArray<char> *mem, const char *filename =
|
|
5337
|
+
bool Open(HeapArray<char> *mem, const char *filename, unsigned int flags = 0,
|
|
5199
5338
|
CompressionType compression_type = CompressionType::None,
|
|
5200
5339
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5201
|
-
{ return Open((HeapArray<uint8_t> *)mem, filename, compression_type, compression_speed); }
|
|
5340
|
+
{ return Open((HeapArray<uint8_t> *)mem, filename, flags, compression_type, compression_speed); }
|
|
5202
5341
|
bool Open(int fd, const char *filename, unsigned int flags = 0,
|
|
5203
5342
|
CompressionType compression_type = CompressionType::None,
|
|
5204
5343
|
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
5205
5344
|
bool Open(const char *filename, unsigned int flags = 0,
|
|
5206
5345
|
CompressionType compression_type = CompressionType::None,
|
|
5207
5346
|
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
5208
|
-
bool Open(const std::function<bool(Span<const uint8_t>)> &func, const char *filename =
|
|
5347
|
+
bool Open(const std::function<bool(Span<const uint8_t>)> &func, const char *filename, unsigned int flags = 0,
|
|
5209
5348
|
CompressionType compression_type = CompressionType::None,
|
|
5210
5349
|
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
5211
5350
|
bool Close() { return Close(false); }
|
|
@@ -5283,13 +5422,13 @@ public:
|
|
|
5283
5422
|
StreamCompressorHelper(CompressionType type, CreateCompressorFunc *func);
|
|
5284
5423
|
};
|
|
5285
5424
|
|
|
5286
|
-
#define
|
|
5287
|
-
static StreamEncoder *
|
|
5425
|
+
#define K_REGISTER_COMPRESSOR(Type, Cls) \
|
|
5426
|
+
static StreamEncoder *K_UNIQUE_NAME(CreateCompressor)(StreamWriter *writer, CompressionType type, CompressionSpeed speed) \
|
|
5288
5427
|
{ \
|
|
5289
5428
|
StreamEncoder *compressor = new Cls(writer, type, speed); \
|
|
5290
5429
|
return compressor; \
|
|
5291
5430
|
} \
|
|
5292
|
-
static StreamCompressorHelper
|
|
5431
|
+
static StreamCompressorHelper K_UNIQUE_NAME(CreateCompressorHelper)((Type), K_UNIQUE_NAME(CreateCompressor))
|
|
5293
5432
|
|
|
5294
5433
|
bool SpliceStream(StreamReader *reader, int64_t max_len, StreamWriter *writer, Span<uint8_t> buf,
|
|
5295
5434
|
FunctionRef<void(int64_t, int64_t)> progress = [](int64_t, int64_t) {});
|
|
@@ -5322,7 +5461,7 @@ struct IniProperty {
|
|
|
5322
5461
|
};
|
|
5323
5462
|
|
|
5324
5463
|
class IniParser {
|
|
5325
|
-
|
|
5464
|
+
K_DELETE_COPY(IniParser)
|
|
5326
5465
|
|
|
5327
5466
|
HeapArray<char> current_section;
|
|
5328
5467
|
|
|
@@ -5362,7 +5501,7 @@ struct AssetInfo {
|
|
|
5362
5501
|
CompressionType compression_type;
|
|
5363
5502
|
Span<const uint8_t> data;
|
|
5364
5503
|
|
|
5365
|
-
|
|
5504
|
+
K_HASHTABLE_HANDLER(AssetInfo, name);
|
|
5366
5505
|
};
|
|
5367
5506
|
|
|
5368
5507
|
#if defined(FELIX_HOT_ASSETS)
|
|
@@ -5415,6 +5554,29 @@ Span<const uint8_t> PatchFile(const AssetInfo &asset, Allocator *alloc,
|
|
|
5415
5554
|
Span<const char> PatchFile(Span<const char> data, Allocator *alloc,
|
|
5416
5555
|
FunctionRef<void(Span<const char> key, StreamWriter *)> func);
|
|
5417
5556
|
|
|
5557
|
+
// ------------------------------------------------------------------------
|
|
5558
|
+
// Translations
|
|
5559
|
+
// ------------------------------------------------------------------------
|
|
5560
|
+
|
|
5561
|
+
struct TranslationTable {
|
|
5562
|
+
struct Pair {
|
|
5563
|
+
const char *key;
|
|
5564
|
+
const char *value;
|
|
5565
|
+
};
|
|
5566
|
+
|
|
5567
|
+
const char *language;
|
|
5568
|
+
Span<Pair> messages;
|
|
5569
|
+
|
|
5570
|
+
K_HASHTABLE_HANDLER(TranslationTable, language);
|
|
5571
|
+
};
|
|
5572
|
+
|
|
5573
|
+
extern "C" const Span<const TranslationTable> TranslationTables;
|
|
5574
|
+
|
|
5575
|
+
void InitLocales(Span<const TranslationTable> tables);
|
|
5576
|
+
|
|
5577
|
+
// Resets the localgale to the process default if lang is NULL or is unknown
|
|
5578
|
+
void ChangeThreadLocale(const char *name);
|
|
5579
|
+
|
|
5418
5580
|
// ------------------------------------------------------------------------
|
|
5419
5581
|
// Options
|
|
5420
5582
|
// ------------------------------------------------------------------------
|
|
@@ -5437,7 +5599,7 @@ enum class OptionType {
|
|
|
5437
5599
|
};
|
|
5438
5600
|
|
|
5439
5601
|
class OptionParser {
|
|
5440
|
-
|
|
5602
|
+
K_DELETE_COPY(OptionParser)
|
|
5441
5603
|
|
|
5442
5604
|
Span<const char *> args;
|
|
5443
5605
|
OptionMode mode;
|
|
@@ -5516,6 +5678,8 @@ bool OptionToEnum(Span<const OptionDesc> options, Span<const char> str, T *out_v
|
|
|
5516
5678
|
template <typename T>
|
|
5517
5679
|
bool OptionToEnumI(Span<const char *const> options, Span<const char> str, T *out_value)
|
|
5518
5680
|
{
|
|
5681
|
+
static_assert(std::is_enum<T>::value);
|
|
5682
|
+
|
|
5519
5683
|
for (Size i = 0; i < options.len; i++) {
|
|
5520
5684
|
const char *opt = options[i];
|
|
5521
5685
|
|
|
@@ -5531,6 +5695,8 @@ bool OptionToEnumI(Span<const char *const> options, Span<const char> str, T *out
|
|
|
5531
5695
|
template <typename T>
|
|
5532
5696
|
bool OptionToEnumI(Span<const OptionDesc> options, Span<const char> str, T *out_value)
|
|
5533
5697
|
{
|
|
5698
|
+
static_assert(std::is_enum<T>::value);
|
|
5699
|
+
|
|
5534
5700
|
for (Size i = 0; i < options.len; i++) {
|
|
5535
5701
|
const OptionDesc &desc = options[i];
|
|
5536
5702
|
|
|
@@ -5608,10 +5774,23 @@ bool OptionToFlagI(Span<const OptionDesc> options, Span<const char> str, T *out_
|
|
|
5608
5774
|
// ------------------------------------------------------------------------
|
|
5609
5775
|
|
|
5610
5776
|
struct PromptChoice {
|
|
5611
|
-
char c;
|
|
5612
5777
|
const char *str;
|
|
5778
|
+
char c;
|
|
5779
|
+
};
|
|
5780
|
+
|
|
5781
|
+
enum class CompleteResult {
|
|
5782
|
+
Success,
|
|
5783
|
+
TooMany,
|
|
5784
|
+
Error
|
|
5613
5785
|
};
|
|
5614
5786
|
|
|
5787
|
+
struct CompleteChoice {
|
|
5788
|
+
const char *name;
|
|
5789
|
+
const char *value;
|
|
5790
|
+
};
|
|
5791
|
+
|
|
5792
|
+
typedef CompleteResult CompleteFunc(Span<const char> value, Allocator *alloc, HeapArray<CompleteChoice> *out_choices);
|
|
5793
|
+
|
|
5615
5794
|
class ConsolePrompter {
|
|
5616
5795
|
int prompt_columns = 0;
|
|
5617
5796
|
|
|
@@ -5631,8 +5810,9 @@ class ConsolePrompter {
|
|
|
5631
5810
|
#endif
|
|
5632
5811
|
|
|
5633
5812
|
public:
|
|
5634
|
-
const char *prompt = ">>>
|
|
5813
|
+
const char *prompt = ">>>";
|
|
5635
5814
|
const char *mask = nullptr;
|
|
5815
|
+
std::function<CompleteFunc> complete = {};
|
|
5636
5816
|
|
|
5637
5817
|
HeapArray<char> str;
|
|
5638
5818
|
|
|
@@ -5667,8 +5847,6 @@ private:
|
|
|
5667
5847
|
Vec2<int> GetConsoleSize();
|
|
5668
5848
|
int32_t ReadChar();
|
|
5669
5849
|
|
|
5670
|
-
int ComputeWidth(Span<const char> str);
|
|
5671
|
-
|
|
5672
5850
|
void EnsureNulTermination();
|
|
5673
5851
|
};
|
|
5674
5852
|
|
|
@@ -5679,6 +5857,13 @@ static inline const char *Prompt(const char *prompt, Allocator *alloc)
|
|
|
5679
5857
|
Size PromptEnum(const char *prompt, Span<const PromptChoice> choices, Size value = 0);
|
|
5680
5858
|
Size PromptEnum(const char *prompt, Span<const char *const> strings, Size value = 0);
|
|
5681
5859
|
|
|
5860
|
+
// Returns -1 if cancelled, otherwise it's 1 for Yes and or 0 for No
|
|
5861
|
+
int PromptYN(const char *prompt);
|
|
5862
|
+
|
|
5863
|
+
const char *PromptPath(const char *prompt, const char *default_path, Span<const char> root_directory, Allocator *alloc);
|
|
5864
|
+
static inline const char *PromptPath(const char *prompt, Allocator *alloc)
|
|
5865
|
+
{ return PromptPath(prompt, nullptr, GetWorkingDirectory(), alloc); }
|
|
5866
|
+
|
|
5682
5867
|
// ------------------------------------------------------------------------
|
|
5683
5868
|
// Mime types
|
|
5684
5869
|
// ------------------------------------------------------------------------
|
|
@@ -5691,7 +5876,118 @@ bool CanCompressFile(const char *filename);
|
|
|
5691
5876
|
// Unicode
|
|
5692
5877
|
// ------------------------------------------------------------------------
|
|
5693
5878
|
|
|
5694
|
-
int
|
|
5879
|
+
static inline int CountUtf8Bytes(char c)
|
|
5880
|
+
{
|
|
5881
|
+
int ones = CountLeadingZeros((uint32_t)~c << 24);
|
|
5882
|
+
return std::min(std::max(ones, 1), 4);
|
|
5883
|
+
}
|
|
5884
|
+
|
|
5885
|
+
static constexpr inline Size DecodeUtf8(const char *str, int32_t *out_c)
|
|
5886
|
+
{
|
|
5887
|
+
K_ASSERT(str[0]);
|
|
5888
|
+
|
|
5889
|
+
#define BYTE(Idx) ((uint8_t)str[Idx])
|
|
5890
|
+
|
|
5891
|
+
if (BYTE(0) < 0x80) {
|
|
5892
|
+
*out_c = BYTE(0);
|
|
5893
|
+
return 1;
|
|
5894
|
+
} else if (BYTE(0) - 0xC2 > 0xF4 - 0xC2) [[unlikely]] {
|
|
5895
|
+
return 0;
|
|
5896
|
+
} else if (BYTE(1)) [[likely]] {
|
|
5897
|
+
if (BYTE(0) < 0xE0 && (BYTE(1) & 0xC0) == 0x80) {
|
|
5898
|
+
*out_c = ((BYTE(0) & 0x1F) << 6) | (BYTE(1) & 0x3F);
|
|
5899
|
+
return 2;
|
|
5900
|
+
} else if (BYTE(2)) [[likely]] {
|
|
5901
|
+
if (BYTE(0) < 0xF0 &&
|
|
5902
|
+
(BYTE(1) & 0xC0) == 0x80 &&
|
|
5903
|
+
(BYTE(2) & 0xC0) == 0x80) {
|
|
5904
|
+
*out_c = ((BYTE(0) & 0xF) << 12) | ((BYTE(1) & 0x3F) << 6) | (BYTE(2) & 0x3F);
|
|
5905
|
+
return 3;
|
|
5906
|
+
} else if (BYTE(3)) [[likely]] {
|
|
5907
|
+
if ((BYTE(1) & 0xC0) == 0x80 &&
|
|
5908
|
+
(BYTE(2) & 0xC0) == 0x80 &&
|
|
5909
|
+
(BYTE(3) & 0xC0) == 0x80) {
|
|
5910
|
+
*out_c = ((BYTE(0) & 0x7) << 18) | ((BYTE(1) & 0x3F) << 12) | ((BYTE(2) & 0x3F) << 6) | (BYTE(3) & 0x3F);
|
|
5911
|
+
return 4;
|
|
5912
|
+
}
|
|
5913
|
+
}
|
|
5914
|
+
}
|
|
5915
|
+
}
|
|
5916
|
+
|
|
5917
|
+
#undef BYTE
|
|
5918
|
+
|
|
5919
|
+
return 0;
|
|
5920
|
+
}
|
|
5921
|
+
|
|
5922
|
+
static constexpr inline Size DecodeUtf8(Span<const char> str, Size offset, int32_t *out_c)
|
|
5923
|
+
{
|
|
5924
|
+
K_ASSERT(offset < str.len);
|
|
5925
|
+
|
|
5926
|
+
str = str.Take(offset, str.len - offset);
|
|
5927
|
+
|
|
5928
|
+
#define BYTE(Idx) ((uint8_t)str[Idx])
|
|
5929
|
+
|
|
5930
|
+
if (BYTE(0) < 0x80) {
|
|
5931
|
+
*out_c = BYTE(0);
|
|
5932
|
+
return 1;
|
|
5933
|
+
} else if (BYTE(0) - 0xC2 > 0xF4 - 0xC2) [[unlikely]] {
|
|
5934
|
+
return 0;
|
|
5935
|
+
} else if (BYTE(0) < 0xE0 && str.len >= 2 && (BYTE(1) & 0xC0) == 0x80) {
|
|
5936
|
+
*out_c = ((BYTE(0) & 0x1F) << 6) | (BYTE(1) & 0x3F);
|
|
5937
|
+
return 2;
|
|
5938
|
+
} else if (BYTE(0) < 0xF0 && str.len >= 3 && (BYTE(1) & 0xC0) == 0x80 &&
|
|
5939
|
+
(BYTE(2) & 0xC0) == 0x80) {
|
|
5940
|
+
*out_c = ((BYTE(0) & 0xF) << 12) | ((BYTE(1) & 0x3F) << 6) | (BYTE(2) & 0x3F);
|
|
5941
|
+
return 3;
|
|
5942
|
+
} else if (str.len >= 4 && (BYTE(1) & 0xC0) == 0x80 &&
|
|
5943
|
+
(BYTE(2) & 0xC0) == 0x80 &&
|
|
5944
|
+
(BYTE(3) & 0xC0) == 0x80) {
|
|
5945
|
+
*out_c = ((BYTE(0) & 0x7) << 18) | ((BYTE(1) & 0x3F) << 12) | ((BYTE(2) & 0x3F) << 6) | (BYTE(3) & 0x3F);
|
|
5946
|
+
return 4;
|
|
5947
|
+
} else {
|
|
5948
|
+
return 0;
|
|
5949
|
+
}
|
|
5950
|
+
|
|
5951
|
+
#undef BYTE
|
|
5952
|
+
}
|
|
5953
|
+
|
|
5954
|
+
static constexpr inline int32_t DecodeUtf8(const char *str)
|
|
5955
|
+
{
|
|
5956
|
+
int32_t uc = -1;
|
|
5957
|
+
DecodeUtf8(str, &uc);
|
|
5958
|
+
return uc;
|
|
5959
|
+
}
|
|
5960
|
+
|
|
5961
|
+
static inline Size EncodeUtf8(int32_t c, char out_buf[4])
|
|
5962
|
+
{
|
|
5963
|
+
if (c < 0x80) {
|
|
5964
|
+
out_buf[0] = (char)c;
|
|
5965
|
+
return 1;
|
|
5966
|
+
} else if (c < 0x800) {
|
|
5967
|
+
out_buf[0] = (char)(0xC0 | (c >> 6));
|
|
5968
|
+
out_buf[1] = (char)(0x80 | (c & 0x3F));
|
|
5969
|
+
return 2;
|
|
5970
|
+
} else if (c >= 0xD800 && c < 0xE000) {
|
|
5971
|
+
return 0;
|
|
5972
|
+
} else if (c < 0x10000) {
|
|
5973
|
+
out_buf[0] = (char)(0xE0 | (c >> 12));
|
|
5974
|
+
out_buf[1] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
5975
|
+
out_buf[2] = (char)(0x80 | (c & 0x3F));
|
|
5976
|
+
return 3;
|
|
5977
|
+
} else if (c < 0x110000) {
|
|
5978
|
+
out_buf[0] = (char)(0xF0 | (c >> 18));
|
|
5979
|
+
out_buf[1] = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
5980
|
+
out_buf[2] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
5981
|
+
out_buf[3] = (char)(0x80 | (c & 0x3F));
|
|
5982
|
+
return 4;
|
|
5983
|
+
} else {
|
|
5984
|
+
return 0;
|
|
5985
|
+
}
|
|
5986
|
+
}
|
|
5987
|
+
|
|
5988
|
+
bool IsValidUtf8(Span<const char> str);
|
|
5989
|
+
|
|
5990
|
+
int ComputeUnicodeWidth(Span<const char> str);
|
|
5695
5991
|
|
|
5696
5992
|
bool IsXidStart(int32_t uc);
|
|
5697
5993
|
bool IsXidContinue(int32_t uc);
|