koffi 2.14.0 → 2.14.1
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 +7 -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/pages/index.md +43 -4
- package/doc/pages/platforms.md +8 -19
- package/doc/pages.ini +0 -7
- package/doc/static/perf_windows.png +0 -0
- package/index.js +3 -2
- package/indirect.js +3 -2
- package/package.json +3 -2
- package/src/cnoke/src/builder.js +1 -2
- package/src/core/base/base.cc +791 -555
- package/src/core/base/base.hh +577 -450
- package/src/core/base/crc.inc +1 -1
- package/src/core/base/crc_gen.py +1 -1
- package/src/core/base/unicode.inc +1 -1
- package/src/core/base/unicode_gen.py +1 -1
- package/src/koffi/src/abi_arm32.cc +24 -24
- package/src/koffi/src/abi_arm64.cc +29 -29
- package/src/koffi/src/abi_riscv64.cc +27 -27
- package/src/koffi/src/abi_x64_sysv.cc +29 -29
- package/src/koffi/src/abi_x64_win.cc +20 -20
- package/src/koffi/src/abi_x86.cc +26 -26
- package/src/koffi/src/call.cc +82 -236
- package/src/koffi/src/call.hh +6 -6
- package/src/koffi/src/ffi.cc +60 -60
- package/src/koffi/src/ffi.hh +9 -9
- package/src/koffi/src/parser.cc +2 -2
- package/src/koffi/src/parser.hh +1 -1
- package/src/koffi/src/trampolines/prototypes.inc +1 -1
- package/src/koffi/src/util.cc +43 -43
- package/src/koffi/src/util.hh +5 -5
- package/src/koffi/src/win32.cc +5 -5
- package/src/koffi/src/win32.hh +1 -1
package/src/core/base/base.hh
CHANGED
|
@@ -75,38 +75,38 @@
|
|
|
75
75
|
struct sigaction;
|
|
76
76
|
struct BrotliEncoderStateStruct;
|
|
77
77
|
|
|
78
|
-
namespace
|
|
78
|
+
namespace K {
|
|
79
79
|
|
|
80
80
|
// ------------------------------------------------------------------------
|
|
81
81
|
// Config
|
|
82
82
|
// ------------------------------------------------------------------------
|
|
83
83
|
|
|
84
84
|
#if !defined(NDEBUG)
|
|
85
|
-
#define
|
|
85
|
+
#define K_DEBUG
|
|
86
86
|
#endif
|
|
87
87
|
|
|
88
|
-
#define
|
|
89
|
-
#define
|
|
88
|
+
#define K_DEFAULT_ALLOCATOR MallocAllocator
|
|
89
|
+
#define K_BLOCK_ALLOCATOR_DEFAULT_SIZE Kibibytes(4)
|
|
90
90
|
|
|
91
|
-
#define
|
|
92
|
-
#define
|
|
91
|
+
#define K_HEAPARRAY_BASE_CAPACITY 8
|
|
92
|
+
#define K_HEAPARRAY_GROWTH_FACTOR 2.0
|
|
93
93
|
|
|
94
94
|
// Must be a power-of-two
|
|
95
|
-
#define
|
|
96
|
-
#define
|
|
95
|
+
#define K_HASHTABLE_BASE_CAPACITY 8
|
|
96
|
+
#define K_HASHTABLE_MAX_LOAD_FACTOR 0.5
|
|
97
97
|
|
|
98
|
-
#define
|
|
99
|
-
#define
|
|
98
|
+
#define K_FMT_STRING_BASE_CAPACITY 256
|
|
99
|
+
#define K_FMT_STRING_PRINT_BUFFER_SIZE 1024
|
|
100
100
|
|
|
101
|
-
#define
|
|
101
|
+
#define K_LINE_READER_STEP_SIZE 65536
|
|
102
102
|
|
|
103
|
-
#define
|
|
104
|
-
#define
|
|
105
|
-
#define
|
|
103
|
+
#define K_ASYNC_MAX_THREADS 2048
|
|
104
|
+
#define K_ASYNC_MAX_IDLE_TIME 10000
|
|
105
|
+
#define K_ASYNC_MAX_PENDING_TASKS 2048
|
|
106
106
|
|
|
107
|
-
#define
|
|
108
|
-
#define
|
|
109
|
-
#define
|
|
107
|
+
#define K_PROGRESS_MAX_NODES 400
|
|
108
|
+
#define K_PROGRESS_USED_NODES 100
|
|
109
|
+
#define K_PROGRESS_TEXT_SIZE 64
|
|
110
110
|
|
|
111
111
|
// ------------------------------------------------------------------------
|
|
112
112
|
// Utility
|
|
@@ -125,13 +125,13 @@ extern StreamWriter *const StdErr;
|
|
|
125
125
|
|
|
126
126
|
#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) || __riscv_xlen == 64 || defined(__loongarch64)
|
|
127
127
|
typedef int64_t Size;
|
|
128
|
-
#define
|
|
128
|
+
#define K_SIZE_MAX INT64_MAX
|
|
129
129
|
#elif defined(_WIN32) || defined(__APPLE__) || defined(__unix__)
|
|
130
130
|
typedef int32_t Size;
|
|
131
|
-
#define
|
|
131
|
+
#define K_SIZE_MAX INT32_MAX
|
|
132
132
|
#elif defined(__thumb__) || defined(__arm__) || defined(__wasm32__)
|
|
133
133
|
typedef int32_t Size;
|
|
134
|
-
#define
|
|
134
|
+
#define K_SIZE_MAX INT32_MAX
|
|
135
135
|
#else
|
|
136
136
|
#error Machine architecture not supported
|
|
137
137
|
#endif
|
|
@@ -139,7 +139,7 @@ extern StreamWriter *const StdErr;
|
|
|
139
139
|
#if defined(_MSC_VER) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
140
140
|
// Sane platform
|
|
141
141
|
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
142
|
-
#define
|
|
142
|
+
#define K_BIG_ENDIAN
|
|
143
143
|
#else
|
|
144
144
|
#error This code base is not designed to support platforms with crazy endianness
|
|
145
145
|
#endif
|
|
@@ -152,16 +152,16 @@ extern StreamWriter *const StdErr;
|
|
|
152
152
|
#endif
|
|
153
153
|
static_assert(sizeof(double) == 8, "This code base is not designed to support single-precision double floats");
|
|
154
154
|
|
|
155
|
-
#define
|
|
156
|
-
#define
|
|
157
|
-
#define
|
|
158
|
-
#define
|
|
159
|
-
#define
|
|
160
|
-
#define
|
|
161
|
-
#define
|
|
155
|
+
#define K_STRINGIFY_(a) #a
|
|
156
|
+
#define K_STRINGIFY(a) K_STRINGIFY_(a)
|
|
157
|
+
#define K_CONCAT_(a, b) a ## b
|
|
158
|
+
#define K_CONCAT(a, b) K_CONCAT_(a, b)
|
|
159
|
+
#define K_UNIQUE_NAME(prefix) K_CONCAT(prefix, __LINE__)
|
|
160
|
+
#define K_FORCE_EXPAND(x) x
|
|
161
|
+
#define K_IGNORE (void)!
|
|
162
162
|
|
|
163
163
|
#if defined(__GNUC__) || defined(__clang__)
|
|
164
|
-
#define
|
|
164
|
+
#define K_PUSH_NO_WARNINGS \
|
|
165
165
|
_Pragma("GCC diagnostic push") \
|
|
166
166
|
_Pragma("GCC diagnostic ignored \"-Wall\"") \
|
|
167
167
|
_Pragma("GCC diagnostic ignored \"-Wextra\"") \
|
|
@@ -173,7 +173,7 @@ static_assert(sizeof(double) == 8, "This code base is not designed to support si
|
|
|
173
173
|
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"") \
|
|
174
174
|
_Pragma("GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"") \
|
|
175
175
|
_Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
|
|
176
|
-
#define
|
|
176
|
+
#define K_POP_NO_WARNINGS \
|
|
177
177
|
_Pragma("GCC diagnostic pop")
|
|
178
178
|
|
|
179
179
|
#if !defined(SCNd8)
|
|
@@ -186,8 +186,8 @@ static_assert(sizeof(double) == 8, "This code base is not designed to support si
|
|
|
186
186
|
#define SCNu8 "hhu"
|
|
187
187
|
#endif
|
|
188
188
|
#elif defined(_MSC_VER)
|
|
189
|
-
#define
|
|
190
|
-
#define
|
|
189
|
+
#define K_PUSH_NO_WARNINGS __pragma(warning(push, 0))
|
|
190
|
+
#define K_POP_NO_WARNINGS __pragma(warning(pop))
|
|
191
191
|
|
|
192
192
|
#define __restrict__ __restrict
|
|
193
193
|
#else
|
|
@@ -209,73 +209,73 @@ static_assert(sizeof(double) == 8, "This code base is not designed to support si
|
|
|
209
209
|
extern "C" void AssertMessage(const char *filename, int line, const char *cond);
|
|
210
210
|
|
|
211
211
|
#if defined(_MSC_VER)
|
|
212
|
-
#define
|
|
212
|
+
#define K_DEBUG_BREAK() __debugbreak()
|
|
213
213
|
#elif defined(__clang__)
|
|
214
|
-
#define
|
|
214
|
+
#define K_DEBUG_BREAK() __builtin_debugtrap()
|
|
215
215
|
#elif defined(__i386__) || defined(__x86_64__)
|
|
216
|
-
#define
|
|
216
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__("int $0x03")
|
|
217
217
|
#elif defined(__thumb__)
|
|
218
|
-
#define
|
|
218
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__(".inst 0xde01")
|
|
219
219
|
#elif defined(__aarch64__)
|
|
220
|
-
#define
|
|
220
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__(".inst 0xd4200000")
|
|
221
221
|
#elif defined(__arm__)
|
|
222
|
-
#define
|
|
222
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__(".inst 0xe7f001f0")
|
|
223
223
|
#elif defined(__riscv)
|
|
224
|
-
#define
|
|
224
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__("ebreak")
|
|
225
225
|
#elif defined(__loongarch64)
|
|
226
|
-
#define
|
|
226
|
+
#define K_DEBUG_BREAK() __asm__ __volatile__("break 1")
|
|
227
227
|
#endif
|
|
228
228
|
|
|
229
229
|
#if defined(_MSC_VER) || __EXCEPTIONS
|
|
230
|
-
#define
|
|
230
|
+
#define K_BAD_ALLOC() \
|
|
231
231
|
do { \
|
|
232
232
|
throw std::bad_alloc(); \
|
|
233
233
|
} while (false)
|
|
234
234
|
#else
|
|
235
|
-
#define
|
|
235
|
+
#define K_BAD_ALLOC() \
|
|
236
236
|
do { \
|
|
237
237
|
PrintLn(StdErr, "Memory allocation failed"); \
|
|
238
238
|
abort(); \
|
|
239
239
|
} while (false);
|
|
240
240
|
#endif
|
|
241
241
|
|
|
242
|
-
#define
|
|
242
|
+
#define K_CRITICAL(Cond, ...) \
|
|
243
243
|
do { \
|
|
244
244
|
if (!(Cond)) [[unlikely]] { \
|
|
245
245
|
PrintLn(StdErr, __VA_ARGS__); \
|
|
246
246
|
abort(); \
|
|
247
247
|
} \
|
|
248
248
|
} while (false)
|
|
249
|
-
#if defined(
|
|
250
|
-
#define
|
|
249
|
+
#if defined(K_DEBUG)
|
|
250
|
+
#define K_ASSERT(Cond) \
|
|
251
251
|
do { \
|
|
252
252
|
if (!(Cond)) [[unlikely]] { \
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
K::AssertMessage(__FILE__, __LINE__, K_STRINGIFY(Cond)); \
|
|
254
|
+
K_DEBUG_BREAK(); \
|
|
255
255
|
abort(); \
|
|
256
256
|
} \
|
|
257
257
|
} while (false)
|
|
258
258
|
#else
|
|
259
|
-
#define
|
|
259
|
+
#define K_ASSERT(Cond) \
|
|
260
260
|
do { \
|
|
261
261
|
(void)sizeof(Cond); \
|
|
262
262
|
} while (false)
|
|
263
263
|
#endif
|
|
264
264
|
|
|
265
|
-
#if defined(
|
|
266
|
-
#define
|
|
265
|
+
#if defined(K_DEBUG)
|
|
266
|
+
#define K_UNREACHABLE() \
|
|
267
267
|
do { \
|
|
268
|
-
|
|
269
|
-
|
|
268
|
+
K::AssertMessage(__FILE__, __LINE__, "Reached code marked as UNREACHABLE"); \
|
|
269
|
+
K_DEBUG_BREAK(); \
|
|
270
270
|
abort(); \
|
|
271
271
|
} while (false)
|
|
272
272
|
#elif defined(__GNUC__) || defined(__clang__)
|
|
273
|
-
#define
|
|
273
|
+
#define K_UNREACHABLE() __builtin_unreachable()
|
|
274
274
|
#else
|
|
275
|
-
#define
|
|
275
|
+
#define K_UNREACHABLE() __assume(0)
|
|
276
276
|
#endif
|
|
277
277
|
|
|
278
|
-
#define
|
|
278
|
+
#define K_DELETE_COPY(Cls) \
|
|
279
279
|
Cls(const Cls&) = delete; \
|
|
280
280
|
Cls &operator=(const Cls&) = delete;
|
|
281
281
|
|
|
@@ -289,11 +289,11 @@ constexpr Size Kibibytes(Size len) { return len * 1024; }
|
|
|
289
289
|
constexpr Size Megabytes(Size len) { return len * 1000 * 1000; }
|
|
290
290
|
constexpr Size Kilobytes(Size len) { return len * 1000; }
|
|
291
291
|
|
|
292
|
-
#define
|
|
292
|
+
#define K_SIZE(Type) ((K::Size)sizeof(Type))
|
|
293
293
|
template <typename T, unsigned N>
|
|
294
294
|
char (&ComputeArraySize(T const (&)[N]))[N];
|
|
295
|
-
#define
|
|
296
|
-
#define
|
|
295
|
+
#define K_BITS(Type) (8 * K_SIZE(Type))
|
|
296
|
+
#define K_LEN(Array) K_SIZE(K::ComputeArraySize(Array))
|
|
297
297
|
|
|
298
298
|
static constexpr inline uint16_t ReverseBytes(uint16_t u)
|
|
299
299
|
{
|
|
@@ -328,7 +328,7 @@ static constexpr inline int32_t ReverseBytes(int32_t i)
|
|
|
328
328
|
static constexpr inline int64_t ReverseBytes(int64_t i)
|
|
329
329
|
{ return (int64_t)ReverseBytes((uint64_t)i); }
|
|
330
330
|
|
|
331
|
-
#if defined(
|
|
331
|
+
#if defined(K_BIG_ENDIAN)
|
|
332
332
|
template <typename T>
|
|
333
333
|
constexpr T LittleEndian(T v) { return ReverseBytes(v); }
|
|
334
334
|
template <typename T>
|
|
@@ -478,9 +478,9 @@ constexpr T BigEndian(T v) { return ReverseBytes(v); }
|
|
|
478
478
|
#endif
|
|
479
479
|
|
|
480
480
|
#if __cplusplus >= 202002L && (defined(_MSC_VER) || defined(__clang__) || __GNUC__ >= 11)
|
|
481
|
-
#define
|
|
481
|
+
#define K_CONSTINIT constinit
|
|
482
482
|
#else
|
|
483
|
-
#define
|
|
483
|
+
#define K_CONSTINIT const
|
|
484
484
|
#endif
|
|
485
485
|
|
|
486
486
|
static inline Size AlignLen(Size len, Size align)
|
|
@@ -507,7 +507,7 @@ static inline T *AlignDown(T *ptr, Size align)
|
|
|
507
507
|
// even if length is 0. This is dumb, work around this.
|
|
508
508
|
static inline void *MemCpy(void *__restrict__ dest, const void *__restrict__ src, Size len)
|
|
509
509
|
{
|
|
510
|
-
|
|
510
|
+
K_ASSERT(len >= 0);
|
|
511
511
|
|
|
512
512
|
#if defined(__clang__)
|
|
513
513
|
// LLVM guarantees sane behavior
|
|
@@ -521,7 +521,7 @@ static inline void *MemCpy(void *__restrict__ dest, const void *__restrict__ src
|
|
|
521
521
|
}
|
|
522
522
|
static inline void *MemMove(void *dest, const void *src, Size len)
|
|
523
523
|
{
|
|
524
|
-
|
|
524
|
+
K_ASSERT(len >= 0);
|
|
525
525
|
|
|
526
526
|
#if defined(__clang__)
|
|
527
527
|
// LLVM guarantees sane behavior
|
|
@@ -535,7 +535,7 @@ static inline void *MemMove(void *dest, const void *src, Size len)
|
|
|
535
535
|
}
|
|
536
536
|
static inline void *MemSet(void *dest, int c, Size len)
|
|
537
537
|
{
|
|
538
|
-
|
|
538
|
+
K_ASSERT(len >= 0);
|
|
539
539
|
|
|
540
540
|
#if defined(__clang__)
|
|
541
541
|
// LLVM guarantees sane behavior
|
|
@@ -556,8 +556,8 @@ void *MemMem(const void *src, Size src_len, const void *needle, Size needle_len)
|
|
|
556
556
|
|
|
557
557
|
static inline void *MemMem(const void *src, Size src_len, const void *needle, Size needle_len)
|
|
558
558
|
{
|
|
559
|
-
|
|
560
|
-
|
|
559
|
+
K_ASSERT(src_len >= 0);
|
|
560
|
+
K_ASSERT(needle_len > 0);
|
|
561
561
|
|
|
562
562
|
void *ptr = memmem(src, (size_t)src_len, needle, (size_t)needle_len);
|
|
563
563
|
return ptr;
|
|
@@ -565,6 +565,9 @@ static inline void *MemMem(const void *src, Size src_len, const void *needle, Si
|
|
|
565
565
|
|
|
566
566
|
#endif
|
|
567
567
|
|
|
568
|
+
// Implemented for translations, but we need it before we get to this part
|
|
569
|
+
const char *T(const char *key);
|
|
570
|
+
|
|
568
571
|
template <typename T, typename = typename std::enable_if<std::is_enum<T>::value, T>>
|
|
569
572
|
typename std::underlying_type<T>::type MaskEnum(T value)
|
|
570
573
|
{
|
|
@@ -574,7 +577,7 @@ typename std::underlying_type<T>::type MaskEnum(T value)
|
|
|
574
577
|
|
|
575
578
|
template <typename Fun>
|
|
576
579
|
class DeferGuard {
|
|
577
|
-
|
|
580
|
+
K_DELETE_COPY(DeferGuard)
|
|
578
581
|
|
|
579
582
|
Fun f;
|
|
580
583
|
bool enabled;
|
|
@@ -610,14 +613,35 @@ DeferGuard<Fun> operator+(DeferGuardHelper, Fun &&f)
|
|
|
610
613
|
// Write 'DEFER { code };' to do something at the end of the current scope, you
|
|
611
614
|
// can use DEFER_N(Name) if you need to disable the guard for some reason, and
|
|
612
615
|
// 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 =
|
|
616
|
+
#define K_DEFER \
|
|
617
|
+
auto K_UNIQUE_NAME(defer) = K::DeferGuardHelper() + [&]()
|
|
618
|
+
#define K_DEFER_N(Name) \
|
|
619
|
+
auto Name = K::DeferGuardHelper() + [&]()
|
|
620
|
+
#define K_DEFER_C(...) \
|
|
621
|
+
auto K_UNIQUE_NAME(defer) = K::DeferGuardHelper() + [&, __VA_ARGS__]()
|
|
622
|
+
#define K_DEFER_NC(Name, ...) \
|
|
623
|
+
auto Name = K::DeferGuardHelper() + [&, __VA_ARGS__]()
|
|
624
|
+
|
|
625
|
+
template <typename T>
|
|
626
|
+
class NoDestroy {
|
|
627
|
+
K_DELETE_COPY(NoDestroy);
|
|
628
|
+
|
|
629
|
+
alignas(T) uint8_t data[K_SIZE(T)];
|
|
630
|
+
|
|
631
|
+
public:
|
|
632
|
+
template <class... Args>
|
|
633
|
+
NoDestroy(Args&&... args) { new (data) T(std::forward<Args>(args)...); }
|
|
634
|
+
|
|
635
|
+
~NoDestroy() = default;
|
|
636
|
+
|
|
637
|
+
const T *Get() const { return (const T *)(data); }
|
|
638
|
+
T *Get() { return (T*)data; }
|
|
639
|
+
|
|
640
|
+
const T &operator*() const { return *Get(); }
|
|
641
|
+
T& operator*() { return *Get(); }
|
|
642
|
+
const T *operator->() const { return Get(); }
|
|
643
|
+
T *operator->() { return Get(); }
|
|
644
|
+
};
|
|
621
645
|
|
|
622
646
|
// Heavily inspired from FunctionRef in LLVM
|
|
623
647
|
template<typename Fn> class FunctionRef;
|
|
@@ -648,24 +672,6 @@ public:
|
|
|
648
672
|
bool IsValid() const { return callback; }
|
|
649
673
|
};
|
|
650
674
|
|
|
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
675
|
template <typename T>
|
|
670
676
|
T MultiCmp()
|
|
671
677
|
{
|
|
@@ -730,19 +736,19 @@ public:
|
|
|
730
736
|
|
|
731
737
|
Size operator*() const
|
|
732
738
|
{
|
|
733
|
-
|
|
739
|
+
K_ASSERT(offset <= K_LEN(bitset->data));
|
|
734
740
|
|
|
735
|
-
if (offset ==
|
|
741
|
+
if (offset == K_LEN(bitset->data))
|
|
736
742
|
return -1;
|
|
737
|
-
return offset *
|
|
743
|
+
return offset * K_SIZE(size_t) * 8 + ctz;
|
|
738
744
|
}
|
|
739
745
|
|
|
740
746
|
Iterator &operator++()
|
|
741
747
|
{
|
|
742
|
-
|
|
748
|
+
K_ASSERT(offset <= K_LEN(bitset->data));
|
|
743
749
|
|
|
744
750
|
while (!bits) {
|
|
745
|
-
if (offset ==
|
|
751
|
+
if (offset == K_LEN(bitset->data) - 1)
|
|
746
752
|
return *this;
|
|
747
753
|
bits = bitset->data[++offset];
|
|
748
754
|
}
|
|
@@ -769,14 +775,14 @@ public:
|
|
|
769
775
|
typedef Iterator<Bitset> iterator_type;
|
|
770
776
|
|
|
771
777
|
static constexpr Size Bits = N;
|
|
772
|
-
size_t data[(N +
|
|
778
|
+
size_t data[(N + K_BITS(size_t) - 1) / K_BITS(size_t)] = {};
|
|
773
779
|
|
|
774
780
|
constexpr Bitset() = default;
|
|
775
781
|
constexpr Bitset(std::initializer_list<Size> bits)
|
|
776
782
|
{
|
|
777
783
|
for (Size idx: bits) {
|
|
778
|
-
Size offset = idx / (
|
|
779
|
-
size_t mask = (size_t)1 << (idx % (
|
|
784
|
+
Size offset = idx / (K_SIZE(size_t) * 8);
|
|
785
|
+
size_t mask = (size_t)1 << (idx % (K_SIZE(size_t) * 8));
|
|
780
786
|
|
|
781
787
|
data[offset] |= mask;
|
|
782
788
|
}
|
|
@@ -784,22 +790,22 @@ public:
|
|
|
784
790
|
|
|
785
791
|
void Clear()
|
|
786
792
|
{
|
|
787
|
-
MemSet(data, 0,
|
|
793
|
+
MemSet(data, 0, K_SIZE(data));
|
|
788
794
|
}
|
|
789
795
|
|
|
790
796
|
Iterator<Bitset> begin() { return Iterator<Bitset>(this, 0); }
|
|
791
797
|
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,
|
|
798
|
+
Iterator<Bitset> end() { return Iterator<Bitset>(this, K_LEN(data)); }
|
|
799
|
+
Iterator<const Bitset> end() const { return Iterator<const Bitset>(this, K_LEN(data)); }
|
|
794
800
|
|
|
795
801
|
Size PopCount() const
|
|
796
802
|
{
|
|
797
803
|
Size count = 0;
|
|
798
804
|
for (size_t bits: data) {
|
|
799
|
-
#if
|
|
800
|
-
count +=
|
|
805
|
+
#if K_SIZE_MAX == INT64_MAX
|
|
806
|
+
count += K::PopCount((uint64_t)bits);
|
|
801
807
|
#else
|
|
802
|
-
count +=
|
|
808
|
+
count += K::PopCount((uint32_t)bits);
|
|
803
809
|
#endif
|
|
804
810
|
}
|
|
805
811
|
return count;
|
|
@@ -807,28 +813,28 @@ public:
|
|
|
807
813
|
|
|
808
814
|
inline bool Test(Size idx) const
|
|
809
815
|
{
|
|
810
|
-
|
|
816
|
+
K_ASSERT(idx >= 0 && idx < N);
|
|
811
817
|
|
|
812
|
-
Size offset = idx / (
|
|
813
|
-
size_t mask = (size_t)1 << (idx % (
|
|
818
|
+
Size offset = idx / (K_SIZE(size_t) * 8);
|
|
819
|
+
size_t mask = (size_t)1 << (idx % (K_SIZE(size_t) * 8));
|
|
814
820
|
|
|
815
821
|
return data[offset] & mask;
|
|
816
822
|
}
|
|
817
823
|
inline void Set(Size idx, bool value = true)
|
|
818
824
|
{
|
|
819
|
-
|
|
825
|
+
K_ASSERT(idx >= 0 && idx < N);
|
|
820
826
|
|
|
821
|
-
Size offset = idx / (
|
|
822
|
-
size_t mask = (size_t)1 << (idx % (
|
|
827
|
+
Size offset = idx / (K_SIZE(size_t) * 8);
|
|
828
|
+
size_t mask = (size_t)1 << (idx % (K_SIZE(size_t) * 8));
|
|
823
829
|
|
|
824
830
|
data[offset] = ApplyMask(data[offset], mask, value);
|
|
825
831
|
}
|
|
826
832
|
inline bool TestAndSet(Size idx, bool value = true)
|
|
827
833
|
{
|
|
828
|
-
|
|
834
|
+
K_ASSERT(idx >= 0 && idx < N);
|
|
829
835
|
|
|
830
|
-
Size offset = idx / (
|
|
831
|
-
size_t mask = (size_t)1 << (idx % (
|
|
836
|
+
Size offset = idx / (K_SIZE(size_t) * 8);
|
|
837
|
+
size_t mask = (size_t)1 << (idx % (K_SIZE(size_t) * 8));
|
|
832
838
|
|
|
833
839
|
bool ret = data[offset] & mask;
|
|
834
840
|
data[offset] = ApplyMask(data[offset], mask, value);
|
|
@@ -838,7 +844,7 @@ public:
|
|
|
838
844
|
|
|
839
845
|
Bitset &operator&=(const Bitset &other)
|
|
840
846
|
{
|
|
841
|
-
for (Size i = 0; i <
|
|
847
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
842
848
|
data[i] &= other.data[i];
|
|
843
849
|
}
|
|
844
850
|
return *this;
|
|
@@ -846,7 +852,7 @@ public:
|
|
|
846
852
|
Bitset operator&(const Bitset &other)
|
|
847
853
|
{
|
|
848
854
|
Bitset ret;
|
|
849
|
-
for (Size i = 0; i <
|
|
855
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
850
856
|
ret.data[i] = data[i] & other.data[i];
|
|
851
857
|
}
|
|
852
858
|
return ret;
|
|
@@ -854,7 +860,7 @@ public:
|
|
|
854
860
|
|
|
855
861
|
Bitset &operator|=(const Bitset &other)
|
|
856
862
|
{
|
|
857
|
-
for (Size i = 0; i <
|
|
863
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
858
864
|
data[i] |= other.data[i];
|
|
859
865
|
}
|
|
860
866
|
return *this;
|
|
@@ -862,7 +868,7 @@ public:
|
|
|
862
868
|
Bitset operator|(const Bitset &other)
|
|
863
869
|
{
|
|
864
870
|
Bitset ret;
|
|
865
|
-
for (Size i = 0; i <
|
|
871
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
866
872
|
ret.data[i] = data[i] | other.data[i];
|
|
867
873
|
}
|
|
868
874
|
return ret;
|
|
@@ -870,7 +876,7 @@ public:
|
|
|
870
876
|
|
|
871
877
|
Bitset &operator^=(const Bitset &other)
|
|
872
878
|
{
|
|
873
|
-
for (Size i = 0; i <
|
|
879
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
874
880
|
data[i] ^= other.data[i];
|
|
875
881
|
}
|
|
876
882
|
return *this;
|
|
@@ -878,7 +884,7 @@ public:
|
|
|
878
884
|
Bitset operator^(const Bitset &other)
|
|
879
885
|
{
|
|
880
886
|
Bitset ret;
|
|
881
|
-
for (Size i = 0; i <
|
|
887
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
882
888
|
ret.data[i] = data[i] ^ other.data[i];
|
|
883
889
|
}
|
|
884
890
|
return ret;
|
|
@@ -886,7 +892,7 @@ public:
|
|
|
886
892
|
|
|
887
893
|
Bitset &Flip()
|
|
888
894
|
{
|
|
889
|
-
for (Size i = 0; i <
|
|
895
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
890
896
|
data[i] = ~data[i];
|
|
891
897
|
}
|
|
892
898
|
return *this;
|
|
@@ -894,7 +900,7 @@ public:
|
|
|
894
900
|
Bitset operator~()
|
|
895
901
|
{
|
|
896
902
|
Bitset ret;
|
|
897
|
-
for (Size i = 0; i <
|
|
903
|
+
for (Size i = 0; i < K_LEN(data); i++) {
|
|
898
904
|
ret.data[i] = ~data[i];
|
|
899
905
|
}
|
|
900
906
|
return ret;
|
|
@@ -936,12 +942,12 @@ struct Span {
|
|
|
936
942
|
|
|
937
943
|
constexpr T &operator[](Size idx)
|
|
938
944
|
{
|
|
939
|
-
|
|
945
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
940
946
|
return ptr[idx];
|
|
941
947
|
}
|
|
942
948
|
constexpr const T &operator[](Size idx) const
|
|
943
949
|
{
|
|
944
|
-
|
|
950
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
945
951
|
return ptr[idx];
|
|
946
952
|
}
|
|
947
953
|
|
|
@@ -963,8 +969,8 @@ struct Span {
|
|
|
963
969
|
|
|
964
970
|
constexpr Span Take(Size offset, Size sub_len) const
|
|
965
971
|
{
|
|
966
|
-
|
|
967
|
-
|
|
972
|
+
K_ASSERT(sub_len >= 0 && sub_len <= len);
|
|
973
|
+
K_ASSERT(offset >= 0 && offset <= len - sub_len);
|
|
968
974
|
|
|
969
975
|
Span<T> sub = { ptr + offset, sub_len };
|
|
970
976
|
return sub;
|
|
@@ -1005,7 +1011,7 @@ struct Span<const char> {
|
|
|
1005
1011
|
|
|
1006
1012
|
constexpr char operator[](Size idx) const
|
|
1007
1013
|
{
|
|
1008
|
-
|
|
1014
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
1009
1015
|
return ptr[idx];
|
|
1010
1016
|
}
|
|
1011
1017
|
|
|
@@ -1017,8 +1023,8 @@ struct Span<const char> {
|
|
|
1017
1023
|
|
|
1018
1024
|
constexpr Span Take(Size offset, Size sub_len) const
|
|
1019
1025
|
{
|
|
1020
|
-
|
|
1021
|
-
|
|
1026
|
+
K_ASSERT(sub_len >= 0 && sub_len <= len);
|
|
1027
|
+
K_ASSERT(offset >= 0 && offset <= len - sub_len);
|
|
1022
1028
|
|
|
1023
1029
|
Span<const char> sub = { ptr + offset, sub_len };
|
|
1024
1030
|
return sub;
|
|
@@ -1051,14 +1057,14 @@ public:
|
|
|
1051
1057
|
Size stride;
|
|
1052
1058
|
|
|
1053
1059
|
Strider() = default;
|
|
1054
|
-
constexpr Strider(T *ptr_) : ptr(ptr_), stride(
|
|
1060
|
+
constexpr Strider(T *ptr_) : ptr(ptr_), stride(K_SIZE(T)) {}
|
|
1055
1061
|
constexpr Strider(T *ptr_, Size stride_) : ptr(ptr_), stride(stride_) {}
|
|
1056
1062
|
|
|
1057
1063
|
constexpr bool IsValid() const { return ptr; }
|
|
1058
1064
|
|
|
1059
1065
|
constexpr T &operator[](Size idx) const
|
|
1060
1066
|
{
|
|
1061
|
-
|
|
1067
|
+
K_ASSERT(idx >= 0);
|
|
1062
1068
|
return *(T *)((uint8_t *)ptr + (idx * stride));
|
|
1063
1069
|
}
|
|
1064
1070
|
};
|
|
@@ -1066,7 +1072,7 @@ public:
|
|
|
1066
1072
|
template <typename T>
|
|
1067
1073
|
static constexpr inline Strider<T> MakeStrider(T *ptr)
|
|
1068
1074
|
{
|
|
1069
|
-
return Strider<T>(ptr,
|
|
1075
|
+
return Strider<T>(ptr, K_SIZE(T));
|
|
1070
1076
|
}
|
|
1071
1077
|
template <typename T>
|
|
1072
1078
|
static constexpr inline Strider<T> MakeStrider(T *ptr, Size stride)
|
|
@@ -1076,7 +1082,7 @@ static constexpr inline Strider<T> MakeStrider(T *ptr, Size stride)
|
|
|
1076
1082
|
template <typename T, Size N>
|
|
1077
1083
|
static constexpr inline Strider<T> MakeStrider(T (&arr)[N])
|
|
1078
1084
|
{
|
|
1079
|
-
return Strider<T>(arr,
|
|
1085
|
+
return Strider<T>(arr, K_SIZE(T));
|
|
1080
1086
|
}
|
|
1081
1087
|
|
|
1082
1088
|
enum class AllocFlag {
|
|
@@ -1085,7 +1091,7 @@ enum class AllocFlag {
|
|
|
1085
1091
|
};
|
|
1086
1092
|
|
|
1087
1093
|
class Allocator {
|
|
1088
|
-
|
|
1094
|
+
K_DELETE_COPY(Allocator)
|
|
1089
1095
|
|
|
1090
1096
|
public:
|
|
1091
1097
|
Allocator() = default;
|
|
@@ -1101,7 +1107,7 @@ Allocator *GetNullAllocator();
|
|
|
1101
1107
|
|
|
1102
1108
|
static inline void *AllocateRaw(Allocator *alloc, Size size, unsigned int flags = 0)
|
|
1103
1109
|
{
|
|
1104
|
-
|
|
1110
|
+
K_ASSERT(size >= 0);
|
|
1105
1111
|
|
|
1106
1112
|
if (!alloc) {
|
|
1107
1113
|
alloc = GetDefaultAllocator();
|
|
@@ -1118,7 +1124,7 @@ T *AllocateOne(Allocator *alloc, unsigned int flags = 0)
|
|
|
1118
1124
|
alloc = GetDefaultAllocator();
|
|
1119
1125
|
}
|
|
1120
1126
|
|
|
1121
|
-
Size size =
|
|
1127
|
+
Size size = K_SIZE(T);
|
|
1122
1128
|
|
|
1123
1129
|
T *ptr = (T *)alloc->Allocate(size, flags);
|
|
1124
1130
|
return ptr;
|
|
@@ -1127,13 +1133,13 @@ T *AllocateOne(Allocator *alloc, unsigned int flags = 0)
|
|
|
1127
1133
|
template <typename T>
|
|
1128
1134
|
Span<T> AllocateSpan(Allocator *alloc, Size len, unsigned int flags = 0)
|
|
1129
1135
|
{
|
|
1130
|
-
|
|
1136
|
+
K_ASSERT(len >= 0);
|
|
1131
1137
|
|
|
1132
1138
|
if (!alloc) {
|
|
1133
1139
|
alloc = GetDefaultAllocator();
|
|
1134
1140
|
}
|
|
1135
1141
|
|
|
1136
|
-
Size size = len *
|
|
1142
|
+
Size size = len * K_SIZE(T);
|
|
1137
1143
|
|
|
1138
1144
|
T *ptr = (T *)alloc->Allocate(size, flags);
|
|
1139
1145
|
return MakeSpan(ptr, len);
|
|
@@ -1142,7 +1148,7 @@ Span<T> AllocateSpan(Allocator *alloc, Size len, unsigned int flags = 0)
|
|
|
1142
1148
|
static inline void *ResizeRaw(Allocator *alloc, void *ptr, Size old_size, Size new_size,
|
|
1143
1149
|
unsigned int flags = 0)
|
|
1144
1150
|
{
|
|
1145
|
-
|
|
1151
|
+
K_ASSERT(new_size >= 0);
|
|
1146
1152
|
|
|
1147
1153
|
if (!alloc) {
|
|
1148
1154
|
alloc = GetDefaultAllocator();
|
|
@@ -1156,14 +1162,14 @@ template <typename T>
|
|
|
1156
1162
|
Span<T> ResizeSpan(Allocator *alloc, Span<T> mem, Size new_len,
|
|
1157
1163
|
unsigned int flags = 0)
|
|
1158
1164
|
{
|
|
1159
|
-
|
|
1165
|
+
K_ASSERT(new_len >= 0);
|
|
1160
1166
|
|
|
1161
1167
|
if (!alloc) {
|
|
1162
1168
|
alloc = GetDefaultAllocator();
|
|
1163
1169
|
}
|
|
1164
1170
|
|
|
1165
|
-
Size old_size = mem.len *
|
|
1166
|
-
Size new_size = new_len *
|
|
1171
|
+
Size old_size = mem.len * K_SIZE(T);
|
|
1172
|
+
Size new_size = new_len * K_SIZE(T);
|
|
1167
1173
|
|
|
1168
1174
|
mem.ptr = (T *)alloc->Resize(mem.ptr, old_size, new_size, flags);
|
|
1169
1175
|
return MakeSpan(mem.ptr, new_len);
|
|
@@ -1185,7 +1191,7 @@ void ReleaseOne(Allocator *alloc, T *ptr)
|
|
|
1185
1191
|
alloc = GetDefaultAllocator();
|
|
1186
1192
|
}
|
|
1187
1193
|
|
|
1188
|
-
alloc->Release((void *)ptr,
|
|
1194
|
+
alloc->Release((void *)ptr, K_SIZE(T));
|
|
1189
1195
|
}
|
|
1190
1196
|
|
|
1191
1197
|
template<typename T>
|
|
@@ -1195,7 +1201,7 @@ void ReleaseSpan(Allocator *alloc, Span<T> mem)
|
|
|
1195
1201
|
alloc = GetDefaultAllocator();
|
|
1196
1202
|
}
|
|
1197
1203
|
|
|
1198
|
-
Size size = mem.len *
|
|
1204
|
+
Size size = mem.len * K_SIZE(T);
|
|
1199
1205
|
|
|
1200
1206
|
alloc->Release((void *)mem.ptr, size);
|
|
1201
1207
|
}
|
|
@@ -1246,10 +1252,10 @@ class BlockAllocator: public Allocator {
|
|
|
1246
1252
|
uint8_t *last_alloc = nullptr;
|
|
1247
1253
|
|
|
1248
1254
|
public:
|
|
1249
|
-
BlockAllocator(Size block_size =
|
|
1255
|
+
BlockAllocator(Size block_size = K_BLOCK_ALLOCATOR_DEFAULT_SIZE)
|
|
1250
1256
|
: block_size(block_size)
|
|
1251
1257
|
{
|
|
1252
|
-
|
|
1258
|
+
K_ASSERT(block_size > 0);
|
|
1253
1259
|
}
|
|
1254
1260
|
|
|
1255
1261
|
BlockAllocator(BlockAllocator &&other) { *this = std::move(other); }
|
|
@@ -1288,9 +1294,9 @@ public:
|
|
|
1288
1294
|
RetainPtr(T *p, void (*delete_func)(std::remove_const_t<T> *))
|
|
1289
1295
|
: p(p)
|
|
1290
1296
|
{
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1297
|
+
K_ASSERT(p);
|
|
1298
|
+
K_ASSERT(delete_func);
|
|
1299
|
+
K_ASSERT(!p->delete_func || delete_func == p->delete_func);
|
|
1294
1300
|
|
|
1295
1301
|
p->Ref();
|
|
1296
1302
|
p->delete_func = delete_func;
|
|
@@ -1299,7 +1305,7 @@ public:
|
|
|
1299
1305
|
: p(p)
|
|
1300
1306
|
{
|
|
1301
1307
|
if (p) {
|
|
1302
|
-
|
|
1308
|
+
K_ASSERT(p->delete_func);
|
|
1303
1309
|
|
|
1304
1310
|
if (ref) {
|
|
1305
1311
|
p->Ref();
|
|
@@ -1346,7 +1352,7 @@ public:
|
|
|
1346
1352
|
|
|
1347
1353
|
T &operator*() const
|
|
1348
1354
|
{
|
|
1349
|
-
|
|
1355
|
+
K_ASSERT(p);
|
|
1350
1356
|
return *p;
|
|
1351
1357
|
}
|
|
1352
1358
|
T *operator->() const { return p; }
|
|
@@ -1363,7 +1369,7 @@ public:
|
|
|
1363
1369
|
bool Unref() const
|
|
1364
1370
|
{
|
|
1365
1371
|
int new_count = --refcount;
|
|
1366
|
-
|
|
1372
|
+
K_ASSERT(new_count >= 0);
|
|
1367
1373
|
return new_count;
|
|
1368
1374
|
}
|
|
1369
1375
|
|
|
@@ -1545,7 +1551,6 @@ static inline bool StartsWith(Span<const char> str, Span<const char> prefix)
|
|
|
1545
1551
|
return false;
|
|
1546
1552
|
i++;
|
|
1547
1553
|
}
|
|
1548
|
-
|
|
1549
1554
|
return (i == prefix.len);
|
|
1550
1555
|
}
|
|
1551
1556
|
static inline bool StartsWith(Span<const char> str, const char *prefix)
|
|
@@ -1556,9 +1561,18 @@ static inline bool StartsWith(Span<const char> str, const char *prefix)
|
|
|
1556
1561
|
return false;
|
|
1557
1562
|
i++;
|
|
1558
1563
|
}
|
|
1559
|
-
|
|
1560
1564
|
return !prefix[i];
|
|
1561
1565
|
}
|
|
1566
|
+
static inline bool StartsWith(const char *str, Span<const char> prefix)
|
|
1567
|
+
{
|
|
1568
|
+
Size i = 0;
|
|
1569
|
+
while (str[i] && i < prefix.len) {
|
|
1570
|
+
if (str[i] != prefix[i])
|
|
1571
|
+
return false;
|
|
1572
|
+
i++;
|
|
1573
|
+
}
|
|
1574
|
+
return (i == prefix.len);
|
|
1575
|
+
}
|
|
1562
1576
|
static inline bool StartsWith(const char *str, const char *prefix)
|
|
1563
1577
|
{
|
|
1564
1578
|
Size i = 0;
|
|
@@ -1567,14 +1581,14 @@ static inline bool StartsWith(const char *str, const char *prefix)
|
|
|
1567
1581
|
return false;
|
|
1568
1582
|
i++;
|
|
1569
1583
|
}
|
|
1570
|
-
|
|
1571
1584
|
return !prefix[i];
|
|
1572
1585
|
}
|
|
1573
1586
|
|
|
1574
|
-
static inline bool EndsWith(Span<const char> str, const char
|
|
1587
|
+
static inline bool EndsWith(Span<const char> str, Span<const char> suffix)
|
|
1575
1588
|
{
|
|
1576
1589
|
Size i = str.len - 1;
|
|
1577
|
-
Size j =
|
|
1590
|
+
Size j = suffix.len - 1;
|
|
1591
|
+
|
|
1578
1592
|
while (i >= 0 && j >= 0) {
|
|
1579
1593
|
if (str[i] != suffix[j])
|
|
1580
1594
|
return false;
|
|
@@ -1649,16 +1663,15 @@ static inline Span<const char> SplitStr(Span<const char> str, char split_char, S
|
|
|
1649
1663
|
static inline Span<const char> SplitStr(const char *str, char split_char, const char **out_remainder = nullptr)
|
|
1650
1664
|
{ return SplitStr((char *)str, split_char, (char **)out_remainder); }
|
|
1651
1665
|
|
|
1652
|
-
static inline Span<char> SplitStr(Span<char> str, const char
|
|
1666
|
+
static inline Span<char> SplitStr(Span<char> str, Span<const char> split, Span<char> *out_remainder = nullptr)
|
|
1653
1667
|
{
|
|
1654
|
-
|
|
1668
|
+
K_ASSERT(split.len);
|
|
1655
1669
|
|
|
1656
1670
|
Size part_len = 0;
|
|
1657
1671
|
while (part_len < str.len) {
|
|
1658
|
-
if (StartsWith(str.Take(part_len, str.len - part_len),
|
|
1672
|
+
if (StartsWith(str.Take(part_len, str.len - part_len), split)) {
|
|
1659
1673
|
if (out_remainder) {
|
|
1660
|
-
|
|
1661
|
-
*out_remainder = str.Take(part_len + split_len, str.len - part_len - split_len);
|
|
1674
|
+
*out_remainder = str.Take(part_len + split.len, str.len - part_len - split.len);
|
|
1662
1675
|
}
|
|
1663
1676
|
return str.Take(0, part_len);
|
|
1664
1677
|
}
|
|
@@ -1670,16 +1683,15 @@ static inline Span<char> SplitStr(Span<char> str, const char *split_str, Span<ch
|
|
|
1670
1683
|
}
|
|
1671
1684
|
return str;
|
|
1672
1685
|
}
|
|
1673
|
-
static inline Span<char> SplitStr(char *str, const char
|
|
1686
|
+
static inline Span<char> SplitStr(char *str, Span<const char> split, char **out_remainder = nullptr)
|
|
1674
1687
|
{
|
|
1675
|
-
|
|
1688
|
+
K_ASSERT(split.len);
|
|
1676
1689
|
|
|
1677
1690
|
Size part_len = 0;
|
|
1678
1691
|
while (str[part_len]) {
|
|
1679
|
-
if (StartsWith(str + part_len,
|
|
1692
|
+
if (StartsWith(str + part_len, split)) {
|
|
1680
1693
|
if (out_remainder) {
|
|
1681
|
-
|
|
1682
|
-
*out_remainder = str + part_len + split_len;
|
|
1694
|
+
*out_remainder = str + part_len + split.len;
|
|
1683
1695
|
}
|
|
1684
1696
|
return MakeSpan(str, part_len);
|
|
1685
1697
|
}
|
|
@@ -1691,10 +1703,10 @@ static inline Span<char> SplitStr(char *str, const char *split_str, char **out_r
|
|
|
1691
1703
|
}
|
|
1692
1704
|
return MakeSpan(str, part_len);
|
|
1693
1705
|
}
|
|
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,
|
|
1706
|
+
static inline Span<const char> SplitStr(Span<const char> str, Span<const char> split, Span<const char> *out_remainder = nullptr)
|
|
1707
|
+
{ return SplitStr(MakeSpan((char *)str.ptr, str.len), split, (Span<char> *)out_remainder); }
|
|
1708
|
+
static inline Span<const char> SplitStr(const char *str, Span<const char> split, const char **out_remainder = nullptr)
|
|
1709
|
+
{ return SplitStr((char *)str, split, (char **)out_remainder); }
|
|
1698
1710
|
|
|
1699
1711
|
static inline Span<char> SplitStrLine(Span<char> str, Span<char> *out_remainder = nullptr)
|
|
1700
1712
|
{
|
|
@@ -1890,117 +1902,6 @@ static inline Span<const char> TrimStrRight(Span<const char> str, const char *tr
|
|
|
1890
1902
|
static inline Span<const char> TrimStr(Span<const char> str, const char *trim_chars = " \t\r\n")
|
|
1891
1903
|
{ return TrimStr(MakeSpan((char *)str.ptr, str.len), trim_chars); }
|
|
1892
1904
|
|
|
1893
|
-
static inline int CountUtf8Bytes(char c)
|
|
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);
|
|
2003
|
-
|
|
2004
1905
|
// ------------------------------------------------------------------------
|
|
2005
1906
|
// Collections
|
|
2006
1907
|
// ------------------------------------------------------------------------
|
|
@@ -2017,7 +1918,7 @@ public:
|
|
|
2017
1918
|
constexpr LocalArray() = default;
|
|
2018
1919
|
constexpr LocalArray(std::initializer_list<T> l)
|
|
2019
1920
|
{
|
|
2020
|
-
|
|
1921
|
+
K_ASSERT(l.size() <= N);
|
|
2021
1922
|
for (const T &it: l) {
|
|
2022
1923
|
data[len++] = it;
|
|
2023
1924
|
}
|
|
@@ -2040,16 +1941,16 @@ public:
|
|
|
2040
1941
|
T *end() { return data + len; }
|
|
2041
1942
|
const T *end() const { return data + len; }
|
|
2042
1943
|
|
|
2043
|
-
Size Available() const { return
|
|
1944
|
+
Size Available() const { return K_LEN(data) - len; }
|
|
2044
1945
|
|
|
2045
1946
|
T &operator[](Size idx)
|
|
2046
1947
|
{
|
|
2047
|
-
|
|
1948
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
2048
1949
|
return data[idx];
|
|
2049
1950
|
}
|
|
2050
1951
|
const T &operator[](Size idx) const
|
|
2051
1952
|
{
|
|
2052
|
-
|
|
1953
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
2053
1954
|
return data[idx];
|
|
2054
1955
|
}
|
|
2055
1956
|
|
|
@@ -2069,7 +1970,7 @@ public:
|
|
|
2069
1970
|
|
|
2070
1971
|
T *AppendDefault(Size count = 1)
|
|
2071
1972
|
{
|
|
2072
|
-
|
|
1973
|
+
K_ASSERT(len <= N - count);
|
|
2073
1974
|
|
|
2074
1975
|
T *first = data + len;
|
|
2075
1976
|
if constexpr(!std::is_trivial<T>::value) {
|
|
@@ -2078,7 +1979,7 @@ public:
|
|
|
2078
1979
|
len++;
|
|
2079
1980
|
}
|
|
2080
1981
|
} else {
|
|
2081
|
-
MemSet(first, 0, count *
|
|
1982
|
+
MemSet(first, 0, count * K_SIZE(T));
|
|
2082
1983
|
len += count;
|
|
2083
1984
|
}
|
|
2084
1985
|
|
|
@@ -2087,7 +1988,7 @@ public:
|
|
|
2087
1988
|
|
|
2088
1989
|
T *Append(const T &value)
|
|
2089
1990
|
{
|
|
2090
|
-
|
|
1991
|
+
K_ASSERT(len < N);
|
|
2091
1992
|
|
|
2092
1993
|
T *it = data + len;
|
|
2093
1994
|
*it = value;
|
|
@@ -2097,7 +1998,7 @@ public:
|
|
|
2097
1998
|
}
|
|
2098
1999
|
T *Append(T &&value)
|
|
2099
2000
|
{
|
|
2100
|
-
|
|
2001
|
+
K_ASSERT(len < N);
|
|
2101
2002
|
|
|
2102
2003
|
T *it = data + len;
|
|
2103
2004
|
*it = std::move(value);
|
|
@@ -2107,7 +2008,7 @@ public:
|
|
|
2107
2008
|
}
|
|
2108
2009
|
T *Append(Span<const T> values)
|
|
2109
2010
|
{
|
|
2110
|
-
|
|
2011
|
+
K_ASSERT(values.len <= N - len);
|
|
2111
2012
|
|
|
2112
2013
|
T *it = data + len;
|
|
2113
2014
|
for (Size i = 0; i < values.len; i++) {
|
|
@@ -2120,7 +2021,7 @@ public:
|
|
|
2120
2021
|
|
|
2121
2022
|
void RemoveFrom(Size first)
|
|
2122
2023
|
{
|
|
2123
|
-
|
|
2024
|
+
K_ASSERT(first >= 0 && first <= len);
|
|
2124
2025
|
|
|
2125
2026
|
for (Size i = first; i < len; i++) {
|
|
2126
2027
|
data[i] = T();
|
|
@@ -2129,7 +2030,7 @@ public:
|
|
|
2129
2030
|
}
|
|
2130
2031
|
void RemoveLast(Size count = 1)
|
|
2131
2032
|
{
|
|
2132
|
-
|
|
2033
|
+
K_ASSERT(count >= 0 && count <= len);
|
|
2133
2034
|
RemoveFrom(len - count);
|
|
2134
2035
|
}
|
|
2135
2036
|
|
|
@@ -2171,8 +2072,8 @@ public:
|
|
|
2171
2072
|
HeapArray &operator=(HeapArray &&other)
|
|
2172
2073
|
{
|
|
2173
2074
|
Clear();
|
|
2174
|
-
MemMove(this, &other,
|
|
2175
|
-
MemSet(&other, 0,
|
|
2075
|
+
MemMove(this, &other, K_SIZE(other));
|
|
2076
|
+
MemSet(&other, 0, K_SIZE(other));
|
|
2176
2077
|
return *this;
|
|
2177
2078
|
}
|
|
2178
2079
|
HeapArray(const HeapArray &other) { *this = other; }
|
|
@@ -2185,7 +2086,7 @@ public:
|
|
|
2185
2086
|
ptr[i] = other.ptr[i];
|
|
2186
2087
|
}
|
|
2187
2088
|
} else {
|
|
2188
|
-
MemCpy(ptr, other.ptr, other.len *
|
|
2089
|
+
MemCpy(ptr, other.ptr, other.len * K_SIZE(*ptr));
|
|
2189
2090
|
}
|
|
2190
2091
|
len = other.len;
|
|
2191
2092
|
return *this;
|
|
@@ -2209,12 +2110,12 @@ public:
|
|
|
2209
2110
|
|
|
2210
2111
|
T &operator[](Size idx)
|
|
2211
2112
|
{
|
|
2212
|
-
|
|
2113
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
2213
2114
|
return ptr[idx];
|
|
2214
2115
|
}
|
|
2215
2116
|
const T &operator[](Size idx) const
|
|
2216
2117
|
{
|
|
2217
|
-
|
|
2118
|
+
K_ASSERT(idx >= 0 && idx < len);
|
|
2218
2119
|
return ptr[idx];
|
|
2219
2120
|
}
|
|
2220
2121
|
|
|
@@ -2234,7 +2135,7 @@ public:
|
|
|
2234
2135
|
|
|
2235
2136
|
void SetCapacity(Size new_capacity)
|
|
2236
2137
|
{
|
|
2237
|
-
|
|
2138
|
+
K_ASSERT(new_capacity >= 0);
|
|
2238
2139
|
|
|
2239
2140
|
if (new_capacity != capacity) {
|
|
2240
2141
|
if (len > new_capacity) {
|
|
@@ -2244,7 +2145,7 @@ public:
|
|
|
2244
2145
|
len = new_capacity;
|
|
2245
2146
|
}
|
|
2246
2147
|
|
|
2247
|
-
ptr = (T *)ResizeRaw(allocator, ptr, capacity *
|
|
2148
|
+
ptr = (T *)ResizeRaw(allocator, ptr, capacity * K_SIZE(T), new_capacity * K_SIZE(T));
|
|
2248
2149
|
capacity = new_capacity;
|
|
2249
2150
|
}
|
|
2250
2151
|
}
|
|
@@ -2258,18 +2159,18 @@ public:
|
|
|
2258
2159
|
|
|
2259
2160
|
T *Grow(Size reserve_capacity = 1)
|
|
2260
2161
|
{
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2162
|
+
K_ASSERT(capacity >= 0);
|
|
2163
|
+
K_ASSERT(reserve_capacity >= 0);
|
|
2164
|
+
K_ASSERT((size_t)capacity + (size_t)reserve_capacity <= K_SIZE_MAX);
|
|
2264
2165
|
|
|
2265
2166
|
if (reserve_capacity > capacity - len) {
|
|
2266
2167
|
Size needed = capacity + reserve_capacity;
|
|
2267
2168
|
|
|
2268
2169
|
Size new_capacity;
|
|
2269
|
-
if (needed <=
|
|
2270
|
-
new_capacity =
|
|
2170
|
+
if (needed <= K_HEAPARRAY_BASE_CAPACITY) {
|
|
2171
|
+
new_capacity = K_HEAPARRAY_BASE_CAPACITY;
|
|
2271
2172
|
} else {
|
|
2272
|
-
new_capacity = (Size)((double)(needed - 1) *
|
|
2173
|
+
new_capacity = (Size)((double)(needed - 1) * K_HEAPARRAY_GROWTH_FACTOR);
|
|
2273
2174
|
}
|
|
2274
2175
|
|
|
2275
2176
|
SetCapacity(new_capacity);
|
|
@@ -2291,7 +2192,7 @@ public:
|
|
|
2291
2192
|
len++;
|
|
2292
2193
|
}
|
|
2293
2194
|
} else {
|
|
2294
|
-
MemSet(first, 0, count *
|
|
2195
|
+
MemSet(first, 0, count * K_SIZE(T));
|
|
2295
2196
|
len += count;
|
|
2296
2197
|
}
|
|
2297
2198
|
|
|
@@ -2336,7 +2237,7 @@ public:
|
|
|
2336
2237
|
|
|
2337
2238
|
void RemoveFrom(Size first)
|
|
2338
2239
|
{
|
|
2339
|
-
|
|
2240
|
+
K_ASSERT(first >= 0 && first <= len);
|
|
2340
2241
|
|
|
2341
2242
|
if constexpr(!std::is_trivial<T>::value) {
|
|
2342
2243
|
for (Size i = first; i < len; i++) {
|
|
@@ -2347,7 +2248,7 @@ public:
|
|
|
2347
2248
|
}
|
|
2348
2249
|
void RemoveLast(Size count = 1)
|
|
2349
2250
|
{
|
|
2350
|
-
|
|
2251
|
+
K_ASSERT(count >= 0 && count <= len);
|
|
2351
2252
|
RemoveFrom(len - count);
|
|
2352
2253
|
}
|
|
2353
2254
|
|
|
@@ -2377,7 +2278,7 @@ public:
|
|
|
2377
2278
|
|
|
2378
2279
|
template <typename T, Size BucketSize = 64, typename AllocatorType = BlockAllocator>
|
|
2379
2280
|
class BucketArray {
|
|
2380
|
-
|
|
2281
|
+
K_DELETE_COPY(BucketArray)
|
|
2381
2282
|
|
|
2382
2283
|
public:
|
|
2383
2284
|
struct Bucket {
|
|
@@ -2495,8 +2396,8 @@ public:
|
|
|
2495
2396
|
BucketArray &operator=(BucketArray &&other)
|
|
2496
2397
|
{
|
|
2497
2398
|
ClearBucketsAndValues();
|
|
2498
|
-
MemMove(this, &other,
|
|
2499
|
-
MemSet(&other, 0,
|
|
2399
|
+
MemMove(this, &other, K_SIZE(other));
|
|
2400
|
+
MemSet(&other, 0, K_SIZE(other));
|
|
2500
2401
|
return *this;
|
|
2501
2402
|
}
|
|
2502
2403
|
|
|
@@ -2529,7 +2430,7 @@ public:
|
|
|
2529
2430
|
|
|
2530
2431
|
const T &operator[](Size idx) const
|
|
2531
2432
|
{
|
|
2532
|
-
|
|
2433
|
+
K_ASSERT(idx >= 0 && idx < count);
|
|
2533
2434
|
|
|
2534
2435
|
idx += offset;
|
|
2535
2436
|
Size bucket_idx = idx / BucketSize;
|
|
@@ -2547,7 +2448,7 @@ public:
|
|
|
2547
2448
|
if (bucket_idx >= buckets.len) {
|
|
2548
2449
|
Bucket *new_bucket = AllocateOne<Bucket>(buckets.allocator);
|
|
2549
2450
|
new (&new_bucket->allocator) AllocatorType();
|
|
2550
|
-
new_bucket->values = (T *)AllocateRaw(&new_bucket->allocator, BucketSize *
|
|
2451
|
+
new_bucket->values = (T *)AllocateRaw(&new_bucket->allocator, BucketSize * K_SIZE(T));
|
|
2551
2452
|
|
|
2552
2453
|
buckets.Append(new_bucket);
|
|
2553
2454
|
}
|
|
@@ -2572,7 +2473,7 @@ public:
|
|
|
2572
2473
|
|
|
2573
2474
|
void RemoveFrom(Size from)
|
|
2574
2475
|
{
|
|
2575
|
-
|
|
2476
|
+
K_ASSERT(from >= 0 && from <= count);
|
|
2576
2477
|
|
|
2577
2478
|
if (from == count)
|
|
2578
2479
|
return;
|
|
@@ -2598,13 +2499,13 @@ public:
|
|
|
2598
2499
|
}
|
|
2599
2500
|
void RemoveLast(Size n = 1)
|
|
2600
2501
|
{
|
|
2601
|
-
|
|
2502
|
+
K_ASSERT(n >= 0 && n <= count);
|
|
2602
2503
|
RemoveFrom(count - n);
|
|
2603
2504
|
}
|
|
2604
2505
|
|
|
2605
2506
|
void RemoveFirst(Size n = 1)
|
|
2606
2507
|
{
|
|
2607
|
-
|
|
2508
|
+
K_ASSERT(n >= 0 && n <= count);
|
|
2608
2509
|
|
|
2609
2510
|
if (n == count) {
|
|
2610
2511
|
Clear();
|
|
@@ -2623,7 +2524,7 @@ public:
|
|
|
2623
2524
|
DeleteBucket(buckets[i]);
|
|
2624
2525
|
}
|
|
2625
2526
|
MemMove(&buckets[0], &buckets[end_bucket_idx],
|
|
2626
|
-
(buckets.len - end_bucket_idx) *
|
|
2527
|
+
(buckets.len - end_bucket_idx) * K_SIZE(Bucket *));
|
|
2627
2528
|
buckets.RemoveLast(end_bucket_idx);
|
|
2628
2529
|
}
|
|
2629
2530
|
|
|
@@ -2650,7 +2551,7 @@ public:
|
|
|
2650
2551
|
|
|
2651
2552
|
count = (it.bucket_idx * BucketSize) + it.bucket_offset - offset;
|
|
2652
2553
|
|
|
2653
|
-
|
|
2554
|
+
K_ASSERT(it == end());
|
|
2654
2555
|
}
|
|
2655
2556
|
void RemoveFrom(const Iterator<const BucketArray<T, BucketSize>> &it) { return RemoveFrom((iterator_type)it); }
|
|
2656
2557
|
|
|
@@ -2670,7 +2571,7 @@ public:
|
|
|
2670
2571
|
DeleteBucket(buckets[i]);
|
|
2671
2572
|
}
|
|
2672
2573
|
MemMove(&buckets[0], &buckets[it.bucket_idx],
|
|
2673
|
-
(buckets.len - it.bucket_idx) *
|
|
2574
|
+
(buckets.len - it.bucket_idx) * K_SIZE(Bucket *));
|
|
2674
2575
|
buckets.RemoveLast(it.bucket_idx);
|
|
2675
2576
|
}
|
|
2676
2577
|
|
|
@@ -2736,18 +2637,18 @@ public:
|
|
|
2736
2637
|
|
|
2737
2638
|
ValueType &operator*()
|
|
2738
2639
|
{
|
|
2739
|
-
|
|
2640
|
+
K_ASSERT(!table->IsEmpty(offset));
|
|
2740
2641
|
return table->data[offset];
|
|
2741
2642
|
}
|
|
2742
2643
|
const ValueType &operator*() const
|
|
2743
2644
|
{
|
|
2744
|
-
|
|
2645
|
+
K_ASSERT(!table->IsEmpty(offset));
|
|
2745
2646
|
return table->data[offset];
|
|
2746
2647
|
}
|
|
2747
2648
|
|
|
2748
2649
|
Iterator &operator++()
|
|
2749
2650
|
{
|
|
2750
|
-
|
|
2651
|
+
K_ASSERT(offset < table->capacity);
|
|
2751
2652
|
while (++offset < table->capacity && table->IsEmpty(offset));
|
|
2752
2653
|
return *this;
|
|
2753
2654
|
}
|
|
@@ -2793,8 +2694,8 @@ public:
|
|
|
2793
2694
|
HashTable &operator=(HashTable &&other)
|
|
2794
2695
|
{
|
|
2795
2696
|
Clear();
|
|
2796
|
-
MemMove(this, &other,
|
|
2797
|
-
MemSet(&other, 0,
|
|
2697
|
+
MemMove(this, &other, K_SIZE(other));
|
|
2698
|
+
MemSet(&other, 0, K_SIZE(other));
|
|
2798
2699
|
return *this;
|
|
2799
2700
|
}
|
|
2800
2701
|
HashTable(const HashTable &other) { *this = other; }
|
|
@@ -2829,7 +2730,7 @@ public:
|
|
|
2829
2730
|
|
|
2830
2731
|
count = 0;
|
|
2831
2732
|
if (used) {
|
|
2832
|
-
size_t len = (size_t)(capacity + (
|
|
2733
|
+
size_t len = (size_t)(capacity + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t);
|
|
2833
2734
|
MemSet(used, 0, len);
|
|
2834
2735
|
}
|
|
2835
2736
|
}
|
|
@@ -2923,7 +2824,7 @@ public:
|
|
|
2923
2824
|
return;
|
|
2924
2825
|
|
|
2925
2826
|
Size clear_idx = it - data;
|
|
2926
|
-
|
|
2827
|
+
K_ASSERT(!IsEmpty(clear_idx));
|
|
2927
2828
|
|
|
2928
2829
|
it->~ValueType();
|
|
2929
2830
|
count--;
|
|
@@ -2943,7 +2844,7 @@ public:
|
|
|
2943
2844
|
|
|
2944
2845
|
MarkUsed(clear_idx);
|
|
2945
2846
|
MarkEmpty(idx);
|
|
2946
|
-
MemMove(&data[clear_idx], &data[idx],
|
|
2847
|
+
MemMove(&data[clear_idx], &data[idx], K_SIZE(*data));
|
|
2947
2848
|
|
|
2948
2849
|
clear_idx = idx;
|
|
2949
2850
|
}
|
|
@@ -2958,9 +2859,9 @@ public:
|
|
|
2958
2859
|
if (count) {
|
|
2959
2860
|
Size new_capacity = (Size)1 << (64 - CountLeadingZeros((uint64_t)count));
|
|
2960
2861
|
|
|
2961
|
-
if (new_capacity <
|
|
2962
|
-
new_capacity =
|
|
2963
|
-
} else if (count > (double)new_capacity *
|
|
2862
|
+
if (new_capacity < K_HASHTABLE_BASE_CAPACITY) {
|
|
2863
|
+
new_capacity = K_HASHTABLE_BASE_CAPACITY;
|
|
2864
|
+
} else if (count > (double)new_capacity * K_HASHTABLE_MAX_LOAD_FACTOR) {
|
|
2964
2865
|
new_capacity *= 2;
|
|
2965
2866
|
}
|
|
2966
2867
|
|
|
@@ -3004,7 +2905,7 @@ private:
|
|
|
3004
2905
|
Size idx = HashToIndex(hash);
|
|
3005
2906
|
ValueType *it = Find(&idx, key);
|
|
3006
2907
|
if (!it) {
|
|
3007
|
-
if (count >= (Size)((double)capacity *
|
|
2908
|
+
if (count >= (Size)((double)capacity * K_HASHTABLE_MAX_LOAD_FACTOR)) {
|
|
3008
2909
|
Rehash(capacity << 1);
|
|
3009
2910
|
idx = HashToIndex(hash);
|
|
3010
2911
|
while (!IsEmpty(idx)) {
|
|
@@ -3021,7 +2922,7 @@ private:
|
|
|
3021
2922
|
return it;
|
|
3022
2923
|
}
|
|
3023
2924
|
} else {
|
|
3024
|
-
Rehash(
|
|
2925
|
+
Rehash(K_HASHTABLE_BASE_CAPACITY);
|
|
3025
2926
|
|
|
3026
2927
|
Size idx = HashToIndex(hash);
|
|
3027
2928
|
count++;
|
|
@@ -3036,7 +2937,7 @@ private:
|
|
|
3036
2937
|
{
|
|
3037
2938
|
if (new_capacity == capacity)
|
|
3038
2939
|
return;
|
|
3039
|
-
|
|
2940
|
+
K_ASSERT(count <= new_capacity);
|
|
3040
2941
|
|
|
3041
2942
|
size_t *old_used = used;
|
|
3042
2943
|
ValueType *old_data = data;
|
|
@@ -3044,9 +2945,9 @@ private:
|
|
|
3044
2945
|
|
|
3045
2946
|
if (new_capacity) {
|
|
3046
2947
|
used = (size_t *)AllocateRaw(allocator,
|
|
3047
|
-
(new_capacity + (
|
|
2948
|
+
(new_capacity + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t),
|
|
3048
2949
|
(int)AllocFlag::Zero);
|
|
3049
|
-
data = (ValueType *)AllocateRaw(allocator, new_capacity *
|
|
2950
|
+
data = (ValueType *)AllocateRaw(allocator, new_capacity * K_SIZE(ValueType));
|
|
3050
2951
|
for (Size i = 0; i < new_capacity; i++) {
|
|
3051
2952
|
new (&data[i]) ValueType();
|
|
3052
2953
|
}
|
|
@@ -3068,22 +2969,22 @@ private:
|
|
|
3068
2969
|
capacity = 0;
|
|
3069
2970
|
}
|
|
3070
2971
|
|
|
3071
|
-
ReleaseRaw(allocator, old_used, (old_capacity + (
|
|
3072
|
-
ReleaseRaw(allocator, old_data, old_capacity *
|
|
2972
|
+
ReleaseRaw(allocator, old_used, (old_capacity + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t));
|
|
2973
|
+
ReleaseRaw(allocator, old_data, old_capacity * K_SIZE(ValueType));
|
|
3073
2974
|
}
|
|
3074
2975
|
|
|
3075
2976
|
inline void MarkUsed(Size idx)
|
|
3076
2977
|
{
|
|
3077
|
-
used[idx / (
|
|
2978
|
+
used[idx / (K_SIZE(size_t) * 8)] |= (1ull << (idx % (K_SIZE(size_t) * 8)));
|
|
3078
2979
|
}
|
|
3079
2980
|
inline void MarkEmpty(Size idx)
|
|
3080
2981
|
{
|
|
3081
|
-
used[idx / (
|
|
2982
|
+
used[idx / (K_SIZE(size_t) * 8)] &= ~(1ull << (idx % (K_SIZE(size_t) * 8)));
|
|
3082
2983
|
}
|
|
3083
2984
|
|
|
3084
2985
|
inline bool IsEmpty(size_t *used, Size idx) const
|
|
3085
2986
|
{
|
|
3086
|
-
bool empty = !(used[idx / (
|
|
2987
|
+
bool empty = !(used[idx / (K_SIZE(size_t) * 8)] & (1ull << (idx % (K_SIZE(size_t) * 8))));
|
|
3087
2988
|
return empty;
|
|
3088
2989
|
}
|
|
3089
2990
|
inline bool IsEmpty(Size idx) const { return IsEmpty(used, idx); }
|
|
@@ -3167,7 +3068,7 @@ DEFINE_INTEGER_HASH_TRAITS_32(unsigned int, constexpr);
|
|
|
3167
3068
|
#endif
|
|
3168
3069
|
DEFINE_INTEGER_HASH_TRAITS_64(long long, constexpr);
|
|
3169
3070
|
DEFINE_INTEGER_HASH_TRAITS_64(unsigned long long, constexpr);
|
|
3170
|
-
#if
|
|
3071
|
+
#if K_SIZE_MAX == INT64_MAX
|
|
3171
3072
|
DEFINE_INTEGER_HASH_TRAITS_64(void *);
|
|
3172
3073
|
DEFINE_INTEGER_HASH_TRAITS_64(const void *);
|
|
3173
3074
|
#else
|
|
@@ -3194,7 +3095,7 @@ static constexpr inline uint64_t HashStr(Span<const char> str)
|
|
|
3194
3095
|
} :
|
|
3195
3096
|
#endif
|
|
3196
3097
|
[](const char *p) {
|
|
3197
|
-
#if defined(
|
|
3098
|
+
#if defined(K_BIG_ENDIAN)
|
|
3198
3099
|
uint64_t result = ((uint64_t)p[0] << 56) |
|
|
3199
3100
|
((uint64_t)p[1] << 48) |
|
|
3200
3101
|
((uint64_t)p[2] << 40) |
|
|
@@ -3275,7 +3176,7 @@ public:
|
|
|
3275
3176
|
static constexpr bool Test(Span<const char> key1, const char * key2) { return key1 == key2; }
|
|
3276
3177
|
};
|
|
3277
3178
|
|
|
3278
|
-
#define
|
|
3179
|
+
#define K_HASHTABLE_HANDLER_EX_N(Name, ValueType, KeyType, KeyMember, HashFunc, TestFunc) \
|
|
3279
3180
|
class Name { \
|
|
3280
3181
|
public: \
|
|
3281
3182
|
static constexpr KeyType GetKey(const ValueType &value) \
|
|
@@ -3289,16 +3190,16 @@ public:
|
|
|
3289
3190
|
static constexpr bool TestKeys(KeyType key1, TestKey key2) \
|
|
3290
3191
|
{ return TestFunc((key1), (key2)); } \
|
|
3291
3192
|
}
|
|
3292
|
-
#define
|
|
3293
|
-
|
|
3294
|
-
#define
|
|
3295
|
-
|
|
3296
|
-
#define
|
|
3297
|
-
|
|
3298
|
-
#define
|
|
3299
|
-
|
|
3300
|
-
#define
|
|
3301
|
-
|
|
3193
|
+
#define K_HASHTABLE_HANDLER_EX(ValueType, KeyType, KeyMember, HashFunc, TestFunc) \
|
|
3194
|
+
K_HASHTABLE_HANDLER_EX_N(HashHandler, ValueType, KeyType, KeyMember, HashFunc, TestFunc)
|
|
3195
|
+
#define K_HASHTABLE_HANDLER(ValueType, KeyMember) \
|
|
3196
|
+
K_HASHTABLE_HANDLER_EX(ValueType, decltype(ValueType::KeyMember), KeyMember, HashTraits<decltype(ValueType::KeyMember)>::Hash, HashTraits<decltype(ValueType::KeyMember)>::Test)
|
|
3197
|
+
#define K_HASHTABLE_HANDLER_N(Name, ValueType, KeyMember) \
|
|
3198
|
+
K_HASHTABLE_HANDLER_EX_N(Name, ValueType, decltype(ValueType::KeyMember), KeyMember, HashTraits<decltype(ValueType::KeyMember)>::Hash, HashTraits<decltype(ValueType::KeyMember)>::Test)
|
|
3199
|
+
#define K_HASHTABLE_HANDLER_T(ValueType, KeyType, KeyMember) \
|
|
3200
|
+
K_HASHTABLE_HANDLER_EX(ValueType, KeyType, KeyMember, HashTraits<KeyType>::Hash, HashTraits<KeyType>::Test)
|
|
3201
|
+
#define K_HASHTABLE_HANDLER_NT(Name, ValueType, KeyType, KeyMember) \
|
|
3202
|
+
K_HASHTABLE_HANDLER_EX_N(Name, ValueType, KeyType, KeyMember, HashTraits<KeyType>::Hash, HashTraits<KeyType>::Test)
|
|
3302
3203
|
|
|
3303
3204
|
template <typename KeyType, typename ValueType>
|
|
3304
3205
|
class HashMap {
|
|
@@ -3307,7 +3208,7 @@ public:
|
|
|
3307
3208
|
KeyType key;
|
|
3308
3209
|
ValueType value;
|
|
3309
3210
|
|
|
3310
|
-
|
|
3211
|
+
K_HASHTABLE_HANDLER(Bucket, key);
|
|
3311
3212
|
};
|
|
3312
3213
|
|
|
3313
3214
|
HashTable<KeyType, Bucket> table;
|
|
@@ -3436,13 +3337,13 @@ public:
|
|
|
3436
3337
|
ValueType value;
|
|
3437
3338
|
};
|
|
3438
3339
|
|
|
3439
|
-
size_t used[(N + (
|
|
3340
|
+
size_t used[(N + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t)] = {};
|
|
3440
3341
|
Bucket data[N] = {};
|
|
3441
3342
|
Size count = 0;
|
|
3442
3343
|
|
|
3443
3344
|
constexpr ConstMap(std::initializer_list<Bucket> l)
|
|
3444
3345
|
{
|
|
3445
|
-
|
|
3346
|
+
K_CRITICAL(l.size() <= N, "ConstMap<%1> cannot be store %2 values", N, l.size());
|
|
3446
3347
|
|
|
3447
3348
|
for (const Bucket &it: l) {
|
|
3448
3349
|
Bucket *bucket = Insert(it.key);
|
|
@@ -3516,11 +3417,11 @@ private:
|
|
|
3516
3417
|
|
|
3517
3418
|
constexpr void MarkUsed(Size idx)
|
|
3518
3419
|
{
|
|
3519
|
-
used[idx / (
|
|
3420
|
+
used[idx / (K_SIZE(size_t) * 8)] |= (1ull << (idx % (K_SIZE(size_t) * 8)));
|
|
3520
3421
|
}
|
|
3521
3422
|
constexpr bool IsEmpty(Size idx) const
|
|
3522
3423
|
{
|
|
3523
|
-
bool empty = !(used[idx / (
|
|
3424
|
+
bool empty = !(used[idx / (K_SIZE(size_t) * 8)] & (1ull << (idx % (K_SIZE(size_t) * 8))));
|
|
3524
3425
|
return empty;
|
|
3525
3426
|
}
|
|
3526
3427
|
|
|
@@ -3537,7 +3438,7 @@ private:
|
|
|
3537
3438
|
union LocalDate {
|
|
3538
3439
|
int32_t value;
|
|
3539
3440
|
struct {
|
|
3540
|
-
#if defined(
|
|
3441
|
+
#if defined(K_BIG_ENDIAN)
|
|
3541
3442
|
int16_t year;
|
|
3542
3443
|
int8_t month;
|
|
3543
3444
|
int8_t day;
|
|
@@ -3549,12 +3450,12 @@ union LocalDate {
|
|
|
3549
3450
|
} st;
|
|
3550
3451
|
|
|
3551
3452
|
LocalDate() = default;
|
|
3552
|
-
#if defined(
|
|
3453
|
+
#if defined(K_BIG_ENDIAN)
|
|
3553
3454
|
LocalDate(int16_t year, int8_t month, int8_t day)
|
|
3554
|
-
: st({ year, month, day }) {
|
|
3455
|
+
: st({ year, month, day }) { K_ASSERT(IsValid()); }
|
|
3555
3456
|
#else
|
|
3556
3457
|
LocalDate(int16_t year, int8_t month, int8_t day)
|
|
3557
|
-
: st({ day, month, year }) {
|
|
3458
|
+
: st({ day, month, year }) { K_ASSERT(IsValid()); }
|
|
3558
3459
|
#endif
|
|
3559
3460
|
|
|
3560
3461
|
static inline bool IsLeapYear(int16_t year)
|
|
@@ -3733,7 +3634,7 @@ public:
|
|
|
3733
3634
|
template <typename T>
|
|
3734
3635
|
explicit FmtCustom(const T &obj)
|
|
3735
3636
|
{
|
|
3736
|
-
static_assert(
|
|
3637
|
+
static_assert(K_SIZE(*this) <= K_SIZE(raw));
|
|
3737
3638
|
new (raw) Concrete<T>(&obj, &FmtTraits<T>::Format);
|
|
3738
3639
|
}
|
|
3739
3640
|
|
|
@@ -3840,7 +3741,7 @@ static inline FmtArg FmtOctal(uint64_t u)
|
|
|
3840
3741
|
}
|
|
3841
3742
|
static inline FmtArg FmtHex(uint64_t u, FmtType type = FmtType::BigHex)
|
|
3842
3743
|
{
|
|
3843
|
-
|
|
3744
|
+
K_ASSERT(type == FmtType::BigHex || type == FmtType::SmallHex);
|
|
3844
3745
|
|
|
3845
3746
|
FmtArg arg;
|
|
3846
3747
|
arg.type = type;
|
|
@@ -3907,7 +3808,7 @@ static inline FmtArg FmtTimeNice(TimeSpec spec, bool ms = false)
|
|
|
3907
3808
|
|
|
3908
3809
|
static inline FmtArg FmtRandom(Size len, const char *chars = nullptr)
|
|
3909
3810
|
{
|
|
3910
|
-
|
|
3811
|
+
K_ASSERT(len < 256);
|
|
3911
3812
|
len = std::min(len, (Size)256);
|
|
3912
3813
|
|
|
3913
3814
|
FmtArg arg;
|
|
@@ -3943,7 +3844,7 @@ FmtArg FmtSpan(Span<T> arr, FmtType type, const char *sep = ", ")
|
|
|
3943
3844
|
FmtArg arg;
|
|
3944
3845
|
arg.type = FmtType::Span;
|
|
3945
3846
|
arg.u.span.type = type;
|
|
3946
|
-
arg.u.span.type_len =
|
|
3847
|
+
arg.u.span.type_len = K_SIZE(T);
|
|
3947
3848
|
arg.u.span.ptr = (const void *)arr.ptr;
|
|
3948
3849
|
arg.u.span.len = arr.len;
|
|
3949
3850
|
arg.u.span.separator = sep;
|
|
@@ -3956,6 +3857,12 @@ FmtArg FmtSpan(T (&arr)[N], FmtType type, const char *sep = ", ") { return FmtSp
|
|
|
3956
3857
|
template <typename T, Size N>
|
|
3957
3858
|
FmtArg FmtSpan(T (&arr)[N], const char *sep = ", ") { return FmtSpan(MakeSpan(arr), sep); }
|
|
3958
3859
|
|
|
3860
|
+
static inline FmtArg FmtHex(Span<const uint8_t> buf, FmtType type = FmtType::BigHex)
|
|
3861
|
+
{
|
|
3862
|
+
K_ASSERT(type == FmtType::BigHex || type == FmtType::SmallHex);
|
|
3863
|
+
return FmtSpan(buf, type, "").Pad0(-2);
|
|
3864
|
+
}
|
|
3865
|
+
|
|
3959
3866
|
class FmtUpperAscii {
|
|
3960
3867
|
Span<const char> str;
|
|
3961
3868
|
|
|
@@ -4101,7 +4008,7 @@ static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args...
|
|
|
4101
4008
|
LogFmt(level, ctx, fmt, fmt_args);
|
|
4102
4009
|
}
|
|
4103
4010
|
|
|
4104
|
-
#if defined(
|
|
4011
|
+
#if defined(K_DEBUG) && __cplusplus >= 202002L && __has_include(<source_location>)
|
|
4105
4012
|
struct LogContext {
|
|
4106
4013
|
const char *fmt;
|
|
4107
4014
|
char str[56] = {};
|
|
@@ -4157,7 +4064,7 @@ static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args...
|
|
|
4157
4064
|
template <typename... Args>
|
|
4158
4065
|
static inline void LogError(LogContext ctx, Args... args) { Log(LogLevel::Error, ctx.str, ctx.fmt, args...); }
|
|
4159
4066
|
#else
|
|
4160
|
-
#if defined(
|
|
4067
|
+
#if defined(K_DEBUG)
|
|
4161
4068
|
template <typename... Args>
|
|
4162
4069
|
static inline void LogDebug(Args... args) { Log(LogLevel::Debug, "Debug: ", args...); }
|
|
4163
4070
|
#else
|
|
@@ -4167,9 +4074,9 @@ static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args...
|
|
|
4167
4074
|
template <typename... Args>
|
|
4168
4075
|
static inline void LogInfo(Args... args) { Log(LogLevel::Info, nullptr, args...); }
|
|
4169
4076
|
template <typename... Args>
|
|
4170
|
-
static inline void LogWarning(Args... args) { Log(LogLevel::Warning, "Warning: ", args...); }
|
|
4077
|
+
static inline void LogWarning(Args... args) { Log(LogLevel::Warning, T("Warning: "), args...); }
|
|
4171
4078
|
template <typename... Args>
|
|
4172
|
-
static inline void LogError(Args... args) { Log(LogLevel::Error, "Error: ", args...); }
|
|
4079
|
+
static inline void LogError(Args... args) { Log(LogLevel::Error, T("Error: "), args...); }
|
|
4173
4080
|
#endif
|
|
4174
4081
|
|
|
4175
4082
|
void SetLogHandler(const std::function<LogFunc> &func, bool vt100);
|
|
@@ -4202,7 +4109,7 @@ struct ProgressInfo {
|
|
|
4202
4109
|
typedef void ProgressFunc(Span<const ProgressInfo> states);
|
|
4203
4110
|
|
|
4204
4111
|
class ProgressHandle {
|
|
4205
|
-
char text[
|
|
4112
|
+
char text[K_PROGRESS_TEXT_SIZE] = {};
|
|
4206
4113
|
|
|
4207
4114
|
std::atomic<ProgressNode *> node = nullptr;
|
|
4208
4115
|
|
|
@@ -4222,7 +4129,7 @@ public:
|
|
|
4222
4129
|
template<typename... Args>
|
|
4223
4130
|
void SetFmt(int64_t value, int64_t min, int64_t max, const char *fmt, Args... args)
|
|
4224
4131
|
{
|
|
4225
|
-
char buf[
|
|
4132
|
+
char buf[K_PROGRESS_TEXT_SIZE];
|
|
4226
4133
|
Fmt(buf, fmt, args...);
|
|
4227
4134
|
|
|
4228
4135
|
Set(value, min, max, (const char *)buf);
|
|
@@ -4240,7 +4147,7 @@ public:
|
|
|
4240
4147
|
|
|
4241
4148
|
private:
|
|
4242
4149
|
ProgressNode *AcquireNode();
|
|
4243
|
-
void CopyText(Span<const char> text, char out[
|
|
4150
|
+
void CopyText(Span<const char> text, char out[K_PROGRESS_TEXT_SIZE]);
|
|
4244
4151
|
};
|
|
4245
4152
|
|
|
4246
4153
|
void SetProgressHandler(const std::function<ProgressFunc> &func);
|
|
@@ -4253,15 +4160,15 @@ void DefaultProgressHandler(Span<const ProgressInfo> bars);
|
|
|
4253
4160
|
// ------------------------------------------------------------------------
|
|
4254
4161
|
|
|
4255
4162
|
#if defined(_WIN32)
|
|
4256
|
-
#define
|
|
4257
|
-
#define
|
|
4258
|
-
#define
|
|
4259
|
-
#define
|
|
4163
|
+
#define K_PATH_SEPARATORS "\\/"
|
|
4164
|
+
#define K_PATH_DELIMITER ';'
|
|
4165
|
+
#define K_EXECUTABLE_EXTENSION ".exe"
|
|
4166
|
+
#define K_SHARED_LIBRARY_EXTENSION ".dll"
|
|
4260
4167
|
#else
|
|
4261
|
-
#define
|
|
4262
|
-
#define
|
|
4263
|
-
#define
|
|
4264
|
-
#define
|
|
4168
|
+
#define K_PATH_SEPARATORS "/"
|
|
4169
|
+
#define K_PATH_DELIMITER ':'
|
|
4170
|
+
#define K_EXECUTABLE_EXTENSION ""
|
|
4171
|
+
#define K_SHARED_LIBRARY_EXTENSION ".so"
|
|
4265
4172
|
#endif
|
|
4266
4173
|
|
|
4267
4174
|
#if defined(_WIN32)
|
|
@@ -4587,18 +4494,40 @@ void WaitDelay(int64_t delay);
|
|
|
4587
4494
|
|
|
4588
4495
|
#if !defined(__wasi__)
|
|
4589
4496
|
|
|
4590
|
-
enum class
|
|
4591
|
-
|
|
4497
|
+
enum class WaitResult {
|
|
4498
|
+
Ready,
|
|
4499
|
+
Timeout,
|
|
4592
4500
|
Interrupt,
|
|
4593
4501
|
Message,
|
|
4594
|
-
|
|
4502
|
+
Exit,
|
|
4503
|
+
Error
|
|
4504
|
+
};
|
|
4505
|
+
|
|
4506
|
+
#if defined(_WIN32)
|
|
4507
|
+
typedef void * WaitHandle; // HANDLE
|
|
4508
|
+
#else
|
|
4509
|
+
typedef int WaitHandle;
|
|
4510
|
+
#endif
|
|
4511
|
+
|
|
4512
|
+
struct WaitSource {
|
|
4513
|
+
#if defined(_WIN32)
|
|
4514
|
+
// Special-cased on Windows: set to NULL to wait for the Win32 message pump too
|
|
4515
|
+
void *handle; // HANDLE
|
|
4516
|
+
#else
|
|
4517
|
+
int fd;
|
|
4518
|
+
int events;
|
|
4519
|
+
#endif
|
|
4520
|
+
|
|
4521
|
+
int timeout;
|
|
4595
4522
|
};
|
|
4596
4523
|
|
|
4597
|
-
// After
|
|
4598
|
-
//
|
|
4524
|
+
// After WaitEvents() has been called once (even with timeout 0), a few signals (such as SIGINT, SIGHUP)
|
|
4525
|
+
// and their Windows equivalent will be permanently ignored.
|
|
4599
4526
|
// Beware, on Unix platforms, this may not work correctly if not called from the main thread.
|
|
4600
|
-
|
|
4601
|
-
|
|
4527
|
+
WaitResult WaitEvents(Span<const WaitSource> sources, int64_t timeout, uint64_t *out_ready = nullptr);
|
|
4528
|
+
WaitResult WaitEvents(int64_t timeout);
|
|
4529
|
+
|
|
4530
|
+
void InterruptWait();
|
|
4602
4531
|
|
|
4603
4532
|
#endif
|
|
4604
4533
|
|
|
@@ -4613,19 +4542,72 @@ bool DropRootIdentity();
|
|
|
4613
4542
|
bool NotifySystemd();
|
|
4614
4543
|
#endif
|
|
4615
4544
|
|
|
4616
|
-
#define
|
|
4545
|
+
#define K_RESTART_EINTR(CallCode, ErrorCond) \
|
|
4617
4546
|
([&]() { \
|
|
4618
4547
|
decltype(CallCode) ret; \
|
|
4619
4548
|
while ((ret = (CallCode)) ErrorCond && errno == EINTR); \
|
|
4620
4549
|
return ret; \
|
|
4621
4550
|
})()
|
|
4622
4551
|
|
|
4552
|
+
class InitHelper {
|
|
4553
|
+
public:
|
|
4554
|
+
const char *name;
|
|
4555
|
+
InitHelper *next = nullptr;
|
|
4556
|
+
|
|
4557
|
+
InitHelper(const char *name);
|
|
4558
|
+
virtual void Run() = 0;
|
|
4559
|
+
};
|
|
4560
|
+
|
|
4561
|
+
class FinalizeHelper {
|
|
4562
|
+
public:
|
|
4563
|
+
const char *name;
|
|
4564
|
+
FinalizeHelper *next = nullptr;
|
|
4565
|
+
|
|
4566
|
+
FinalizeHelper(const char *name);
|
|
4567
|
+
virtual void Run() = 0;
|
|
4568
|
+
};
|
|
4569
|
+
|
|
4570
|
+
#define K_INIT_(ClassName, Name) \
|
|
4571
|
+
class ClassName: public InitHelper { \
|
|
4572
|
+
public: \
|
|
4573
|
+
ClassName(): InitHelper(Name) {} \
|
|
4574
|
+
void Run() override; \
|
|
4575
|
+
}; \
|
|
4576
|
+
static ClassName K_UNIQUE_NAME(init); \
|
|
4577
|
+
void ClassName::Run()
|
|
4578
|
+
#define K_INIT(Name) K_INIT_(K_CONCAT(K_UNIQUE_NAME(InitHelper), Name), K_STRINGIFY(Name))
|
|
4579
|
+
|
|
4580
|
+
#define K_FINALIZE_(ClassName, Name) \
|
|
4581
|
+
class ClassName: public FinalizeHelper { \
|
|
4582
|
+
public: \
|
|
4583
|
+
ClassName(): FinalizeHelper(Name) {} \
|
|
4584
|
+
void Run() override; \
|
|
4585
|
+
}; \
|
|
4586
|
+
static ClassName K_UNIQUE_NAME(finalize); \
|
|
4587
|
+
void ClassName::Run()
|
|
4588
|
+
#define K_FINALIZE(Name) K_FINALIZE_(K_CONCAT(K_UNIQUE_NAME(FinalizeHelper), Name), K_STRINGIFY(Name))
|
|
4589
|
+
|
|
4590
|
+
#define K_EXIT_(ClassName) \
|
|
4591
|
+
class ClassName { \
|
|
4592
|
+
public: \
|
|
4593
|
+
~ClassName(); \
|
|
4594
|
+
}; \
|
|
4595
|
+
static ClassName K_UNIQUE_NAME(exit); \
|
|
4596
|
+
ClassName::~ClassName()
|
|
4597
|
+
#define K_EXIT(Name) K_EXIT_(K_CONCAT(K_UNIQUE_NAME(ExitHelper), Name))
|
|
4598
|
+
|
|
4623
4599
|
void InitApp();
|
|
4600
|
+
void ExitApp();
|
|
4601
|
+
|
|
4624
4602
|
int Main(int argc, char **argv);
|
|
4625
4603
|
|
|
4626
4604
|
static inline int RunApp(int argc, char **argv)
|
|
4627
4605
|
{
|
|
4606
|
+
K_CRITICAL(argc >= 1, "First argument is missing");
|
|
4607
|
+
|
|
4628
4608
|
InitApp();
|
|
4609
|
+
K_DEFER { ExitApp(); };
|
|
4610
|
+
|
|
4629
4611
|
return Main(argc, argv);
|
|
4630
4612
|
}
|
|
4631
4613
|
|
|
@@ -4661,10 +4643,10 @@ enum class ParseFlag {
|
|
|
4661
4643
|
Validate = 1 << 1,
|
|
4662
4644
|
End = 1 << 2
|
|
4663
4645
|
};
|
|
4664
|
-
#define
|
|
4646
|
+
#define K_DEFAULT_PARSE_FLAGS ((int)ParseFlag::Log | (int)ParseFlag::Validate | (int)ParseFlag::End)
|
|
4665
4647
|
|
|
4666
4648
|
template <typename T>
|
|
4667
|
-
bool ParseInt(Span<const char> str, T *out_value, unsigned int flags =
|
|
4649
|
+
bool ParseInt(Span<const char> str, T *out_value, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4668
4650
|
Span<const char> *out_remaining = nullptr)
|
|
4669
4651
|
{
|
|
4670
4652
|
if (!str.len) [[unlikely]] {
|
|
@@ -4723,20 +4705,20 @@ overflow:
|
|
|
4723
4705
|
return false;
|
|
4724
4706
|
}
|
|
4725
4707
|
|
|
4726
|
-
bool ParseBool(Span<const char> str, bool *out_value, unsigned int flags =
|
|
4708
|
+
bool ParseBool(Span<const char> str, bool *out_value, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4727
4709
|
Span<const char> *out_remaining = nullptr);
|
|
4728
4710
|
|
|
4729
|
-
bool ParseSize(Span<const char> str, int64_t *out_size, unsigned int flags =
|
|
4711
|
+
bool ParseSize(Span<const char> str, int64_t *out_size, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4730
4712
|
Span<const char> *out_remaining = nullptr);
|
|
4731
|
-
#if
|
|
4713
|
+
#if K_SIZE_MAX < INT64_MAX
|
|
4732
4714
|
static inline bool ParseSize(Span<const char> str, Size *out_size,
|
|
4733
|
-
unsigned int flags =
|
|
4715
|
+
unsigned int flags = K_DEFAULT_PARSE_FLAGS, Span<const char> *out_remaining = nullptr)
|
|
4734
4716
|
{
|
|
4735
4717
|
int64_t size = 0;
|
|
4736
4718
|
if (!ParseSize(str, &size, flags, out_remaining))
|
|
4737
4719
|
return false;
|
|
4738
4720
|
|
|
4739
|
-
if (size >
|
|
4721
|
+
if (size > K_SIZE_MAX) [[unlikely]] {
|
|
4740
4722
|
if (flags & (int)ParseFlag::Log) {
|
|
4741
4723
|
LogError("Size value is too high");
|
|
4742
4724
|
}
|
|
@@ -4748,13 +4730,13 @@ static inline bool ParseSize(Span<const char> str, Size *out_size,
|
|
|
4748
4730
|
}
|
|
4749
4731
|
#endif
|
|
4750
4732
|
|
|
4751
|
-
bool ParseDate(Span<const char> date_str, LocalDate *out_date, unsigned int flags =
|
|
4733
|
+
bool ParseDate(Span<const char> date_str, LocalDate *out_date, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4752
4734
|
Span<const char> *out_remaining = nullptr);
|
|
4753
4735
|
|
|
4754
|
-
bool ParseDuration(Span<const char> str, int64_t *out_duration, unsigned int flags =
|
|
4736
|
+
bool ParseDuration(Span<const char> str, int64_t *out_duration, unsigned int flags = K_DEFAULT_PARSE_FLAGS,
|
|
4755
4737
|
Span<const char> *out_remaining = nullptr);
|
|
4756
4738
|
static inline bool ParseDuration(Span<const char> str, int *out_duration,
|
|
4757
|
-
unsigned int flags =
|
|
4739
|
+
unsigned int flags = K_DEFAULT_PARSE_FLAGS, Span<const char> *out_remaining = nullptr)
|
|
4758
4740
|
{
|
|
4759
4741
|
int64_t duration = 0;
|
|
4760
4742
|
if (!ParseDuration(str, &duration, flags, out_remaining))
|
|
@@ -4772,12 +4754,15 @@ static inline bool ParseDuration(Span<const char> str, int *out_duration,
|
|
|
4772
4754
|
}
|
|
4773
4755
|
|
|
4774
4756
|
bool ParseVersion(Span<const char> str, int parts, int multiplier, int64_t *out_duration,
|
|
4775
|
-
unsigned int flags =
|
|
4757
|
+
unsigned int flags = K_DEFAULT_PARSE_FLAGS, Span<const char> *out_remaining = nullptr);
|
|
4776
4758
|
|
|
4777
4759
|
// ------------------------------------------------------------------------
|
|
4778
4760
|
// Random
|
|
4779
4761
|
// ------------------------------------------------------------------------
|
|
4780
4762
|
|
|
4763
|
+
void InitChaCha20(uint32_t state[16], const uint8_t key[32], const uint8_t iv[8], const uint8_t counter[8] = nullptr);
|
|
4764
|
+
void RunChaCha20(uint32_t state[16], uint8_t out_buf[64]);
|
|
4765
|
+
|
|
4781
4766
|
void FillRandomSafe(void *buf, Size len);
|
|
4782
4767
|
static inline void FillRandomSafe(Span<uint8_t> buf) { FillRandomSafe(buf.ptr, buf.len); }
|
|
4783
4768
|
|
|
@@ -4788,14 +4773,13 @@ public:
|
|
|
4788
4773
|
FastRandom();
|
|
4789
4774
|
FastRandom(uint64_t seed);
|
|
4790
4775
|
|
|
4776
|
+
uint64_t Next();
|
|
4777
|
+
|
|
4791
4778
|
void Fill(void *buf, Size len);
|
|
4792
4779
|
void Fill(Span<uint8_t> buf) { Fill(buf.ptr, buf.len); }
|
|
4793
4780
|
|
|
4794
4781
|
int GetInt(int min, int max);
|
|
4795
4782
|
int64_t GetInt64(int64_t min, int64_t max);
|
|
4796
|
-
|
|
4797
|
-
private:
|
|
4798
|
-
uint64_t Next();
|
|
4799
4783
|
};
|
|
4800
4784
|
|
|
4801
4785
|
template <typename T>
|
|
@@ -4811,11 +4795,12 @@ public:
|
|
|
4811
4795
|
T operator()()
|
|
4812
4796
|
{
|
|
4813
4797
|
T value;
|
|
4814
|
-
rng.Fill(&value,
|
|
4798
|
+
rng.Fill(&value, K_SIZE(value));
|
|
4815
4799
|
return value;
|
|
4816
4800
|
}
|
|
4817
4801
|
};
|
|
4818
4802
|
|
|
4803
|
+
uint64_t GetRandom();
|
|
4819
4804
|
int GetRandomInt(int min, int max);
|
|
4820
4805
|
int64_t GetRandomInt64(int64_t min, int64_t max);
|
|
4821
4806
|
|
|
@@ -4868,7 +4853,7 @@ void CloseSocket(int fd);
|
|
|
4868
4853
|
// ------------------------------------------------------------------------
|
|
4869
4854
|
|
|
4870
4855
|
class Async {
|
|
4871
|
-
|
|
4856
|
+
K_DELETE_COPY(Async)
|
|
4872
4857
|
|
|
4873
4858
|
#if !defined(__wasi__)
|
|
4874
4859
|
std::atomic_bool success { true };
|
|
@@ -4913,8 +4898,12 @@ enum class CompressionSpeed {
|
|
|
4913
4898
|
class StreamDecoder;
|
|
4914
4899
|
class StreamEncoder;
|
|
4915
4900
|
|
|
4901
|
+
enum class StreamReaderFlag {
|
|
4902
|
+
LazyFill = 1 << 0
|
|
4903
|
+
};
|
|
4904
|
+
|
|
4916
4905
|
class StreamReader {
|
|
4917
|
-
|
|
4906
|
+
K_DELETE_COPY(StreamReader)
|
|
4918
4907
|
|
|
4919
4908
|
enum class SourceType {
|
|
4920
4909
|
Memory,
|
|
@@ -4923,6 +4912,7 @@ class StreamReader {
|
|
|
4923
4912
|
};
|
|
4924
4913
|
|
|
4925
4914
|
const char *filename = nullptr;
|
|
4915
|
+
bool lazy = false;
|
|
4926
4916
|
bool error = true;
|
|
4927
4917
|
|
|
4928
4918
|
int64_t read_total = 0;
|
|
@@ -4962,29 +4952,30 @@ class StreamReader {
|
|
|
4962
4952
|
|
|
4963
4953
|
public:
|
|
4964
4954
|
StreamReader() { Close(true); }
|
|
4965
|
-
StreamReader(Span<const uint8_t> buf, const char *filename =
|
|
4955
|
+
StreamReader(Span<const uint8_t> buf, const char *filename, unsigned int flags = 0,
|
|
4966
4956
|
CompressionType compression_type = CompressionType::None)
|
|
4967
|
-
: StreamReader() { Open(buf, filename, compression_type); }
|
|
4968
|
-
StreamReader(int fd, const char *filename,
|
|
4957
|
+
: StreamReader() { Open(buf, filename, flags, compression_type); }
|
|
4958
|
+
StreamReader(int fd, const char *filename, unsigned int flags = 0,
|
|
4969
4959
|
CompressionType compression_type = CompressionType::None)
|
|
4970
|
-
: StreamReader() { Open(fd, filename, compression_type); }
|
|
4971
|
-
StreamReader(const char *filename,
|
|
4960
|
+
: StreamReader() { Open(fd, filename, flags, compression_type); }
|
|
4961
|
+
StreamReader(const char *filename, unsigned int flags = 0,
|
|
4972
4962
|
CompressionType compression_type = CompressionType::None)
|
|
4973
|
-
: StreamReader() { Open(filename, compression_type); }
|
|
4974
|
-
StreamReader(const std::function<Size(Span<uint8_t>)> &func, const char *filename =
|
|
4963
|
+
: StreamReader() { Open(filename, flags, compression_type); }
|
|
4964
|
+
StreamReader(const std::function<Size(Span<uint8_t>)> &func, const char *filename, unsigned int flags = 0,
|
|
4975
4965
|
CompressionType compression_type = CompressionType::None)
|
|
4976
|
-
: StreamReader() { Open(func, filename, compression_type); }
|
|
4966
|
+
: StreamReader() { Open(func, filename, flags, compression_type); }
|
|
4977
4967
|
~StreamReader() { Close(true); }
|
|
4978
4968
|
|
|
4979
4969
|
// Call before Open. Takes ownership and deletes the decoder at the end.
|
|
4980
4970
|
void SetDecoder(StreamDecoder *decoder);
|
|
4981
4971
|
|
|
4982
|
-
bool Open(Span<const uint8_t> buf, const char *filename =
|
|
4972
|
+
bool Open(Span<const uint8_t> buf, const char *filename, unsigned int flags = 0,
|
|
4983
4973
|
CompressionType compression_type = CompressionType::None);
|
|
4984
|
-
bool Open(int fd, const char *filename,
|
|
4974
|
+
bool Open(int fd, const char *filename, unsigned int flags = 0,
|
|
4985
4975
|
CompressionType compression_type = CompressionType::None);
|
|
4986
|
-
OpenResult Open(const char *filename,
|
|
4987
|
-
|
|
4976
|
+
OpenResult Open(const char *filename, unsigned int flags = 0,
|
|
4977
|
+
CompressionType compression_type = CompressionType::None);
|
|
4978
|
+
bool Open(const std::function<Size(Span<uint8_t>)> &func, const char *filename, unsigned int flags = 0,
|
|
4988
4979
|
CompressionType compression_type = CompressionType::None);
|
|
4989
4980
|
bool Close() { return Close(false); }
|
|
4990
4981
|
|
|
@@ -5071,16 +5062,16 @@ public:
|
|
|
5071
5062
|
StreamDecompressorHelper(CompressionType type, CreateDecompressorFunc *func);
|
|
5072
5063
|
};
|
|
5073
5064
|
|
|
5074
|
-
#define
|
|
5075
|
-
static StreamDecoder *
|
|
5065
|
+
#define K_REGISTER_DECOMPRESSOR(Type, Cls) \
|
|
5066
|
+
static StreamDecoder *K_UNIQUE_NAME(CreateDecompressor)(StreamReader *reader, CompressionType type) \
|
|
5076
5067
|
{ \
|
|
5077
5068
|
StreamDecoder *decompressor = new Cls(reader, type); \
|
|
5078
5069
|
return decompressor; \
|
|
5079
5070
|
} \
|
|
5080
|
-
static StreamDecompressorHelper
|
|
5071
|
+
static StreamDecompressorHelper K_UNIQUE_NAME(CreateDecompressorHelper)((Type), K_UNIQUE_NAME(CreateDecompressor))
|
|
5081
5072
|
|
|
5082
5073
|
class LineReader {
|
|
5083
|
-
|
|
5074
|
+
K_DELETE_COPY(LineReader)
|
|
5084
5075
|
|
|
5085
5076
|
HeapArray<char> buf;
|
|
5086
5077
|
Span<char> view = {};
|
|
@@ -5107,14 +5098,14 @@ public:
|
|
|
5107
5098
|
};
|
|
5108
5099
|
|
|
5109
5100
|
enum class StreamWriterFlag {
|
|
5110
|
-
Exclusive = 1 << 0,
|
|
5111
|
-
Atomic = 1 << 1,
|
|
5112
|
-
NoBuffer = 1 << 2,
|
|
5113
|
-
LineBuffer = 1 << 3
|
|
5101
|
+
Exclusive = 1 << 0, // Only for files
|
|
5102
|
+
Atomic = 1 << 1, // Only for files
|
|
5103
|
+
NoBuffer = 1 << 2, // Only for files and descriptors
|
|
5104
|
+
LineBuffer = 1 << 3 // Only for files and descriptors
|
|
5114
5105
|
};
|
|
5115
5106
|
|
|
5116
5107
|
class StreamWriter {
|
|
5117
|
-
|
|
5108
|
+
K_DELETE_COPY(StreamWriter)
|
|
5118
5109
|
|
|
5119
5110
|
enum class DestinationType {
|
|
5120
5111
|
Memory,
|
|
@@ -5167,14 +5158,14 @@ class StreamWriter {
|
|
|
5167
5158
|
|
|
5168
5159
|
public:
|
|
5169
5160
|
StreamWriter() { Close(true); }
|
|
5170
|
-
StreamWriter(HeapArray<uint8_t> *mem, const char *filename =
|
|
5161
|
+
StreamWriter(HeapArray<uint8_t> *mem, const char *filename, unsigned int flags = 0,
|
|
5171
5162
|
CompressionType compression_type = CompressionType::None,
|
|
5172
5163
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5173
|
-
: StreamWriter() { Open(mem, filename, compression_type, compression_speed); }
|
|
5174
|
-
StreamWriter(HeapArray<char> *mem, const char *filename =
|
|
5164
|
+
: StreamWriter() { Open(mem, filename, flags, compression_type, compression_speed); }
|
|
5165
|
+
StreamWriter(HeapArray<char> *mem, const char *filename, unsigned int flags = 0,
|
|
5175
5166
|
CompressionType compression_type = CompressionType::None,
|
|
5176
5167
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5177
|
-
: StreamWriter() { Open(mem, filename, compression_type, compression_speed); }
|
|
5168
|
+
: StreamWriter() { Open(mem, filename, flags, compression_type, compression_speed); }
|
|
5178
5169
|
StreamWriter(int fd, const char *filename, unsigned int flags = 0,
|
|
5179
5170
|
CompressionType compression_type = CompressionType::None,
|
|
5180
5171
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
@@ -5183,29 +5174,29 @@ public:
|
|
|
5183
5174
|
CompressionType compression_type = CompressionType::None,
|
|
5184
5175
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5185
5176
|
: StreamWriter() { Open(filename, flags, compression_type, compression_speed); }
|
|
5186
|
-
StreamWriter(const std::function<bool(Span<const uint8_t>)> &func, const char *filename =
|
|
5177
|
+
StreamWriter(const std::function<bool(Span<const uint8_t>)> &func, const char *filename, unsigned int flags = 0,
|
|
5187
5178
|
CompressionType compression_type = CompressionType::None,
|
|
5188
5179
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5189
|
-
: StreamWriter() { Open(func, filename, compression_type, compression_speed); }
|
|
5180
|
+
: StreamWriter() { Open(func, filename, flags, compression_type, compression_speed); }
|
|
5190
5181
|
~StreamWriter() { Close(true); }
|
|
5191
5182
|
|
|
5192
5183
|
// Call before Open. Takes ownership and deletes the encoder at the end.
|
|
5193
5184
|
void SetEncoder(StreamEncoder *encoder);
|
|
5194
5185
|
|
|
5195
|
-
bool Open(HeapArray<uint8_t> *mem, const char *filename =
|
|
5186
|
+
bool Open(HeapArray<uint8_t> *mem, const char *filename, unsigned int flags = 0,
|
|
5196
5187
|
CompressionType compression_type = CompressionType::None,
|
|
5197
5188
|
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
5198
|
-
bool Open(HeapArray<char> *mem, const char *filename =
|
|
5189
|
+
bool Open(HeapArray<char> *mem, const char *filename, unsigned int flags = 0,
|
|
5199
5190
|
CompressionType compression_type = CompressionType::None,
|
|
5200
5191
|
CompressionSpeed compression_speed = CompressionSpeed::Default)
|
|
5201
|
-
{ return Open((HeapArray<uint8_t> *)mem, filename, compression_type, compression_speed); }
|
|
5192
|
+
{ return Open((HeapArray<uint8_t> *)mem, filename, flags, compression_type, compression_speed); }
|
|
5202
5193
|
bool Open(int fd, const char *filename, unsigned int flags = 0,
|
|
5203
5194
|
CompressionType compression_type = CompressionType::None,
|
|
5204
5195
|
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
5205
5196
|
bool Open(const char *filename, unsigned int flags = 0,
|
|
5206
5197
|
CompressionType compression_type = CompressionType::None,
|
|
5207
5198
|
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
5208
|
-
bool Open(const std::function<bool(Span<const uint8_t>)> &func, const char *filename =
|
|
5199
|
+
bool Open(const std::function<bool(Span<const uint8_t>)> &func, const char *filename, unsigned int flags = 0,
|
|
5209
5200
|
CompressionType compression_type = CompressionType::None,
|
|
5210
5201
|
CompressionSpeed compression_speed = CompressionSpeed::Default);
|
|
5211
5202
|
bool Close() { return Close(false); }
|
|
@@ -5283,13 +5274,13 @@ public:
|
|
|
5283
5274
|
StreamCompressorHelper(CompressionType type, CreateCompressorFunc *func);
|
|
5284
5275
|
};
|
|
5285
5276
|
|
|
5286
|
-
#define
|
|
5287
|
-
static StreamEncoder *
|
|
5277
|
+
#define K_REGISTER_COMPRESSOR(Type, Cls) \
|
|
5278
|
+
static StreamEncoder *K_UNIQUE_NAME(CreateCompressor)(StreamWriter *writer, CompressionType type, CompressionSpeed speed) \
|
|
5288
5279
|
{ \
|
|
5289
5280
|
StreamEncoder *compressor = new Cls(writer, type, speed); \
|
|
5290
5281
|
return compressor; \
|
|
5291
5282
|
} \
|
|
5292
|
-
static StreamCompressorHelper
|
|
5283
|
+
static StreamCompressorHelper K_UNIQUE_NAME(CreateCompressorHelper)((Type), K_UNIQUE_NAME(CreateCompressor))
|
|
5293
5284
|
|
|
5294
5285
|
bool SpliceStream(StreamReader *reader, int64_t max_len, StreamWriter *writer, Span<uint8_t> buf,
|
|
5295
5286
|
FunctionRef<void(int64_t, int64_t)> progress = [](int64_t, int64_t) {});
|
|
@@ -5322,7 +5313,7 @@ struct IniProperty {
|
|
|
5322
5313
|
};
|
|
5323
5314
|
|
|
5324
5315
|
class IniParser {
|
|
5325
|
-
|
|
5316
|
+
K_DELETE_COPY(IniParser)
|
|
5326
5317
|
|
|
5327
5318
|
HeapArray<char> current_section;
|
|
5328
5319
|
|
|
@@ -5362,7 +5353,7 @@ struct AssetInfo {
|
|
|
5362
5353
|
CompressionType compression_type;
|
|
5363
5354
|
Span<const uint8_t> data;
|
|
5364
5355
|
|
|
5365
|
-
|
|
5356
|
+
K_HASHTABLE_HANDLER(AssetInfo, name);
|
|
5366
5357
|
};
|
|
5367
5358
|
|
|
5368
5359
|
#if defined(FELIX_HOT_ASSETS)
|
|
@@ -5415,6 +5406,29 @@ Span<const uint8_t> PatchFile(const AssetInfo &asset, Allocator *alloc,
|
|
|
5415
5406
|
Span<const char> PatchFile(Span<const char> data, Allocator *alloc,
|
|
5416
5407
|
FunctionRef<void(Span<const char> key, StreamWriter *)> func);
|
|
5417
5408
|
|
|
5409
|
+
// ------------------------------------------------------------------------
|
|
5410
|
+
// Translations
|
|
5411
|
+
// ------------------------------------------------------------------------
|
|
5412
|
+
|
|
5413
|
+
struct TranslationTable {
|
|
5414
|
+
struct Pair {
|
|
5415
|
+
const char *key;
|
|
5416
|
+
const char *value;
|
|
5417
|
+
};
|
|
5418
|
+
|
|
5419
|
+
const char *language;
|
|
5420
|
+
Span<Pair> messages;
|
|
5421
|
+
|
|
5422
|
+
K_HASHTABLE_HANDLER(TranslationTable, language);
|
|
5423
|
+
};
|
|
5424
|
+
|
|
5425
|
+
extern "C" const Span<const TranslationTable> TranslationTables;
|
|
5426
|
+
|
|
5427
|
+
void InitLocales(Span<const TranslationTable> tables);
|
|
5428
|
+
|
|
5429
|
+
// Resets the localgale to the process default if lang is NULL or is unknown
|
|
5430
|
+
void ChangeThreadLocale(const char *name);
|
|
5431
|
+
|
|
5418
5432
|
// ------------------------------------------------------------------------
|
|
5419
5433
|
// Options
|
|
5420
5434
|
// ------------------------------------------------------------------------
|
|
@@ -5437,7 +5451,7 @@ enum class OptionType {
|
|
|
5437
5451
|
};
|
|
5438
5452
|
|
|
5439
5453
|
class OptionParser {
|
|
5440
|
-
|
|
5454
|
+
K_DELETE_COPY(OptionParser)
|
|
5441
5455
|
|
|
5442
5456
|
Span<const char *> args;
|
|
5443
5457
|
OptionMode mode;
|
|
@@ -5516,6 +5530,8 @@ bool OptionToEnum(Span<const OptionDesc> options, Span<const char> str, T *out_v
|
|
|
5516
5530
|
template <typename T>
|
|
5517
5531
|
bool OptionToEnumI(Span<const char *const> options, Span<const char> str, T *out_value)
|
|
5518
5532
|
{
|
|
5533
|
+
static_assert(std::is_enum<T>::value);
|
|
5534
|
+
|
|
5519
5535
|
for (Size i = 0; i < options.len; i++) {
|
|
5520
5536
|
const char *opt = options[i];
|
|
5521
5537
|
|
|
@@ -5531,6 +5547,8 @@ bool OptionToEnumI(Span<const char *const> options, Span<const char> str, T *out
|
|
|
5531
5547
|
template <typename T>
|
|
5532
5548
|
bool OptionToEnumI(Span<const OptionDesc> options, Span<const char> str, T *out_value)
|
|
5533
5549
|
{
|
|
5550
|
+
static_assert(std::is_enum<T>::value);
|
|
5551
|
+
|
|
5534
5552
|
for (Size i = 0; i < options.len; i++) {
|
|
5535
5553
|
const OptionDesc &desc = options[i];
|
|
5536
5554
|
|
|
@@ -5631,7 +5649,7 @@ class ConsolePrompter {
|
|
|
5631
5649
|
#endif
|
|
5632
5650
|
|
|
5633
5651
|
public:
|
|
5634
|
-
const char *prompt = ">>>
|
|
5652
|
+
const char *prompt = ">>>";
|
|
5635
5653
|
const char *mask = nullptr;
|
|
5636
5654
|
|
|
5637
5655
|
HeapArray<char> str;
|
|
@@ -5667,8 +5685,6 @@ private:
|
|
|
5667
5685
|
Vec2<int> GetConsoleSize();
|
|
5668
5686
|
int32_t ReadChar();
|
|
5669
5687
|
|
|
5670
|
-
int ComputeWidth(Span<const char> str);
|
|
5671
|
-
|
|
5672
5688
|
void EnsureNulTermination();
|
|
5673
5689
|
};
|
|
5674
5690
|
|
|
@@ -5691,7 +5707,118 @@ bool CanCompressFile(const char *filename);
|
|
|
5691
5707
|
// Unicode
|
|
5692
5708
|
// ------------------------------------------------------------------------
|
|
5693
5709
|
|
|
5694
|
-
int
|
|
5710
|
+
static inline int CountUtf8Bytes(char c)
|
|
5711
|
+
{
|
|
5712
|
+
int ones = CountLeadingZeros((uint32_t)~c << 24);
|
|
5713
|
+
return std::min(std::max(ones, 1), 4);
|
|
5714
|
+
}
|
|
5715
|
+
|
|
5716
|
+
static constexpr inline Size DecodeUtf8(const char *str, int32_t *out_c)
|
|
5717
|
+
{
|
|
5718
|
+
K_ASSERT(str[0]);
|
|
5719
|
+
|
|
5720
|
+
#define BYTE(Idx) ((uint8_t)str[Idx])
|
|
5721
|
+
|
|
5722
|
+
if (BYTE(0) < 0x80) {
|
|
5723
|
+
*out_c = BYTE(0);
|
|
5724
|
+
return 1;
|
|
5725
|
+
} else if (BYTE(0) - 0xC2 > 0xF4 - 0xC2) [[unlikely]] {
|
|
5726
|
+
return 0;
|
|
5727
|
+
} else if (BYTE(1)) [[likely]] {
|
|
5728
|
+
if (BYTE(0) < 0xE0 && (BYTE(1) & 0xC0) == 0x80) {
|
|
5729
|
+
*out_c = ((BYTE(0) & 0x1F) << 6) | (BYTE(1) & 0x3F);
|
|
5730
|
+
return 2;
|
|
5731
|
+
} else if (BYTE(2)) [[likely]] {
|
|
5732
|
+
if (BYTE(0) < 0xF0 &&
|
|
5733
|
+
(BYTE(1) & 0xC0) == 0x80 &&
|
|
5734
|
+
(BYTE(2) & 0xC0) == 0x80) {
|
|
5735
|
+
*out_c = ((BYTE(0) & 0xF) << 12) | ((BYTE(1) & 0x3F) << 6) | (BYTE(2) & 0x3F);
|
|
5736
|
+
return 3;
|
|
5737
|
+
} else if (BYTE(3)) [[likely]] {
|
|
5738
|
+
if ((BYTE(1) & 0xC0) == 0x80 &&
|
|
5739
|
+
(BYTE(2) & 0xC0) == 0x80 &&
|
|
5740
|
+
(BYTE(3) & 0xC0) == 0x80) {
|
|
5741
|
+
*out_c = ((BYTE(0) & 0x7) << 18) | ((BYTE(1) & 0x3F) << 12) | ((BYTE(2) & 0x3F) << 6) | (BYTE(3) & 0x3F);
|
|
5742
|
+
return 4;
|
|
5743
|
+
}
|
|
5744
|
+
}
|
|
5745
|
+
}
|
|
5746
|
+
}
|
|
5747
|
+
|
|
5748
|
+
#undef BYTE
|
|
5749
|
+
|
|
5750
|
+
return 0;
|
|
5751
|
+
}
|
|
5752
|
+
|
|
5753
|
+
static constexpr inline Size DecodeUtf8(Span<const char> str, Size offset, int32_t *out_c)
|
|
5754
|
+
{
|
|
5755
|
+
K_ASSERT(offset < str.len);
|
|
5756
|
+
|
|
5757
|
+
str = str.Take(offset, str.len - offset);
|
|
5758
|
+
|
|
5759
|
+
#define BYTE(Idx) ((uint8_t)str[Idx])
|
|
5760
|
+
|
|
5761
|
+
if (BYTE(0) < 0x80) {
|
|
5762
|
+
*out_c = BYTE(0);
|
|
5763
|
+
return 1;
|
|
5764
|
+
} else if (BYTE(0) - 0xC2 > 0xF4 - 0xC2) [[unlikely]] {
|
|
5765
|
+
return 0;
|
|
5766
|
+
} else if (BYTE(0) < 0xE0 && str.len >= 2 && (BYTE(1) & 0xC0) == 0x80) {
|
|
5767
|
+
*out_c = ((BYTE(0) & 0x1F) << 6) | (BYTE(1) & 0x3F);
|
|
5768
|
+
return 2;
|
|
5769
|
+
} else if (BYTE(0) < 0xF0 && str.len >= 3 && (BYTE(1) & 0xC0) == 0x80 &&
|
|
5770
|
+
(BYTE(2) & 0xC0) == 0x80) {
|
|
5771
|
+
*out_c = ((BYTE(0) & 0xF) << 12) | ((BYTE(1) & 0x3F) << 6) | (BYTE(2) & 0x3F);
|
|
5772
|
+
return 3;
|
|
5773
|
+
} else if (str.len >= 4 && (BYTE(1) & 0xC0) == 0x80 &&
|
|
5774
|
+
(BYTE(2) & 0xC0) == 0x80 &&
|
|
5775
|
+
(BYTE(3) & 0xC0) == 0x80) {
|
|
5776
|
+
*out_c = ((BYTE(0) & 0x7) << 18) | ((BYTE(1) & 0x3F) << 12) | ((BYTE(2) & 0x3F) << 6) | (BYTE(3) & 0x3F);
|
|
5777
|
+
return 4;
|
|
5778
|
+
} else {
|
|
5779
|
+
return 0;
|
|
5780
|
+
}
|
|
5781
|
+
|
|
5782
|
+
#undef BYTE
|
|
5783
|
+
}
|
|
5784
|
+
|
|
5785
|
+
static constexpr inline int32_t DecodeUtf8(const char *str)
|
|
5786
|
+
{
|
|
5787
|
+
int32_t uc = -1;
|
|
5788
|
+
DecodeUtf8(str, &uc);
|
|
5789
|
+
return uc;
|
|
5790
|
+
}
|
|
5791
|
+
|
|
5792
|
+
static inline Size EncodeUtf8(int32_t c, char out_buf[4])
|
|
5793
|
+
{
|
|
5794
|
+
if (c < 0x80) {
|
|
5795
|
+
out_buf[0] = (char)c;
|
|
5796
|
+
return 1;
|
|
5797
|
+
} else if (c < 0x800) {
|
|
5798
|
+
out_buf[0] = (char)(0xC0 | (c >> 6));
|
|
5799
|
+
out_buf[1] = (char)(0x80 | (c & 0x3F));
|
|
5800
|
+
return 2;
|
|
5801
|
+
} else if (c >= 0xD800 && c < 0xE000) {
|
|
5802
|
+
return 0;
|
|
5803
|
+
} else if (c < 0x10000) {
|
|
5804
|
+
out_buf[0] = (char)(0xE0 | (c >> 12));
|
|
5805
|
+
out_buf[1] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
5806
|
+
out_buf[2] = (char)(0x80 | (c & 0x3F));
|
|
5807
|
+
return 3;
|
|
5808
|
+
} else if (c < 0x110000) {
|
|
5809
|
+
out_buf[0] = (char)(0xF0 | (c >> 18));
|
|
5810
|
+
out_buf[1] = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
5811
|
+
out_buf[2] = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
5812
|
+
out_buf[3] = (char)(0x80 | (c & 0x3F));
|
|
5813
|
+
return 4;
|
|
5814
|
+
} else {
|
|
5815
|
+
return 0;
|
|
5816
|
+
}
|
|
5817
|
+
}
|
|
5818
|
+
|
|
5819
|
+
bool IsValidUtf8(Span<const char> str);
|
|
5820
|
+
|
|
5821
|
+
int ComputeUnicodeWidth(Span<const char> str);
|
|
5695
5822
|
|
|
5696
5823
|
bool IsXidStart(int32_t uc);
|
|
5697
5824
|
bool IsXidContinue(int32_t uc);
|