koffi 2.14.1 → 2.15.1

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 (113) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/build/koffi/darwin_arm64/koffi.node +0 -0
  3. package/build/koffi/darwin_x64/koffi.node +0 -0
  4. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  5. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  6. package/build/koffi/freebsd_x64/koffi.node +0 -0
  7. package/build/koffi/linux_arm64/koffi.node +0 -0
  8. package/build/koffi/linux_armhf/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_loong64/koffi.node +0 -0
  11. package/build/koffi/linux_riscv64d/koffi.node +0 -0
  12. package/build/koffi/linux_x64/koffi.node +0 -0
  13. package/build/koffi/musl_arm64/koffi.node +0 -0
  14. package/build/koffi/musl_x64/koffi.node +0 -0
  15. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  16. package/build/koffi/openbsd_x64/koffi.node +0 -0
  17. package/build/koffi/win32_arm64/koffi.node +0 -0
  18. package/build/koffi/win32_ia32/koffi.node +0 -0
  19. package/build/koffi/win32_x64/koffi.node +0 -0
  20. package/doc/assets.ini +2 -1
  21. package/doc/build.sh +9 -0
  22. package/doc/pages/404.md +17 -0
  23. package/doc/pages/index.md +5 -3
  24. package/doc/pages/misc.md +18 -11
  25. package/doc/pages.ini +4 -0
  26. package/doc/static/highlight.js +2 -14
  27. package/doc/static/koffi.css +3 -15
  28. package/doc/static/print.css +2 -14
  29. package/doc/templates/code.html +1 -2
  30. package/doc/templates/page.html +1 -2
  31. package/index.d.ts +29 -24
  32. package/index.js +9 -9
  33. package/indirect.js +9 -9
  34. package/{src/core → lib/native}/base/base.cc +1137 -674
  35. package/{src/core → lib/native}/base/base.hh +362 -195
  36. package/{src/core → lib/native}/base/crc.inc +2 -20
  37. package/lib/native/base/crc_gen.py +72 -0
  38. package/{src/core → lib/native}/base/mimetypes.inc +2 -20
  39. package/{src/core → lib/native}/base/mimetypes_gen.py +2 -21
  40. package/lib/native/base/tower.cc +821 -0
  41. package/lib/native/base/tower.hh +81 -0
  42. package/{src/core → lib/native}/base/unicode.inc +2 -20
  43. package/{src/core → lib/native}/base/unicode_gen.py +4 -41
  44. package/package.json +2 -2
  45. package/src/cnoke/assets/FindCNoke.cmake +24 -30
  46. package/src/cnoke/assets/win_delay_hook.c +6 -20
  47. package/src/cnoke/cnoke.js +2 -21
  48. package/src/cnoke/src/builder.js +51 -66
  49. package/src/cnoke/src/index.js +2 -20
  50. package/src/cnoke/src/tools.js +2 -20
  51. package/src/koffi/CMakeLists.txt +30 -23
  52. package/src/koffi/cmake/raylib.cmake +5 -22
  53. package/src/koffi/cmake/sqlite3.cmake +2 -20
  54. package/src/koffi/src/abi_arm32.cc +7 -25
  55. package/src/koffi/src/abi_arm32_asm.S +2 -20
  56. package/src/koffi/src/abi_arm64.cc +7 -25
  57. package/src/koffi/src/abi_arm64_asm.S +2 -20
  58. package/src/koffi/src/abi_arm64_asm.asm +2 -20
  59. package/src/koffi/src/abi_loong64.cc +2 -20
  60. package/src/koffi/src/abi_loong64_asm.S +2 -20
  61. package/src/koffi/src/abi_riscv64.cc +7 -25
  62. package/src/koffi/src/abi_riscv64_asm.S +2 -20
  63. package/src/koffi/src/abi_x64_sysv.cc +7 -25
  64. package/src/koffi/src/abi_x64_sysv_asm.S +2 -20
  65. package/src/koffi/src/abi_x64_win.cc +12 -30
  66. package/src/koffi/src/abi_x64_win_asm.S +162 -0
  67. package/src/koffi/src/abi_x64_win_asm.asm +2 -20
  68. package/src/koffi/src/abi_x86.cc +7 -25
  69. package/src/koffi/src/abi_x86_asm.S +2 -20
  70. package/src/koffi/src/abi_x86_asm.asm +2 -20
  71. package/src/koffi/src/call.cc +25 -45
  72. package/src/koffi/src/call.hh +3 -21
  73. package/src/koffi/src/errno.inc +2 -20
  74. package/src/koffi/src/ffi.cc +64 -63
  75. package/src/koffi/src/ffi.hh +15 -30
  76. package/src/koffi/src/init.js +2 -20
  77. package/src/koffi/src/parser.cc +13 -27
  78. package/src/koffi/src/parser.hh +3 -21
  79. package/src/koffi/src/trampolines/armasm.inc +0 -21
  80. package/src/koffi/src/trampolines/gnu.inc +0 -21
  81. package/src/koffi/src/trampolines/masm32.inc +0 -21
  82. package/src/koffi/src/trampolines/masm64.inc +0 -21
  83. package/src/koffi/src/trampolines/prototypes.inc +0 -21
  84. package/src/koffi/src/util.cc +50 -64
  85. package/src/koffi/src/util.hh +8 -25
  86. package/src/koffi/src/uv.cc +193 -0
  87. package/src/koffi/src/uv.def +10 -0
  88. package/src/koffi/src/uv.hh +40 -0
  89. package/src/koffi/src/win32.cc +2 -20
  90. package/src/koffi/src/win32.hh +3 -21
  91. package/vendor/node-api-headers/CHANGELOG.md +22 -0
  92. package/vendor/node-api-headers/README.md +6 -17
  93. package/vendor/node-api-headers/include/js_native_api.h +3 -13
  94. package/vendor/node-api-headers/include/js_native_api_types.h +15 -0
  95. package/vendor/node-api-headers/include/node_api.h +0 -4
  96. package/vendor/node-api-headers/include/node_api_types.h +6 -0
  97. package/vendor/node-api-headers/include/uv/aix.h +32 -0
  98. package/vendor/node-api-headers/include/uv/bsd.h +34 -0
  99. package/vendor/node-api-headers/include/uv/darwin.h +61 -0
  100. package/vendor/node-api-headers/include/uv/errno.h +483 -0
  101. package/vendor/node-api-headers/include/uv/linux.h +34 -0
  102. package/vendor/node-api-headers/include/uv/os390.h +33 -0
  103. package/vendor/node-api-headers/include/uv/posix.h +31 -0
  104. package/vendor/node-api-headers/include/uv/sunos.h +44 -0
  105. package/vendor/node-api-headers/include/uv/threadpool.h +37 -0
  106. package/vendor/node-api-headers/include/uv/tree.h +521 -0
  107. package/vendor/node-api-headers/include/uv/unix.h +512 -0
  108. package/vendor/node-api-headers/include/uv/version.h +43 -0
  109. package/vendor/node-api-headers/include/uv/win.h +698 -0
  110. package/vendor/node-api-headers/include/uv.h +1990 -0
  111. package/vendor/node-api-headers/package.json +1 -1
  112. package/vendor/node-api-headers/scripts/update-headers.js +6 -0
  113. package/src/core/base/crc_gen.py +0 -109
@@ -1,23 +1,5 @@
1
- // Copyright (C) 2025 Niels Martignène <niels.martignene@protonmail.com>
2
-
3
- // Permission is hereby granted, free of charge, to any person obtaining a copy of
4
- // this software and associated documentation files (the “Software”), to deal in
5
- // the Software without restriction, including without limitation the rights to use,
6
- // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
7
- // Software, and to permit persons to whom the Software is furnished to do so,
8
- // subject to the following conditions:
9
-
10
- // The above copyright notice and this permission notice shall be included in all
11
- // copies or substantial portions of the Software.
12
-
13
- // THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
14
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15
- // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17
- // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
- // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
- // OTHER DEALINGS IN THE SOFTWARE.
1
+ // SPDX-License-Identifier: MIT
2
+ // SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
21
3
 
22
4
  #pragma once
23
5
 
@@ -108,6 +90,8 @@ namespace K {
108
90
  #define K_PROGRESS_USED_NODES 100
109
91
  #define K_PROGRESS_TEXT_SIZE 64
110
92
 
93
+ #define K_COMPLETE_PATH_LIMIT 256
94
+
111
95
  // ------------------------------------------------------------------------
112
96
  // Utility
113
97
  // ------------------------------------------------------------------------
@@ -1404,7 +1388,7 @@ static constexpr inline bool IsAsciiWhite(int c)
1404
1388
  }
1405
1389
  static constexpr inline bool IsAsciiControl(int c)
1406
1390
  {
1407
- return c == 0x7F || (c < ' ' && c != '\t');
1391
+ return c == 0x7F || ((uint8_t)c < ' ' && c != '\t');
1408
1392
  }
1409
1393
 
1410
1394
  static constexpr inline char UpperAscii(int c)
@@ -1584,6 +1568,47 @@ static inline bool StartsWith(const char *str, const char *prefix)
1584
1568
  return !prefix[i];
1585
1569
  }
1586
1570
 
1571
+ static inline bool StartsWithI(Span<const char> str, Span<const char> prefix)
1572
+ {
1573
+ Size i = 0;
1574
+ while (i < str.len && i < prefix.len) {
1575
+ if (LowerAscii(str[i]) != LowerAscii(prefix[i]))
1576
+ return false;
1577
+ i++;
1578
+ }
1579
+ return (i == prefix.len);
1580
+ }
1581
+ static inline bool StartsWithI(Span<const char> str, const char *prefix)
1582
+ {
1583
+ Size i = 0;
1584
+ while (i < str.len && prefix[i]) {
1585
+ if (LowerAscii(str[i]) != LowerAscii(prefix[i]))
1586
+ return false;
1587
+ i++;
1588
+ }
1589
+ return !prefix[i];
1590
+ }
1591
+ static inline bool StartsWithI(const char *str, Span<const char> prefix)
1592
+ {
1593
+ Size i = 0;
1594
+ while (str[i] && i < prefix.len) {
1595
+ if (LowerAscii(str[i]) != LowerAscii(prefix[i]))
1596
+ return false;
1597
+ i++;
1598
+ }
1599
+ return (i == prefix.len);
1600
+ }
1601
+ static inline bool StartsWithI(const char *str, const char *prefix)
1602
+ {
1603
+ Size i = 0;
1604
+ while (str[i] && prefix[i]) {
1605
+ if (LowerAscii(str[i]) != LowerAscii(prefix[i]))
1606
+ return false;
1607
+ i++;
1608
+ }
1609
+ return !prefix[i];
1610
+ }
1611
+
1587
1612
  static inline bool EndsWith(Span<const char> str, Span<const char> suffix)
1588
1613
  {
1589
1614
  Size i = str.len - 1;
@@ -1599,6 +1624,21 @@ static inline bool EndsWith(Span<const char> str, Span<const char> suffix)
1599
1624
 
1600
1625
  return j < 0;
1601
1626
  }
1627
+ static inline bool EndsWithI(Span<const char> str, Span<const char> suffix)
1628
+ {
1629
+ Size i = str.len - 1;
1630
+ Size j = suffix.len - 1;
1631
+
1632
+ while (i >= 0 && j >= 0) {
1633
+ if (LowerAscii(str[i]) != LowerAscii(suffix[j]))
1634
+ return false;
1635
+
1636
+ i--;
1637
+ j--;
1638
+ }
1639
+
1640
+ return j < 0;
1641
+ }
1602
1642
 
1603
1643
  static inline Size FindStr(Span<const char> str, Span<const char> needle)
1604
1644
  {
@@ -1902,6 +1942,9 @@ static inline Span<const char> TrimStrRight(Span<const char> str, const char *tr
1902
1942
  static inline Span<const char> TrimStr(Span<const char> str, const char *trim_chars = " \t\r\n")
1903
1943
  { return TrimStr(MakeSpan((char *)str.ptr, str.len), trim_chars); }
1904
1944
 
1945
+ int CmpNatural(Span<const char> str1, Span<const char> str2);
1946
+ int CmpNaturalI(Span<const char> str1, Span<const char> str2);
1947
+
1905
1948
  // ------------------------------------------------------------------------
1906
1949
  // Collections
1907
1950
  // ------------------------------------------------------------------------
@@ -2787,7 +2830,7 @@ public:
2787
2830
  return ptr;
2788
2831
  }
2789
2832
 
2790
- ValueType *TrySet(const ValueType &value, bool *out_inserted = nullptr)
2833
+ ValueType *InsertOrGet(const ValueType &value, bool *out_inserted = nullptr)
2791
2834
  {
2792
2835
  const KeyType &key = Handler::GetKey(value);
2793
2836
 
@@ -2803,7 +2846,7 @@ public:
2803
2846
  }
2804
2847
  return ptr;
2805
2848
  }
2806
- ValueType *TrySetDefault(const KeyType &key, bool *out_inserted = nullptr)
2849
+ ValueType *InsertOrGetDefault(const KeyType &key, bool *out_inserted = nullptr)
2807
2850
  {
2808
2851
  bool inserted;
2809
2852
  ValueType *ptr = Insert(key, &inserted);
@@ -3247,15 +3290,15 @@ public:
3247
3290
  return table_it;
3248
3291
  }
3249
3292
 
3250
- ValueType *TrySet(const KeyType &key, const ValueType &value, bool *out_inserted = nullptr)
3293
+ ValueType *InsertOrGet(const KeyType &key, const ValueType &value, bool *out_inserted = nullptr)
3251
3294
  {
3252
- Bucket *ptr = table.TrySet({ key, value }, out_inserted);
3295
+ Bucket *ptr = table.InsertOrGet({ key, value }, out_inserted);
3253
3296
  return &ptr->value;
3254
3297
  }
3255
- Bucket *TrySetDefault(const KeyType &key, bool *out_inserted = nullptr)
3298
+ Bucket *InsertOrGetDefault(const KeyType &key, bool *out_inserted = nullptr)
3256
3299
  {
3257
3300
  bool inserted;
3258
- Bucket *ptr = table.TrySetDefault(key, &inserted);
3301
+ Bucket *ptr = table.InsertOrGetDefault(key, &inserted);
3259
3302
 
3260
3303
  if (inserted) {
3261
3304
  ptr->key = key;
@@ -3318,14 +3361,23 @@ public:
3318
3361
  { return table.FindValue(value, default_value); }
3319
3362
 
3320
3363
  ValueType *Set(const ValueType &value) { return table.Set(value); }
3321
- ValueType *TrySet(const ValueType &value, bool *out_inserted = nullptr)
3322
- { return table.TrySet(value, out_inserted); }
3364
+
3365
+ ValueType *InsertOrGet(const ValueType &value, bool *out_inserted = nullptr)
3366
+ { return table.InsertOrGet(value, out_inserted); }
3367
+ bool InsertOrFail(const ValueType &value)
3368
+ {
3369
+ bool inserted;
3370
+ InsertOrGet(value, &inserted);
3371
+ return inserted;
3372
+ }
3323
3373
 
3324
3374
  void Remove(ValueType *it) { table.Remove(it); }
3325
3375
  template <typename T = ValueType>
3326
3376
  void Remove(const T &value) { Remove(Find(value)); }
3327
3377
 
3328
3378
  void Trim() { table.Trim(); }
3379
+
3380
+ private:
3329
3381
  };
3330
3382
 
3331
3383
  // XXX: Switch to perfect hashing later on
@@ -3343,7 +3395,7 @@ public:
3343
3395
 
3344
3396
  constexpr ConstMap(std::initializer_list<Bucket> l)
3345
3397
  {
3346
- K_CRITICAL(l.size() <= N, "ConstMap<%1> cannot be store %2 values", N, l.size());
3398
+ K_CRITICAL(l.size() <= N, "ConstMap<%1> cannot store %2 values", N, l.size());
3347
3399
 
3348
3400
  for (const Bucket &it: l) {
3349
3401
  Bucket *bucket = Insert(it.key);
@@ -3352,14 +3404,6 @@ public:
3352
3404
  bucket->value = it.value;
3353
3405
  }
3354
3406
  }
3355
- ~ConstMap()
3356
- {
3357
- if constexpr(!std::is_trivial<ValueType>::value) {
3358
- for (Size i = 0; i < N; i++) {
3359
- data[i].~ValueType();
3360
- }
3361
- }
3362
- }
3363
3407
 
3364
3408
  template <typename T = KeyType>
3365
3409
  ValueType *Find(const T &key)
@@ -3535,24 +3579,6 @@ union LocalDate {
3535
3579
  // ------------------------------------------------------------------------
3536
3580
 
3537
3581
  int64_t GetUnixTime();
3538
- int64_t GetMonotonicTime();
3539
-
3540
- #if defined(_MSC_VER) && !defined(_M_ARM64)
3541
- static inline int64_t GetClockCounter()
3542
- {
3543
- return (int64_t)__rdtsc();
3544
- }
3545
- #elif defined(__i386__) || defined(__x86_64__)
3546
- static inline int64_t GetClockCounter()
3547
- {
3548
- uint32_t counter_low, counter_high;
3549
- __asm__ __volatile__ ("cpuid; rdtsc"
3550
- : "=a" (counter_low), "=d" (counter_high)
3551
- : : "%ebx", "%ecx");
3552
- int64_t counter = ((int64_t)counter_high << 32) | counter_low;
3553
- return counter;
3554
- }
3555
- #endif
3556
3582
 
3557
3583
  struct TimeSpec {
3558
3584
  int16_t year;
@@ -3572,15 +3598,46 @@ TimeSpec DecomposeTimeUTC(int64_t time);
3572
3598
  TimeSpec DecomposeTimeLocal(int64_t time);
3573
3599
  int64_t ComposeTimeUTC(const TimeSpec &spec);
3574
3600
 
3601
+ // ------------------------------------------------------------------------
3602
+ // Clock
3603
+ // ------------------------------------------------------------------------
3604
+
3605
+ #if defined(_MSC_VER) && !defined(_M_ARM64)
3606
+ static inline int64_t GetCoreCycles()
3607
+ {
3608
+ return (int64_t)__rdtsc();
3609
+ }
3610
+ #elif defined(__i386__) || defined(__x86_64__)
3611
+ static inline int64_t GetCoreCycles()
3612
+ {
3613
+ uint32_t counter_low, counter_high;
3614
+ __asm__ __volatile__ ("cpuid; rdtsc"
3615
+ : "=a" (counter_low), "=d" (counter_high)
3616
+ : : "%ebx", "%ecx");
3617
+ int64_t counter = ((int64_t)counter_high << 32) | counter_low;
3618
+ return counter;
3619
+ }
3620
+ #elif defined(__aarch64__)
3621
+ static inline int64_t GetCoreCycles()
3622
+ {
3623
+ uint64_t counter;
3624
+ __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (counter));
3625
+ return counter;
3626
+ }
3627
+ #endif
3628
+
3629
+ int64_t GetMonotonicClock();
3630
+
3575
3631
  // ------------------------------------------------------------------------
3576
3632
  // Format
3577
3633
  // ------------------------------------------------------------------------
3578
3634
 
3579
3635
  enum class FmtType {
3580
- Str1,
3581
- Str2,
3582
- Buffer,
3636
+ Str,
3637
+ PadStr,
3638
+ RepeatStr,
3583
3639
  Char,
3640
+ Buffer,
3584
3641
  Custom,
3585
3642
  Bool,
3586
3643
  Integer,
@@ -3591,15 +3648,19 @@ enum class FmtType {
3591
3648
  Octal,
3592
3649
  BigHex,
3593
3650
  SmallHex,
3651
+ BigBytes,
3652
+ SmallBytes,
3594
3653
  MemorySize,
3595
3654
  DiskSize,
3596
3655
  Date,
3597
3656
  TimeISO,
3598
3657
  TimeNice,
3599
- Random,
3658
+ List,
3600
3659
  FlagNames,
3601
3660
  FlagOptions,
3602
- Span
3661
+ Random,
3662
+ SafeStr,
3663
+ SafeChar
3603
3664
  };
3604
3665
 
3605
3666
  template <typename T>
@@ -3649,14 +3710,18 @@ class FmtArg {
3649
3710
  public:
3650
3711
  FmtType type;
3651
3712
  union {
3652
- const char *str1;
3653
- Span<const char> str2;
3713
+ Span<const char> str;
3714
+ struct {
3715
+ const char *str;
3716
+ int count;
3717
+ } repeat;
3654
3718
  char buf[32];
3655
3719
  char ch;
3656
3720
  FmtCustom custom;
3657
3721
  bool b;
3658
3722
  int64_t i;
3659
3723
  uint64_t u;
3724
+ Span<const uint8_t> hex;
3660
3725
  struct {
3661
3726
  float value;
3662
3727
  int min_prec;
@@ -3684,68 +3749,123 @@ public:
3684
3749
  Span<const struct OptionDesc> options;
3685
3750
  } u;
3686
3751
  const char *separator;
3687
- } flags;
3688
-
3689
- struct {
3690
- FmtType type;
3691
- int type_len;
3692
- const void *ptr;
3693
- Size len;
3694
- const char *separator;
3695
- } span;
3752
+ } list;
3696
3753
  } u;
3697
3754
 
3698
- int repeat = 1;
3699
- int pad_len = 0;
3700
- char pad_char = 0;
3755
+ int pad = 0;
3756
+ char padding = 0;
3701
3757
 
3702
3758
  FmtArg() = default;
3703
- FmtArg(std::nullptr_t) : type(FmtType::Str1) { u.str1 = "(null)"; }
3704
- FmtArg(const char *str) : type(FmtType::Str1) { u.str1 = str ? str : "(null)"; }
3705
- FmtArg(Span<const char> str) : type(FmtType::Str2) { u.str2 = str; }
3706
- FmtArg(char c) : type(FmtType::Char) { u.ch = c; }
3707
- FmtArg(const FmtCustom &custom) : type(FmtType::Custom) { u.custom = custom; }
3708
- FmtArg(bool b) : type(FmtType::Bool) { u.b = b; }
3709
- FmtArg(unsigned char i) : type(FmtType::Unsigned) { u.u = i; }
3710
- FmtArg(short i) : type(FmtType::Integer) { u.i = i; }
3711
- FmtArg(unsigned short i) : type(FmtType::Unsigned) { u.u = i; }
3712
- FmtArg(int i) : type(FmtType::Integer) { u.i = i; }
3713
- FmtArg(unsigned int i) : type(FmtType::Unsigned) { u.u = i; }
3714
- FmtArg(long i) : type(FmtType::Integer) { u.i = i; }
3715
- FmtArg(unsigned long i) : type(FmtType::Unsigned) { u.u = i; }
3716
- FmtArg(long long i) : type(FmtType::Integer) { u.i = i; }
3717
- FmtArg(unsigned long long i) : type(FmtType::Unsigned) { u.u = i; }
3718
- FmtArg(float f) : type(FmtType::Float) { u.f = { f, 0, INT_MAX }; }
3719
- FmtArg(double d) : type(FmtType::Double) { u.d = { d, 0, INT_MAX }; }
3720
- FmtArg(const void *ptr) : type(FmtType::BigHex) { u.u = (uint64_t)ptr; }
3721
- FmtArg(const LocalDate &date) : type(FmtType::Date) { u.date = date; }
3722
-
3723
- FmtArg &Repeat(int new_repeat) { repeat = new_repeat; return *this; }
3724
- FmtArg &Pad(int len, char c = ' ') { pad_char = c; pad_len = len; return *this; }
3725
- FmtArg &Pad0(int len) { return Pad(len, '0'); }
3759
+ FmtArg(const FmtArg &other) = default;
3760
+ FmtArg(std::nullptr_t) : FmtArg(FmtType::Str) { u.str = "(null)"; }
3761
+ FmtArg(const char *str) : FmtArg(FmtType::Str) { u.str = str ? str : "(null)"; }
3762
+ FmtArg(Span<const char> str) : FmtArg(FmtType::Str) { u.str = str; }
3763
+ FmtArg(char c) : FmtArg(FmtType::Char) { u.ch = c; }
3764
+ FmtArg(const FmtCustom &custom) : FmtArg(FmtType::Custom) { u.custom = custom; }
3765
+ FmtArg(bool b) : FmtArg(FmtType::Bool) { u.b = b; }
3766
+ FmtArg(unsigned char i) : FmtArg(FmtType::Unsigned) { u.u = i; }
3767
+ FmtArg(short i) : FmtArg(FmtType::Integer) { u.i = i; }
3768
+ FmtArg(unsigned short i) : FmtArg(FmtType::Unsigned) { u.u = i; }
3769
+ FmtArg(int i) : FmtArg(FmtType::Integer) { u.i = i; }
3770
+ FmtArg(unsigned int i) : FmtArg(FmtType::Unsigned) { u.u = i; }
3771
+ FmtArg(long i) : FmtArg(FmtType::Integer) { u.i = i; }
3772
+ FmtArg(unsigned long i) : FmtArg(FmtType::Unsigned) { u.u = i; }
3773
+ FmtArg(long long i) : FmtArg(FmtType::Integer) { u.i = i; }
3774
+ FmtArg(unsigned long long i) : FmtArg(FmtType::Unsigned) { u.u = i; }
3775
+ FmtArg(float f) : FmtArg(FmtType::Float) { u.f = { f, 0, INT_MAX }; }
3776
+ FmtArg(double d) : FmtArg(FmtType::Double) { u.d = { d, 0, INT_MAX }; }
3777
+ FmtArg(const void *ptr) : FmtArg(FmtType::BigHex) { u.u = (uint64_t)ptr; }
3778
+ FmtArg(const LocalDate &date) : FmtArg(FmtType::Date) { u.date = date; }
3779
+
3780
+ protected:
3781
+ FmtArg(FmtType type) : type(type) {}
3782
+ };
3783
+
3784
+ class FmtSafe: public FmtArg {
3785
+ public:
3786
+ FmtSafe() = default;
3787
+ FmtSafe(FmtArg arg) : FmtArg(arg) {}
3788
+ FmtSafe(std::nullptr_t) : FmtArg(FmtType::Str) { u.str = "(null)"; }
3789
+ FmtSafe(const char *str) : FmtArg(FmtType::SafeStr) { u.str = str ? str : "(null)"; } // safe
3790
+ FmtSafe(Span<const char> str) : FmtArg(FmtType::SafeStr) { u.str = str; } // safe
3791
+ FmtSafe(char c) : FmtArg(FmtType::SafeChar) { u.ch = c; } // safe
3792
+ FmtSafe(const FmtCustom &custom) : FmtArg(custom) {}
3793
+ FmtSafe(bool b) : FmtArg(b) {}
3794
+ FmtSafe(unsigned char i) : FmtArg(i) {}
3795
+ FmtSafe(short i) : FmtArg(i) {}
3796
+ FmtSafe(unsigned short i) : FmtArg(i) {}
3797
+ FmtSafe(int i) : FmtArg(i) {}
3798
+ FmtSafe(unsigned int i) : FmtArg(i) {}
3799
+ FmtSafe(long i) : FmtArg(i) {}
3800
+ FmtSafe(unsigned long i) : FmtArg(i) {}
3801
+ FmtSafe(long long i) : FmtArg(i) {}
3802
+ FmtSafe(unsigned long long i) : FmtArg(i) {}
3803
+ FmtSafe(float f) : FmtArg(f) {}
3804
+ FmtSafe(double d) : FmtArg(d) {}
3805
+ FmtSafe(const void *ptr) : FmtArg(ptr) {}
3806
+ FmtSafe(const LocalDate &date) : FmtArg(date) {}
3726
3807
  };
3727
3808
 
3728
- static inline FmtArg FmtBin(uint64_t u)
3809
+ static inline FmtArg FmtInt(long long i, int pad = 0, char padding = '0')
3810
+ {
3811
+ FmtArg arg;
3812
+ arg.type = FmtType::Integer;
3813
+ arg.u.i = i;
3814
+ arg.pad = pad;
3815
+ arg.padding = padding;
3816
+ return arg;
3817
+ }
3818
+ static inline FmtArg FmtInt(unsigned long long u, int pad = 0, char padding = '0')
3819
+ {
3820
+ FmtArg arg;
3821
+ arg.type = FmtType::Unsigned;
3822
+ arg.u.u = u;
3823
+ arg.pad = pad;
3824
+ arg.padding = padding;
3825
+ return arg;
3826
+ }
3827
+ static inline FmtArg FmtInt(unsigned char u, int pad = 0, char padding = '0') { return FmtInt((unsigned long long)u, pad, padding); }
3828
+ static inline FmtArg FmtInt(short i, int pad = 0, char padding = '0') { return FmtInt((long long)i, pad, padding); }
3829
+ static inline FmtArg FmtInt(unsigned short u, int pad = 0, char padding = '0') { return FmtInt((unsigned long long)u, pad, padding); }
3830
+ static inline FmtArg FmtInt(int i, int pad = 0, char padding = '0') { return FmtInt((long long)i, pad, padding); }
3831
+ static inline FmtArg FmtInt(unsigned int u, int pad = 0, char padding = '0') { return FmtInt((unsigned long long)u, pad, padding); }
3832
+ static inline FmtArg FmtInt(long i, int pad = 0, char padding = '0') { return FmtInt((long long)i, pad, padding); }
3833
+ static inline FmtArg FmtInt(unsigned long u, int pad = 0, char padding = '0') { return FmtInt((unsigned long long)u, pad, padding); }
3834
+
3835
+ static inline FmtArg FmtBin(uint64_t u, int pad = 0, char padding = '0')
3729
3836
  {
3730
3837
  FmtArg arg;
3731
3838
  arg.type = FmtType::Binary;
3732
3839
  arg.u.u = u;
3840
+ arg.pad = pad;
3841
+ arg.padding = padding;
3733
3842
  return arg;
3734
3843
  }
3735
- static inline FmtArg FmtOctal(uint64_t u)
3844
+ static inline FmtArg FmtOctal(uint64_t u, int pad = 0, char padding = '0')
3736
3845
  {
3737
3846
  FmtArg arg;
3738
3847
  arg.type = FmtType::Octal;
3739
3848
  arg.u.u = u;
3849
+ arg.pad = pad;
3850
+ arg.padding = padding;
3740
3851
  return arg;
3741
3852
  }
3742
- static inline FmtArg FmtHex(uint64_t u, FmtType type = FmtType::BigHex)
3853
+ static inline FmtArg FmtHex(uint64_t u, int pad = 0, char padding = '0')
3743
3854
  {
3744
- K_ASSERT(type == FmtType::BigHex || type == FmtType::SmallHex);
3745
-
3746
3855
  FmtArg arg;
3747
- arg.type = type;
3856
+ arg.type = FmtType::BigHex;
3748
3857
  arg.u.u = u;
3858
+ arg.pad = pad;
3859
+ arg.padding = padding;
3860
+ return arg;
3861
+ }
3862
+ static inline FmtArg FmtHexSmall(uint64_t u, int pad = 0, char padding = '0')
3863
+ {
3864
+ FmtArg arg;
3865
+ arg.type = FmtType::SmallHex;
3866
+ arg.u.u = u;
3867
+ arg.pad = pad;
3868
+ arg.padding = padding;
3749
3869
  return arg;
3750
3870
  }
3751
3871
 
@@ -3806,61 +3926,76 @@ static inline FmtArg FmtTimeNice(TimeSpec spec, bool ms = false)
3806
3926
  return arg;
3807
3927
  }
3808
3928
 
3809
- static inline FmtArg FmtRandom(Size len, const char *chars = nullptr)
3929
+ static inline FmtArg FmtList(Span<const char *const> names, const char *sep = ", ")
3810
3930
  {
3811
- K_ASSERT(len < 256);
3812
- len = std::min(len, (Size)256);
3813
-
3814
3931
  FmtArg arg;
3815
- arg.type = FmtType::Random;
3816
- arg.u.random.len = len;
3817
- arg.u.random.chars = chars;
3932
+ arg.type = FmtType::List;
3933
+ arg.u.list.u.names = names;
3934
+ arg.u.list.separator = sep;
3818
3935
  return arg;
3819
3936
  }
3820
-
3821
3937
  static inline FmtArg FmtFlags(uint64_t flags, Span<const char *const> names, const char *sep = ", ")
3822
3938
  {
3823
3939
  FmtArg arg;
3824
3940
  arg.type = FmtType::FlagNames;
3825
- arg.u.flags.flags = flags & ((1ull << names.len) - 1);
3826
- arg.u.flags.u.names = names;
3827
- arg.u.flags.separator = sep;
3941
+ arg.u.list.flags = flags & ((1ull << names.len) - 1);
3942
+ arg.u.list.u.names = names;
3943
+ arg.u.list.separator = sep;
3828
3944
  return arg;
3829
3945
  }
3830
-
3831
3946
  static inline FmtArg FmtFlags(uint64_t flags, Span<const struct OptionDesc> options, const char *sep = ", ")
3832
3947
  {
3833
3948
  FmtArg arg;
3834
3949
  arg.type = FmtType::FlagOptions;
3835
- arg.u.flags.flags = flags & ((1ull << options.len) - 1);
3836
- arg.u.flags.u.options = options;
3837
- arg.u.flags.separator = sep;
3950
+ arg.u.list.flags = flags & ((1ull << options.len) - 1);
3951
+ arg.u.list.u.options = options;
3952
+ arg.u.list.separator = sep;
3838
3953
  return arg;
3839
3954
  }
3840
3955
 
3841
- template <typename T>
3842
- FmtArg FmtSpan(Span<T> arr, FmtType type, const char *sep = ", ")
3956
+ static inline FmtArg FmtPad(Span<const char> str, int pad, char padding = ' ')
3843
3957
  {
3844
3958
  FmtArg arg;
3845
- arg.type = FmtType::Span;
3846
- arg.u.span.type = type;
3847
- arg.u.span.type_len = K_SIZE(T);
3848
- arg.u.span.ptr = (const void *)arr.ptr;
3849
- arg.u.span.len = arr.len;
3850
- arg.u.span.separator = sep;
3959
+ arg.type = FmtType::PadStr;
3960
+ arg.u.str = str;
3961
+ arg.pad = pad;
3962
+ arg.padding = padding;
3963
+ return arg;
3964
+ }
3965
+ static inline FmtArg FmtRepeat(const char *str, int count)
3966
+ {
3967
+ FmtArg arg;
3968
+ arg.type = FmtType::RepeatStr;
3969
+ arg.u.repeat.str = str;
3970
+ arg.u.repeat.count = count;
3851
3971
  return arg;
3852
3972
  }
3853
- template <typename T>
3854
- FmtArg FmtSpan(Span<T> arr, const char *sep = ", ") { return FmtSpan(arr, FmtArg(T()).type, sep); }
3855
- template <typename T, Size N>
3856
- FmtArg FmtSpan(T (&arr)[N], FmtType type, const char *sep = ", ") { return FmtSpan(MakeSpan(arr), type, sep); }
3857
- template <typename T, Size N>
3858
- FmtArg FmtSpan(T (&arr)[N], const char *sep = ", ") { return FmtSpan(MakeSpan(arr), sep); }
3859
3973
 
3860
- static inline FmtArg FmtHex(Span<const uint8_t> buf, FmtType type = FmtType::BigHex)
3974
+ static inline FmtArg FmtHex(Span<const uint8_t> buf)
3861
3975
  {
3862
- K_ASSERT(type == FmtType::BigHex || type == FmtType::SmallHex);
3863
- return FmtSpan(buf, type, "").Pad0(-2);
3976
+ FmtArg arg;
3977
+ arg.type = FmtType::BigBytes;
3978
+ arg.u.hex = buf;
3979
+ return arg;
3980
+ }
3981
+ static inline FmtArg FmtHexSmall(Span<const uint8_t> buf)
3982
+ {
3983
+ FmtArg arg;
3984
+ arg.type = FmtType::SmallBytes;
3985
+ arg.u.hex = buf;
3986
+ return arg;
3987
+ }
3988
+
3989
+ static inline FmtArg FmtRandom(Size len, const char *chars = nullptr)
3990
+ {
3991
+ K_ASSERT(len < 256);
3992
+ len = std::min(len, (Size)256);
3993
+
3994
+ FmtArg arg;
3995
+ arg.type = FmtType::Random;
3996
+ arg.u.random.len = len;
3997
+ arg.u.random.chars = chars;
3998
+ return arg;
3864
3999
  }
3865
4000
 
3866
4001
  class FmtUpperAscii {
@@ -3883,23 +4018,34 @@ public:
3883
4018
  operator FmtArg() const { return FmtCustom(*this); }
3884
4019
  };
3885
4020
 
3886
- class FmtEscape {
4021
+ class FmtUrlSafe {
3887
4022
  Span<const char> str;
4023
+ const char *passthrough;
3888
4024
 
3889
4025
  public:
3890
- FmtEscape(Span<const char> str) : str(str) {}
4026
+ FmtUrlSafe(Span<const char> str, const char *passthrough)
4027
+ : str(str), passthrough(passthrough) {}
3891
4028
 
3892
4029
  void Format(FunctionRef<void(Span<const char>)> append) const;
3893
4030
  operator FmtArg() const { return FmtCustom(*this); }
3894
4031
  };
3895
4032
 
3896
- class FmtUrlSafe {
4033
+ class FmtHtmlSafe {
3897
4034
  Span<const char> str;
3898
- const char *passthrough;
3899
4035
 
3900
4036
  public:
3901
- FmtUrlSafe(Span<const char> str, const char *passthrough)
3902
- : str(str), passthrough(passthrough) {}
4037
+ FmtHtmlSafe(Span<const char> str) : str(str) {}
4038
+
4039
+ void Format(FunctionRef<void(Span<const char>)> append) const;
4040
+ operator FmtArg() const { return FmtCustom(*this); }
4041
+ };
4042
+
4043
+ class FmtEscape {
4044
+ Span<const char> str;
4045
+ char quote;
4046
+
4047
+ public:
4048
+ FmtEscape(Span<const char> str, char quote) : str(str), quote(quote) {}
3903
4049
 
3904
4050
  void Format(FunctionRef<void(Span<const char>)> append) const;
3905
4051
  operator FmtArg() const { return FmtCustom(*this); }
@@ -4004,7 +4150,7 @@ static inline void Log(LogLevel level, const char *ctx, const char *fmt)
4004
4150
  template <typename... Args>
4005
4151
  static inline void Log(LogLevel level, const char *ctx, const char *fmt, Args... args)
4006
4152
  {
4007
- const FmtArg fmt_args[] = { FmtArg(args)... };
4153
+ const FmtArg fmt_args[] = { FmtSafe(args)... };
4008
4154
  LogFmt(level, ctx, fmt, fmt_args);
4009
4155
  }
4010
4156
 
@@ -4215,11 +4361,11 @@ static const char *const CompressionTypeExtensions[] = {
4215
4361
  Span<const char> GetPathDirectory(Span<const char> filename);
4216
4362
  Span<const char> GetPathExtension(Span<const char> filename,
4217
4363
  CompressionType *out_compression_type = nullptr);
4218
- CompressionType GetPathCompression(Span<const char> filename);
4219
4364
 
4220
4365
  enum class NormalizeFlag {
4221
4366
  EndWithSeparator = 1 << 0,
4222
- ForceSlash = 1 << 1
4367
+ ForceSlash = 1 << 1,
4368
+ NoExpansion = 1 << 2
4223
4369
  };
4224
4370
 
4225
4371
  Span<char> NormalizePath(Span<const char> path, Span<const char> root_directory, unsigned int flags, Allocator *alloc);
@@ -4233,6 +4379,7 @@ static inline Span<char> NormalizePath(Span<const char> path, Allocator *alloc)
4233
4379
  bool PathIsAbsolute(const char *path);
4234
4380
  bool PathIsAbsolute(Span<const char> path);
4235
4381
  bool PathContainsDotDot(const char *path);
4382
+ bool PathContainsDotDot(Span<const char> path);
4236
4383
 
4237
4384
  enum class StatFlag {
4238
4385
  SilentMissing = 1 << 0,
@@ -4305,7 +4452,20 @@ static inline RenameResult RenameFile(const char *src_filename, const char *dest
4305
4452
  { return RenameFile(src_filename, dest_filename, 0, flags); }
4306
4453
 
4307
4454
  bool ResizeFile(int fd, const char *filename, int64_t len);
4308
- bool SetFileMetaData(int fd, const char *filename, int64_t mtime, int64_t ctime, uint32_t mode);
4455
+
4456
+ #if !defined(_WIN32)
4457
+ bool SetFileMode(int fd, const char *filename, uint32_t mode);
4458
+ static inline bool SetFileMode(const char *filename, uint32_t mode)
4459
+ { return SetFileMode(-1, filename, mode); }
4460
+
4461
+ bool SetFileOwner(int fd, const char *filename, uint32_t uid, uint32_t gid);
4462
+ static inline bool SetFileOwner(const char *filename, uint32_t uid, uint32_t gid)
4463
+ { return SetFileOwner(-1, filename, uid, gid); }
4464
+ #endif
4465
+
4466
+ bool SetFileTimes(int fd, const char *filename, int64_t mtime, int64_t ctime);
4467
+ static inline bool SetFileTimes(const char *filename, int64_t mtime, int64_t ctime)
4468
+ { return SetFileTimes(-1, filename, mtime, ctime); }
4309
4469
 
4310
4470
  struct VolumeInfo {
4311
4471
  int64_t total;
@@ -4430,7 +4590,7 @@ void CloseHandleSafe(void **handle_ptr); // HANDLE
4430
4590
  #else
4431
4591
  void SetSignalHandler(int signal, void (*func)(int), struct sigaction *prev = nullptr);
4432
4592
 
4433
- bool CreatePipe(int pfd[2]);
4593
+ bool CreatePipe(bool block, int out_pfd[2]);
4434
4594
  void CloseDescriptorSafe(int *fd_ptr);
4435
4595
  #endif
4436
4596
 
@@ -4454,7 +4614,7 @@ bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
4454
4614
  HeapArray<uint8_t> *out_buf, int *out_code);
4455
4615
 
4456
4616
  // Simple variants
4457
- static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,int *out_code)
4617
+ static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info, int *out_code)
4458
4618
  { return ExecuteCommandLine(cmd_line, info, {}, {}, out_code); }
4459
4619
  static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
4460
4620
  Span<const uint8_t> in_buf,
@@ -4499,35 +4659,29 @@ enum class WaitResult {
4499
4659
  Timeout,
4500
4660
  Interrupt,
4501
4661
  Message,
4502
- Exit,
4503
- Error
4662
+ Exit
4504
4663
  };
4505
4664
 
4506
- #if defined(_WIN32)
4507
- typedef void * WaitHandle; // HANDLE
4508
- #else
4509
- typedef int WaitHandle;
4510
- #endif
4511
-
4512
4665
  struct WaitSource {
4513
4666
  #if defined(_WIN32)
4514
4667
  // Special-cased on Windows: set to NULL to wait for the Win32 message pump too
4515
4668
  void *handle; // HANDLE
4669
+ int timeout;
4516
4670
  #else
4517
4671
  int fd;
4518
- int events;
4519
- #endif
4520
-
4521
4672
  int timeout;
4673
+ int events = 0;
4674
+ #endif
4522
4675
  };
4523
4676
 
4524
4677
  // After WaitEvents() has been called once (even with timeout 0), a few signals (such as SIGINT, SIGHUP)
4525
4678
  // and their Windows equivalent will be permanently ignored.
4526
- // Beware, on Unix platforms, this may not work correctly if not called from the main thread.
4679
+ // Only the main thread (running main) will get WaitResult::Message events (and SIGUSR1).
4527
4680
  WaitResult WaitEvents(Span<const WaitSource> sources, int64_t timeout, uint64_t *out_ready = nullptr);
4528
4681
  WaitResult WaitEvents(int64_t timeout);
4529
4682
 
4530
- void InterruptWait();
4683
+ void PostWaitMessage();
4684
+ void PostTerminate();
4531
4685
 
4532
4686
  #endif
4533
4687
 
@@ -4833,12 +4987,10 @@ bool InitWinsock();
4833
4987
 
4834
4988
  int CreateSocket(SocketType type, int flags);
4835
4989
 
4836
- bool BindIPSocket(int sock, SocketType type, int port);
4990
+ bool BindIPSocket(int sock, SocketType type, const char *addr, int port);
4837
4991
  bool BindUnixSocket(int sock, const char *path);
4838
-
4839
- int OpenIPSocket(SocketType type, int port, int flags);
4840
- int OpenUnixSocket(const char *path, int flags);
4841
- int ConnectToUnixSocket(const char *path, int flags);
4992
+ bool ConnectIPSocket(int sock, const char *addr, int port);
4993
+ bool ConnectUnixSocket(int sock, const char *path);
4842
4994
 
4843
4995
  // Only for sockets on Windows
4844
4996
  void SetDescriptorNonBlock(int fd, bool enable);
@@ -4898,10 +5050,6 @@ enum class CompressionSpeed {
4898
5050
  class StreamDecoder;
4899
5051
  class StreamEncoder;
4900
5052
 
4901
- enum class StreamReaderFlag {
4902
- LazyFill = 1 << 0
4903
- };
4904
-
4905
5053
  class StreamReader {
4906
5054
  K_DELETE_COPY(StreamReader)
4907
5055
 
@@ -4912,7 +5060,6 @@ class StreamReader {
4912
5060
  };
4913
5061
 
4914
5062
  const char *filename = nullptr;
4915
- bool lazy = false;
4916
5063
  bool error = true;
4917
5064
 
4918
5065
  int64_t read_total = 0;
@@ -4952,30 +5099,24 @@ class StreamReader {
4952
5099
 
4953
5100
  public:
4954
5101
  StreamReader() { Close(true); }
4955
- StreamReader(Span<const uint8_t> buf, const char *filename, unsigned int flags = 0,
5102
+ StreamReader(Span<const uint8_t> buf, const char *filename, CompressionType compression_type = CompressionType::None)
5103
+ : StreamReader() { Open(buf, filename, compression_type); }
5104
+ StreamReader(int fd, const char *filename, CompressionType compression_type = CompressionType::None)
5105
+ : StreamReader() { Open(fd, filename, compression_type); }
5106
+ StreamReader(const char *filename, CompressionType compression_type = CompressionType::None)
5107
+ : StreamReader() { Open(filename, compression_type); }
5108
+ StreamReader(const std::function<Size(Span<uint8_t>)> &func, const char *filename,
4956
5109
  CompressionType compression_type = CompressionType::None)
4957
- : StreamReader() { Open(buf, filename, flags, compression_type); }
4958
- StreamReader(int fd, const char *filename, unsigned int flags = 0,
4959
- CompressionType compression_type = CompressionType::None)
4960
- : StreamReader() { Open(fd, filename, flags, compression_type); }
4961
- StreamReader(const char *filename, unsigned int flags = 0,
4962
- CompressionType compression_type = CompressionType::None)
4963
- : StreamReader() { Open(filename, flags, compression_type); }
4964
- StreamReader(const std::function<Size(Span<uint8_t>)> &func, const char *filename, unsigned int flags = 0,
4965
- CompressionType compression_type = CompressionType::None)
4966
- : StreamReader() { Open(func, filename, flags, compression_type); }
5110
+ : StreamReader() { Open(func, filename, compression_type); }
4967
5111
  ~StreamReader() { Close(true); }
4968
5112
 
4969
5113
  // Call before Open. Takes ownership and deletes the decoder at the end.
4970
5114
  void SetDecoder(StreamDecoder *decoder);
4971
5115
 
4972
- bool Open(Span<const uint8_t> buf, const char *filename, unsigned int flags = 0,
4973
- CompressionType compression_type = CompressionType::None);
4974
- bool Open(int fd, const char *filename, unsigned int flags = 0,
4975
- CompressionType compression_type = CompressionType::None);
4976
- OpenResult Open(const char *filename, unsigned int flags = 0,
4977
- CompressionType compression_type = CompressionType::None);
4978
- bool Open(const std::function<Size(Span<uint8_t>)> &func, const char *filename, unsigned int flags = 0,
5116
+ bool Open(Span<const uint8_t> buf, const char *filename, CompressionType compression_type = CompressionType::None);
5117
+ bool Open(int fd, const char *filename, CompressionType compression_type = CompressionType::None);
5118
+ OpenResult Open(const char *filename, CompressionType compression_type = CompressionType::None);
5119
+ bool Open(const std::function<Size(Span<uint8_t>)> &func, const char *filename,
4979
5120
  CompressionType compression_type = CompressionType::None);
4980
5121
  bool Close() { return Close(false); }
4981
5122
 
@@ -4995,7 +5136,11 @@ public:
4995
5136
  // Thread safe methods
4996
5137
  Size Read(Span<uint8_t> out_buf);
4997
5138
  Size Read(Span<char> out_buf) { return Read(out_buf.As<uint8_t>()); }
4998
- Size Read(Size buf_len, void *out_buf) { return Read(MakeSpan((uint8_t *)out_buf, buf_len)); }
5139
+
5140
+ // Thread safe methods
5141
+ Size ReadFill(Span<uint8_t> out_buf);
5142
+ Size ReadFill(Span<char> out_buf) { return ReadFill(out_buf.As<uint8_t>()); }
5143
+ Size ReadFill(Size buf_len, void *out_buf) { return ReadFill(MakeSpan((uint8_t *)out_buf, buf_len)); }
4999
5144
 
5000
5145
  Size ReadAll(Size max_len, HeapArray<uint8_t> *out_buf);
5001
5146
  Size ReadAll(Size max_len, HeapArray<char> *out_buf)
@@ -5017,12 +5162,12 @@ private:
5017
5162
  static inline Size ReadFile(const char *filename, Span<uint8_t> out_buf)
5018
5163
  {
5019
5164
  StreamReader st(filename);
5020
- return st.Read(out_buf);
5165
+ return st.ReadFill(out_buf);
5021
5166
  }
5022
5167
  static inline Size ReadFile(const char *filename, Span<char> out_buf)
5023
5168
  {
5024
5169
  StreamReader st(filename);
5025
- return st.Read(out_buf);
5170
+ return st.ReadFill(out_buf);
5026
5171
  }
5027
5172
  static inline Size ReadFile(const char *filename, Size max_len, HeapArray<uint8_t> *out_buf)
5028
5173
  {
@@ -5424,10 +5569,11 @@ struct TranslationTable {
5424
5569
 
5425
5570
  extern "C" const Span<const TranslationTable> TranslationTables;
5426
5571
 
5427
- void InitLocales(Span<const TranslationTable> tables);
5572
+ void InitLocales(Span<const TranslationTable> tables, const char *default_lang);
5428
5573
 
5429
- // Resets the localgale to the process default if lang is NULL or is unknown
5574
+ // Resets the locale to the process default if lang is NULL or is unknown
5430
5575
  void ChangeThreadLocale(const char *name);
5576
+ const char *GetThreadLocale();
5431
5577
 
5432
5578
  // ------------------------------------------------------------------------
5433
5579
  // Options
@@ -5626,10 +5772,23 @@ bool OptionToFlagI(Span<const OptionDesc> options, Span<const char> str, T *out_
5626
5772
  // ------------------------------------------------------------------------
5627
5773
 
5628
5774
  struct PromptChoice {
5629
- char c;
5630
5775
  const char *str;
5776
+ char c;
5777
+ };
5778
+
5779
+ enum class CompleteResult {
5780
+ Success,
5781
+ TooMany,
5782
+ Error
5631
5783
  };
5632
5784
 
5785
+ struct CompleteChoice {
5786
+ const char *name;
5787
+ const char *value;
5788
+ };
5789
+
5790
+ typedef CompleteResult CompleteFunc(Span<const char> value, Allocator *alloc, HeapArray<CompleteChoice> *out_choices);
5791
+
5633
5792
  class ConsolePrompter {
5634
5793
  int prompt_columns = 0;
5635
5794
 
@@ -5651,6 +5810,7 @@ class ConsolePrompter {
5651
5810
  public:
5652
5811
  const char *prompt = ">>>";
5653
5812
  const char *mask = nullptr;
5813
+ std::function<CompleteFunc> complete = {};
5654
5814
 
5655
5815
  HeapArray<char> str;
5656
5816
 
@@ -5695,6 +5855,13 @@ static inline const char *Prompt(const char *prompt, Allocator *alloc)
5695
5855
  Size PromptEnum(const char *prompt, Span<const PromptChoice> choices, Size value = 0);
5696
5856
  Size PromptEnum(const char *prompt, Span<const char *const> strings, Size value = 0);
5697
5857
 
5858
+ // Returns -1 if cancelled, otherwise it's 1 for Yes and or 0 for No
5859
+ int PromptYN(const char *prompt);
5860
+
5861
+ const char *PromptPath(const char *prompt, const char *default_path, Span<const char> root_directory, Allocator *alloc);
5862
+ static inline const char *PromptPath(const char *prompt, Allocator *alloc)
5863
+ { return PromptPath(prompt, nullptr, GetWorkingDirectory(), alloc); }
5864
+
5698
5865
  // ------------------------------------------------------------------------
5699
5866
  // Mime types
5700
5867
  // ------------------------------------------------------------------------