koffi 3.0.1 → 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.
Files changed (50) hide show
  1. package/CHANGELOG.md +32 -3
  2. package/cnoke.cjs +2 -2
  3. package/doc/benchmarks.md +1 -1
  4. package/doc/callbacks.md +7 -26
  5. package/doc/{input.md → composites.md} +161 -147
  6. package/doc/contribute.md +3 -2
  7. package/doc/index.md +0 -14
  8. package/doc/{functions.md → load.md} +54 -113
  9. package/doc/migration.md +4 -7
  10. package/doc/misc.md +0 -103
  11. package/doc/output.md +5 -11
  12. package/doc/pointers.md +76 -17
  13. package/doc/primitives.md +151 -0
  14. package/doc/start.md +3 -13
  15. package/doc/types.md +88 -0
  16. package/doc/unions.md +0 -186
  17. package/doc/values.md +134 -0
  18. package/index.d.ts +375 -308
  19. package/lib/native/base/base.cc +66 -24
  20. package/lib/native/base/base.hh +55 -153
  21. package/package.json +16 -16
  22. package/src/koffi/CMakeLists.txt +20 -17
  23. package/src/koffi/index.cjs +30 -111
  24. package/src/koffi/index.js +22 -96
  25. package/src/koffi/indirect.cjs +30 -111
  26. package/src/koffi/indirect.js +24 -24
  27. package/src/koffi/src/abi/arm64.cc +48 -62
  28. package/src/koffi/src/abi/riscv64.cc +39 -57
  29. package/src/koffi/src/abi/x64sysv.cc +39 -57
  30. package/src/koffi/src/abi/x64win.cc +48 -65
  31. package/src/koffi/src/abi/x86.cc +47 -59
  32. package/src/koffi/src/call.cc +426 -209
  33. package/src/koffi/src/call.hh +7 -11
  34. package/src/koffi/src/ffi.cc +534 -303
  35. package/src/koffi/src/ffi.hh +71 -15
  36. package/src/koffi/src/parser.cc +5 -3
  37. package/src/koffi/src/parser.hh +2 -2
  38. package/src/koffi/src/static.cjs +122 -0
  39. package/src/koffi/src/static.js +125 -0
  40. package/src/koffi/src/type.cc +725 -0
  41. package/src/koffi/src/type.hh +71 -0
  42. package/src/koffi/src/util.cc +117 -1202
  43. package/src/koffi/src/util.hh +158 -156
  44. package/src/koffi/src/uv.cc +17 -11
  45. package/src/koffi/src/uv.hh +2 -1
  46. package/vendor/node-addon-api/README.md +1 -1
  47. package/vendor/node-addon-api/napi-inl.h +213 -35
  48. package/vendor/node-addon-api/napi.h +118 -7
  49. package/doc/variables.md +0 -102
  50. package/indirect.d.ts +0 -322
@@ -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::TimeISO: {
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 FmtHtmlSafe::Format(FunctionRef<void(Span<const char>)> append) const
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 = true;
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<char> out_output)
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<char> *out_output)
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, bool soon);
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, false);
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, nullptr);
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, bool soon)
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, soon ? async : nullptr);
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
- LogError("Unknown MIME type for extension '%1'", extension);
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/"))
@@ -3074,8 +3074,8 @@ private:
3074
3074
  template <typename T>
3075
3075
  class HashTraits {
3076
3076
  public:
3077
- static constexpr uint64_t Hash(const T &key) { return key.Hash(); }
3078
- static constexpr bool Test(const T &key1, const T &key2) { return key1 == key2; }
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 constexpr inline uint64_t HashStr(Span<const char> str)
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
- __builtin_memcpy(&result, p, sizeof(result));
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 constexpr inline uint64_t HashStr(const char *str)
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 constexpr uint64_t Hash(Span<const char> key) { return HashStr(key); }
3229
- static constexpr uint64_t Hash(const char *key) { return HashStr(key); }
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 constexpr bool Test(const char *key1, const char *key2) { return TestStr(key1, key2); }
3232
- static constexpr bool Test(const char *key1, Span<const char> key2) { return key2 == key1; }
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 constexpr uint64_t Hash(Span<const char> key) { return HashStr(key); }
3239
- static constexpr uint64_t Hash(const char *key) { return HashStr(key); }
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 constexpr bool Test(Span<const char> key1, Span<const char> key2) { return key1 == key2; }
3242
- static constexpr bool Test(Span<const char> key1, const char * key2) { return key1 == key2; }
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 constexpr KeyType GetKey(const ValueType &value) \
3221
+ static KeyType GetKey(const ValueType &value) \
3249
3222
  { return (KeyType)(value.KeyMember); } \
3250
- static constexpr KeyType GetKey(const ValueType *value) \
3223
+ static KeyType GetKey(const ValueType *value) \
3251
3224
  { return (KeyType)(value->KeyMember); } \
3252
3225
  template <typename TestKey> \
3253
- static constexpr uint64_t HashKey(TestKey key) \
3226
+ static uint64_t HashKey(TestKey key) \
3254
3227
  { return HashFunc(key); } \
3255
3228
  template <typename TestKey> \
3256
- static constexpr bool TestKeys(KeyType key1, TestKey key2) \
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 constexpr ValueType GetKey(const ValueType &value) { return value; }
3359
- static constexpr ValueType GetKey(const ValueType *value) { return *value; }
3360
- static constexpr uint64_t HashKey(const ValueType &value)
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 constexpr bool TestKeys(const ValueType &value1, const ValueType &value2)
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
- TimeISO,
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 FmtTimeISO(TimeSpec spec, bool ms = false)
3820
+ static inline FmtArg FmtTimeBasic(TimeSpec spec, bool ms = false)
3942
3821
  {
3943
3822
  FmtArg arg;
3944
- arg.type = FmtType::TimeISO;
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 FmtHtmlSafe {
3951
+ class FmtXmlSafe {
4064
3952
  Span<const char> str;
4065
3953
 
4066
3954
  public:
4067
- FmtHtmlSafe(Span<const char> str) : str(str) {}
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<char> out_output);
4679
- bool ReadCommandOutput(const char *cmd_line, HeapArray<char> *out_output);
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.1",
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.1",
37
- "@koromix/koffi-linux-ia32": "3.0.1",
38
- "@koromix/koffi-linux-x64": "3.0.1",
39
- "@koromix/koffi-linux-riscv64": "3.0.1",
40
- "@koromix/koffi-freebsd-ia32": "3.0.1",
41
- "@koromix/koffi-freebsd-x64": "3.0.1",
42
- "@koromix/koffi-freebsd-arm64": "3.0.1",
43
- "@koromix/koffi-openbsd-ia32": "3.0.1",
44
- "@koromix/koffi-openbsd-x64": "3.0.1",
45
- "@koromix/koffi-win32-ia32": "3.0.1",
46
- "@koromix/koffi-win32-x64": "3.0.1",
47
- "@koromix/koffi-darwin-x64": "3.0.1",
48
- "@koromix/koffi-darwin-arm64": "3.0.1",
49
- "@koromix/koffi-linux-loong64": "3.0.1"
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",
@@ -60,7 +60,7 @@
60
60
  "./indirect": {
61
61
  "import": "./indirect.js",
62
62
  "require": "./indirect.cjs",
63
- "types": "./indirect.d.ts"
63
+ "types": "./index.d.ts"
64
64
  }
65
65
  },
66
66
  "types": "./index.d.ts"
@@ -67,6 +67,7 @@ set(KOFFI_SRC
67
67
  src/call.cc
68
68
  src/ffi.cc
69
69
  src/parser.cc
70
+ src/type.cc
70
71
  src/util.cc
71
72
  src/uv.cc
72
73
  src/win32.cc
@@ -136,7 +137,8 @@ if(WIN32)
136
137
  target_link_libraries(koffi PRIVATE ${UV_LINK_LIB})
137
138
  endif()
138
139
 
139
- target_compile_definitions(koffi PRIVATE FELIX_TARGET=koffi NAPI_DISABLE_CPP_EXCEPTIONS NAPI_VERSION=NAPI_VERSION_EXPERIMENTAL)
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)
140
142
 
141
143
  if(WIN32)
142
144
  target_compile_definitions(koffi PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE)
@@ -174,12 +176,11 @@ endif()
174
176
  if(NOT MSVC OR CMAKE_C_COMPILER_ID MATCHES "[Cc]lang")
175
177
  # Restore C/C++ compiler sanity
176
178
 
177
- target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti -fno-strict-aliasing
178
- -fno-delete-null-pointer-checks>)
179
+ target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-strict-aliasing -fno-delete-null-pointer-checks>)
179
180
  if(MSVC)
180
- 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>)
181
182
  else()
182
- target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fwrapv>)
183
+ target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fwrapv -fno-exceptions -fno-rtti>)
183
184
  endif()
184
185
 
185
186
  check_cxx_compiler_flag(-fno-finite-loops use_no_finite_loops)
@@ -216,18 +217,20 @@ else()
216
217
  enable_unity_build(koffi)
217
218
  endif()
218
219
 
219
- if(APPLE)
220
- add_custom_command(
221
- TARGET koffi POST_BUILD
222
- COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
223
- ARGS -x $<TARGET_FILE:koffi>
224
- )
225
- elseif(UNIX)
226
- add_custom_command(
227
- TARGET koffi POST_BUILD
228
- COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
229
- ARGS $<TARGET_FILE:koffi>
230
- )
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()
231
234
  endif()
232
235
 
233
236
  # ---- Debug ----