koffi 2.3.14 → 2.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/build/2.3.16/koffi_darwin_arm64/koffi.node +0 -0
- package/build/{2.3.14 → 2.3.16}/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.16/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.16/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.16/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.16/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.16/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.16/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.16/koffi_win32_arm64/koffi.exp +0 -0
- package/build/2.3.16/koffi_win32_arm64/koffi.lib +0 -0
- package/build/2.3.16/koffi_win32_arm64/koffi.node +0 -0
- package/build/{2.3.14 → 2.3.16}/koffi_win32_ia32/koffi.exp +0 -0
- package/build/{2.3.14 → 2.3.16}/koffi_win32_ia32/koffi.lib +0 -0
- package/build/2.3.16/koffi_win32_ia32/koffi.node +0 -0
- package/build/{2.3.14 → 2.3.16}/koffi_win32_x64/koffi.exp +0 -0
- package/build/{2.3.14/koffi_win32_arm64 → 2.3.16/koffi_win32_x64}/koffi.lib +0 -0
- package/build/2.3.16/koffi_win32_x64/koffi.node +0 -0
- package/doc/calls.md +54 -0
- package/package.json +2 -2
- package/src/cnoke/cnoke.js +1 -1
- package/src/cnoke/package.json +1 -1
- package/src/cnoke/src/builder.js +2 -2
- package/src/core/libcc/libcc.cc +15 -0
- package/src/core/libcc/libcc.hh +7 -1
- package/src/koffi/CMakeLists.txt +4 -0
- package/src/koffi/src/ffi.cc +40 -18
- package/src/koffi/src/ffi.hh +6 -0
- package/src/koffi/src/util.cc +35 -12
- package/src/koffi/src/util.hh +2 -2
- package/build/2.3.14/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.14/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.14/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.14/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.14/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.14/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.14/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.14/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.14/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.14/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.14/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.14/koffi_win32_arm64/koffi.exp +0 -0
- package/build/2.3.14/koffi_win32_arm64/koffi.node +0 -0
- package/build/2.3.14/koffi_win32_ia32/koffi.node +0 -0
- package/build/2.3.14/koffi_win32_x64/koffi.lib +0 -0
- package/build/2.3.14/koffi_win32_x64/koffi.node +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
### Koffi 2.3
|
|
6
6
|
|
|
7
|
+
#### Koffi 2.3.16
|
|
8
|
+
|
|
9
|
+
**Main changes:**
|
|
10
|
+
|
|
11
|
+
- Fix Windows ARM64 build to work with official Node.js version
|
|
12
|
+
- Compile Windows builds with Visual Studio 2022 17.5.3
|
|
13
|
+
|
|
14
|
+
**Other changes:**
|
|
15
|
+
|
|
16
|
+
- Support null in koffi.free() and koffi.address()
|
|
17
|
+
|
|
18
|
+
#### Koffi 2.3.15
|
|
19
|
+
|
|
20
|
+
**Main changes:**
|
|
21
|
+
|
|
22
|
+
- Improve manual decoding of 0-terminated strings
|
|
23
|
+
- Add checks around array conversion hints
|
|
24
|
+
|
|
7
25
|
#### Koffi 2.3.14
|
|
8
26
|
|
|
9
27
|
**Main changes:**
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/doc/calls.md
CHANGED
|
@@ -68,6 +68,60 @@ The same can be done when declaring a function with a C-like prototype string, w
|
|
|
68
68
|
- `_Out_` for output parameters
|
|
69
69
|
- `_Inout_` for dual input/output parameters
|
|
70
70
|
|
|
71
|
+
### Primitive value
|
|
72
|
+
|
|
73
|
+
This Windows example enumerate all Chrome windows along with their PID and their title. The `GetWindowThreadProcessId()` function illustrates how to get a primitive value from an output argument.
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
const koffi = require('koffi');
|
|
77
|
+
const user32 = koffi.load('user32.dll');
|
|
78
|
+
|
|
79
|
+
const DWORD = koffi.alias('DWORD', 'uint32_t');
|
|
80
|
+
const HANDLE = koffi.pointer(koffi.opaque('HANDLE'));
|
|
81
|
+
const HWND = koffi.alias('HWND', HANDLE);
|
|
82
|
+
|
|
83
|
+
const FindWindowEx = user32.func('HWND __stdcall FindWindowExW(HWND hWndParent, HWND hWndChildAfter, const char16_t *lpszClass, const char16_t *lpszWindow)');
|
|
84
|
+
const GetWindowThreadProcessId = user32.func('DWORD __stdcall GetWindowThreadProcessId(HWND hWnd, _Out_ DWORD *lpdwProcessId)');
|
|
85
|
+
const GetWindowText = user32.func('int __stdcall GetWindowTextA(HWND hWnd, _Out_ uint8_t *lpString, int nMaxCount)');
|
|
86
|
+
|
|
87
|
+
for (let hwnd = null;;) {
|
|
88
|
+
hwnd = FindWindowEx(0, hwnd, 'Chrome_WidgetWin_1', null);
|
|
89
|
+
|
|
90
|
+
if (!hwnd)
|
|
91
|
+
break;
|
|
92
|
+
|
|
93
|
+
// Get PID
|
|
94
|
+
let pid;
|
|
95
|
+
{
|
|
96
|
+
let ptr = [null];
|
|
97
|
+
let tid = GetWindowThreadProcessId(hwnd, ptr);
|
|
98
|
+
|
|
99
|
+
if (!tid) {
|
|
100
|
+
// Maybe the process ended in-between?
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
pid = ptr[0];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Get window title
|
|
108
|
+
let title;
|
|
109
|
+
{
|
|
110
|
+
let buf = Buffer.allocUnsafe(1024);
|
|
111
|
+
let length = GetWindowText(hwnd, buf, buf.length);
|
|
112
|
+
|
|
113
|
+
if (!length) {
|
|
114
|
+
// Maybe the process ended in-between?
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
title = koffi.decode(buf, 'char', length);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
console.log({ PID: pid, Title: title });
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
71
125
|
### Struct example
|
|
72
126
|
|
|
73
127
|
This example calls the POSIX function `gettimeofday()`, and uses the prototype-like syntax.
|
package/package.json
CHANGED
package/src/cnoke/cnoke.js
CHANGED
|
@@ -155,7 +155,7 @@ Options:
|
|
|
155
155
|
(default: ${cnoke.DefaultOptions.mode})
|
|
156
156
|
-D, --debug Shortcut for --config Debug
|
|
157
157
|
|
|
158
|
-
--prebuild Use prebuilt
|
|
158
|
+
--prebuild Use prebuilt binary if available
|
|
159
159
|
|
|
160
160
|
-a, --arch <ARCH> Change architecture and ABI
|
|
161
161
|
(default: ${cnoke.determine_arch()})
|
package/src/cnoke/package.json
CHANGED
package/src/cnoke/src/builder.js
CHANGED
|
@@ -103,7 +103,7 @@ function Builder(config = {}) {
|
|
|
103
103
|
let basename = `node-v${runtime_version}-headers.tar.gz`;
|
|
104
104
|
let urls = [
|
|
105
105
|
`https://nodejs.org/dist/v${runtime_version}/${basename}`,
|
|
106
|
-
`https://unofficial-builds.nodejs.org/download/release/v${runtime_version}/${basename}`
|
|
106
|
+
// `https://unofficial-builds.nodejs.org/download/release/v${runtime_version}/${basename}`
|
|
107
107
|
];
|
|
108
108
|
let destname = `${cache_dir}/${basename}`;
|
|
109
109
|
|
|
@@ -130,7 +130,7 @@ function Builder(config = {}) {
|
|
|
130
130
|
if (!fs.existsSync(destname)) {
|
|
131
131
|
let urls = [
|
|
132
132
|
`https://nodejs.org/dist/v${runtime_version}/${dirname}/node.lib`,
|
|
133
|
-
`https://unofficial-builds.nodejs.org/download/release/v${runtime_version}/${dirname}/node.lib`
|
|
133
|
+
// `https://unofficial-builds.nodejs.org/download/release/v${runtime_version}/${dirname}/node.lib`
|
|
134
134
|
];
|
|
135
135
|
await tools.download_http(urls, destname);
|
|
136
136
|
}
|
package/src/core/libcc/libcc.cc
CHANGED
|
@@ -5891,6 +5891,8 @@ bool StreamReader::Open(Span<const uint8_t> buf, const char *filename,
|
|
|
5891
5891
|
RG_DEFER_N(err_guard) { error = true; };
|
|
5892
5892
|
error = false;
|
|
5893
5893
|
raw_read = 0;
|
|
5894
|
+
read_total = 0;
|
|
5895
|
+
read_max = -1;
|
|
5894
5896
|
|
|
5895
5897
|
this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<memory>";
|
|
5896
5898
|
|
|
@@ -5912,6 +5914,8 @@ bool StreamReader::Open(FILE *fp, const char *filename, CompressionType compress
|
|
|
5912
5914
|
RG_DEFER_N(err_guard) { error = true; };
|
|
5913
5915
|
error = false;
|
|
5914
5916
|
raw_read = 0;
|
|
5917
|
+
read_total = 0;
|
|
5918
|
+
read_max = -1;
|
|
5915
5919
|
|
|
5916
5920
|
RG_ASSERT(fp);
|
|
5917
5921
|
RG_ASSERT(filename);
|
|
@@ -5935,6 +5939,8 @@ OpenResult StreamReader::Open(const char *filename, CompressionType compression_
|
|
|
5935
5939
|
RG_DEFER_N(err_guard) { error = true; };
|
|
5936
5940
|
error = false;
|
|
5937
5941
|
raw_read = 0;
|
|
5942
|
+
read_total = 0;
|
|
5943
|
+
read_max = -1;
|
|
5938
5944
|
|
|
5939
5945
|
RG_ASSERT(filename);
|
|
5940
5946
|
this->filename = DuplicateString(filename, &str_alloc).ptr;
|
|
@@ -5962,6 +5968,8 @@ bool StreamReader::Open(const std::function<Size(Span<uint8_t>)> &func, const ch
|
|
|
5962
5968
|
RG_DEFER_N(err_guard) { error = true; };
|
|
5963
5969
|
error = false;
|
|
5964
5970
|
raw_read = 0;
|
|
5971
|
+
read_total = 0;
|
|
5972
|
+
read_max = -1;
|
|
5965
5973
|
|
|
5966
5974
|
this->filename = filename ? DuplicateString(filename, &str_alloc).ptr : "<closure>";
|
|
5967
5975
|
|
|
@@ -6081,6 +6089,13 @@ Size StreamReader::Read(Span<uint8_t> out_buf)
|
|
|
6081
6089
|
eof = source.eof;
|
|
6082
6090
|
}
|
|
6083
6091
|
|
|
6092
|
+
if (RG_UNLIKELY(!error && read_max >= 0 && read_len > read_max - read_total)) {
|
|
6093
|
+
LogError("Exceeded max stream size of %1", FmtDiskSize(read_max));
|
|
6094
|
+
error = true;
|
|
6095
|
+
return -1;
|
|
6096
|
+
}
|
|
6097
|
+
read_total += read_len;
|
|
6098
|
+
|
|
6084
6099
|
return read_len;
|
|
6085
6100
|
}
|
|
6086
6101
|
|
package/src/core/libcc/libcc.hh
CHANGED
|
@@ -4229,6 +4229,9 @@ class StreamReader {
|
|
|
4229
4229
|
const char *filename = nullptr;
|
|
4230
4230
|
bool error = true;
|
|
4231
4231
|
|
|
4232
|
+
int64_t read_total = 0;
|
|
4233
|
+
int64_t read_max = -1;
|
|
4234
|
+
|
|
4232
4235
|
struct {
|
|
4233
4236
|
SourceType type = SourceType::Memory;
|
|
4234
4237
|
union U {
|
|
@@ -4289,15 +4292,18 @@ public:
|
|
|
4289
4292
|
|
|
4290
4293
|
const char *GetFileName() const { return filename; }
|
|
4291
4294
|
CompressionType GetCompressionType() const { return compression_type; }
|
|
4295
|
+
int64_t GetReadLimit() { return read_max; }
|
|
4292
4296
|
bool IsValid() const { return filename && !error; }
|
|
4293
4297
|
bool IsEOF() const { return eof; }
|
|
4294
4298
|
|
|
4295
4299
|
FILE *GetFile() const;
|
|
4296
4300
|
int GetDescriptor() const;
|
|
4297
4301
|
|
|
4302
|
+
void SetReadLimit(int64_t limit) { read_max = limit; }
|
|
4303
|
+
|
|
4298
4304
|
Size Read(Span<uint8_t> out_buf);
|
|
4299
4305
|
Size Read(Span<char> out_buf) { return Read(out_buf.As<uint8_t>()); }
|
|
4300
|
-
Size Read(Size
|
|
4306
|
+
Size Read(Size buf_len, void *out_buf) { return Read(MakeSpan((uint8_t *)out_buf, buf_len)); }
|
|
4301
4307
|
|
|
4302
4308
|
Size ReadAll(Size max_len, HeapArray<uint8_t> *out_buf);
|
|
4303
4309
|
Size ReadAll(Size max_len, HeapArray<char> *out_buf)
|
package/src/koffi/CMakeLists.txt
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
# OTHER DEALINGS IN THE SOFTWARE.
|
|
21
21
|
|
|
22
22
|
cmake_minimum_required(VERSION 3.6)
|
|
23
|
+
cmake_policy(SET CMP0091 NEW)
|
|
24
|
+
|
|
23
25
|
project(koffi C CXX ASM)
|
|
24
26
|
|
|
25
27
|
include(CheckCXXCompilerFlag)
|
|
@@ -58,6 +60,8 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
|
58
60
|
# CMAKE_SYSTEM_PROCESSOR is wrong on Windows ARM64
|
|
59
61
|
|
|
60
62
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch|arm" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm")
|
|
63
|
+
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
|
|
64
|
+
|
|
61
65
|
if(WIN32)
|
|
62
66
|
get_filename_component(cl_dir "${CMAKE_CXX_COMPILER}" DIRECTORY)
|
|
63
67
|
file(TO_CMAKE_PATH "${cl_dir}/armasm64.exe" asm_compiler)
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -723,18 +723,25 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
|
|
|
723
723
|
return WrapType(env, instance, type);
|
|
724
724
|
}
|
|
725
725
|
|
|
726
|
-
static inline bool
|
|
726
|
+
static inline bool GetExternalPointer(Napi::Env env, Napi::Value value, void **out_ptr)
|
|
727
727
|
{
|
|
728
728
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
729
729
|
|
|
730
|
-
if (
|
|
731
|
-
|
|
732
|
-
|
|
730
|
+
if (IsNullOrUndefined(value)) {
|
|
731
|
+
*out_ptr = 0;
|
|
732
|
+
return true;
|
|
733
|
+
} else if (value.IsExternal() && !CheckValueTag(instance, value, &TypeInfoMarker) &&
|
|
734
|
+
!CheckValueTag(instance, value, &CastMarker) &&
|
|
735
|
+
!CheckValueTag(instance, value, &MagicUnionMarker)) {
|
|
736
|
+
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
737
|
+
void *ptr = external.Data();
|
|
738
|
+
|
|
739
|
+
*out_ptr = ptr;
|
|
740
|
+
return true;
|
|
741
|
+
} else {
|
|
733
742
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for ptr, expected external pointer", GetValueType(instance, value));
|
|
734
743
|
return false;
|
|
735
744
|
}
|
|
736
|
-
|
|
737
|
-
return true;
|
|
738
745
|
}
|
|
739
746
|
|
|
740
747
|
static Napi::Value CallFree(const Napi::CallbackInfo &info)
|
|
@@ -745,11 +752,10 @@ static Napi::Value CallFree(const Napi::CallbackInfo &info)
|
|
|
745
752
|
ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
|
|
746
753
|
return env.Null();
|
|
747
754
|
}
|
|
748
|
-
if (!CheckExternalPointer(env, info[0]))
|
|
749
|
-
return env.Null();
|
|
750
755
|
|
|
751
|
-
|
|
752
|
-
|
|
756
|
+
void *ptr = nullptr;
|
|
757
|
+
if (!GetExternalPointer(env, info[0], &ptr))
|
|
758
|
+
return env.Null();
|
|
753
759
|
|
|
754
760
|
free(ptr);
|
|
755
761
|
|
|
@@ -816,6 +822,11 @@ static Napi::Value CreateArrayType(const Napi::CallbackInfo &info)
|
|
|
816
822
|
ArrayHint hint = {};
|
|
817
823
|
|
|
818
824
|
if (to == "Typed" || to == "typed") {
|
|
825
|
+
if (!(ref->flags & (int)TypeFlag::HasTypedArray)) {
|
|
826
|
+
ThrowError<Napi::Error>(env, "Array hint 'Typed' cannot be used with type %1", ref->name);
|
|
827
|
+
return env.Null();
|
|
828
|
+
}
|
|
829
|
+
|
|
819
830
|
hint = ArrayHint::Typed;
|
|
820
831
|
} else if (to == "Array" || to == "array") {
|
|
821
832
|
hint = ArrayHint::Array;
|
|
@@ -1733,7 +1744,6 @@ void LibraryHolder::Unref() const
|
|
|
1733
1744
|
}
|
|
1734
1745
|
}
|
|
1735
1746
|
|
|
1736
|
-
|
|
1737
1747
|
static void RegisterPrimitiveType(Napi::Env env, Napi::Object map, std::initializer_list<const char *> names,
|
|
1738
1748
|
PrimitiveKind primitive, int32_t size, int16_t align, const char *ref = nullptr)
|
|
1739
1749
|
{
|
|
@@ -1750,6 +1760,13 @@ static void RegisterPrimitiveType(Napi::Env env, Napi::Object map, std::initiali
|
|
|
1750
1760
|
type->size = size;
|
|
1751
1761
|
type->align = align;
|
|
1752
1762
|
|
|
1763
|
+
if (IsInteger(type) || IsFloat(type)) {
|
|
1764
|
+
type->flags |= (int)TypeFlag::HasTypedArray;
|
|
1765
|
+
}
|
|
1766
|
+
if (TestStr(type->name, "char") || TestStr(type->name, "char16") || TestStr(type->name, "char16_t")) {
|
|
1767
|
+
type->flags |= (int)TypeFlag::IsCharLike;
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1753
1770
|
if (ref) {
|
|
1754
1771
|
const TypeInfo *marker = instance->types_map.FindValue(ref, nullptr);
|
|
1755
1772
|
RG_ASSERT(marker);
|
|
@@ -1999,10 +2016,16 @@ static Napi::Value DecodeValue(const Napi::CallbackInfo &info)
|
|
|
1999
2016
|
|
|
2000
2017
|
Napi::Value value = info[0];
|
|
2001
2018
|
int64_t offset = has_offset ? info[1].As<Napi::Number>().Int64Value() : 0;
|
|
2002
|
-
int64_t len = has_len ? info[2u + has_offset].As<Napi::Number>().Int64Value() : -1;
|
|
2003
2019
|
|
|
2004
|
-
|
|
2005
|
-
|
|
2020
|
+
if (has_len) {
|
|
2021
|
+
Size len = info[2u + has_offset].As<Napi::Number>();
|
|
2022
|
+
|
|
2023
|
+
Napi::Value ret = Decode(value, offset, type, &len);
|
|
2024
|
+
return ret;
|
|
2025
|
+
} else {
|
|
2026
|
+
Napi::Value ret = Decode(value, offset, type);
|
|
2027
|
+
return ret;
|
|
2028
|
+
}
|
|
2006
2029
|
}
|
|
2007
2030
|
|
|
2008
2031
|
static Napi::Value GetPointerAddress(const Napi::CallbackInfo &info)
|
|
@@ -2013,11 +2036,10 @@ static Napi::Value GetPointerAddress(const Napi::CallbackInfo &info)
|
|
|
2013
2036
|
ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
|
|
2014
2037
|
return env.Null();
|
|
2015
2038
|
}
|
|
2016
|
-
if (!CheckExternalPointer(env, info[0]))
|
|
2017
|
-
return env.Null();
|
|
2018
2039
|
|
|
2019
|
-
|
|
2020
|
-
|
|
2040
|
+
void *ptr = nullptr;
|
|
2041
|
+
if (!GetExternalPointer(env, info[0], &ptr))
|
|
2042
|
+
return env.Null();
|
|
2021
2043
|
|
|
2022
2044
|
uint64_t ptr64 = (uint64_t)(uintptr_t)ptr;
|
|
2023
2045
|
Napi::BigInt bigint = Napi::BigInt::New(env, ptr64);
|
package/src/koffi/src/ffi.hh
CHANGED
|
@@ -103,6 +103,11 @@ struct FunctionInfo;
|
|
|
103
103
|
|
|
104
104
|
typedef void DisposeFunc (Napi::Env env, const TypeInfo *type, const void *ptr);
|
|
105
105
|
|
|
106
|
+
enum class TypeFlag {
|
|
107
|
+
HasTypedArray = 1 << 0,
|
|
108
|
+
IsCharLike = 1 << 1
|
|
109
|
+
};
|
|
110
|
+
|
|
106
111
|
enum class ArrayHint {
|
|
107
112
|
Array,
|
|
108
113
|
Typed,
|
|
@@ -120,6 +125,7 @@ struct TypeInfo {
|
|
|
120
125
|
PrimitiveKind primitive;
|
|
121
126
|
int32_t size;
|
|
122
127
|
int16_t align;
|
|
128
|
+
uint16_t flags;
|
|
123
129
|
|
|
124
130
|
DisposeFunc *dispose;
|
|
125
131
|
Napi::FunctionReference dispose_ref;
|
package/src/koffi/src/util.cc
CHANGED
|
@@ -329,11 +329,12 @@ const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size
|
|
|
329
329
|
{
|
|
330
330
|
ArrayHint hint = {};
|
|
331
331
|
|
|
332
|
-
if (
|
|
333
|
-
TestStr(ref->name, "char16_t")) {
|
|
332
|
+
if (ref->flags & (int)TypeFlag::IsCharLike) {
|
|
334
333
|
hint = ArrayHint::String;
|
|
335
|
-
} else {
|
|
334
|
+
} else if (ref->flags & (int)TypeFlag::HasTypedArray) {
|
|
336
335
|
hint = ArrayHint::Typed;
|
|
336
|
+
} else {
|
|
337
|
+
hint = ArrayHint::Array;
|
|
337
338
|
}
|
|
338
339
|
|
|
339
340
|
return MakeArrayType(instance, ref, len, hint, true);
|
|
@@ -1002,7 +1003,7 @@ void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *r
|
|
|
1002
1003
|
#undef SWAP
|
|
1003
1004
|
}
|
|
1004
1005
|
|
|
1005
|
-
Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, Size len)
|
|
1006
|
+
Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const Size *len)
|
|
1006
1007
|
{
|
|
1007
1008
|
Napi::Env env = value.Env();
|
|
1008
1009
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
@@ -1035,13 +1036,35 @@ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, Size le
|
|
|
1035
1036
|
return ret;
|
|
1036
1037
|
}
|
|
1037
1038
|
|
|
1038
|
-
Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, Size len)
|
|
1039
|
+
Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, const Size *len)
|
|
1039
1040
|
{
|
|
1040
1041
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1041
1042
|
|
|
1042
|
-
if (len
|
|
1043
|
-
|
|
1044
|
-
|
|
1043
|
+
if (len && type->primitive != PrimitiveKind::String &&
|
|
1044
|
+
type->primitive != PrimitiveKind::String16) {
|
|
1045
|
+
if (*len >= 0) {
|
|
1046
|
+
type = MakeArrayType(instance, type, *len);
|
|
1047
|
+
} else {
|
|
1048
|
+
if (RG_UNLIKELY(!(type->flags & (int)TypeFlag::IsCharLike))) {
|
|
1049
|
+
ThrowError<Napi::TypeError>(env, "Only char-like types can find their length automatically", type->name);
|
|
1050
|
+
return env.Null();
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
switch (type->primitive) {
|
|
1054
|
+
case PrimitiveKind::Int8: {
|
|
1055
|
+
Size count = strlen((const char *)ptr);
|
|
1056
|
+
type = MakeArrayType(instance, type, count);
|
|
1057
|
+
} break;
|
|
1058
|
+
case PrimitiveKind::Int16: {
|
|
1059
|
+
Size count = WideStringLength((const char16_t *)ptr, RG_SIZE_MAX);
|
|
1060
|
+
type = MakeArrayType(instance, type, count);
|
|
1061
|
+
} break;
|
|
1062
|
+
|
|
1063
|
+
default: { RG_UNREACHABLE(); } break;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1045
1068
|
}
|
|
1046
1069
|
|
|
1047
1070
|
#define RETURN_INT(Type, NewCall) \
|
|
@@ -1080,18 +1103,18 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, Size
|
|
|
1080
1103
|
case PrimitiveKind::UInt64: { RETURN_INT(uint64_t, NewBigInt); } break;
|
|
1081
1104
|
case PrimitiveKind::UInt64S: { RETURN_INT_SWAP(uint64_t, NewBigInt); } break;
|
|
1082
1105
|
case PrimitiveKind::String: {
|
|
1083
|
-
if (len
|
|
1106
|
+
if (len) {
|
|
1084
1107
|
const char *str = *(const char **)ptr;
|
|
1085
|
-
return str ? Napi::String::New(env, str, len) : env.Null();
|
|
1108
|
+
return str ? Napi::String::New(env, str, *len) : env.Null();
|
|
1086
1109
|
} else {
|
|
1087
1110
|
const char *str = *(const char **)ptr;
|
|
1088
1111
|
return str ? Napi::String::New(env, str) : env.Null();
|
|
1089
1112
|
}
|
|
1090
1113
|
} break;
|
|
1091
1114
|
case PrimitiveKind::String16: {
|
|
1092
|
-
if (len
|
|
1115
|
+
if (len) {
|
|
1093
1116
|
const char16_t *str16 = *(const char16_t **)ptr;
|
|
1094
|
-
return str16 ? Napi::String::New(env, str16, len) : env.Null();
|
|
1117
|
+
return str16 ? Napi::String::New(env, str16, *len) : env.Null();
|
|
1095
1118
|
} else {
|
|
1096
1119
|
const char16_t *str16 = *(const char16_t **)ptr;
|
|
1097
1120
|
return str16 ? Napi::String::New(env, str16) : env.Null();
|
package/src/koffi/src/util.hh
CHANGED
|
@@ -160,8 +160,8 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
160
160
|
void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref);
|
|
161
161
|
void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *ref);
|
|
162
162
|
|
|
163
|
-
Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, Size len =
|
|
164
|
-
Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, Size len =
|
|
163
|
+
Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const Size *len = nullptr);
|
|
164
|
+
Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, const Size *len = nullptr);
|
|
165
165
|
|
|
166
166
|
static inline Napi::Value NewBigInt(Napi::Env env, int64_t value)
|
|
167
167
|
{
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|