koffi 2.12.2 → 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 +16 -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.d.ts +226 -143
- package/index.js +9 -9
- package/indirect.js +9 -9
- package/package.json +2 -2
- package/src/core/base/base.cc +515 -78
- package/src/core/base/base.hh +56 -11
- package/src/core/base/crc.inc +2232 -0
- package/src/core/base/crc_gen.py +109 -0
- package/src/core/base/unicode.inc +426 -0
- package/src/core/{unicode/generate.py → base/unicode_gen.py} +84 -19
- package/src/koffi/CMakeLists.txt +0 -1
- package/src/koffi/src/ffi.cc +0 -1
- package/src/koffi/src/parser.cc +0 -1
- package/src/core/unicode/xid.cc +0 -52
- package/src/core/unicode/xid.hh +0 -29
- package/src/core/unicode/xid.inc +0 -465
package/src/core/base/base.cc
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
// OTHER DEALINGS IN THE SOFTWARE.
|
|
21
21
|
|
|
22
22
|
#include "base.hh"
|
|
23
|
+
#include "crc.inc"
|
|
24
|
+
#include "unicode.inc"
|
|
23
25
|
|
|
24
26
|
#if __has_include("vendor/dragonbox/include/dragonbox/dragonbox.h")
|
|
25
27
|
#include "vendor/dragonbox/include/dragonbox/dragonbox.h"
|
|
@@ -1854,6 +1856,35 @@ void FmtLowerAscii::Format(FunctionRef<void(Span<const char>)> append) const
|
|
|
1854
1856
|
}
|
|
1855
1857
|
}
|
|
1856
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
|
+
|
|
1857
1888
|
void FmtUrlSafe::Format(FunctionRef<void(Span<const char>)> append) const
|
|
1858
1889
|
{
|
|
1859
1890
|
static const char literals[] = "0123456789ABCDEF";
|
|
@@ -4473,14 +4504,44 @@ bool SpliceFile(int src_fd, const char *src_filename, int64_t src_offset,
|
|
|
4473
4504
|
int64_t max = size;
|
|
4474
4505
|
progress(0, max);
|
|
4475
4506
|
|
|
4476
|
-
#if defined(__linux__) || defined(__FreeBSD__)
|
|
4477
4507
|
// Try copy_file_range() if available
|
|
4508
|
+
#if defined(SYS_copy_file_range)
|
|
4478
4509
|
{
|
|
4479
4510
|
bool first = true;
|
|
4480
4511
|
|
|
4481
4512
|
while (size) {
|
|
4513
|
+
// glibc < 2.27 doesn't define copy_file_range
|
|
4514
|
+
|
|
4482
4515
|
size_t count = (size_t)std::min(size, (int64_t)Mebibytes(64));
|
|
4483
|
-
ssize_t ret =
|
|
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__)
|
|
4539
|
+
{
|
|
4540
|
+
bool first = true;
|
|
4541
|
+
|
|
4542
|
+
while (size) {
|
|
4543
|
+
size_t count = (size_t)std::min(size, (int64_t)Mebibytes(64));
|
|
4544
|
+
ssize_t ret = copy_file_range(src_fd, (off_t *)&src_offset, dest_fd, (off_t *)&dest_offset, count, 0u);
|
|
4484
4545
|
|
|
4485
4546
|
if (ret < 0) {
|
|
4486
4547
|
if (first && errno == EXDEV)
|
|
@@ -5963,16 +6024,12 @@ const char *GetTemporaryDirectory()
|
|
|
5963
6024
|
|
|
5964
6025
|
#endif
|
|
5965
6026
|
|
|
5966
|
-
const char *FindConfigFile(Span<const char *const> names,
|
|
5967
|
-
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)
|
|
5968
6029
|
{
|
|
5969
|
-
|
|
5970
|
-
[](const char *name, Allocator *alloc) {
|
|
5971
|
-
Span<const char> dir = GetApplicationDirectory();
|
|
6030
|
+
RG_ASSERT(!directory || directory[0]);
|
|
5972
6031
|
|
|
5973
|
-
|
|
5974
|
-
return filename;
|
|
5975
|
-
},
|
|
6032
|
+
decltype(GetUserConfigPath) *funcs[] = {
|
|
5976
6033
|
GetUserConfigPath,
|
|
5977
6034
|
#if !defined(_WIN32)
|
|
5978
6035
|
GetSystemConfigPath
|
|
@@ -5981,19 +6038,46 @@ const char *FindConfigFile(Span<const char *const> names, Allocator *alloc,
|
|
|
5981
6038
|
|
|
5982
6039
|
const char *filename = nullptr;
|
|
5983
6040
|
|
|
5984
|
-
|
|
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
|
+
|
|
5985
6058
|
for (const char *name: names) {
|
|
5986
|
-
|
|
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);
|
|
5987
6072
|
|
|
5988
6073
|
if (!path)
|
|
5989
6074
|
continue;
|
|
5990
6075
|
|
|
5991
|
-
if (TestFile(path, FileType::File)) {
|
|
6076
|
+
if (!filename && TestFile(path, FileType::File)) {
|
|
5992
6077
|
filename = path;
|
|
5993
6078
|
}
|
|
5994
6079
|
if (out_possibilities) {
|
|
5995
6080
|
out_possibilities->Append(path);
|
|
5996
|
-
break;
|
|
5997
6081
|
}
|
|
5998
6082
|
}
|
|
5999
6083
|
}
|
|
@@ -7555,6 +7639,8 @@ bool StreamReader::Rewind()
|
|
|
7555
7639
|
}
|
|
7556
7640
|
|
|
7557
7641
|
source.eof = false;
|
|
7642
|
+
raw_len = -1;
|
|
7643
|
+
raw_read = 0;
|
|
7558
7644
|
eof = false;
|
|
7559
7645
|
|
|
7560
7646
|
return true;
|
|
@@ -7992,6 +8078,59 @@ bool StreamWriter::Open(const std::function<bool(Span<const uint8_t>)> &func, co
|
|
|
7992
8078
|
return true;
|
|
7993
8079
|
}
|
|
7994
8080
|
|
|
8081
|
+
bool StreamWriter::Rewind()
|
|
8082
|
+
{
|
|
8083
|
+
if (error) [[unlikely]]
|
|
8084
|
+
return false;
|
|
8085
|
+
|
|
8086
|
+
if (encoder) [[unlikely]] {
|
|
8087
|
+
LogError("Cannot rewind stream with encoder");
|
|
8088
|
+
return false;
|
|
8089
|
+
}
|
|
8090
|
+
|
|
8091
|
+
switch (dest.type) {
|
|
8092
|
+
case DestinationType::Memory: { dest.u.mem.memory->RemoveFrom(dest.u.mem.start); } break;
|
|
8093
|
+
|
|
8094
|
+
case DestinationType::LineFile:
|
|
8095
|
+
case DestinationType::BufferedFile:
|
|
8096
|
+
case DestinationType::DirectFile: {
|
|
8097
|
+
if (lseek(dest.u.file.fd, 0, SEEK_SET) < 0) {
|
|
8098
|
+
LogError("Failed to rewind '%1': %2", filename, strerror(errno));
|
|
8099
|
+
error = true;
|
|
8100
|
+
return false;
|
|
8101
|
+
}
|
|
8102
|
+
|
|
8103
|
+
#if defined(_WIN32)
|
|
8104
|
+
HANDLE h = (HANDLE)_get_osfhandle(dest.u.file.fd);
|
|
8105
|
+
|
|
8106
|
+
if (!SetEndOfFile(h)) {
|
|
8107
|
+
LogError("Failed to truncate '%1': %2", filename, GetWin32ErrorString());
|
|
8108
|
+
error = true;
|
|
8109
|
+
return false;
|
|
8110
|
+
}
|
|
8111
|
+
#else
|
|
8112
|
+
if (ftruncate(dest.u.file.fd, 0) < 0) {
|
|
8113
|
+
LogError("Failed to truncate '%1': %2", filename, strerror(errno));
|
|
8114
|
+
error = true;
|
|
8115
|
+
return false;
|
|
8116
|
+
}
|
|
8117
|
+
#endif
|
|
8118
|
+
|
|
8119
|
+
dest.u.file.buf_used = 0;
|
|
8120
|
+
} break;
|
|
8121
|
+
|
|
8122
|
+
case DestinationType::Function: {
|
|
8123
|
+
LogError("Cannot rewind stream '%1'", filename);
|
|
8124
|
+
error = true;
|
|
8125
|
+
return false;
|
|
8126
|
+
} break;
|
|
8127
|
+
}
|
|
8128
|
+
|
|
8129
|
+
raw_written = 0;
|
|
8130
|
+
|
|
8131
|
+
return true;
|
|
8132
|
+
}
|
|
8133
|
+
|
|
7995
8134
|
bool StreamWriter::Flush()
|
|
7996
8135
|
{
|
|
7997
8136
|
#if !defined(__wasm__)
|
|
@@ -9027,8 +9166,10 @@ bool ConsolePrompter::Read(Span<const char> *out_str)
|
|
|
9027
9166
|
}
|
|
9028
9167
|
}
|
|
9029
9168
|
|
|
9030
|
-
|
|
9169
|
+
Size ConsolePrompter::ReadEnum(Span<const PromptChoice> choices, Size value)
|
|
9031
9170
|
{
|
|
9171
|
+
RG_ASSERT(value < choices.len);
|
|
9172
|
+
|
|
9032
9173
|
#if !defined(_WIN32) && !defined(__wasm__)
|
|
9033
9174
|
struct sigaction old_sa;
|
|
9034
9175
|
IgnoreSigWinch(&old_sa);
|
|
@@ -9041,9 +9182,9 @@ bool ConsolePrompter::ReadYN(bool *out_value)
|
|
|
9041
9182
|
DisableRawMode();
|
|
9042
9183
|
};
|
|
9043
9184
|
|
|
9044
|
-
return
|
|
9185
|
+
return ReadRawEnum(choices, value);
|
|
9045
9186
|
} else {
|
|
9046
|
-
return
|
|
9187
|
+
return ReadBufferedEnum(choices);
|
|
9047
9188
|
}
|
|
9048
9189
|
}
|
|
9049
9190
|
|
|
@@ -9070,8 +9211,8 @@ bool ConsolePrompter::ReadRaw(Span<const char> *out_str)
|
|
|
9070
9211
|
StdErr->Flush();
|
|
9071
9212
|
|
|
9072
9213
|
prompt_columns = ComputeWidth(prompt);
|
|
9073
|
-
|
|
9074
9214
|
str_offset = str.len;
|
|
9215
|
+
|
|
9075
9216
|
RenderRaw();
|
|
9076
9217
|
|
|
9077
9218
|
int32_t uc;
|
|
@@ -9294,18 +9435,13 @@ bool ConsolePrompter::ReadRaw(Span<const char> *out_str)
|
|
|
9294
9435
|
return true;
|
|
9295
9436
|
}
|
|
9296
9437
|
|
|
9297
|
-
|
|
9438
|
+
Size ConsolePrompter::ReadRawEnum(Span<const PromptChoice> choices, Size value)
|
|
9298
9439
|
{
|
|
9299
|
-
const char *yn = "[Y/N]";
|
|
9300
|
-
|
|
9301
9440
|
StdErr->Flush();
|
|
9302
9441
|
|
|
9303
|
-
prompt_columns =
|
|
9304
|
-
|
|
9305
|
-
str.RemoveFrom(0);
|
|
9306
|
-
str_offset = 0;
|
|
9442
|
+
prompt_columns = 0;
|
|
9443
|
+
FormatChoices(choices, value);
|
|
9307
9444
|
RenderRaw();
|
|
9308
|
-
Print(StdErr, "%!D..%1%!0 ", yn);
|
|
9309
9445
|
|
|
9310
9446
|
int32_t uc;
|
|
9311
9447
|
while ((uc = ReadChar()) >= 0) {
|
|
@@ -9316,36 +9452,86 @@ bool ConsolePrompter::ReadRawYN(bool *out_value)
|
|
|
9316
9452
|
}
|
|
9317
9453
|
|
|
9318
9454
|
switch (uc) {
|
|
9319
|
-
case
|
|
9320
|
-
|
|
9321
|
-
StdErr->Flush();
|
|
9455
|
+
case 0x1B: {
|
|
9456
|
+
LocalArray<char, 16> buf;
|
|
9322
9457
|
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
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
|
+
}
|
|
9327
9485
|
} break;
|
|
9328
9486
|
|
|
9329
|
-
case
|
|
9330
|
-
case
|
|
9331
|
-
|
|
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");
|
|
9332
9493
|
StdErr->Flush();
|
|
9333
9494
|
|
|
9334
|
-
|
|
9335
|
-
|
|
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
|
+
}
|
|
9336
9509
|
} break;
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
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");
|
|
9340
9527
|
StdErr->Flush();
|
|
9341
9528
|
|
|
9342
|
-
|
|
9343
|
-
return true;
|
|
9529
|
+
return value;
|
|
9344
9530
|
} break;
|
|
9345
9531
|
}
|
|
9346
9532
|
}
|
|
9347
9533
|
|
|
9348
|
-
return
|
|
9534
|
+
return -1;
|
|
9349
9535
|
}
|
|
9350
9536
|
|
|
9351
9537
|
bool ConsolePrompter::ReadBuffered(Span<const char> *out_str)
|
|
@@ -9374,41 +9560,43 @@ bool ConsolePrompter::ReadBuffered(Span<const char> *out_str)
|
|
|
9374
9560
|
return false;
|
|
9375
9561
|
}
|
|
9376
9562
|
|
|
9377
|
-
|
|
9563
|
+
Size ConsolePrompter::ReadBufferedEnum(Span<const PromptChoice> choices)
|
|
9378
9564
|
{
|
|
9379
|
-
const char
|
|
9565
|
+
static const Span<const char> prefix = "Input your choice: ";
|
|
9380
9566
|
|
|
9381
|
-
prompt_columns =
|
|
9567
|
+
prompt_columns = 0;
|
|
9568
|
+
FormatChoices(choices, 0);
|
|
9569
|
+
RenderBuffered();
|
|
9382
9570
|
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
str_offset = 0;
|
|
9386
|
-
RenderBuffered();
|
|
9387
|
-
Print(StdErr, "%1 ", yn);
|
|
9571
|
+
Print(StdErr, "\n%1", prefix);
|
|
9572
|
+
StdErr->Flush();
|
|
9388
9573
|
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9574
|
+
do {
|
|
9575
|
+
uint8_t c = 0;
|
|
9576
|
+
if (StdIn->Read(1, &c) < 0)
|
|
9577
|
+
return -1;
|
|
9393
9578
|
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
break;
|
|
9403
|
-
}
|
|
9404
|
-
} else if (c >= 32 || c == '\t') {
|
|
9405
|
-
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;
|
|
9406
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);
|
|
9407
9595
|
}
|
|
9408
|
-
}
|
|
9596
|
+
} while (!StdIn->IsEOF());
|
|
9409
9597
|
|
|
9410
9598
|
// EOF
|
|
9411
|
-
return
|
|
9599
|
+
return -1;
|
|
9412
9600
|
}
|
|
9413
9601
|
|
|
9414
9602
|
void ConsolePrompter::ChangeEntry(Size new_idx)
|
|
@@ -9492,6 +9680,27 @@ void ConsolePrompter::Delete(Size start, Size end)
|
|
|
9492
9680
|
}
|
|
9493
9681
|
}
|
|
9494
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
|
+
|
|
9495
9704
|
void ConsolePrompter::RenderRaw()
|
|
9496
9705
|
{
|
|
9497
9706
|
columns = GetConsoleSize().x;
|
|
@@ -9524,7 +9733,7 @@ void ConsolePrompter::RenderRaw()
|
|
|
9524
9733
|
int width = mask ? mask_columns : ComputeWidth(str.Take(i, bytes));
|
|
9525
9734
|
|
|
9526
9735
|
if (x2 + width >= columns || str[i] == '\n') {
|
|
9527
|
-
FmtArg prefix = FmtArg(
|
|
9736
|
+
FmtArg prefix = FmtArg(' ').Repeat(prompt_columns - 1);
|
|
9528
9737
|
Print(StdErr, "\x1B[0K\r\n%!D.+%1%!0 %!..+", prefix);
|
|
9529
9738
|
|
|
9530
9739
|
x2 = prompt_columns;
|
|
@@ -9568,8 +9777,10 @@ void ConsolePrompter::RenderBuffered()
|
|
|
9568
9777
|
Print(StdErr, "%1%2", prompt, line);
|
|
9569
9778
|
while (remain.len) {
|
|
9570
9779
|
line = SplitStr(remain, '\n', &remain);
|
|
9571
|
-
Print(StdErr, "\n%1
|
|
9780
|
+
Print(StdErr, "\n%1%2", FmtArg(' ').Repeat(prompt_columns), line);
|
|
9572
9781
|
}
|
|
9782
|
+
|
|
9783
|
+
StdErr->Flush();
|
|
9573
9784
|
}
|
|
9574
9785
|
|
|
9575
9786
|
Vec2<int> ConsolePrompter::GetConsoleSize()
|
|
@@ -9732,12 +9943,18 @@ error:
|
|
|
9732
9943
|
|
|
9733
9944
|
int ConsolePrompter::ComputeWidth(Span<const char> str)
|
|
9734
9945
|
{
|
|
9946
|
+
Size i = 0;
|
|
9735
9947
|
int width = 0;
|
|
9736
9948
|
|
|
9737
|
-
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9949
|
+
while (i < str.len) {
|
|
9950
|
+
int32_t uc;
|
|
9951
|
+
Size bytes = DecodeUtf8(str, i, &uc);
|
|
9952
|
+
|
|
9953
|
+
if (!bytes) [[unlikely]]
|
|
9954
|
+
return false;
|
|
9955
|
+
|
|
9956
|
+
i += bytes;
|
|
9957
|
+
width += ComputeCharacterWidth(uc);
|
|
9741
9958
|
}
|
|
9742
9959
|
|
|
9743
9960
|
return width;
|
|
@@ -9769,12 +9986,42 @@ const char *Prompt(const char *prompt, const char *default_value, const char *ma
|
|
|
9769
9986
|
return str;
|
|
9770
9987
|
}
|
|
9771
9988
|
|
|
9772
|
-
|
|
9989
|
+
Size PromptEnum(const char *prompt, Span<const PromptChoice> choices, Size value)
|
|
9773
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
|
+
|
|
9774
10004
|
ConsolePrompter prompter;
|
|
9775
10005
|
prompter.prompt = prompt;
|
|
9776
10006
|
|
|
9777
|
-
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);
|
|
9778
10025
|
}
|
|
9779
10026
|
|
|
9780
10027
|
// ------------------------------------------------------------------------
|
|
@@ -9856,4 +10103,194 @@ bool CanCompressFile(const char *filename)
|
|
|
9856
10103
|
return true;
|
|
9857
10104
|
}
|
|
9858
10105
|
|
|
10106
|
+
// ------------------------------------------------------------------------
|
|
10107
|
+
// Unicode
|
|
10108
|
+
// ------------------------------------------------------------------------
|
|
10109
|
+
|
|
10110
|
+
static bool TestUnicodeTable(Span<const int32_t> table, int32_t uc)
|
|
10111
|
+
{
|
|
10112
|
+
RG_ASSERT(table.len > 0);
|
|
10113
|
+
RG_ASSERT(table.len % 2 == 0);
|
|
10114
|
+
|
|
10115
|
+
auto it = std::upper_bound(table.begin(), table.end(), uc,
|
|
10116
|
+
[](int32_t uc, int32_t x) { return uc < x; });
|
|
10117
|
+
Size idx = it - table.ptr;
|
|
10118
|
+
|
|
10119
|
+
// Each pair of value in table represents a valid interval
|
|
10120
|
+
return idx & 0x1;
|
|
10121
|
+
}
|
|
10122
|
+
|
|
10123
|
+
int ComputeCharacterWidth(int32_t uc)
|
|
10124
|
+
{
|
|
10125
|
+
if (uc < 32)
|
|
10126
|
+
return 0;
|
|
10127
|
+
|
|
10128
|
+
if (TestUnicodeTable(WcWidthNull, uc))
|
|
10129
|
+
return 0;
|
|
10130
|
+
if (TestUnicodeTable(WcWidthWide, uc))
|
|
10131
|
+
return 2;
|
|
10132
|
+
|
|
10133
|
+
return 1;
|
|
10134
|
+
}
|
|
10135
|
+
|
|
10136
|
+
bool IsXidStart(int32_t uc)
|
|
10137
|
+
{
|
|
10138
|
+
if (IsAsciiAlpha(uc))
|
|
10139
|
+
return true;
|
|
10140
|
+
if (uc == '_')
|
|
10141
|
+
return true;
|
|
10142
|
+
if (TestUnicodeTable(XidStartTable, uc))
|
|
10143
|
+
return true;
|
|
10144
|
+
|
|
10145
|
+
return false;
|
|
10146
|
+
}
|
|
10147
|
+
|
|
10148
|
+
bool IsXidContinue(int32_t uc)
|
|
10149
|
+
{
|
|
10150
|
+
if (IsAsciiAlphaOrDigit(uc))
|
|
10151
|
+
return true;
|
|
10152
|
+
if (uc == '_')
|
|
10153
|
+
return true;
|
|
10154
|
+
if (TestUnicodeTable(XidContinueTable, uc))
|
|
10155
|
+
return true;
|
|
10156
|
+
|
|
10157
|
+
return false;
|
|
10158
|
+
}
|
|
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
|
+
|
|
9859
10296
|
}
|