koffi 2.12.3 → 2.12.4
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 +6 -0
- 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/index.js +2 -2
- package/indirect.js +2 -2
- package/package.json +2 -2
- package/src/core/base/base.cc +395 -74
- package/src/core/base/base.hh +44 -11
- package/src/core/base/crc.inc +2232 -0
- package/src/core/base/crc_gen.py +109 -0
package/src/core/base/base.cc
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
// OTHER DEALINGS IN THE SOFTWARE.
|
|
21
21
|
|
|
22
22
|
#include "base.hh"
|
|
23
|
+
#include "crc.inc"
|
|
23
24
|
#include "unicode.inc"
|
|
24
25
|
|
|
25
26
|
#if __has_include("vendor/dragonbox/include/dragonbox/dragonbox.h")
|
|
@@ -1855,6 +1856,35 @@ void FmtLowerAscii::Format(FunctionRef<void(Span<const char>)> append) const
|
|
|
1855
1856
|
}
|
|
1856
1857
|
}
|
|
1857
1858
|
|
|
1859
|
+
void FmtEscape::Format(FunctionRef<void(Span<const char>)> append) const
|
|
1860
|
+
{
|
|
1861
|
+
static const char literals[] = "0123456789ABCDEF";
|
|
1862
|
+
|
|
1863
|
+
for (char c: str) {
|
|
1864
|
+
if (c >= 32 && (unsigned int)c < 128) {
|
|
1865
|
+
append(c);
|
|
1866
|
+
} else {
|
|
1867
|
+
switch (c) {
|
|
1868
|
+
case '\t': { append('\t'); } break;
|
|
1869
|
+
case '\r': { append("\r"); } break;
|
|
1870
|
+
case '\n': { append("\n"); } break;
|
|
1871
|
+
|
|
1872
|
+
default: {
|
|
1873
|
+
char encoded[4];
|
|
1874
|
+
|
|
1875
|
+
encoded[0] = '\\';
|
|
1876
|
+
encoded[1] = 'x';
|
|
1877
|
+
encoded[2] = literals[((uint8_t)c >> 4) & 0xF];
|
|
1878
|
+
encoded[3] = literals[((uint8_t)c >> 0) & 0xF];
|
|
1879
|
+
|
|
1880
|
+
Span<const char> buf = MakeSpan(encoded, 4);
|
|
1881
|
+
append(buf);
|
|
1882
|
+
} break;
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1858
1888
|
void FmtUrlSafe::Format(FunctionRef<void(Span<const char>)> append) const
|
|
1859
1889
|
{
|
|
1860
1890
|
static const char literals[] = "0123456789ABCDEF";
|
|
@@ -4474,14 +4504,44 @@ bool SpliceFile(int src_fd, const char *src_filename, int64_t src_offset,
|
|
|
4474
4504
|
int64_t max = size;
|
|
4475
4505
|
progress(0, max);
|
|
4476
4506
|
|
|
4477
|
-
#if defined(__linux__) || defined(__FreeBSD__)
|
|
4478
4507
|
// Try copy_file_range() if available
|
|
4508
|
+
#if defined(SYS_copy_file_range)
|
|
4509
|
+
{
|
|
4510
|
+
bool first = true;
|
|
4511
|
+
|
|
4512
|
+
while (size) {
|
|
4513
|
+
// glibc < 2.27 doesn't define copy_file_range
|
|
4514
|
+
|
|
4515
|
+
size_t count = (size_t)std::min(size, (int64_t)Mebibytes(64));
|
|
4516
|
+
ssize_t ret = syscall(SYS_copy_file_range, src_fd, (off_t *)&src_offset, dest_fd, (off_t *)&dest_offset, count, 0u);
|
|
4517
|
+
|
|
4518
|
+
if (ret < 0) {
|
|
4519
|
+
if (first && errno == EXDEV)
|
|
4520
|
+
goto xdev;
|
|
4521
|
+
if (errno == EINTR)
|
|
4522
|
+
continue;
|
|
4523
|
+
|
|
4524
|
+
LogError("Failed to copy '%1' to '%2': %3", src_filename, dest_filename, strerror(errno));
|
|
4525
|
+
return false;
|
|
4526
|
+
}
|
|
4527
|
+
|
|
4528
|
+
first = false;
|
|
4529
|
+
size -= ret;
|
|
4530
|
+
|
|
4531
|
+
progress(max - size, max);
|
|
4532
|
+
}
|
|
4533
|
+
|
|
4534
|
+
return true;
|
|
4535
|
+
}
|
|
4536
|
+
|
|
4537
|
+
xdev:
|
|
4538
|
+
#elif defined(__FreeBSD__)
|
|
4479
4539
|
{
|
|
4480
4540
|
bool first = true;
|
|
4481
4541
|
|
|
4482
4542
|
while (size) {
|
|
4483
4543
|
size_t count = (size_t)std::min(size, (int64_t)Mebibytes(64));
|
|
4484
|
-
ssize_t ret = copy_file_range(src_fd, (off_t *)&src_offset, dest_fd, (off_t *)&dest_offset, count,
|
|
4544
|
+
ssize_t ret = copy_file_range(src_fd, (off_t *)&src_offset, dest_fd, (off_t *)&dest_offset, count, 0u);
|
|
4485
4545
|
|
|
4486
4546
|
if (ret < 0) {
|
|
4487
4547
|
if (first && errno == EXDEV)
|
|
@@ -5964,16 +6024,12 @@ const char *GetTemporaryDirectory()
|
|
|
5964
6024
|
|
|
5965
6025
|
#endif
|
|
5966
6026
|
|
|
5967
|
-
const char *FindConfigFile(Span<const char *const> names,
|
|
5968
|
-
HeapArray<const char *> *out_possibilities)
|
|
6027
|
+
const char *FindConfigFile(const char *directory, Span<const char *const> names,
|
|
6028
|
+
Allocator *alloc, HeapArray<const char *> *out_possibilities)
|
|
5969
6029
|
{
|
|
5970
|
-
|
|
5971
|
-
[](const char *name, Allocator *alloc) {
|
|
5972
|
-
Span<const char> dir = GetApplicationDirectory();
|
|
6030
|
+
RG_ASSERT(!directory || directory[0]);
|
|
5973
6031
|
|
|
5974
|
-
|
|
5975
|
-
return filename;
|
|
5976
|
-
},
|
|
6032
|
+
decltype(GetUserConfigPath) *funcs[] = {
|
|
5977
6033
|
GetUserConfigPath,
|
|
5978
6034
|
#if !defined(_WIN32)
|
|
5979
6035
|
GetSystemConfigPath
|
|
@@ -5982,19 +6038,46 @@ const char *FindConfigFile(Span<const char *const> names, Allocator *alloc,
|
|
|
5982
6038
|
|
|
5983
6039
|
const char *filename = nullptr;
|
|
5984
6040
|
|
|
5985
|
-
|
|
6041
|
+
// Try application directory
|
|
6042
|
+
for (const char *name: names) {
|
|
6043
|
+
Span<const char> dir = GetApplicationDirectory();
|
|
6044
|
+
const char *path = Fmt(alloc, "%1%/%2", dir, name).ptr;
|
|
6045
|
+
|
|
6046
|
+
if (!filename && TestFile(path, FileType::File)) {
|
|
6047
|
+
filename = path;
|
|
6048
|
+
}
|
|
6049
|
+
if (out_possibilities) {
|
|
6050
|
+
out_possibilities->Append(path);
|
|
6051
|
+
}
|
|
6052
|
+
}
|
|
6053
|
+
|
|
6054
|
+
LocalArray<const char *, 8> tests;
|
|
6055
|
+
{
|
|
6056
|
+
RG_ASSERT(names.len <= tests.Available());
|
|
6057
|
+
|
|
5986
6058
|
for (const char *name: names) {
|
|
5987
|
-
|
|
6059
|
+
if (directory) {
|
|
6060
|
+
const char *test = Fmt(alloc, "%1%/%2", directory, name).ptr;
|
|
6061
|
+
tests.Append(test);
|
|
6062
|
+
} else {
|
|
6063
|
+
tests.Append(name);
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6067
|
+
|
|
6068
|
+
// Try standard paths
|
|
6069
|
+
for (const auto &func: funcs) {
|
|
6070
|
+
for (const char *test: tests) {
|
|
6071
|
+
const char *path = func(test, alloc);
|
|
5988
6072
|
|
|
5989
6073
|
if (!path)
|
|
5990
6074
|
continue;
|
|
5991
6075
|
|
|
5992
|
-
if (TestFile(path, FileType::File)) {
|
|
6076
|
+
if (!filename && TestFile(path, FileType::File)) {
|
|
5993
6077
|
filename = path;
|
|
5994
6078
|
}
|
|
5995
6079
|
if (out_possibilities) {
|
|
5996
6080
|
out_possibilities->Append(path);
|
|
5997
|
-
break;
|
|
5998
6081
|
}
|
|
5999
6082
|
}
|
|
6000
6083
|
}
|
|
@@ -9083,8 +9166,10 @@ bool ConsolePrompter::Read(Span<const char> *out_str)
|
|
|
9083
9166
|
}
|
|
9084
9167
|
}
|
|
9085
9168
|
|
|
9086
|
-
|
|
9169
|
+
Size ConsolePrompter::ReadEnum(Span<const PromptChoice> choices, Size value)
|
|
9087
9170
|
{
|
|
9171
|
+
RG_ASSERT(value < choices.len);
|
|
9172
|
+
|
|
9088
9173
|
#if !defined(_WIN32) && !defined(__wasm__)
|
|
9089
9174
|
struct sigaction old_sa;
|
|
9090
9175
|
IgnoreSigWinch(&old_sa);
|
|
@@ -9097,9 +9182,9 @@ bool ConsolePrompter::ReadYN(bool *out_value)
|
|
|
9097
9182
|
DisableRawMode();
|
|
9098
9183
|
};
|
|
9099
9184
|
|
|
9100
|
-
return
|
|
9185
|
+
return ReadRawEnum(choices, value);
|
|
9101
9186
|
} else {
|
|
9102
|
-
return
|
|
9187
|
+
return ReadBufferedEnum(choices);
|
|
9103
9188
|
}
|
|
9104
9189
|
}
|
|
9105
9190
|
|
|
@@ -9126,8 +9211,8 @@ bool ConsolePrompter::ReadRaw(Span<const char> *out_str)
|
|
|
9126
9211
|
StdErr->Flush();
|
|
9127
9212
|
|
|
9128
9213
|
prompt_columns = ComputeWidth(prompt);
|
|
9129
|
-
|
|
9130
9214
|
str_offset = str.len;
|
|
9215
|
+
|
|
9131
9216
|
RenderRaw();
|
|
9132
9217
|
|
|
9133
9218
|
int32_t uc;
|
|
@@ -9350,18 +9435,13 @@ bool ConsolePrompter::ReadRaw(Span<const char> *out_str)
|
|
|
9350
9435
|
return true;
|
|
9351
9436
|
}
|
|
9352
9437
|
|
|
9353
|
-
|
|
9438
|
+
Size ConsolePrompter::ReadRawEnum(Span<const PromptChoice> choices, Size value)
|
|
9354
9439
|
{
|
|
9355
|
-
const char *yn = "[Y/N]";
|
|
9356
|
-
|
|
9357
9440
|
StdErr->Flush();
|
|
9358
9441
|
|
|
9359
|
-
prompt_columns =
|
|
9360
|
-
|
|
9361
|
-
str.RemoveFrom(0);
|
|
9362
|
-
str_offset = 0;
|
|
9442
|
+
prompt_columns = 0;
|
|
9443
|
+
FormatChoices(choices, value);
|
|
9363
9444
|
RenderRaw();
|
|
9364
|
-
Print(StdErr, "%!D..%1%!0 ", yn);
|
|
9365
9445
|
|
|
9366
9446
|
int32_t uc;
|
|
9367
9447
|
while ((uc = ReadChar()) >= 0) {
|
|
@@ -9372,36 +9452,86 @@ bool ConsolePrompter::ReadRawYN(bool *out_value)
|
|
|
9372
9452
|
}
|
|
9373
9453
|
|
|
9374
9454
|
switch (uc) {
|
|
9375
|
-
case
|
|
9376
|
-
|
|
9377
|
-
StdErr->Flush();
|
|
9455
|
+
case 0x1B: {
|
|
9456
|
+
LocalArray<char, 16> buf;
|
|
9378
9457
|
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9458
|
+
const auto match_escape = [&](const char *seq) {
|
|
9459
|
+
RG_ASSERT(strlen(seq) < RG_SIZE(buf.data));
|
|
9460
|
+
|
|
9461
|
+
for (Size i = 0; seq[i]; i++) {
|
|
9462
|
+
if (i >= buf.len) {
|
|
9463
|
+
uc = ReadChar();
|
|
9464
|
+
|
|
9465
|
+
if (uc >= 128) {
|
|
9466
|
+
// Got some kind of non-ASCII character, make sure nothing else matches
|
|
9467
|
+
buf.Append(0);
|
|
9468
|
+
return false;
|
|
9469
|
+
}
|
|
9470
|
+
|
|
9471
|
+
buf.Append((char)uc);
|
|
9472
|
+
}
|
|
9473
|
+
if (buf[i] != seq[i])
|
|
9474
|
+
return false;
|
|
9475
|
+
}
|
|
9476
|
+
|
|
9477
|
+
return true;
|
|
9478
|
+
};
|
|
9479
|
+
|
|
9480
|
+
if (match_escape("[A")) { // Up
|
|
9481
|
+
fake_input = "\x10";
|
|
9482
|
+
} else if (match_escape("[B")) { // Down
|
|
9483
|
+
fake_input = "\x0E";
|
|
9484
|
+
}
|
|
9383
9485
|
} break;
|
|
9384
9486
|
|
|
9385
|
-
case
|
|
9386
|
-
case
|
|
9387
|
-
|
|
9487
|
+
case 0x3: // Ctrl-C
|
|
9488
|
+
case 0x4: { // Ctrl-D
|
|
9489
|
+
if (rows > y) {
|
|
9490
|
+
Print(StdErr, "\x1B[%1B", rows - y);
|
|
9491
|
+
}
|
|
9492
|
+
StdErr->Write("\r");
|
|
9388
9493
|
StdErr->Flush();
|
|
9389
9494
|
|
|
9390
|
-
|
|
9391
|
-
|
|
9495
|
+
return -1;
|
|
9496
|
+
} break;
|
|
9497
|
+
|
|
9498
|
+
case 0xE: { // Down
|
|
9499
|
+
if (value + 1 < choices.len) {
|
|
9500
|
+
FormatChoices(choices, ++value);
|
|
9501
|
+
RenderRaw();
|
|
9502
|
+
}
|
|
9503
|
+
} break;
|
|
9504
|
+
case 0x10: { // Up
|
|
9505
|
+
if (value > 0) {
|
|
9506
|
+
FormatChoices(choices, --value);
|
|
9507
|
+
RenderRaw();
|
|
9508
|
+
}
|
|
9392
9509
|
} break;
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9510
|
+
|
|
9511
|
+
default: {
|
|
9512
|
+
const auto it = std::find_if(choices.begin(), choices.end(),
|
|
9513
|
+
[&](const PromptChoice &choice) { return choice.c == uc; });
|
|
9514
|
+
if (it == choices.end())
|
|
9515
|
+
break;
|
|
9516
|
+
value = it - choices.begin();
|
|
9517
|
+
} [[fallthrough]];
|
|
9518
|
+
|
|
9519
|
+
case '\r':
|
|
9520
|
+
case '\n': {
|
|
9521
|
+
str.RemoveFrom(0);
|
|
9522
|
+
str.Append(choices[value].str);
|
|
9523
|
+
str_offset = str.len;
|
|
9524
|
+
RenderRaw();
|
|
9525
|
+
|
|
9526
|
+
StdErr->Write("\r\n");
|
|
9396
9527
|
StdErr->Flush();
|
|
9397
9528
|
|
|
9398
|
-
|
|
9399
|
-
return true;
|
|
9529
|
+
return value;
|
|
9400
9530
|
} break;
|
|
9401
9531
|
}
|
|
9402
9532
|
}
|
|
9403
9533
|
|
|
9404
|
-
return
|
|
9534
|
+
return -1;
|
|
9405
9535
|
}
|
|
9406
9536
|
|
|
9407
9537
|
bool ConsolePrompter::ReadBuffered(Span<const char> *out_str)
|
|
@@ -9430,41 +9560,43 @@ bool ConsolePrompter::ReadBuffered(Span<const char> *out_str)
|
|
|
9430
9560
|
return false;
|
|
9431
9561
|
}
|
|
9432
9562
|
|
|
9433
|
-
|
|
9563
|
+
Size ConsolePrompter::ReadBufferedEnum(Span<const PromptChoice> choices)
|
|
9434
9564
|
{
|
|
9435
|
-
const char
|
|
9565
|
+
static const Span<const char> prefix = "Input your choice: ";
|
|
9436
9566
|
|
|
9437
|
-
prompt_columns =
|
|
9567
|
+
prompt_columns = 0;
|
|
9568
|
+
FormatChoices(choices, 0);
|
|
9569
|
+
RenderBuffered();
|
|
9438
9570
|
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
str_offset = 0;
|
|
9442
|
-
RenderBuffered();
|
|
9443
|
-
Print(StdErr, "%1 ", yn);
|
|
9571
|
+
Print(StdErr, "\n%1", prefix);
|
|
9572
|
+
StdErr->Flush();
|
|
9444
9573
|
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9574
|
+
do {
|
|
9575
|
+
uint8_t c = 0;
|
|
9576
|
+
if (StdIn->Read(1, &c) < 0)
|
|
9577
|
+
return -1;
|
|
9449
9578
|
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
break;
|
|
9459
|
-
}
|
|
9460
|
-
} else if (c >= 32 || c == '\t') {
|
|
9461
|
-
str.Append((char)c);
|
|
9579
|
+
if (c == '\n') {
|
|
9580
|
+
Span<const char> end = TrimStr(SplitStrReverse(str, '\n'));
|
|
9581
|
+
|
|
9582
|
+
if (end.len == 1) {
|
|
9583
|
+
const auto it = std::find_if(choices.begin(), choices.end(),
|
|
9584
|
+
[&](const PromptChoice &choice) { return choice.c == end[0]; });
|
|
9585
|
+
if (it != choices.end())
|
|
9586
|
+
return it - choices.ptr;
|
|
9462
9587
|
}
|
|
9588
|
+
|
|
9589
|
+
str.RemoveFrom(end.ptr - str.ptr);
|
|
9590
|
+
|
|
9591
|
+
StdErr->Write(prefix);
|
|
9592
|
+
StdErr->Flush();
|
|
9593
|
+
} else if (c >= 32 || c == '\t') {
|
|
9594
|
+
str.Append((char)c);
|
|
9463
9595
|
}
|
|
9464
|
-
}
|
|
9596
|
+
} while (!StdIn->IsEOF());
|
|
9465
9597
|
|
|
9466
9598
|
// EOF
|
|
9467
|
-
return
|
|
9599
|
+
return -1;
|
|
9468
9600
|
}
|
|
9469
9601
|
|
|
9470
9602
|
void ConsolePrompter::ChangeEntry(Size new_idx)
|
|
@@ -9548,6 +9680,27 @@ void ConsolePrompter::Delete(Size start, Size end)
|
|
|
9548
9680
|
}
|
|
9549
9681
|
}
|
|
9550
9682
|
|
|
9683
|
+
void ConsolePrompter::FormatChoices(Span<const PromptChoice> choices, Size value)
|
|
9684
|
+
{
|
|
9685
|
+
int align = 0;
|
|
9686
|
+
|
|
9687
|
+
for (const PromptChoice &choice: choices) {
|
|
9688
|
+
align = std::max(align, (int)strlen(choice.str));
|
|
9689
|
+
}
|
|
9690
|
+
|
|
9691
|
+
str.RemoveFrom(0);
|
|
9692
|
+
str.Append('\n');
|
|
9693
|
+
for (Size i = 0; i < choices.len; i++) {
|
|
9694
|
+
const PromptChoice &choice = choices[i];
|
|
9695
|
+
|
|
9696
|
+
Fmt(&str, " [%1] %2 ", choice.c, FmtArg(choice.str).Pad(align));
|
|
9697
|
+
if (i == value) {
|
|
9698
|
+
str_offset = str.len;
|
|
9699
|
+
}
|
|
9700
|
+
str.Append('\n');
|
|
9701
|
+
}
|
|
9702
|
+
}
|
|
9703
|
+
|
|
9551
9704
|
void ConsolePrompter::RenderRaw()
|
|
9552
9705
|
{
|
|
9553
9706
|
columns = GetConsoleSize().x;
|
|
@@ -9580,7 +9733,7 @@ void ConsolePrompter::RenderRaw()
|
|
|
9580
9733
|
int width = mask ? mask_columns : ComputeWidth(str.Take(i, bytes));
|
|
9581
9734
|
|
|
9582
9735
|
if (x2 + width >= columns || str[i] == '\n') {
|
|
9583
|
-
FmtArg prefix = FmtArg(
|
|
9736
|
+
FmtArg prefix = FmtArg(' ').Repeat(prompt_columns - 1);
|
|
9584
9737
|
Print(StdErr, "\x1B[0K\r\n%!D.+%1%!0 %!..+", prefix);
|
|
9585
9738
|
|
|
9586
9739
|
x2 = prompt_columns;
|
|
@@ -9624,8 +9777,10 @@ void ConsolePrompter::RenderBuffered()
|
|
|
9624
9777
|
Print(StdErr, "%1%2", prompt, line);
|
|
9625
9778
|
while (remain.len) {
|
|
9626
9779
|
line = SplitStr(remain, '\n', &remain);
|
|
9627
|
-
Print(StdErr, "\n%1
|
|
9780
|
+
Print(StdErr, "\n%1%2", FmtArg(' ').Repeat(prompt_columns), line);
|
|
9628
9781
|
}
|
|
9782
|
+
|
|
9783
|
+
StdErr->Flush();
|
|
9629
9784
|
}
|
|
9630
9785
|
|
|
9631
9786
|
Vec2<int> ConsolePrompter::GetConsoleSize()
|
|
@@ -9831,12 +9986,42 @@ const char *Prompt(const char *prompt, const char *default_value, const char *ma
|
|
|
9831
9986
|
return str;
|
|
9832
9987
|
}
|
|
9833
9988
|
|
|
9834
|
-
|
|
9989
|
+
Size PromptEnum(const char *prompt, Span<const PromptChoice> choices, Size value)
|
|
9835
9990
|
{
|
|
9991
|
+
#if defined(RG_DEBUG)
|
|
9992
|
+
{
|
|
9993
|
+
HashSet<char> keys;
|
|
9994
|
+
|
|
9995
|
+
for (const PromptChoice &choice: choices) {
|
|
9996
|
+
keys.Set(choice.c);
|
|
9997
|
+
}
|
|
9998
|
+
|
|
9999
|
+
bool duplicates = (keys.table.count < choices.len);
|
|
10000
|
+
RG_ASSERT(!duplicates);
|
|
10001
|
+
}
|
|
10002
|
+
#endif
|
|
10003
|
+
|
|
9836
10004
|
ConsolePrompter prompter;
|
|
9837
10005
|
prompter.prompt = prompt;
|
|
9838
10006
|
|
|
9839
|
-
return prompter.
|
|
10007
|
+
return prompter.ReadEnum(choices, value);
|
|
10008
|
+
}
|
|
10009
|
+
|
|
10010
|
+
Size PromptEnum(const char *prompt, Span<const char *const> strings, Size value)
|
|
10011
|
+
{
|
|
10012
|
+
static const char literals[] = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
10013
|
+
RG_ASSERT(strings.len <= RG_LEN(literals));
|
|
10014
|
+
|
|
10015
|
+
HeapArray<PromptChoice> choices;
|
|
10016
|
+
|
|
10017
|
+
for (Size i = 0; i < strings.len; i++) {
|
|
10018
|
+
const char *str = strings[i];
|
|
10019
|
+
PromptChoice choice = { literals[i], str };
|
|
10020
|
+
|
|
10021
|
+
choices.Append(choice);
|
|
10022
|
+
}
|
|
10023
|
+
|
|
10024
|
+
return PromptEnum(prompt, choices, value);
|
|
9840
10025
|
}
|
|
9841
10026
|
|
|
9842
10027
|
// ------------------------------------------------------------------------
|
|
@@ -9972,4 +10157,140 @@ bool IsXidContinue(int32_t uc)
|
|
|
9972
10157
|
return false;
|
|
9973
10158
|
}
|
|
9974
10159
|
|
|
10160
|
+
// ------------------------------------------------------------------------
|
|
10161
|
+
// CRC
|
|
10162
|
+
// ------------------------------------------------------------------------
|
|
10163
|
+
|
|
10164
|
+
uint32_t CRC32(uint32_t state, Span<const uint8_t> buf)
|
|
10165
|
+
{
|
|
10166
|
+
state = ~state;
|
|
10167
|
+
|
|
10168
|
+
Size right = buf.len & (RG_SIZE_MAX - 3);
|
|
10169
|
+
|
|
10170
|
+
for (Size i = 0; i < right; i += 4) {
|
|
10171
|
+
state = (state >> 8) ^ Crc32Table[(state ^ buf[i + 0]) & 0xFF];
|
|
10172
|
+
state = (state >> 8) ^ Crc32Table[(state ^ buf[i + 1]) & 0xFF];
|
|
10173
|
+
state = (state >> 8) ^ Crc32Table[(state ^ buf[i + 2]) & 0xFF];
|
|
10174
|
+
state = (state >> 8) ^ Crc32Table[(state ^ buf[i + 3]) & 0xFF];
|
|
10175
|
+
}
|
|
10176
|
+
for (Size i = right; i < buf.len; i++) {
|
|
10177
|
+
state = (state >> 8) ^ Crc32Table[(state ^ buf[i]) & 0xFF];
|
|
10178
|
+
}
|
|
10179
|
+
|
|
10180
|
+
return ~state;
|
|
10181
|
+
}
|
|
10182
|
+
|
|
10183
|
+
uint32_t CRC32C(uint32_t state, Span<const uint8_t> buf)
|
|
10184
|
+
{
|
|
10185
|
+
state = ~state;
|
|
10186
|
+
|
|
10187
|
+
Size right = buf.len & (RG_SIZE_MAX - 3);
|
|
10188
|
+
|
|
10189
|
+
for (Size i = 0; i < right; i += 4) {
|
|
10190
|
+
state = (state >> 8) ^ Crc32CTable[(state ^ buf[i + 0]) & 0xFF];
|
|
10191
|
+
state = (state >> 8) ^ Crc32CTable[(state ^ buf[i + 1]) & 0xFF];
|
|
10192
|
+
state = (state >> 8) ^ Crc32CTable[(state ^ buf[i + 2]) & 0xFF];
|
|
10193
|
+
state = (state >> 8) ^ Crc32CTable[(state ^ buf[i + 3]) & 0xFF];
|
|
10194
|
+
}
|
|
10195
|
+
for (Size i = right; i < buf.len; i++) {
|
|
10196
|
+
state = (state >> 8) ^ Crc32CTable[(state ^ buf[i]) & 0xFF];
|
|
10197
|
+
}
|
|
10198
|
+
|
|
10199
|
+
return ~state;
|
|
10200
|
+
}
|
|
10201
|
+
|
|
10202
|
+
static uint64_t XzUpdate1(uint64_t state, uint8_t byte)
|
|
10203
|
+
{
|
|
10204
|
+
uint64_t ret = (state >> 8) ^ Crc64XzTable0[byte ^ (uint8_t)state];
|
|
10205
|
+
return ret;
|
|
10206
|
+
}
|
|
10207
|
+
|
|
10208
|
+
static uint64_t XzUpdate16(uint64_t state, const uint8_t *bytes)
|
|
10209
|
+
{
|
|
10210
|
+
uint64_t ret = Crc64XzTable0[bytes[15]] ^
|
|
10211
|
+
Crc64XzTable1[bytes[14]] ^
|
|
10212
|
+
Crc64XzTable2[bytes[13]] ^
|
|
10213
|
+
Crc64XzTable3[bytes[12]] ^
|
|
10214
|
+
Crc64XzTable4[bytes[11]] ^
|
|
10215
|
+
Crc64XzTable5[bytes[10]] ^
|
|
10216
|
+
Crc64XzTable6[bytes[9]] ^
|
|
10217
|
+
Crc64XzTable7[bytes[8]] ^
|
|
10218
|
+
Crc64XzTable8[bytes[7] ^ (uint8_t)(state >> 56)] ^
|
|
10219
|
+
Crc64XzTable9[bytes[6] ^ (uint8_t)(state >> 48)] ^
|
|
10220
|
+
Crc64XzTable10[bytes[5] ^ (uint8_t)(state >> 40)] ^
|
|
10221
|
+
Crc64XzTable11[bytes[4] ^ (uint8_t)(state >> 32)] ^
|
|
10222
|
+
Crc64XzTable12[bytes[3] ^ (uint8_t)(state >> 24)] ^
|
|
10223
|
+
Crc64XzTable13[bytes[2] ^ (uint8_t)(state >> 16)] ^
|
|
10224
|
+
Crc64XzTable14[bytes[1] ^ (uint8_t)(state >> 8)] ^
|
|
10225
|
+
Crc64XzTable15[bytes[0] ^ (uint8_t)(state >> 0)];
|
|
10226
|
+
return ret;
|
|
10227
|
+
}
|
|
10228
|
+
|
|
10229
|
+
uint64_t CRC64xz(uint64_t state, Span<const uint8_t> buf)
|
|
10230
|
+
{
|
|
10231
|
+
state = ~state;
|
|
10232
|
+
|
|
10233
|
+
Size left = std::min(buf.len, (Size)(AlignUp(buf.ptr, 16) - buf.ptr));
|
|
10234
|
+
Size right = std::max(left, (Size)(AlignDown(buf.end(), 16) - buf.ptr));
|
|
10235
|
+
|
|
10236
|
+
for (Size i = 0; i < left; i++) {
|
|
10237
|
+
state = XzUpdate1(state, buf[i]);
|
|
10238
|
+
}
|
|
10239
|
+
for (Size i = left; i < right; i += 16) {
|
|
10240
|
+
state = XzUpdate16(state, buf.ptr + i);
|
|
10241
|
+
}
|
|
10242
|
+
for (Size i = right; i < buf.len; i++) {
|
|
10243
|
+
state = XzUpdate1(state, buf[i]);
|
|
10244
|
+
}
|
|
10245
|
+
|
|
10246
|
+
return ~state;
|
|
10247
|
+
}
|
|
10248
|
+
|
|
10249
|
+
static uint64_t NvmeUpdate1(uint64_t state, uint8_t byte)
|
|
10250
|
+
{
|
|
10251
|
+
uint64_t ret = (state >> 8) ^ Crc64NvmeTable0[byte ^ (uint8_t)state];
|
|
10252
|
+
return ret;
|
|
10253
|
+
}
|
|
10254
|
+
|
|
10255
|
+
static uint64_t NvmeUpdate16(uint64_t state, const uint8_t *bytes)
|
|
10256
|
+
{
|
|
10257
|
+
uint64_t ret = Crc64NvmeTable0[bytes[15]] ^
|
|
10258
|
+
Crc64NvmeTable1[bytes[14]] ^
|
|
10259
|
+
Crc64NvmeTable2[bytes[13]] ^
|
|
10260
|
+
Crc64NvmeTable3[bytes[12]] ^
|
|
10261
|
+
Crc64NvmeTable4[bytes[11]] ^
|
|
10262
|
+
Crc64NvmeTable5[bytes[10]] ^
|
|
10263
|
+
Crc64NvmeTable6[bytes[9]] ^
|
|
10264
|
+
Crc64NvmeTable7[bytes[8]] ^
|
|
10265
|
+
Crc64NvmeTable8[bytes[7] ^ (uint8_t)(state >> 56)] ^
|
|
10266
|
+
Crc64NvmeTable9[bytes[6] ^ (uint8_t)(state >> 48)] ^
|
|
10267
|
+
Crc64NvmeTable10[bytes[5] ^ (uint8_t)(state >> 40)] ^
|
|
10268
|
+
Crc64NvmeTable11[bytes[4] ^ (uint8_t)(state >> 32)] ^
|
|
10269
|
+
Crc64NvmeTable12[bytes[3] ^ (uint8_t)(state >> 24)] ^
|
|
10270
|
+
Crc64NvmeTable13[bytes[2] ^ (uint8_t)(state >> 16)] ^
|
|
10271
|
+
Crc64NvmeTable14[bytes[1] ^ (uint8_t)(state >> 8)] ^
|
|
10272
|
+
Crc64NvmeTable15[bytes[0] ^ (uint8_t)(state >> 0)];
|
|
10273
|
+
return ret;
|
|
10274
|
+
}
|
|
10275
|
+
|
|
10276
|
+
uint64_t CRC64nvme(uint64_t state, Span<const uint8_t> buf)
|
|
10277
|
+
{
|
|
10278
|
+
state = ~state;
|
|
10279
|
+
|
|
10280
|
+
Size left = std::min(buf.len, (Size)(AlignUp(buf.ptr, 16) - buf.ptr));
|
|
10281
|
+
Size right = std::max(left, (Size)(AlignDown(buf.end(), 16) - buf.ptr));
|
|
10282
|
+
|
|
10283
|
+
for (Size i = 0; i < left; i++) {
|
|
10284
|
+
state = NvmeUpdate1(state, buf[i]);
|
|
10285
|
+
}
|
|
10286
|
+
for (Size i = left; i < right; i += 16) {
|
|
10287
|
+
state = NvmeUpdate16(state, buf.ptr + i);
|
|
10288
|
+
}
|
|
10289
|
+
for (Size i = right; i < buf.len; i++) {
|
|
10290
|
+
state = NvmeUpdate1(state, buf[i]);
|
|
10291
|
+
}
|
|
10292
|
+
|
|
10293
|
+
return ~state;
|
|
10294
|
+
}
|
|
10295
|
+
|
|
9975
10296
|
}
|