koffi 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -7
- package/cnoke.cjs +9 -9
- package/doc/benchmarks.md +2 -2
- package/doc/callbacks.md +7 -26
- package/doc/{input.md → composites.md} +161 -147
- package/doc/contribute.md +2 -1
- package/doc/index.md +0 -14
- package/doc/{functions.md → load.md} +54 -113
- package/doc/migration.md +4 -7
- package/doc/misc.md +0 -103
- package/doc/output.md +5 -11
- package/doc/pointers.md +76 -17
- package/doc/primitives.md +151 -0
- package/doc/start.md +3 -13
- package/doc/types.md +88 -0
- package/doc/unions.md +0 -186
- package/doc/values.md +134 -0
- package/index.d.ts +23 -4
- package/lib/native/base/base.cc +66 -24
- package/lib/native/base/base.hh +55 -153
- package/package.json +15 -15
- package/src/koffi/CMakeLists.txt +19 -17
- package/src/koffi/index.cjs +15 -10
- package/src/koffi/index.js +6 -6
- package/src/koffi/indirect.cjs +15 -10
- package/src/koffi/indirect.js +6 -6
- package/src/koffi/src/abi/arm64.cc +47 -62
- package/src/koffi/src/abi/riscv64.cc +38 -57
- package/src/koffi/src/abi/x64sysv.cc +38 -57
- package/src/koffi/src/abi/x64win.cc +47 -65
- package/src/koffi/src/abi/x86.cc +46 -59
- package/src/koffi/src/call.cc +239 -133
- package/src/koffi/src/call.hh +5 -10
- package/src/koffi/src/ffi.cc +211 -90
- package/src/koffi/src/ffi.hh +36 -16
- package/src/koffi/src/parser.cc +3 -3
- package/src/koffi/src/parser.hh +2 -2
- package/src/koffi/src/static.js +3 -0
- package/src/koffi/src/type.cc +43 -33
- package/src/koffi/src/type.hh +1 -1
- package/src/koffi/src/util.cc +73 -173
- package/src/koffi/src/util.hh +84 -43
- package/src/koffi/src/uv.cc +1 -1
- package/vendor/node-addon-api/README.md +1 -1
- package/vendor/node-addon-api/napi-inl.h +213 -35
- package/vendor/node-addon-api/napi.h +118 -7
- package/doc/variables.md +0 -102
package/lib/native/base/base.cc
CHANGED
|
@@ -1511,7 +1511,7 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
|
|
|
1511
1511
|
append(FormatUnsignedToDecimal((uint64_t)arg.u.date.st.day, buf));
|
|
1512
1512
|
} break;
|
|
1513
1513
|
|
|
1514
|
-
case FmtType::
|
|
1514
|
+
case FmtType::TimeBasic: {
|
|
1515
1515
|
const TimeSpec &spec = arg.u.time.spec;
|
|
1516
1516
|
|
|
1517
1517
|
LocalArray<char, 128> buf;
|
|
@@ -1548,6 +1548,43 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
|
|
|
1548
1548
|
|
|
1549
1549
|
append(buf);
|
|
1550
1550
|
} break;
|
|
1551
|
+
case FmtType::TimeIso: {
|
|
1552
|
+
const TimeSpec &spec = arg.u.time.spec;
|
|
1553
|
+
|
|
1554
|
+
LocalArray<char, 128> buf;
|
|
1555
|
+
|
|
1556
|
+
if (spec.offset && arg.u.time.ms) {
|
|
1557
|
+
int offset_h = spec.offset / 60;
|
|
1558
|
+
int offset_m = spec.offset % 60;
|
|
1559
|
+
|
|
1560
|
+
buf.len = Fmt(buf.data, "%1-%2-%3T%4:%5:%6.%7%8%9%10",
|
|
1561
|
+
FmtInt(spec.year, 2), FmtInt(spec.month, 2),
|
|
1562
|
+
FmtInt(spec.day, 2), FmtInt(spec.hour, 2),
|
|
1563
|
+
FmtInt(spec.min, 2), FmtInt(spec.sec, 2), FmtInt(spec.msec, 3),
|
|
1564
|
+
offset_h >= 0 ? "+" : "", FmtInt(offset_h, 2), FmtInt(offset_m, 2)).len;
|
|
1565
|
+
} else if (spec.offset) {
|
|
1566
|
+
int offset_h = spec.offset / 60;
|
|
1567
|
+
int offset_m = spec.offset % 60;
|
|
1568
|
+
|
|
1569
|
+
buf.len = Fmt(buf.data, "%1-%2-%3T%4:%5:%6%7%8%9",
|
|
1570
|
+
FmtInt(spec.year, 2), FmtInt(spec.month, 2),
|
|
1571
|
+
FmtInt(spec.day, 2), FmtInt(spec.hour, 2),
|
|
1572
|
+
FmtInt(spec.min, 2), FmtInt(spec.sec, 2),
|
|
1573
|
+
offset_h >= 0 ? "+" : "", FmtInt(offset_h, 2), FmtInt(offset_m, 2)).len;
|
|
1574
|
+
} else if (arg.u.time.ms) {
|
|
1575
|
+
buf.len = Fmt(buf.data, "%1-%2-%3T%4:%5:%6.%7Z",
|
|
1576
|
+
FmtInt(spec.year, 2), FmtInt(spec.month, 2),
|
|
1577
|
+
FmtInt(spec.day, 2), FmtInt(spec.hour, 2),
|
|
1578
|
+
FmtInt(spec.min, 2), FmtInt(spec.sec, 2), FmtInt(spec.msec, 3)).len;
|
|
1579
|
+
} else {
|
|
1580
|
+
buf.len = Fmt(buf.data, "%1-%2-%3T%4:%5:%6Z",
|
|
1581
|
+
FmtInt(spec.year, 2), FmtInt(spec.month, 2),
|
|
1582
|
+
FmtInt(spec.day, 2), FmtInt(spec.hour, 2),
|
|
1583
|
+
FmtInt(spec.min, 2), FmtInt(spec.sec, 2)).len;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
append(buf);
|
|
1587
|
+
} break;
|
|
1551
1588
|
case FmtType::TimeNice: {
|
|
1552
1589
|
const TimeSpec &spec = arg.u.time.spec;
|
|
1553
1590
|
|
|
@@ -1947,7 +1984,7 @@ void FmtUrlSafe::Format(FunctionRef<void(Span<const char>)> append) const
|
|
|
1947
1984
|
}
|
|
1948
1985
|
}
|
|
1949
1986
|
|
|
1950
|
-
void
|
|
1987
|
+
void FmtXmlSafe::Format(FunctionRef<void(Span<const char>)> append) const
|
|
1951
1988
|
{
|
|
1952
1989
|
for (char c: str) {
|
|
1953
1990
|
switch (c) {
|
|
@@ -5171,7 +5208,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
|
5171
5208
|
|
|
5172
5209
|
// Read and write standard process streams
|
|
5173
5210
|
{
|
|
5174
|
-
bool running =
|
|
5211
|
+
bool running = in_func.IsValid() || out_func.IsValid();
|
|
5175
5212
|
|
|
5176
5213
|
PendingIO proc_in;
|
|
5177
5214
|
Span<const uint8_t> write_buf = {};
|
|
@@ -5201,6 +5238,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
|
5201
5238
|
}
|
|
5202
5239
|
} else {
|
|
5203
5240
|
CloseHandleSafe(&in_pipe[1]);
|
|
5241
|
+
running &= out_func.IsValid();
|
|
5204
5242
|
}
|
|
5205
5243
|
}
|
|
5206
5244
|
|
|
@@ -5632,7 +5670,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
|
5632
5670
|
return true;
|
|
5633
5671
|
}
|
|
5634
5672
|
|
|
5635
|
-
Size ReadCommandOutput(const char *cmd_line, Span<
|
|
5673
|
+
Size ReadCommandOutput(const char *cmd_line, Span<uint8_t> out_output)
|
|
5636
5674
|
{
|
|
5637
5675
|
static ExecuteInfo::KeyValue variables[] = {
|
|
5638
5676
|
{ "LANG", "C" },
|
|
@@ -5654,14 +5692,14 @@ Size ReadCommandOutput(const char *cmd_line, Span<char> out_output)
|
|
|
5654
5692
|
if (!ExecuteCommandLine(cmd_line, info, MakeSpan((const uint8_t *)nullptr, 0), write, &exit_code))
|
|
5655
5693
|
return -1;
|
|
5656
5694
|
if (exit_code) {
|
|
5657
|
-
LogDebug("Command '%1 failed (exit code: %2)", cmd_line, exit_code);
|
|
5695
|
+
LogDebug("Command '%1' failed (exit code: %2)", cmd_line, exit_code);
|
|
5658
5696
|
return -1;
|
|
5659
5697
|
}
|
|
5660
5698
|
|
|
5661
5699
|
return total_len;
|
|
5662
5700
|
}
|
|
5663
5701
|
|
|
5664
|
-
bool ReadCommandOutput(const char *cmd_line, HeapArray<
|
|
5702
|
+
bool ReadCommandOutput(const char *cmd_line, HeapArray<uint8_t> *out_output)
|
|
5665
5703
|
{
|
|
5666
5704
|
static ExecuteInfo::KeyValue variables[] = {
|
|
5667
5705
|
{ "LANG", "C" },
|
|
@@ -5675,7 +5713,7 @@ bool ReadCommandOutput(const char *cmd_line, HeapArray<char> *out_output)
|
|
|
5675
5713
|
if (!ExecuteCommandLine(cmd_line, info, {}, Mebibytes(1), out_output, &exit_code))
|
|
5676
5714
|
return false;
|
|
5677
5715
|
if (exit_code) {
|
|
5678
|
-
LogDebug("Command '%1 failed (exit code: %2)", cmd_line, exit_code);
|
|
5716
|
+
LogDebug("Command '%1' failed (exit code: %2)", cmd_line, exit_code);
|
|
5679
5717
|
return false;
|
|
5680
5718
|
}
|
|
5681
5719
|
|
|
@@ -7405,7 +7443,7 @@ public:
|
|
|
7405
7443
|
void AddTask(Async *async, int worker_idx, const std::function<bool()> &func);
|
|
7406
7444
|
|
|
7407
7445
|
void RunWorker(int worker_idx);
|
|
7408
|
-
void SyncOn(Async *async,
|
|
7446
|
+
void SyncOn(Async *async, Async *only);
|
|
7409
7447
|
bool WaitOn(Async *async, int timeout);
|
|
7410
7448
|
|
|
7411
7449
|
void RunTasks(int worker_idx, Async *only);
|
|
@@ -7419,7 +7457,7 @@ static thread_local AsyncPool *async_running_pool = nullptr;
|
|
|
7419
7457
|
static thread_local int async_running_worker_idx;
|
|
7420
7458
|
static thread_local bool async_running_task = false;
|
|
7421
7459
|
|
|
7422
|
-
Async::Async(int threads)
|
|
7460
|
+
Async::Async(int threads, unsigned int flags)
|
|
7423
7461
|
{
|
|
7424
7462
|
K_ASSERT(threads);
|
|
7425
7463
|
|
|
@@ -7441,14 +7479,22 @@ Async::Async(int threads)
|
|
|
7441
7479
|
}
|
|
7442
7480
|
|
|
7443
7481
|
pool->RegisterAsync();
|
|
7482
|
+
|
|
7483
|
+
if (flags & (int)AsyncFlag::Selfish) {
|
|
7484
|
+
only = this;
|
|
7485
|
+
}
|
|
7444
7486
|
}
|
|
7445
7487
|
|
|
7446
|
-
Async::Async(Async *parent)
|
|
7488
|
+
Async::Async(Async *parent, unsigned int flags)
|
|
7447
7489
|
{
|
|
7448
7490
|
K_ASSERT(parent);
|
|
7449
7491
|
|
|
7450
7492
|
pool = parent->pool;
|
|
7451
7493
|
pool->RegisterAsync();
|
|
7494
|
+
|
|
7495
|
+
if (flags & (int)AsyncFlag::Selfish) {
|
|
7496
|
+
only = this;
|
|
7497
|
+
}
|
|
7452
7498
|
}
|
|
7453
7499
|
|
|
7454
7500
|
Async::~Async()
|
|
@@ -7471,13 +7517,7 @@ void Async::Run(int worker, const std::function<bool()> &func)
|
|
|
7471
7517
|
|
|
7472
7518
|
bool Async::Sync()
|
|
7473
7519
|
{
|
|
7474
|
-
pool->SyncOn(this,
|
|
7475
|
-
return success;
|
|
7476
|
-
}
|
|
7477
|
-
|
|
7478
|
-
bool Async::SyncSoon()
|
|
7479
|
-
{
|
|
7480
|
-
pool->SyncOn(this, true);
|
|
7520
|
+
pool->SyncOn(this, only);
|
|
7481
7521
|
return success;
|
|
7482
7522
|
}
|
|
7483
7523
|
|
|
@@ -7613,7 +7653,7 @@ void AsyncPool::AddTask(Async *async, int worker_idx, const std::function<bool()
|
|
|
7613
7653
|
int worker_idx = async_running_worker_idx;
|
|
7614
7654
|
|
|
7615
7655
|
do {
|
|
7616
|
-
RunTasks(worker_idx,
|
|
7656
|
+
RunTasks(worker_idx, async->only);
|
|
7617
7657
|
} while (pending_tasks >= K_ASYNC_MAX_PENDING_TASKS);
|
|
7618
7658
|
} else if (!prev_pending) {
|
|
7619
7659
|
std::lock_guard<std::mutex> lock_pool(pool_mutex);
|
|
@@ -7647,7 +7687,7 @@ void AsyncPool::RunWorker(int worker_idx)
|
|
|
7647
7687
|
}
|
|
7648
7688
|
}
|
|
7649
7689
|
|
|
7650
|
-
void AsyncPool::SyncOn(Async *async,
|
|
7690
|
+
void AsyncPool::SyncOn(Async *async, Async *only)
|
|
7651
7691
|
{
|
|
7652
7692
|
K_DEFER_C(pool = async_running_pool,
|
|
7653
7693
|
worker_idx = async_running_worker_idx) {
|
|
@@ -7659,7 +7699,7 @@ void AsyncPool::SyncOn(Async *async, bool soon)
|
|
|
7659
7699
|
async_running_worker_idx = 0;
|
|
7660
7700
|
|
|
7661
7701
|
while (async->remaining_tasks) {
|
|
7662
|
-
RunTasks(0,
|
|
7702
|
+
RunTasks(0, only);
|
|
7663
7703
|
|
|
7664
7704
|
std::unique_lock<std::mutex> lock_sync(pool_mutex);
|
|
7665
7705
|
sync_cv.wait(lock_sync, [&]() { return pending_tasks || !async->remaining_tasks; });
|
|
@@ -7739,12 +7779,12 @@ void AsyncPool::RunTask(Task *task)
|
|
|
7739
7779
|
#else
|
|
7740
7780
|
|
|
7741
7781
|
|
|
7742
|
-
Async::Async(int threads)
|
|
7782
|
+
Async::Async(int threads, unsigned int)
|
|
7743
7783
|
{
|
|
7744
7784
|
K_ASSERT(threads);
|
|
7745
7785
|
}
|
|
7746
7786
|
|
|
7747
|
-
Async::Async(Async *parent)
|
|
7787
|
+
Async::Async(Async *parent, unsigned int)
|
|
7748
7788
|
{
|
|
7749
7789
|
K_ASSERT(parent);
|
|
7750
7790
|
}
|
|
@@ -10728,7 +10768,7 @@ const char *GetMimeType(Span<const char> extension, const char *default_type)
|
|
|
10728
10768
|
const char *mimetype = mimetypes.FindValue(lower, nullptr);
|
|
10729
10769
|
|
|
10730
10770
|
if (!mimetype) {
|
|
10731
|
-
|
|
10771
|
+
LogDebug("Unknown MIME type for extension '%1'", extension);
|
|
10732
10772
|
mimetype = default_type;
|
|
10733
10773
|
}
|
|
10734
10774
|
|
|
@@ -10768,8 +10808,10 @@ bool CanCompressFile(const char *filename)
|
|
|
10768
10808
|
if (TestStrI(extension, ".db") || TestStrI(extension, ".sqlite3"))
|
|
10769
10809
|
return false;
|
|
10770
10810
|
|
|
10771
|
-
const char *mimetype = GetMimeType(extension);
|
|
10811
|
+
const char *mimetype = GetMimeType(extension, nullptr);
|
|
10772
10812
|
|
|
10813
|
+
if (!mimetype)
|
|
10814
|
+
return false;
|
|
10773
10815
|
if (StartsWith(mimetype, "video/"))
|
|
10774
10816
|
return false;
|
|
10775
10817
|
if (StartsWith(mimetype, "audio/"))
|
package/lib/native/base/base.hh
CHANGED
|
@@ -3074,8 +3074,8 @@ private:
|
|
|
3074
3074
|
template <typename T>
|
|
3075
3075
|
class HashTraits {
|
|
3076
3076
|
public:
|
|
3077
|
-
static
|
|
3078
|
-
static
|
|
3077
|
+
static uint64_t Hash(const T &key) { return key.Hash(); }
|
|
3078
|
+
static bool Test(const T &key1, const T &key2) { return key1 == key2; }
|
|
3079
3079
|
};
|
|
3080
3080
|
|
|
3081
3081
|
// Stole the Hash function from Thomas Wang (see here: https://gist.github.com/badboy/6267743)
|
|
@@ -3146,44 +3146,17 @@ DEFINE_INTEGER_HASH_TRAITS_64(unsigned long long, constexpr);
|
|
|
3146
3146
|
#undef DEFINE_INTEGER_HASH_TRAITS_64
|
|
3147
3147
|
|
|
3148
3148
|
// MurmurHash2
|
|
3149
|
-
static
|
|
3149
|
+
static inline uint64_t HashStr(Span<const char> str)
|
|
3150
3150
|
{
|
|
3151
3151
|
const uint64_t Seed = 0;
|
|
3152
3152
|
const uint64_t Mult = (((uint64_t)0xc6a4a793ull) << 32ull) + (uint64_t)0x5bd1e995ull;
|
|
3153
3153
|
|
|
3154
3154
|
const auto unaligned_load =
|
|
3155
|
-
#if __cplusplus >= 202002L && (__GNUC__ >= 12 || __clang_major__ >= 16)
|
|
3156
|
-
!std::is_constant_evaluated() ?
|
|
3157
3155
|
[](const char *p) {
|
|
3158
3156
|
uint64_t result;
|
|
3159
|
-
|
|
3160
|
-
return result;
|
|
3161
|
-
} :
|
|
3162
|
-
#endif
|
|
3163
|
-
[](const char *p) {
|
|
3164
|
-
#if defined(K_BIG_ENDIAN)
|
|
3165
|
-
uint64_t result = ((uint64_t)p[0] << 56) |
|
|
3166
|
-
((uint64_t)p[1] << 48) |
|
|
3167
|
-
((uint64_t)p[2] << 40) |
|
|
3168
|
-
((uint64_t)p[3] << 32) |
|
|
3169
|
-
((uint64_t)p[4] << 24) |
|
|
3170
|
-
((uint64_t)p[5] << 16) |
|
|
3171
|
-
((uint64_t)p[6] << 8) |
|
|
3172
|
-
((uint64_t)p[7] << 0);
|
|
3173
|
-
#else
|
|
3174
|
-
uint64_t result = ((uint64_t)p[0] << 0) |
|
|
3175
|
-
((uint64_t)p[1] << 8) |
|
|
3176
|
-
((uint64_t)p[2] << 16) |
|
|
3177
|
-
((uint64_t)p[3] << 24) |
|
|
3178
|
-
((uint64_t)p[4] << 32) |
|
|
3179
|
-
((uint64_t)p[5] << 40) |
|
|
3180
|
-
((uint64_t)p[6] << 48) |
|
|
3181
|
-
((uint64_t)p[7] << 56);
|
|
3182
|
-
#endif
|
|
3183
|
-
|
|
3157
|
+
memcpy(&result, p, sizeof(result));
|
|
3184
3158
|
return result;
|
|
3185
3159
|
};
|
|
3186
|
-
|
|
3187
3160
|
const auto load_bytes = [](const char *p, int n) {
|
|
3188
3161
|
uint64_t result = 0;
|
|
3189
3162
|
|
|
@@ -3216,7 +3189,7 @@ static constexpr inline uint64_t HashStr(Span<const char> str)
|
|
|
3216
3189
|
return hash;
|
|
3217
3190
|
}
|
|
3218
3191
|
|
|
3219
|
-
static
|
|
3192
|
+
static inline uint64_t HashStr(const char *str)
|
|
3220
3193
|
{
|
|
3221
3194
|
Span<const char> span = str;
|
|
3222
3195
|
return HashStr(span);
|
|
@@ -3225,35 +3198,35 @@ static constexpr inline uint64_t HashStr(const char *str)
|
|
|
3225
3198
|
template <>
|
|
3226
3199
|
class HashTraits<const char *> {
|
|
3227
3200
|
public:
|
|
3228
|
-
static
|
|
3229
|
-
static
|
|
3201
|
+
static uint64_t Hash(Span<const char> key) { return HashStr(key); }
|
|
3202
|
+
static uint64_t Hash(const char *key) { return HashStr(key); }
|
|
3230
3203
|
|
|
3231
|
-
static
|
|
3232
|
-
static
|
|
3204
|
+
static bool Test(const char *key1, const char *key2) { return TestStr(key1, key2); }
|
|
3205
|
+
static bool Test(const char *key1, Span<const char> key2) { return key2 == key1; }
|
|
3233
3206
|
};
|
|
3234
3207
|
|
|
3235
3208
|
template <>
|
|
3236
3209
|
class HashTraits<Span<const char>> {
|
|
3237
3210
|
public:
|
|
3238
|
-
static
|
|
3239
|
-
static
|
|
3211
|
+
static uint64_t Hash(Span<const char> key) { return HashStr(key); }
|
|
3212
|
+
static uint64_t Hash(const char *key) { return HashStr(key); }
|
|
3240
3213
|
|
|
3241
|
-
static
|
|
3242
|
-
static
|
|
3214
|
+
static bool Test(Span<const char> key1, Span<const char> key2) { return key1 == key2; }
|
|
3215
|
+
static bool Test(Span<const char> key1, const char * key2) { return key1 == key2; }
|
|
3243
3216
|
};
|
|
3244
3217
|
|
|
3245
3218
|
#define K_HASHTABLE_HANDLER_EX_N(Name, ValueType, KeyType, KeyMember, HashFunc, TestFunc) \
|
|
3246
3219
|
class Name { \
|
|
3247
3220
|
public: \
|
|
3248
|
-
static
|
|
3221
|
+
static KeyType GetKey(const ValueType &value) \
|
|
3249
3222
|
{ return (KeyType)(value.KeyMember); } \
|
|
3250
|
-
static
|
|
3223
|
+
static KeyType GetKey(const ValueType *value) \
|
|
3251
3224
|
{ return (KeyType)(value->KeyMember); } \
|
|
3252
3225
|
template <typename TestKey> \
|
|
3253
|
-
static
|
|
3226
|
+
static uint64_t HashKey(TestKey key) \
|
|
3254
3227
|
{ return HashFunc(key); } \
|
|
3255
3228
|
template <typename TestKey> \
|
|
3256
|
-
static
|
|
3229
|
+
static bool TestKeys(KeyType key1, TestKey key2) \
|
|
3257
3230
|
{ return TestFunc((key1), (key2)); } \
|
|
3258
3231
|
}
|
|
3259
3232
|
#define K_HASHTABLE_HANDLER_EX(ValueType, KeyType, KeyMember, HashFunc, TestFunc) \
|
|
@@ -3355,11 +3328,11 @@ template <typename ValueType>
|
|
|
3355
3328
|
class HashSet {
|
|
3356
3329
|
class Handler {
|
|
3357
3330
|
public:
|
|
3358
|
-
static
|
|
3359
|
-
static
|
|
3360
|
-
static
|
|
3331
|
+
static ValueType GetKey(const ValueType &value) { return value; }
|
|
3332
|
+
static ValueType GetKey(const ValueType *value) { return *value; }
|
|
3333
|
+
static uint64_t HashKey(const ValueType &value)
|
|
3361
3334
|
{ return HashTraits<ValueType>::Hash(value); }
|
|
3362
|
-
static
|
|
3335
|
+
static bool TestKeys(const ValueType &value1, const ValueType &value2)
|
|
3363
3336
|
{ return HashTraits<ValueType>::Test(value1, value2); }
|
|
3364
3337
|
};
|
|
3365
3338
|
|
|
@@ -3403,101 +3376,6 @@ public:
|
|
|
3403
3376
|
private:
|
|
3404
3377
|
};
|
|
3405
3378
|
|
|
3406
|
-
// XXX: Switch to perfect hashing later on
|
|
3407
|
-
template <Size N, typename KeyType, typename ValueType>
|
|
3408
|
-
class ConstMap {
|
|
3409
|
-
public:
|
|
3410
|
-
struct Bucket {
|
|
3411
|
-
KeyType key;
|
|
3412
|
-
ValueType value;
|
|
3413
|
-
};
|
|
3414
|
-
|
|
3415
|
-
size_t used[(N + (K_SIZE(size_t) * 8) - 1) / K_SIZE(size_t)] = {};
|
|
3416
|
-
Bucket data[N] = {};
|
|
3417
|
-
Size count = 0;
|
|
3418
|
-
|
|
3419
|
-
constexpr ConstMap(std::initializer_list<Bucket> l)
|
|
3420
|
-
{
|
|
3421
|
-
K_CRITICAL(l.size() <= N, "ConstMap<%1> cannot store %2 values", N, l.size());
|
|
3422
|
-
|
|
3423
|
-
for (const Bucket &it: l) {
|
|
3424
|
-
Bucket *bucket = Insert(it.key);
|
|
3425
|
-
|
|
3426
|
-
bucket->key = it.key;
|
|
3427
|
-
bucket->value = it.value;
|
|
3428
|
-
}
|
|
3429
|
-
}
|
|
3430
|
-
|
|
3431
|
-
template <typename T = KeyType>
|
|
3432
|
-
ValueType *Find(const T &key)
|
|
3433
|
-
{ return (ValueType *)((const ConstMap *)this)->Find(key); }
|
|
3434
|
-
template <typename T = KeyType>
|
|
3435
|
-
const ValueType *Find(const T &key) const
|
|
3436
|
-
{
|
|
3437
|
-
uint64_t hash = HashTraits<KeyType>::Hash(key);
|
|
3438
|
-
Size idx = HashToIndex(hash);
|
|
3439
|
-
|
|
3440
|
-
const Bucket *bucket = Find(&idx, key);
|
|
3441
|
-
return bucket ? &bucket->value : nullptr;
|
|
3442
|
-
}
|
|
3443
|
-
|
|
3444
|
-
template <typename T = KeyType>
|
|
3445
|
-
ValueType FindValue(const T &key, const ValueType &default_value)
|
|
3446
|
-
{ return (ValueType)((const ConstMap *)this)->FindValue(key, default_value); }
|
|
3447
|
-
template <typename T = KeyType>
|
|
3448
|
-
const ValueType FindValue(const T &key, const ValueType &default_value) const
|
|
3449
|
-
{
|
|
3450
|
-
const ValueType *it = Find(key);
|
|
3451
|
-
return it ? *it : default_value;
|
|
3452
|
-
}
|
|
3453
|
-
|
|
3454
|
-
private:
|
|
3455
|
-
template <typename T = KeyType>
|
|
3456
|
-
constexpr Bucket *Find(Size *idx, const T &key)
|
|
3457
|
-
{ return (Bucket *)((const ConstMap *)this)->Find(idx, key); }
|
|
3458
|
-
template <typename T = KeyType>
|
|
3459
|
-
constexpr const Bucket *Find(Size *idx, const T &key) const
|
|
3460
|
-
{
|
|
3461
|
-
while (!IsEmpty(*idx)) {
|
|
3462
|
-
if (HashTraits<KeyType>::Test(data[*idx].key, key))
|
|
3463
|
-
return &data[*idx];
|
|
3464
|
-
*idx = (*idx + 1) & (N - 1);
|
|
3465
|
-
}
|
|
3466
|
-
return nullptr;
|
|
3467
|
-
}
|
|
3468
|
-
|
|
3469
|
-
constexpr Bucket *Insert(const KeyType &key)
|
|
3470
|
-
{
|
|
3471
|
-
uint64_t hash = HashTraits<KeyType>::Hash(key);
|
|
3472
|
-
Size idx = HashToIndex(hash);
|
|
3473
|
-
Bucket *it = Find(&idx, key);
|
|
3474
|
-
|
|
3475
|
-
if (!it) {
|
|
3476
|
-
count++;
|
|
3477
|
-
MarkUsed(idx);
|
|
3478
|
-
|
|
3479
|
-
return &data[idx];
|
|
3480
|
-
} else {
|
|
3481
|
-
return it;
|
|
3482
|
-
}
|
|
3483
|
-
}
|
|
3484
|
-
|
|
3485
|
-
constexpr void MarkUsed(Size idx)
|
|
3486
|
-
{
|
|
3487
|
-
used[idx / (K_SIZE(size_t) * 8)] |= (1ull << (idx % (K_SIZE(size_t) * 8)));
|
|
3488
|
-
}
|
|
3489
|
-
constexpr bool IsEmpty(Size idx) const
|
|
3490
|
-
{
|
|
3491
|
-
bool empty = !(used[idx / (K_SIZE(size_t) * 8)] & (1ull << (idx % (K_SIZE(size_t) * 8))));
|
|
3492
|
-
return empty;
|
|
3493
|
-
}
|
|
3494
|
-
|
|
3495
|
-
constexpr Size HashToIndex(uint64_t hash) const
|
|
3496
|
-
{
|
|
3497
|
-
return (Size)(hash & (uint64_t)(N - 1));
|
|
3498
|
-
}
|
|
3499
|
-
};
|
|
3500
|
-
|
|
3501
3379
|
// ------------------------------------------------------------------------
|
|
3502
3380
|
// Date
|
|
3503
3381
|
// ------------------------------------------------------------------------
|
|
@@ -3683,7 +3561,8 @@ enum class FmtType {
|
|
|
3683
3561
|
MemorySize,
|
|
3684
3562
|
DiskSize,
|
|
3685
3563
|
Date,
|
|
3686
|
-
|
|
3564
|
+
TimeBasic,
|
|
3565
|
+
TimeIso,
|
|
3687
3566
|
TimeNice,
|
|
3688
3567
|
List,
|
|
3689
3568
|
FlagNames,
|
|
@@ -3938,10 +3817,19 @@ static inline FmtArg FmtDiskSize(int64_t size)
|
|
|
3938
3817
|
return arg;
|
|
3939
3818
|
}
|
|
3940
3819
|
|
|
3941
|
-
static inline FmtArg
|
|
3820
|
+
static inline FmtArg FmtTimeBasic(TimeSpec spec, bool ms = false)
|
|
3942
3821
|
{
|
|
3943
3822
|
FmtArg arg;
|
|
3944
|
-
arg.type = FmtType::
|
|
3823
|
+
arg.type = FmtType::TimeBasic;
|
|
3824
|
+
arg.u.time.spec = spec;
|
|
3825
|
+
arg.u.time.ms = ms;
|
|
3826
|
+
return arg;
|
|
3827
|
+
}
|
|
3828
|
+
|
|
3829
|
+
static inline FmtArg FmtTimeIso(TimeSpec spec, bool ms = false)
|
|
3830
|
+
{
|
|
3831
|
+
FmtArg arg;
|
|
3832
|
+
arg.type = FmtType::TimeIso;
|
|
3945
3833
|
arg.u.time.spec = spec;
|
|
3946
3834
|
arg.u.time.ms = ms;
|
|
3947
3835
|
return arg;
|
|
@@ -4060,11 +3948,11 @@ public:
|
|
|
4060
3948
|
operator FmtArg() const { return FmtCustom(*this); }
|
|
4061
3949
|
};
|
|
4062
3950
|
|
|
4063
|
-
class
|
|
3951
|
+
class FmtXmlSafe {
|
|
4064
3952
|
Span<const char> str;
|
|
4065
3953
|
|
|
4066
3954
|
public:
|
|
4067
|
-
|
|
3955
|
+
FmtXmlSafe(Span<const char> str) : str(str) {}
|
|
4068
3956
|
|
|
4069
3957
|
void Format(FunctionRef<void(Span<const char>)> append) const;
|
|
4070
3958
|
operator FmtArg() const { return FmtCustom(*this); }
|
|
@@ -4675,8 +4563,17 @@ static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &i
|
|
|
4675
4563
|
(HeapArray<uint8_t> *)out_buf, out_code);
|
|
4676
4564
|
}
|
|
4677
4565
|
|
|
4678
|
-
Size ReadCommandOutput(const char *cmd_line, Span<
|
|
4679
|
-
bool ReadCommandOutput(const char *cmd_line, HeapArray<
|
|
4566
|
+
Size ReadCommandOutput(const char *cmd_line, Span<uint8_t> out_output);
|
|
4567
|
+
bool ReadCommandOutput(const char *cmd_line, HeapArray<uint8_t> *out_output);
|
|
4568
|
+
|
|
4569
|
+
// Char variants
|
|
4570
|
+
static inline Size ReadCommandOutput(const char *cmd_line, Span<char> out_output)
|
|
4571
|
+
{ return ReadCommandOutput(cmd_line, out_output.As<uint8_t>()); }
|
|
4572
|
+
static inline bool ReadCommandOutput(const char *cmd_line, HeapArray<char> *out_output)
|
|
4573
|
+
{
|
|
4574
|
+
HeapArray<uint8_t> *out = (HeapArray<uint8_t> *)out_output;
|
|
4575
|
+
return ReadCommandOutput(cmd_line, out);
|
|
4576
|
+
}
|
|
4680
4577
|
|
|
4681
4578
|
#endif
|
|
4682
4579
|
|
|
@@ -5034,6 +4931,10 @@ void CloseSocket(int fd);
|
|
|
5034
4931
|
// Tasks
|
|
5035
4932
|
// ------------------------------------------------------------------------
|
|
5036
4933
|
|
|
4934
|
+
enum class AsyncFlag {
|
|
4935
|
+
Selfish = 1 << 0
|
|
4936
|
+
};
|
|
4937
|
+
|
|
5037
4938
|
class Async {
|
|
5038
4939
|
K_DELETE_COPY(Async)
|
|
5039
4940
|
|
|
@@ -5042,20 +4943,21 @@ class Async {
|
|
|
5042
4943
|
std::atomic_int remaining_tasks { 0 };
|
|
5043
4944
|
|
|
5044
4945
|
class AsyncPool *pool;
|
|
4946
|
+
|
|
4947
|
+
Async *only = nullptr;
|
|
5045
4948
|
#else
|
|
5046
4949
|
bool success = true;
|
|
5047
4950
|
#endif
|
|
5048
4951
|
|
|
5049
4952
|
public:
|
|
5050
|
-
Async(int threads = -1);
|
|
5051
|
-
Async(Async *parent);
|
|
4953
|
+
Async(int threads = -1, unsigned int flags = 0);
|
|
4954
|
+
Async(Async *parent, unsigned int flags = 0);
|
|
5052
4955
|
~Async();
|
|
5053
4956
|
|
|
5054
4957
|
void Run(const std::function<bool()> &f);
|
|
5055
4958
|
void Run(int worker, const std::function<bool()> &f);
|
|
5056
4959
|
|
|
5057
4960
|
bool Sync();
|
|
5058
|
-
bool SyncSoon();
|
|
5059
4961
|
bool Wait(int timeout);
|
|
5060
4962
|
bool IsSuccess() const { return success; }
|
|
5061
4963
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koffi",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Fast and easy-to-use dynamic C FFI (foreign function interface) for Node.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"foreign",
|
|
@@ -33,20 +33,20 @@
|
|
|
33
33
|
},
|
|
34
34
|
"funding": "https://liberapay.com/Koromix",
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@koromix/koffi-linux-arm64": "3.0
|
|
37
|
-
"@koromix/koffi-linux-ia32": "3.0
|
|
38
|
-
"@koromix/koffi-linux-x64": "3.0
|
|
39
|
-
"@koromix/koffi-linux-riscv64": "3.0
|
|
40
|
-
"@koromix/koffi-freebsd-ia32": "3.0
|
|
41
|
-
"@koromix/koffi-freebsd-x64": "3.0
|
|
42
|
-
"@koromix/koffi-freebsd-arm64": "3.0
|
|
43
|
-
"@koromix/koffi-openbsd-ia32": "3.0
|
|
44
|
-
"@koromix/koffi-openbsd-x64": "3.0
|
|
45
|
-
"@koromix/koffi-win32-ia32": "3.0
|
|
46
|
-
"@koromix/koffi-win32-x64": "3.0
|
|
47
|
-
"@koromix/koffi-darwin-x64": "3.0
|
|
48
|
-
"@koromix/koffi-darwin-arm64": "3.0
|
|
49
|
-
"@koromix/koffi-linux-loong64": "3.0
|
|
36
|
+
"@koromix/koffi-linux-arm64": "3.1.0",
|
|
37
|
+
"@koromix/koffi-linux-ia32": "3.1.0",
|
|
38
|
+
"@koromix/koffi-linux-x64": "3.1.0",
|
|
39
|
+
"@koromix/koffi-linux-riscv64": "3.1.0",
|
|
40
|
+
"@koromix/koffi-freebsd-ia32": "3.1.0",
|
|
41
|
+
"@koromix/koffi-freebsd-x64": "3.1.0",
|
|
42
|
+
"@koromix/koffi-freebsd-arm64": "3.1.0",
|
|
43
|
+
"@koromix/koffi-openbsd-ia32": "3.1.0",
|
|
44
|
+
"@koromix/koffi-openbsd-x64": "3.1.0",
|
|
45
|
+
"@koromix/koffi-win32-ia32": "3.1.0",
|
|
46
|
+
"@koromix/koffi-win32-x64": "3.1.0",
|
|
47
|
+
"@koromix/koffi-darwin-x64": "3.1.0",
|
|
48
|
+
"@koromix/koffi-darwin-arm64": "3.1.0",
|
|
49
|
+
"@koromix/koffi-linux-loong64": "3.1.0"
|
|
50
50
|
},
|
|
51
51
|
"type": "module",
|
|
52
52
|
"main": "./index.cjs",
|
package/src/koffi/CMakeLists.txt
CHANGED
|
@@ -137,7 +137,8 @@ if(WIN32)
|
|
|
137
137
|
target_link_libraries(koffi PRIVATE ${UV_LINK_LIB})
|
|
138
138
|
endif()
|
|
139
139
|
|
|
140
|
-
target_compile_definitions(koffi PRIVATE FELIX_TARGET=koffi
|
|
140
|
+
target_compile_definitions(koffi PRIVATE FELIX_TARGET=koffi NAPI_VERSION=NAPI_VERSION_EXPERIMENTAL
|
|
141
|
+
NODE_ADDON_API_DISABLE_CPP_EXCEPTIONS NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS)
|
|
141
142
|
|
|
142
143
|
if(WIN32)
|
|
143
144
|
target_compile_definitions(koffi PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE)
|
|
@@ -175,12 +176,11 @@ endif()
|
|
|
175
176
|
if(NOT MSVC OR CMAKE_C_COMPILER_ID MATCHES "[Cc]lang")
|
|
176
177
|
# Restore C/C++ compiler sanity
|
|
177
178
|
|
|
178
|
-
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-
|
|
179
|
-
-fno-delete-null-pointer-checks>)
|
|
179
|
+
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-strict-aliasing -fno-delete-null-pointer-checks>)
|
|
180
180
|
if(MSVC)
|
|
181
|
-
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/clang:-fwrapv>)
|
|
181
|
+
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/clang:-fwrapv /clang:-fno-exceptions /clang:-fno-rtti>)
|
|
182
182
|
else()
|
|
183
|
-
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fwrapv>)
|
|
183
|
+
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fwrapv -fno-exceptions -fno-rtti>)
|
|
184
184
|
endif()
|
|
185
185
|
|
|
186
186
|
check_cxx_compiler_flag(-fno-finite-loops use_no_finite_loops)
|
|
@@ -217,18 +217,20 @@ else()
|
|
|
217
217
|
enable_unity_build(koffi)
|
|
218
218
|
endif()
|
|
219
219
|
|
|
220
|
-
if(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
220
|
+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
|
221
|
+
if(APPLE)
|
|
222
|
+
add_custom_command(
|
|
223
|
+
TARGET koffi POST_BUILD
|
|
224
|
+
COMMAND ${CMAKE_STRIP}
|
|
225
|
+
ARGS -x $<TARGET_FILE:koffi>
|
|
226
|
+
)
|
|
227
|
+
elseif(UNIX)
|
|
228
|
+
add_custom_command(
|
|
229
|
+
TARGET koffi POST_BUILD
|
|
230
|
+
COMMAND ${CMAKE_STRIP}
|
|
231
|
+
ARGS $<TARGET_FILE:koffi>
|
|
232
|
+
)
|
|
233
|
+
endif()
|
|
232
234
|
endif()
|
|
233
235
|
|
|
234
236
|
# ---- Debug ----
|