koffi 2.1.4 → 2.2.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 (89) hide show
  1. package/{src/koffi/ChangeLog.md → ChangeLog.md} +21 -1
  2. package/{src/koffi/LICENSE.txt → LICENSE.txt} +0 -0
  3. package/{src/koffi/README.md → README.md} +0 -0
  4. package/{src/koffi/doc → doc}/Makefile +1 -1
  5. package/{src/koffi/doc → doc}/benchmarks.md +0 -0
  6. package/{src/koffi/doc → doc}/benchmarks.xlsx +0 -0
  7. package/doc/callbacks.md +175 -0
  8. package/{src/koffi/doc → doc}/changes.md +2 -3
  9. package/{src/koffi/doc → doc}/conf.py +29 -6
  10. package/{src/koffi/doc → doc}/contribute.md +0 -0
  11. package/{src/koffi/doc → doc}/functions.md +39 -124
  12. package/{src/koffi/doc → doc}/index.rst +1 -0
  13. package/{src/koffi/doc → doc}/make.bat +1 -1
  14. package/{src/koffi/doc → doc}/memory.md +0 -0
  15. package/{src/koffi/doc → doc}/platforms.md +0 -0
  16. package/{src/koffi/doc → doc}/poetry.lock +0 -0
  17. package/{src/koffi/doc → doc}/pyproject.toml +0 -0
  18. package/{src/koffi/doc → doc}/start.md +0 -0
  19. package/{src/koffi/doc → doc}/static/bench_linux.png +0 -0
  20. package/{src/koffi/doc → doc}/static/bench_windows.png +0 -0
  21. package/{src/koffi/doc → doc}/static/custom.css +0 -0
  22. package/{src/koffi/doc → doc}/static/perf_linux_20220623.png +0 -0
  23. package/{src/koffi/doc → doc}/static/perf_linux_20220623_2.png +0 -0
  24. package/{src/koffi/doc → doc}/static/perf_linux_20220627.png +0 -0
  25. package/{src/koffi/doc → doc}/static/perf_linux_20220628.png +0 -0
  26. package/{src/koffi/doc → doc}/static/perf_linux_20220812.png +0 -0
  27. package/{src/koffi/doc → doc}/static/perf_windows_20220623.png +0 -0
  28. package/{src/koffi/doc → doc}/static/perf_windows_20220623_2.png +0 -0
  29. package/{src/koffi/doc → doc}/static/perf_windows_20220627.png +0 -0
  30. package/{src/koffi/doc → doc}/static/perf_windows_20220628.png +0 -0
  31. package/{src/koffi/doc → doc}/static/perf_windows_20220812.png +0 -0
  32. package/{src/koffi/doc → doc}/templates/badges.html +0 -0
  33. package/{src/koffi/doc → doc}/types.md +36 -9
  34. package/package.json +2 -2
  35. package/src/core/libcc/libcc.cc +89 -27
  36. package/src/core/libcc/libcc.hh +74 -39
  37. package/src/koffi/build/2.2.0/koffi_darwin_arm64.tar.gz +0 -0
  38. package/src/koffi/build/2.2.0/koffi_darwin_x64.tar.gz +0 -0
  39. package/src/koffi/build/2.2.0/koffi_freebsd_arm64.tar.gz +0 -0
  40. package/src/koffi/build/2.2.0/koffi_freebsd_ia32.tar.gz +0 -0
  41. package/src/koffi/build/2.2.0/koffi_freebsd_x64.tar.gz +0 -0
  42. package/src/koffi/build/2.2.0/koffi_linux_arm32hf.tar.gz +0 -0
  43. package/src/koffi/build/2.2.0/koffi_linux_arm64.tar.gz +0 -0
  44. package/src/koffi/build/2.2.0/koffi_linux_ia32.tar.gz +0 -0
  45. package/src/koffi/build/2.2.0/koffi_linux_riscv64hf64.tar.gz +0 -0
  46. package/src/koffi/build/2.2.0/koffi_linux_x64.tar.gz +0 -0
  47. package/src/koffi/build/2.2.0/koffi_openbsd_ia32.tar.gz +0 -0
  48. package/src/koffi/build/2.2.0/koffi_openbsd_x64.tar.gz +0 -0
  49. package/src/koffi/build/2.2.0/koffi_win32_arm64.tar.gz +0 -0
  50. package/src/koffi/build/2.2.0/koffi_win32_ia32.tar.gz +0 -0
  51. package/src/koffi/build/2.2.0/koffi_win32_x64.tar.gz +0 -0
  52. package/src/koffi/qemu/qemu.js +17 -7
  53. package/src/koffi/src/abi_arm32.cc +25 -23
  54. package/src/koffi/src/abi_arm64.cc +24 -22
  55. package/src/koffi/src/abi_riscv64.cc +20 -18
  56. package/src/koffi/src/abi_x64_sysv.cc +19 -17
  57. package/src/koffi/src/abi_x64_win.cc +18 -16
  58. package/src/koffi/src/abi_x86.cc +22 -20
  59. package/src/koffi/src/call.cc +220 -607
  60. package/src/koffi/src/call.hh +7 -11
  61. package/src/koffi/src/ffi.cc +229 -29
  62. package/src/koffi/src/ffi.hh +6 -2
  63. package/src/koffi/src/parser.cc +3 -9
  64. package/src/koffi/src/util.cc +546 -8
  65. package/src/koffi/src/util.hh +8 -2
  66. package/src/koffi/test/CMakeLists.txt +3 -3
  67. package/src/koffi/test/callbacks.js +70 -0
  68. package/src/koffi/test/misc.c +67 -0
  69. package/src/koffi/test/raylib.js +2 -2
  70. package/src/koffi/test/sqlite.js +1 -1
  71. package/src/koffi/test/sync.js +28 -6
  72. package/vendor/brotli/c/common/platform.h +2 -0
  73. package/vendor/sqlite3mc/sqlite3.c +243532 -0
  74. package/vendor/sqlite3mc/sqlite3.h +12887 -0
  75. package/src/koffi/build/2.1.4/koffi_darwin_arm64.tar.gz +0 -0
  76. package/src/koffi/build/2.1.4/koffi_darwin_x64.tar.gz +0 -0
  77. package/src/koffi/build/2.1.4/koffi_freebsd_arm64.tar.gz +0 -0
  78. package/src/koffi/build/2.1.4/koffi_freebsd_ia32.tar.gz +0 -0
  79. package/src/koffi/build/2.1.4/koffi_freebsd_x64.tar.gz +0 -0
  80. package/src/koffi/build/2.1.4/koffi_linux_arm32hf.tar.gz +0 -0
  81. package/src/koffi/build/2.1.4/koffi_linux_arm64.tar.gz +0 -0
  82. package/src/koffi/build/2.1.4/koffi_linux_ia32.tar.gz +0 -0
  83. package/src/koffi/build/2.1.4/koffi_linux_riscv64hf64.tar.gz +0 -0
  84. package/src/koffi/build/2.1.4/koffi_linux_x64.tar.gz +0 -0
  85. package/src/koffi/build/2.1.4/koffi_openbsd_ia32.tar.gz +0 -0
  86. package/src/koffi/build/2.1.4/koffi_openbsd_x64.tar.gz +0 -0
  87. package/src/koffi/build/2.1.4/koffi_win32_arm64.tar.gz +0 -0
  88. package/src/koffi/build/2.1.4/koffi_win32_ia32.tar.gz +0 -0
  89. package/src/koffi/build/2.1.4/koffi_win32_x64.tar.gz +0 -0
@@ -1764,10 +1764,11 @@ const char *GetQualifiedEnv(const char *name)
1764
1764
  // Each accessed environment variable is kept in memory and thus leaked once
1765
1765
  static HashMap<const char *, const char *> values;
1766
1766
 
1767
- std::pair<const char **, bool> ret = values.TrySet(name, nullptr);
1767
+ bool inserted;
1768
+ const char **ptr = values.TrySet(name, nullptr, &inserted);
1768
1769
 
1769
- if (ret.second) {
1770
- const char *ptr = (const char *)EM_ASM_INT({
1770
+ if (inserted) {
1771
+ const char *str = (const char *)EM_ASM_INT({
1771
1772
  try {
1772
1773
  var name = UTF8ToString($0);
1773
1774
  var str = process.env[name];
@@ -1785,10 +1786,10 @@ const char *GetQualifiedEnv(const char *name)
1785
1786
  }
1786
1787
  }, buf.data);
1787
1788
 
1788
- *ret.first = ptr;
1789
+ *ptr = str;
1789
1790
  }
1790
1791
 
1791
- return *ret.first;
1792
+ return *ptr;
1792
1793
  #else
1793
1794
  return getenv(buf.data);
1794
1795
  #endif
@@ -2131,6 +2132,7 @@ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info
2131
2132
  out_info->type = FileAttributesToType(attr.dwFileAttributes);
2132
2133
  out_info->size = ((uint64_t)attr.nFileSizeHigh << 32) | attr.nFileSizeLow;
2133
2134
  out_info->mtime = FileTimeToUnixTime(attr.ftLastWriteTime);
2135
+ out_info->btime = FileTimeToUnixTime(attr.ftCreationTime);
2134
2136
  out_info->mode = (out_info->type == FileType::Directory) ? 0755 : 0644;
2135
2137
 
2136
2138
  return StatResult::Success;
@@ -2281,6 +2283,42 @@ static FileType FileModeToType(mode_t mode)
2281
2283
 
2282
2284
  StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
2283
2285
  {
2286
+ #ifdef __linux__
2287
+ int stat_flags = (flags & (int)StatFlag::FollowSymlink) ? 0 : AT_SYMLINK_NOFOLLOW;
2288
+ int stat_mask = STATX_TYPE | STATX_MODE | STATX_MTIME | STATX_BTIME | STATX_SIZE;
2289
+
2290
+ struct statx sxb;
2291
+ if (statx(AT_FDCWD, filename, stat_flags, stat_mask, &sxb) < 0) {
2292
+ switch (errno) {
2293
+ case ENOENT: {
2294
+ if (!(flags & (int)StatFlag::IgnoreMissing)) {
2295
+ LogError("Cannot stat '%1': %2", filename, strerror(errno));
2296
+ }
2297
+ return StatResult::MissingPath;
2298
+ } break;
2299
+ case EACCES: {
2300
+ LogError("Cannot stat '%1': %2", filename, strerror(errno));
2301
+ return StatResult::AccessDenied;
2302
+ } break;
2303
+ default: {
2304
+ LogError("Cannot stat '%1': %2", filename, strerror(errno));
2305
+ return StatResult::OtherError;
2306
+ } break;
2307
+ }
2308
+ }
2309
+
2310
+ out_info->type = FileModeToType(sxb.stx_mode);
2311
+ out_info->size = (int64_t)sxb.stx_size;
2312
+ out_info->mtime = (int64_t)sxb.stx_mtime.tv_sec * 1000 +
2313
+ (int64_t)sxb.stx_mtime.tv_nsec / 1000000;
2314
+ if (sxb.stx_mask & STATX_BTIME) {
2315
+ out_info->btime = (int64_t)sxb.stx_btime.tv_sec * 1000 +
2316
+ (int64_t)sxb.stx_btime.tv_nsec / 1000000;
2317
+ } else {
2318
+ out_info->btime = out_info->mtime;
2319
+ }
2320
+ out_info->mode = (unsigned int)sxb.stx_mode & ~S_IFMT;
2321
+ #else
2284
2322
  int stat_flags = (flags & (int)StatFlag::FollowSymlink) ? 0 : AT_SYMLINK_NOFOLLOW;
2285
2323
 
2286
2324
  struct stat sb;
@@ -2305,16 +2343,24 @@ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info
2305
2343
 
2306
2344
  out_info->type = FileModeToType(sb.st_mode);
2307
2345
  out_info->size = (int64_t)sb.st_size;
2308
- #if defined(__linux__)
2309
- out_info->mtime = (int64_t)sb.st_mtim.tv_sec * 1000 +
2310
- (int64_t)sb.st_mtim.tv_nsec / 1000000;
2311
- #elif defined(__APPLE__)
2346
+ #if defined(__APPLE__)
2312
2347
  out_info->mtime = (int64_t)sb.st_mtimespec.tv_sec * 1000 +
2313
- (int64_t)sb.st_mtimespec.tv_nsec / 1000000;
2348
+ (int64_t)sb.st_mtimespec.tv_nsec / 1000000;
2349
+ out_info->btime = (int64_t)sb.st_birthtimespec.tv_sec * 1000 +
2350
+ (int64_t)sb.st_birthtimespec.tv_nsec / 1000000;
2351
+ #elif defined(__OpenBSD__)
2352
+ out_info->mtime = (int64_t)sb.st_mtim.tv_sec * 1000 +
2353
+ (int64_t)sb.st_mtim.tv_nsec / 1000000;
2354
+ out_info->btime = (int64_t)sb.__st_birthtim.tv_sec * 1000 +
2355
+ (int64_t)sb.__st_birthtim.tv_nsec / 1000000;
2314
2356
  #else
2315
- out_info->mtime = (int64_t)sb.st_mtime * 1000;
2357
+ out_info->mtime = (int64_t)sb.st_mtim.tv_sec * 1000 +
2358
+ (int64_t)sb.st_mtim.tv_nsec / 1000000;
2359
+ out_info->btime = (int64_t)sb.st_birthtim.tv_sec * 1000 +
2360
+ (int64_t)sb.st_birthtim.tv_nsec / 1000000;
2316
2361
  #endif
2317
2362
  out_info->mode = (unsigned int)sb.st_mode;
2363
+ #endif
2318
2364
 
2319
2365
  return StatResult::Success;
2320
2366
  }
@@ -2540,6 +2586,14 @@ bool TestFile(const char *filename, FileType type)
2540
2586
  return true;
2541
2587
  }
2542
2588
 
2589
+ bool IsDirectory(const char *filename)
2590
+ {
2591
+ FileInfo file_info;
2592
+ if (StatFile(filename, (int)StatFlag::IgnoreMissing, &file_info) != StatResult::Success)
2593
+ return false;
2594
+ return file_info.type == FileType::Directory;
2595
+ }
2596
+
2543
2597
  static Size MatchPathItem(const char *path, const char *spec)
2544
2598
  {
2545
2599
  Size i = 0;
@@ -2843,7 +2897,7 @@ const char *GetApplicationExecutable()
2843
2897
  static char executable_path[4096];
2844
2898
 
2845
2899
  if (!executable_path[0]) {
2846
- int name[4] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV};
2900
+ int name[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
2847
2901
 
2848
2902
  size_t argc;
2849
2903
  {
@@ -2879,7 +2933,7 @@ const char *GetApplicationExecutable()
2879
2933
  static char executable_path[4096];
2880
2934
 
2881
2935
  if (!executable_path[0]) {
2882
- int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
2936
+ int name[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
2883
2937
  size_t len = sizeof(executable_path);
2884
2938
 
2885
2939
  int ret = sysctl(name, RG_LEN(name), executable_path, &len, NULL, 0);
@@ -3431,7 +3485,8 @@ OpenResult OpenDescriptor(const char *filename, unsigned int flags, unsigned int
3431
3485
  RG_ASSERT(!(flags & (int)OpenFlag::Exclusive));
3432
3486
  RG_ASSERT(!(flags & (int)OpenFlag::Append));
3433
3487
 
3434
- oflags &= ~O_CREAT;
3488
+ oflags &= ~(O_CREAT | O_WRONLY | O_RDWR | O_TRUNC);
3489
+ oflags |= O_RDONLY;
3435
3490
  }
3436
3491
  if (flags & (int)OpenFlag::Exists) {
3437
3492
  RG_ASSERT(!(flags & (int)OpenFlag::Exclusive));
@@ -3951,8 +4006,8 @@ bool ExecuteCommandLine(const char *cmd_line, FunctionRef<Span<const uint8_t>()>
3951
4006
  #if defined(__OpenBSD__) || defined(__FreeBSD__)
3952
4007
  static const pthread_t main_thread = pthread_self();
3953
4008
  #endif
3954
- static std::atomic_bool flag_interrupt {false};
3955
- static std::atomic_bool explicit_interrupt {false};
4009
+ static std::atomic_bool flag_interrupt { false };
4010
+ static std::atomic_bool explicit_interrupt { false };
3956
4011
  static int interrupt_pfd[2] = {-1, -1};
3957
4012
 
3958
4013
  void SetSignalHandler(int signal, void (*func)(int), struct sigaction *prev)
@@ -4141,15 +4196,15 @@ bool ExecuteCommandLine(const char *cmd_line, FunctionRef<Span<const uint8_t>()>
4141
4196
  int in_idx = -1, out_idx = -1, term_idx = -1;
4142
4197
  if (in_pfd[1] >= 0) {
4143
4198
  in_idx = pfds.len;
4144
- pfds.Append({in_pfd[1], POLLOUT});
4199
+ pfds.Append({ in_pfd[1], POLLOUT, 0 });
4145
4200
  }
4146
4201
  if (out_pfd[0] >= 0) {
4147
4202
  out_idx = pfds.len;
4148
- pfds.Append({out_pfd[0], POLLIN});
4203
+ pfds.Append({ out_pfd[0], POLLIN, 0 });
4149
4204
  }
4150
4205
  if (interrupt_pfd[0] >= 0) {
4151
4206
  term_idx = pfds.len;
4152
- pfds.Append({interrupt_pfd[0], POLLIN});
4207
+ pfds.Append({ interrupt_pfd[0], POLLIN, 0 });
4153
4208
  }
4154
4209
 
4155
4210
  if (RG_POSIX_RESTART_EINTR(poll(pfds.data, (nfds_t)pfds.len, -1), < 0) < 0) {
@@ -4378,7 +4433,7 @@ void WaitDelay(int64_t delay)
4378
4433
 
4379
4434
  WaitForResult WaitForInterrupt(int64_t timeout)
4380
4435
  {
4381
- static std::atomic_bool message {false};
4436
+ static std::atomic_bool message { false };
4382
4437
 
4383
4438
  flag_interrupt = true;
4384
4439
  SetSignalHandler(SIGUSR1, [](int) { message = true; });
@@ -5262,7 +5317,7 @@ class AsyncPool {
5262
5317
 
5263
5318
  HeapArray<TaskQueue> queues;
5264
5319
  int next_queue_idx = 0;
5265
- std::atomic_int pending_tasks {0};
5320
+ std::atomic_int pending_tasks { 0 };
5266
5321
 
5267
5322
  public:
5268
5323
  AsyncPool(int threads, bool leak);
@@ -5325,7 +5380,9 @@ Async::Async(Async *parent, bool stop_after_error)
5325
5380
 
5326
5381
  Async::~Async()
5327
5382
  {
5383
+ success = false;
5328
5384
  Sync();
5385
+
5329
5386
  pool->UnregisterAsync();
5330
5387
  }
5331
5388
 
@@ -5409,7 +5466,7 @@ void AsyncPool::AddTask(Async *async, const std::function<bool()> &func)
5409
5466
 
5410
5467
  std::unique_lock<std::mutex> lock_queue(queue->queue_mutex, std::try_to_lock);
5411
5468
  if (lock_queue.owns_lock()) {
5412
- queue->tasks.Append({async, func});
5469
+ queue->tasks.Append({ async, func });
5413
5470
  break;
5414
5471
  }
5415
5472
  }
@@ -5417,7 +5474,7 @@ void AsyncPool::AddTask(Async *async, const std::function<bool()> &func)
5417
5474
  TaskQueue *queue = &queues[async_running_worker_idx];
5418
5475
 
5419
5476
  std::lock_guard<std::mutex> lock_queue(queue->queue_mutex);
5420
- queue->tasks.Append({async, func});
5477
+ queue->tasks.Append({ async, func });
5421
5478
  }
5422
5479
 
5423
5480
  async->remaining_tasks++;
@@ -7168,19 +7225,24 @@ IniParser::LineType IniParser::FindNextLine(IniProperty *out_prop)
7168
7225
  }
7169
7226
 
7170
7227
  current_section.RemoveFrom(0);
7228
+ current_section.Grow(section.len + 1);
7171
7229
  current_section.Append(section);
7230
+ current_section.ptr[current_section.len] = 0;
7172
7231
 
7173
7232
  err_guard.Disable();
7174
7233
  return LineType::Section;
7175
7234
  } else {
7176
7235
  Span<char> value;
7177
- Span<const char> key = TrimStr(SplitStr(line, '=', &value));
7236
+
7237
+ Span<char> key = TrimStr(SplitStr(line, '=', &value));
7178
7238
  if (!key.len || key.end() == line.end()) {
7179
7239
  LogError("Expected [section] or <key> = <value> pair");
7180
7240
  return LineType::Exit;
7181
7241
  }
7182
7242
  if (!CheckIniKey(key))
7183
7243
  return LineType::Exit;
7244
+ key.ptr[key.len] = 0;
7245
+
7184
7246
  value = TrimStr(value);
7185
7247
  *value.end() = 0;
7186
7248
 
@@ -8245,15 +8307,15 @@ Vec2<int> ConsolePrompter::GetConsoleSize()
8245
8307
 
8246
8308
  CONSOLE_SCREEN_BUFFER_INFO screen;
8247
8309
  if (GetConsoleScreenBufferInfo(h, &screen))
8248
- return {screen.dwSize.X, screen.dwSize.Y};
8310
+ return { screen.dwSize.X, screen.dwSize.Y };
8249
8311
  #else
8250
8312
  struct winsize ws;
8251
8313
  if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0 && ws.ws_col)
8252
- return {ws.ws_col, ws.ws_row};
8314
+ return { ws.ws_col, ws.ws_row };
8253
8315
  #endif
8254
8316
 
8255
8317
  // Give up!
8256
- return {80, 24};
8318
+ return { 80, 24 };
8257
8319
  }
8258
8320
 
8259
8321
  int32_t ConsolePrompter::ReadChar()
@@ -31,6 +31,7 @@
31
31
  #include <stdio.h>
32
32
  #include <stdlib.h>
33
33
  #include <string.h>
34
+ #include <thread>
34
35
  #include <type_traits>
35
36
  #include <utility>
36
37
  #if defined(_WIN32)
@@ -38,8 +39,6 @@
38
39
  #elif !defined(__APPLE__) && (!defined(__linux__) || defined(__GLIBC__)) && __has_include(<ucontext.h>)
39
40
  #define RG_FIBER_USE_UCONTEXT
40
41
  #include <ucontext.h>
41
- #else
42
- #include <thread>
43
42
  #endif
44
43
  #ifdef __EMSCRIPTEN__
45
44
  #include <emscripten.h>
@@ -1123,7 +1122,7 @@ public:
1123
1122
  template <typename T>
1124
1123
  class RetainObject {
1125
1124
  mutable void (*delete_func)(T *) = nullptr;
1126
- mutable std::atomic_int refcount {0};
1125
+ mutable std::atomic_int refcount { 0 };
1127
1126
 
1128
1127
  public:
1129
1128
  void Ref() const { refcount++; }
@@ -2143,36 +2142,56 @@ public:
2143
2142
  ValueType *Set(const ValueType &value)
2144
2143
  {
2145
2144
  const KeyType &key = Handler::GetKey(value);
2146
- ValueType *it = Insert(key).first;
2147
- *it = value;
2148
- return it;
2145
+
2146
+ bool inserted;
2147
+ ValueType *ptr = Insert(key, &inserted);
2148
+
2149
+ *ptr = value;
2150
+
2151
+ return ptr;
2149
2152
  }
2150
2153
  ValueType *SetDefault(const KeyType &key)
2151
2154
  {
2152
- std::pair<ValueType *, bool> ret = Insert(key);
2153
- if (!ret.second) {
2154
- ret.first->~ValueType();
2155
+ bool inserted;
2156
+ ValueType *ptr = Insert(key, &inserted);
2157
+
2158
+ if (!inserted) {
2159
+ ptr->~ValueType();
2155
2160
  }
2156
- new (ret.first) ValueType();
2157
- return ret.first;
2161
+ new (ptr) ValueType();
2162
+
2163
+ return ptr;
2158
2164
  }
2159
2165
 
2160
- std::pair<ValueType *, bool> TrySet(const ValueType &value)
2166
+ ValueType *TrySet(const ValueType &value, bool *out_inserted = nullptr)
2161
2167
  {
2162
2168
  const KeyType &key = Handler::GetKey(value);
2163
- std::pair<ValueType *, bool> ret = Insert(key);
2164
- if (ret.second) {
2165
- *ret.first = value;
2169
+
2170
+ bool inserted;
2171
+ ValueType *ptr = Insert(key, &inserted);
2172
+
2173
+ if (inserted) {
2174
+ *ptr = value;
2166
2175
  }
2167
- return ret;
2176
+
2177
+ if (out_inserted) {
2178
+ *out_inserted = inserted;
2179
+ }
2180
+ return ptr;
2168
2181
  }
2169
- std::pair<ValueType *, bool> TrySetDefault(const KeyType &key)
2182
+ ValueType *TrySetDefault(const KeyType &key, bool *out_inserted = nullptr)
2170
2183
  {
2171
- std::pair<ValueType *, bool> ret = Insert(key);
2172
- if (ret.second) {
2173
- new (ret.first) ValueType();
2184
+ bool inserted;
2185
+ ValueType *ptr = Insert(key, &inserted);
2186
+
2187
+ if (inserted) {
2188
+ new (ptr) ValueType();
2174
2189
  }
2175
- return ret;
2190
+
2191
+ if (out_inserted) {
2192
+ *out_inserted = inserted;
2193
+ }
2194
+ return ptr;
2176
2195
  }
2177
2196
 
2178
2197
  void Remove(ValueType *it)
@@ -2257,7 +2276,7 @@ private:
2257
2276
  }
2258
2277
  }
2259
2278
 
2260
- std::pair<ValueType *, bool> Insert(const KeyType &key)
2279
+ ValueType *Insert(const KeyType &key, bool *out_inserted)
2261
2280
  {
2262
2281
  uint64_t hash = Handler::HashKey(key);
2263
2282
 
@@ -2274,9 +2293,12 @@ private:
2274
2293
  }
2275
2294
  count++;
2276
2295
  MarkUsed(idx);
2277
- return {&data[idx], true};
2296
+
2297
+ *out_inserted = true;
2298
+ return &data[idx];
2278
2299
  } else {
2279
- return {it, false};
2300
+ *out_inserted = false;
2301
+ return it;
2280
2302
  }
2281
2303
  } else {
2282
2304
  Rehash(RG_HASHTABLE_BASE_CAPACITY);
@@ -2284,7 +2306,9 @@ private:
2284
2306
  Size idx = HashToIndex(hash);
2285
2307
  count++;
2286
2308
  MarkUsed(idx);
2287
- return {&data[idx], true};
2309
+
2310
+ *out_inserted = true;
2311
+ return &data[idx];
2288
2312
  }
2289
2313
  }
2290
2314
 
@@ -2566,7 +2590,7 @@ public:
2566
2590
  }
2567
2591
 
2568
2592
  ValueType *Set(const KeyType &key, const ValueType &value)
2569
- { return &table.Set({key, value})->value; }
2593
+ { return &table.Set({ key, value })->value; }
2570
2594
  ValueType *SetDefault(const KeyType &key)
2571
2595
  {
2572
2596
  Bucket *table_it = table.SetDefault(key);
@@ -2574,16 +2598,24 @@ public:
2574
2598
  return &table_it->value;
2575
2599
  }
2576
2600
 
2577
- std::pair<ValueType *, bool> TrySet(const KeyType &key, const ValueType &value)
2601
+ ValueType *TrySet(const KeyType &key, const ValueType &value, bool *out_inserted = nullptr)
2578
2602
  {
2579
- std::pair<Bucket *, bool> ret = table.TrySet({key, value});
2580
- return { &ret.first->value, ret.second };
2603
+ Bucket *ptr = table.TrySet({ key, value }, out_inserted);
2604
+ return &ptr->value;
2581
2605
  }
2582
- std::pair<ValueType *, bool> TrySetDefault(const KeyType &key)
2606
+ ValueType *TrySetDefault(const KeyType &key, bool *out_inserted = nullptr)
2583
2607
  {
2584
- std::pair<Bucket *, bool> ret = table.TrySetDefault(key);
2585
- ret.first->key = key;
2586
- return { &ret.first->value, ret.second };
2608
+ bool inserted;
2609
+ Bucket *ptr = table.TrySetDefault(key, &inserted);
2610
+
2611
+ if (inserted) {
2612
+ ptr->key = key;
2613
+ }
2614
+
2615
+ if (out_inserted) {
2616
+ *out_inserted = inserted;
2617
+ }
2618
+ return &ptr->value;
2587
2619
  }
2588
2620
 
2589
2621
  void Remove(ValueType *it)
@@ -2636,7 +2668,8 @@ public:
2636
2668
  { return table.FindValue(value, default_value); }
2637
2669
 
2638
2670
  ValueType *Set(const ValueType &value) { return table.Set(value); }
2639
- std::pair<ValueType *, bool> TrySet(const ValueType &value) { return table.TrySet(value); }
2671
+ ValueType *TrySet(const ValueType &value, bool *out_inserted = nullptr)
2672
+ { return table.TrySet(value, out_inserted); }
2640
2673
 
2641
2674
  void Remove(ValueType *it) { table.Remove(it); }
2642
2675
  template <typename T = ValueType>
@@ -2666,10 +2699,10 @@ union LocalDate {
2666
2699
  LocalDate() = default;
2667
2700
  #ifdef RG_BIG_ENDIAN
2668
2701
  LocalDate(int16_t year, int8_t month, int8_t day)
2669
- : st({year, month, day}) { RG_ASSERT(IsValid()); }
2702
+ : st({ year, month, day }) { RG_ASSERT(IsValid()); }
2670
2703
  #else
2671
2704
  LocalDate(int16_t year, int8_t month, int8_t day)
2672
- : st({day, month, year}) { RG_ASSERT(IsValid()); }
2705
+ : st({ day, month, year }) { RG_ASSERT(IsValid()); }
2673
2706
  #endif
2674
2707
 
2675
2708
  static inline bool IsLeapYear(int16_t year)
@@ -2678,7 +2711,7 @@ union LocalDate {
2678
2711
  }
2679
2712
  static inline int8_t DaysInMonth(int16_t year, int8_t month)
2680
2713
  {
2681
- static const int8_t DaysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
2714
+ static const int8_t DaysPerMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2682
2715
  return (int8_t)(DaysPerMonth[month - 1] + (month == 2 && IsLeapYear(year)));
2683
2716
  }
2684
2717
 
@@ -3799,6 +3832,7 @@ struct FileInfo {
3799
3832
 
3800
3833
  int64_t size;
3801
3834
  int64_t mtime;
3835
+ int64_t btime;
3802
3836
  unsigned int mode;
3803
3837
  };
3804
3838
 
@@ -3842,6 +3876,7 @@ bool IsDirectoryEmpty(const char *dirname);
3842
3876
 
3843
3877
  bool TestFile(const char *filename);
3844
3878
  bool TestFile(const char *filename, FileType type);
3879
+ bool IsDirectory(const char *filename);
3845
3880
 
3846
3881
  bool MatchPathName(const char *path, const char *spec);
3847
3882
  bool MatchPathSpec(const char *path, const char *spec);
@@ -4080,8 +4115,8 @@ class Async {
4080
4115
  RG_DELETE_COPY(Async)
4081
4116
 
4082
4117
  bool stop_after_error;
4083
- std::atomic_bool success {true};
4084
- std::atomic_int remaining_tasks {0};
4118
+ std::atomic_bool success { true };
4119
+ std::atomic_int remaining_tasks { 0 };
4085
4120
 
4086
4121
  class AsyncPool *pool;
4087
4122
 
@@ -296,7 +296,9 @@ async function pack() {
296
296
  if (!success)
297
297
  return false;
298
298
 
299
- execFileSync('npm', ['pack', '--pack-destination', pack_dir], {
299
+ let npm = (process.platform == 'win32') ? 'npm.cmd' : 'npm';
300
+
301
+ execFileSync(npm, ['pack', '--pack-destination', pack_dir], {
300
302
  cwd: dist_dir,
301
303
  stdio: 'inherit',
302
304
  });
@@ -309,7 +311,9 @@ async function publish() {
309
311
  if (!success)
310
312
  return false;
311
313
 
312
- execFileSync('npm', ['publish'], {
314
+ let npm = (process.platform == 'win32') ? 'npm.cmd' : 'npm';
315
+
316
+ execFileSync(npm, ['publish'], {
313
317
  cwd: dist_dir,
314
318
  stdio: 'inherit'
315
319
  });
@@ -483,8 +487,12 @@ async function prepare(dist_dir) {
483
487
  pkg.cnoke.require = "./src/koffi/build/koffi.node";
484
488
 
485
489
  fs.writeFileSync(dist_dir + '/package.json', JSON.stringify(pkg, null, 4));
486
- fs.unlinkSync(dist_dir + '/src/koffi/package.json', '');
487
- fs.unlinkSync(dist_dir + '/src/koffi/.gitignore', '');
490
+ fs.unlinkSync(dist_dir + '/src/koffi/package.json');
491
+ fs.unlinkSync(dist_dir + '/src/koffi/.gitignore');
492
+ fs.renameSync(dist_dir + '/src/koffi/README.md', dist_dir + '/README.md');
493
+ fs.renameSync(dist_dir + '/src/koffi/LICENSE.txt', dist_dir + '/LICENSE.txt');
494
+ fs.renameSync(dist_dir + '/src/koffi/ChangeLog.md', dist_dir + '/ChangeLog.md');
495
+ fs.renameSync(dist_dir + '/web/koffi.dev', dist_dir + '/doc');
488
496
  }
489
497
 
490
498
  return true;
@@ -498,7 +506,7 @@ function snapshot() {
498
506
 
499
507
  console.log('>> Snapshot code...');
500
508
  copy_recursive(root_dir, snapshot_dir, filename => {
501
- let parts = filename.split(/[\/\\]/);
509
+ let parts = filename.split('/');
502
510
 
503
511
  if (parts[0] == 'src' && parts[1] == 'core') {
504
512
  return parts[2] == null || parts[2] == 'libcc';
@@ -512,6 +520,8 @@ function snapshot() {
512
520
  parts[1] == 'node-addon-api' ||
513
521
  parts[1] == 'raylib' ||
514
522
  parts[1] == 'sqlite3mc';
523
+ } else if (parts[0] == 'web') {
524
+ return parts[1] == null || parts[1] == 'koffi.dev';
515
525
  } else {
516
526
  return false;
517
527
  }
@@ -783,7 +793,7 @@ function check_qemu() {
783
793
 
784
794
  function copy_recursive(src, dest, validate = filename => true) {
785
795
  let proc = spawnSync('git', ['ls-files', '-i', '-o', '--exclude-standard', '--directory'], { cwd: src });
786
- let ignored = new Set(proc.stdout.toString().split('\n').map(it => it.trim().replace(/[\\\/+]$/, '')).filter(it => it));
796
+ let ignored = new Set(proc.stdout.toString().split('\n').map(it => it.trim().replace(/[\\\/+]$/, '').replaceAll('\\', '/')).filter(it => it));
787
797
 
788
798
  recurse(src, dest, '');
789
799
 
@@ -793,7 +803,7 @@ function copy_recursive(src, dest, validate = filename => true) {
793
803
  for (let entry of entries) {
794
804
  let src_filename = path.join(src, entry.name);
795
805
  let dest_filename = path.join(dest, entry.name);
796
- let filename = path.join(nice, entry.name);
806
+ let filename = nice + (nice ? '/' : '') + entry.name;
797
807
 
798
808
  if (ignored.has(filename))
799
809
  continue;