koffi 0.9.48 → 1.0.2
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/CMakeLists.txt +12 -11
- package/README.md +152 -91
- package/build/qemu/1.0.2/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_win32_x64.tar.gz +0 -0
- package/package.json +8 -4
- package/qemu/qemu.js +794 -0
- package/qemu/registry/machines.json +415 -0
- package/qemu/registry/sha256sum.txt +45 -0
- package/src/{call_arm32.cc → abi_arm32.cc} +76 -50
- package/src/{call_arm32_fwd.S → abi_arm32_fwd.S} +0 -0
- package/src/{call_arm64.cc → abi_arm64.cc} +79 -51
- package/src/{call_arm64_fwd.S → abi_arm64_fwd.S} +0 -0
- package/src/{call_x64_sysv.cc → abi_x64_sysv.cc} +77 -49
- package/src/{call_x64_sysv_fwd.S → abi_x64_sysv_fwd.S} +0 -0
- package/src/{call_x64_win.cc → abi_x64_win.cc} +71 -47
- package/src/{call_x64_win_fwd.asm → abi_x64_win_fwd.asm} +0 -0
- package/src/{call_x86.cc → abi_x86.cc} +74 -56
- package/src/{call_x86_fwd.S → abi_x86_fwd.S} +0 -0
- package/src/{call_x86_fwd.asm → abi_x86_fwd.asm} +0 -0
- package/src/call.cc +228 -0
- package/src/call.hh +96 -4
- package/src/ffi.cc +8 -3
- package/src/ffi.hh +2 -0
- package/src/util.cc +11 -157
- package/src/util.hh +0 -91
- package/test/CMakeLists.txt +1 -0
- package/test/misc.c +289 -0
- package/test/misc.def +3 -0
- package/test/misc.js +180 -0
- package/test/raylib.js +165 -0
- package/test/sqlite.js +104 -0
- package/build/qemu/0.9.48/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/0.9.48/koffi_win32_x64.tar.gz +0 -0
package/src/util.cc
CHANGED
|
@@ -56,6 +56,13 @@ const TypeInfo *ResolveType(const InstanceData *instance, Napi::Value value, int
|
|
|
56
56
|
|
|
57
57
|
const TypeInfo *GetPointerType(InstanceData *instance, const TypeInfo *ref)
|
|
58
58
|
{
|
|
59
|
+
// Special cases
|
|
60
|
+
if (TestStr(ref->name, "char")) {
|
|
61
|
+
return instance->types_map.FindValue("string", nullptr);
|
|
62
|
+
} else if (TestStr(ref->name, "char16") || TestStr(ref->name, "char16_t")) {
|
|
63
|
+
return instance->types_map.FindValue("string16", nullptr);
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
char name_buf[256];
|
|
60
67
|
Fmt(name_buf, "%1%2*", ref->name, ref->primitive == PrimitiveKind::Pointer ? "" : " ");
|
|
61
68
|
|
|
@@ -119,163 +126,6 @@ bool CheckValueTag(const InstanceData *instance, Napi::Value value, const void *
|
|
|
119
126
|
return match;
|
|
120
127
|
}
|
|
121
128
|
|
|
122
|
-
CallData::CallData(Napi::Env env, InstanceData *instance, const FunctionInfo *func)
|
|
123
|
-
: env(env), instance(instance), func(func),
|
|
124
|
-
stack_mem(&instance->stack_mem), heap_mem(&instance->heap_mem),
|
|
125
|
-
old_stack_mem(instance->stack_mem), old_heap_mem(instance->heap_mem)
|
|
126
|
-
{
|
|
127
|
-
RG_ASSERT(AlignUp(stack_mem->ptr, 16) == stack_mem->ptr);
|
|
128
|
-
RG_ASSERT(AlignUp(stack_mem->end(), 16) == stack_mem->end());
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
CallData::~CallData()
|
|
132
|
-
{
|
|
133
|
-
instance->stack_mem = old_stack_mem;
|
|
134
|
-
instance->heap_mem = old_heap_mem;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const char *CallData::PushString(const Napi::Value &value)
|
|
138
|
-
{
|
|
139
|
-
RG_ASSERT(value.IsString());
|
|
140
|
-
|
|
141
|
-
Napi::Env env = value.Env();
|
|
142
|
-
|
|
143
|
-
Span<char> buf;
|
|
144
|
-
size_t len = 0;
|
|
145
|
-
napi_status status;
|
|
146
|
-
|
|
147
|
-
buf.ptr = (char *)heap_mem->ptr;
|
|
148
|
-
buf.len = std::max((Size)0, heap_mem->len - Kibibytes(32));
|
|
149
|
-
|
|
150
|
-
status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
151
|
-
RG_ASSERT(status == napi_ok);
|
|
152
|
-
|
|
153
|
-
len++;
|
|
154
|
-
|
|
155
|
-
if (RG_LIKELY(len < (size_t)buf.len)) {
|
|
156
|
-
heap_mem->ptr += (Size)len;
|
|
157
|
-
heap_mem->len -= (Size)len;
|
|
158
|
-
} else {
|
|
159
|
-
status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
|
|
160
|
-
RG_ASSERT(status == napi_ok);
|
|
161
|
-
|
|
162
|
-
len++;
|
|
163
|
-
|
|
164
|
-
buf.ptr = (char *)Allocator::Allocate(&big_alloc, (Size)len);
|
|
165
|
-
buf.len = (Size)len;
|
|
166
|
-
|
|
167
|
-
status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
168
|
-
RG_ASSERT(status == napi_ok);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return buf.ptr;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest)
|
|
175
|
-
{
|
|
176
|
-
Napi::Env env = obj.Env();
|
|
177
|
-
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
178
|
-
|
|
179
|
-
RG_ASSERT(IsObject(obj));
|
|
180
|
-
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
181
|
-
|
|
182
|
-
for (const RecordMember &member: type->members) {
|
|
183
|
-
Napi::Value value = obj.Get(member.name);
|
|
184
|
-
|
|
185
|
-
if (RG_UNLIKELY(value.IsUndefined())) {
|
|
186
|
-
ThrowError<Napi::TypeError>(env, "Missing expected object property '%1'", member.name);
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
dest = AlignUp(dest, member.align);
|
|
191
|
-
|
|
192
|
-
switch (member.type->primitive) {
|
|
193
|
-
case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
|
|
194
|
-
|
|
195
|
-
case PrimitiveKind::Bool: {
|
|
196
|
-
if (RG_UNLIKELY(!value.IsBoolean())) {
|
|
197
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected boolean", GetValueType(instance, value), member.name);
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
bool b = value.As<Napi::Boolean>();
|
|
202
|
-
*(bool *)dest = b;
|
|
203
|
-
} break;
|
|
204
|
-
|
|
205
|
-
case PrimitiveKind::Int8:
|
|
206
|
-
case PrimitiveKind::UInt8:
|
|
207
|
-
case PrimitiveKind::Int16:
|
|
208
|
-
case PrimitiveKind::UInt16:
|
|
209
|
-
case PrimitiveKind::Int32:
|
|
210
|
-
case PrimitiveKind::UInt32:
|
|
211
|
-
case PrimitiveKind::Int64:
|
|
212
|
-
case PrimitiveKind::UInt64: {
|
|
213
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
214
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
215
|
-
return false;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
int64_t v = CopyNumber<int64_t>(value);
|
|
219
|
-
memcpy(dest, &v, member.type->size); // Little Endian
|
|
220
|
-
} break;
|
|
221
|
-
case PrimitiveKind::Float32: {
|
|
222
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
223
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
float f = CopyNumber<float>(value);
|
|
228
|
-
memcpy(dest, &f, 4);
|
|
229
|
-
} break;
|
|
230
|
-
case PrimitiveKind::Float64: {
|
|
231
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
232
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
233
|
-
return false;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
double d = CopyNumber<double>(value);
|
|
237
|
-
memcpy(dest, &d, 8);
|
|
238
|
-
} break;
|
|
239
|
-
case PrimitiveKind::String: {
|
|
240
|
-
if (RG_UNLIKELY(!value.IsString())) {
|
|
241
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected string", GetValueType(instance, value), member.name);
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const char *str = PushString(value);
|
|
246
|
-
if (RG_UNLIKELY(!str))
|
|
247
|
-
return false;
|
|
248
|
-
*(const char **)dest = str;
|
|
249
|
-
} break;
|
|
250
|
-
case PrimitiveKind::Pointer: {
|
|
251
|
-
if (RG_UNLIKELY(!CheckValueTag(instance, value, member.type))) {
|
|
252
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected %3", GetValueType(instance, value), member.name, member.type->name);
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
Napi::External external = value.As<Napi::External<void>>();
|
|
257
|
-
void *ptr = external.Data();
|
|
258
|
-
*(void **)dest = ptr;
|
|
259
|
-
} break;
|
|
260
|
-
|
|
261
|
-
case PrimitiveKind::Record: {
|
|
262
|
-
if (RG_UNLIKELY(!IsObject(value))) {
|
|
263
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected object", GetValueType(instance, value), member.name);
|
|
264
|
-
return false;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
Napi::Object obj = value.As<Napi::Object>();
|
|
268
|
-
if (!PushObject(obj, member.type, dest))
|
|
269
|
-
return false;
|
|
270
|
-
} break;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
dest += member.type->size;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return true;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
129
|
void PopObject(Napi::Object obj, const uint8_t *ptr, const TypeInfo *type)
|
|
280
130
|
{
|
|
281
131
|
Napi::Env env = obj.Env();
|
|
@@ -339,6 +189,10 @@ void PopObject(Napi::Object obj, const uint8_t *ptr, const TypeInfo *type)
|
|
|
339
189
|
const char *str = *(const char **)ptr;
|
|
340
190
|
obj.Set(member.name, Napi::String::New(env, str));
|
|
341
191
|
} break;
|
|
192
|
+
case PrimitiveKind::String16: {
|
|
193
|
+
const char16_t *str16 = *(const char16_t **)ptr;
|
|
194
|
+
obj.Set(member.name, Napi::String::New(env, str16));
|
|
195
|
+
} break;
|
|
342
196
|
case PrimitiveKind::Pointer: {
|
|
343
197
|
void *ptr2 = *(void **)ptr;
|
|
344
198
|
|
package/src/util.hh
CHANGED
|
@@ -72,97 +72,6 @@ static inline bool IsObject(Napi::Value value)
|
|
|
72
72
|
return value.IsObject() && !IsNullOrUndefined(value) && !value.IsArray();
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
class CallData {
|
|
76
|
-
Napi::Env env;
|
|
77
|
-
InstanceData *instance;
|
|
78
|
-
const FunctionInfo *func;
|
|
79
|
-
|
|
80
|
-
Span<uint8_t> *stack_mem;
|
|
81
|
-
Span<uint8_t> *heap_mem;
|
|
82
|
-
BlockAllocator big_alloc;
|
|
83
|
-
|
|
84
|
-
Span<uint8_t> old_stack_mem;
|
|
85
|
-
Span<uint8_t> old_heap_mem;
|
|
86
|
-
|
|
87
|
-
public:
|
|
88
|
-
CallData(Napi::Env env, InstanceData *instance, const FunctionInfo *func);
|
|
89
|
-
~CallData();
|
|
90
|
-
|
|
91
|
-
Span<uint8_t> GetStack() const
|
|
92
|
-
{
|
|
93
|
-
uint8_t *sp = stack_mem->end();
|
|
94
|
-
Size len = old_stack_mem.end() - sp;
|
|
95
|
-
|
|
96
|
-
return MakeSpan(sp, len);
|
|
97
|
-
}
|
|
98
|
-
uint8_t *GetSP() const { return stack_mem->end(); };
|
|
99
|
-
|
|
100
|
-
Span<uint8_t> GetHeap() const
|
|
101
|
-
{
|
|
102
|
-
uint8_t *ptr = old_heap_mem.ptr;
|
|
103
|
-
Size len = heap_mem->ptr - ptr;
|
|
104
|
-
|
|
105
|
-
return MakeSpan(ptr, len);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
template <typename T = void>
|
|
109
|
-
bool AllocStack(Size size, Size align, T **out_ptr = nullptr);
|
|
110
|
-
template <typename T = void>
|
|
111
|
-
bool AllocHeap(Size size, Size align, T **out_ptr = nullptr);
|
|
112
|
-
|
|
113
|
-
const char *PushString(const Napi::Value &value);
|
|
114
|
-
bool PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest);
|
|
115
|
-
|
|
116
|
-
void DumpDebug() const;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
template <typename T>
|
|
120
|
-
bool CallData::AllocStack(Size size, Size align, T **out_ptr)
|
|
121
|
-
{
|
|
122
|
-
uint8_t *ptr = AlignDown(stack_mem->end() - size, align);
|
|
123
|
-
Size delta = stack_mem->end() - ptr;
|
|
124
|
-
|
|
125
|
-
if (RG_UNLIKELY(stack_mem->len < delta)) {
|
|
126
|
-
ThrowError<Napi::Error>(env, "FFI call is taking up too much memory");
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (instance->debug) {
|
|
131
|
-
memset(ptr, 0, delta);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
stack_mem->len -= delta;
|
|
135
|
-
|
|
136
|
-
if (out_ptr) {
|
|
137
|
-
*out_ptr = (T *)ptr;
|
|
138
|
-
}
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
template <typename T>
|
|
143
|
-
bool CallData::AllocHeap(Size size, Size align, T **out_ptr)
|
|
144
|
-
{
|
|
145
|
-
uint8_t *ptr = AlignUp(heap_mem->ptr, align);
|
|
146
|
-
Size delta = size + (ptr - heap_mem->ptr);
|
|
147
|
-
|
|
148
|
-
if (RG_UNLIKELY(delta > heap_mem->len)) {
|
|
149
|
-
ThrowError<Napi::Error>(env, "FFI call is taking up too much memory");
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (instance->debug) {
|
|
154
|
-
memset(heap_mem->ptr, 0, (size_t)delta);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
heap_mem->ptr += delta;
|
|
158
|
-
heap_mem->len -= delta;
|
|
159
|
-
|
|
160
|
-
if (out_ptr) {
|
|
161
|
-
*out_ptr = (T *)ptr;
|
|
162
|
-
}
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
75
|
template <typename T>
|
|
167
76
|
T CopyNumber(const Napi::Value &value)
|
|
168
77
|
{
|
package/test/CMakeLists.txt
CHANGED
package/test/misc.c
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
// This program is free software: you can redistribute it and/or modify
|
|
2
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
3
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
4
|
+
// (at your option) any later version.
|
|
5
|
+
//
|
|
6
|
+
// This program is distributed in the hope that it will be useful,
|
|
7
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
8
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
9
|
+
// GNU Affero General Public License for more details.
|
|
10
|
+
//
|
|
11
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
12
|
+
// along with this program. If not, see https://www.gnu.org/licenses/.
|
|
13
|
+
|
|
14
|
+
#include <stdlib.h>
|
|
15
|
+
#include <stdio.h>
|
|
16
|
+
#include <inttypes.h>
|
|
17
|
+
#include <string.h>
|
|
18
|
+
#include <stdarg.h>
|
|
19
|
+
#if __has_include(<uchar.h>)
|
|
20
|
+
#include <uchar.h>
|
|
21
|
+
#else
|
|
22
|
+
typedef uint16_t char16_t;
|
|
23
|
+
typedef uint32_t char32_t;
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
#ifdef _WIN32
|
|
27
|
+
#define EXPORT __declspec(dllexport)
|
|
28
|
+
#else
|
|
29
|
+
#define EXPORT __attribute__((visibility("default")))
|
|
30
|
+
#endif
|
|
31
|
+
#if defined(_M_IX86) || defined(__i386__)
|
|
32
|
+
#ifdef _MSC_VER
|
|
33
|
+
#define FASTCALL __fastcall
|
|
34
|
+
#define STDCALL __stdcall
|
|
35
|
+
#else
|
|
36
|
+
#define FASTCALL __attribute__((fastcall))
|
|
37
|
+
#define STDCALL __attribute__((stdcall))
|
|
38
|
+
#endif
|
|
39
|
+
#else
|
|
40
|
+
#define FASTCALL
|
|
41
|
+
#define STDCALL
|
|
42
|
+
#endif
|
|
43
|
+
|
|
44
|
+
typedef struct Pack1 {
|
|
45
|
+
int a;
|
|
46
|
+
} Pack1;
|
|
47
|
+
typedef struct Pack2 {
|
|
48
|
+
int a;
|
|
49
|
+
int b;
|
|
50
|
+
} Pack2;
|
|
51
|
+
typedef struct Pack3 {
|
|
52
|
+
int a;
|
|
53
|
+
int b;
|
|
54
|
+
int c;
|
|
55
|
+
} Pack3;
|
|
56
|
+
|
|
57
|
+
typedef struct IJK1 { int8_t i; int8_t j; int8_t k; } IJK1;
|
|
58
|
+
typedef struct IJK4 { int32_t i; int32_t j; int32_t k; } IJK4;
|
|
59
|
+
typedef struct IJK8 { int64_t i; int64_t j; int64_t k; } IJK8;
|
|
60
|
+
|
|
61
|
+
typedef struct BFG {
|
|
62
|
+
int8_t a;
|
|
63
|
+
int64_t b;
|
|
64
|
+
signed char c;
|
|
65
|
+
const char *d;
|
|
66
|
+
short e;
|
|
67
|
+
struct {
|
|
68
|
+
float f;
|
|
69
|
+
double g;
|
|
70
|
+
} inner;
|
|
71
|
+
} BFG;
|
|
72
|
+
#pragma pack(push, 1)
|
|
73
|
+
typedef struct PackedBFG {
|
|
74
|
+
int8_t a;
|
|
75
|
+
int64_t b;
|
|
76
|
+
signed char c;
|
|
77
|
+
const char *d;
|
|
78
|
+
short e;
|
|
79
|
+
struct {
|
|
80
|
+
float f;
|
|
81
|
+
double g;
|
|
82
|
+
} inner;
|
|
83
|
+
} PackedBFG;
|
|
84
|
+
#pragma pack(pop)
|
|
85
|
+
|
|
86
|
+
EXPORT void FillPack1(int a, Pack1 *p)
|
|
87
|
+
{
|
|
88
|
+
p->a = a;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
EXPORT Pack1 RetPack1(int a)
|
|
92
|
+
{
|
|
93
|
+
Pack1 p;
|
|
94
|
+
|
|
95
|
+
p.a = a;
|
|
96
|
+
|
|
97
|
+
return p;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
EXPORT void FASTCALL AddPack1(int a, Pack1 *p)
|
|
101
|
+
{
|
|
102
|
+
p->a += a;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
EXPORT void FillPack2(int a, int b, Pack2 *p)
|
|
106
|
+
{
|
|
107
|
+
p->a = a;
|
|
108
|
+
p->b = b;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
EXPORT Pack2 RetPack2(int a, int b)
|
|
112
|
+
{
|
|
113
|
+
Pack2 p;
|
|
114
|
+
|
|
115
|
+
p.a = a;
|
|
116
|
+
p.b = b;
|
|
117
|
+
|
|
118
|
+
return p;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
EXPORT void FASTCALL AddPack2(int a, int b, Pack2 *p)
|
|
122
|
+
{
|
|
123
|
+
p->a += a;
|
|
124
|
+
p->b += b;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
EXPORT void FillPack3(int a, int b, int c, Pack3 *p)
|
|
128
|
+
{
|
|
129
|
+
p->a = a;
|
|
130
|
+
p->b = b;
|
|
131
|
+
p->c = c;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
EXPORT Pack3 RetPack3(int a, int b, int c)
|
|
135
|
+
{
|
|
136
|
+
Pack3 p;
|
|
137
|
+
|
|
138
|
+
p.a = a;
|
|
139
|
+
p.b = b;
|
|
140
|
+
p.c = c;
|
|
141
|
+
|
|
142
|
+
return p;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
EXPORT void FASTCALL AddPack3(int a, int b, int c, Pack3 *p)
|
|
146
|
+
{
|
|
147
|
+
p->a += a;
|
|
148
|
+
p->b += b;
|
|
149
|
+
p->c += c;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
EXPORT int64_t ConcatenateToInt1(int8_t a, int8_t b, int8_t c, int8_t d, int8_t e, int8_t f,
|
|
153
|
+
int8_t g, int8_t h, int8_t i, int8_t j, int8_t k, int8_t l)
|
|
154
|
+
{
|
|
155
|
+
int64_t ret = 100000000000ull * a + 10000000000ull * b + 1000000000ull * c +
|
|
156
|
+
100000000ull * d + 10000000ull * e + 1000000ull * f +
|
|
157
|
+
100000ull * g + 10000ull * h + 1000ull * i +
|
|
158
|
+
100ull * j + 10ull * k + 1ull * l;
|
|
159
|
+
return ret;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
EXPORT int64_t ConcatenateToInt4(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f,
|
|
163
|
+
int32_t g, int32_t h, int32_t i, int32_t j, int32_t k, int32_t l)
|
|
164
|
+
{
|
|
165
|
+
int64_t ret = 100000000000ull * a + 10000000000ull * b + 1000000000ull * c +
|
|
166
|
+
100000000ull * d + 10000000ull * e + 1000000ull * f +
|
|
167
|
+
100000ull * g + 10000ull * h + 1000ull * i +
|
|
168
|
+
100ull * j + 10ull * k + 1ull * l;
|
|
169
|
+
return ret;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
EXPORT int64_t ConcatenateToInt8(int64_t a, int64_t b, int64_t c, int64_t d, int64_t e, int64_t f,
|
|
173
|
+
int64_t g, int64_t h, int64_t i, int64_t j, int64_t k, int64_t l)
|
|
174
|
+
{
|
|
175
|
+
int64_t ret = 100000000000ull * a + 10000000000ull * b + 1000000000ull * c +
|
|
176
|
+
100000000ull * d + 10000000ull * e + 1000000ull * f +
|
|
177
|
+
100000ull * g + 10000ull * h + 1000ull * i +
|
|
178
|
+
100ull * j + 10ull * k + 1ull * l;
|
|
179
|
+
return ret;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
EXPORT const char *ConcatenateToStr1(int8_t a, int8_t b, int8_t c, int8_t d, int8_t e, int8_t f,
|
|
183
|
+
int8_t g, int8_t h, IJK1 ijk, int8_t l)
|
|
184
|
+
{
|
|
185
|
+
static char buf[128];
|
|
186
|
+
snprintf(buf, sizeof(buf), "%d%d%d%d%d%d%d%d%d%d%d%d", a, b, c, d, e, f, g, h, ijk.i, ijk.j, ijk.k, l);
|
|
187
|
+
return buf;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
EXPORT const char *ConcatenateToStr4(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f,
|
|
191
|
+
int32_t g, int32_t h, IJK4 *ijk, int32_t l)
|
|
192
|
+
{
|
|
193
|
+
static char buf[128];
|
|
194
|
+
snprintf(buf, sizeof(buf), "%d%d%d%d%d%d%d%d%d%d%d%d", a, b, c, d, e, f, g, h, ijk->i, ijk->j, ijk->k, l);
|
|
195
|
+
return buf;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
EXPORT const char *ConcatenateToStr8(int64_t a, int64_t b, int64_t c, int64_t d, int64_t e, int64_t f,
|
|
199
|
+
int64_t g, int64_t h, IJK8 ijk, int64_t l)
|
|
200
|
+
{
|
|
201
|
+
static char buf[128];
|
|
202
|
+
snprintf(buf, sizeof(buf), "%" PRIi64 "%" PRIi64 "%" PRIi64 "%" PRIi64 "%" PRIi64 "%" PRIi64
|
|
203
|
+
"%" PRIi64 "%" PRIi64 "%" PRIi64 "%" PRIi64 "%" PRIi64 "%" PRIi64,
|
|
204
|
+
a, b, c, d, e, f, g, h, ijk.i, ijk.j, ijk.k, l);
|
|
205
|
+
return buf;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
EXPORT BFG STDCALL MakeBFG(BFG *p, int x, double y, const char *str)
|
|
209
|
+
{
|
|
210
|
+
BFG bfg;
|
|
211
|
+
|
|
212
|
+
char buf[64];
|
|
213
|
+
snprintf(buf, sizeof(buf), "X/%s/X", str);
|
|
214
|
+
|
|
215
|
+
bfg.a = x;
|
|
216
|
+
bfg.b = x * 2;
|
|
217
|
+
bfg.c = x - 27;
|
|
218
|
+
bfg.d = buf;
|
|
219
|
+
bfg.e = x * 27;
|
|
220
|
+
bfg.inner.f = (float)y * x;
|
|
221
|
+
bfg.inner.g = (double)y - x;
|
|
222
|
+
*p = bfg;
|
|
223
|
+
|
|
224
|
+
return bfg;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
EXPORT PackedBFG FASTCALL MakePackedBFG(int x, double y, PackedBFG *p, const char *str)
|
|
228
|
+
{
|
|
229
|
+
PackedBFG bfg;
|
|
230
|
+
|
|
231
|
+
char buf[64];
|
|
232
|
+
snprintf(buf, sizeof(buf), "X/%s/X", str);
|
|
233
|
+
|
|
234
|
+
bfg.a = x;
|
|
235
|
+
bfg.b = x * 2;
|
|
236
|
+
bfg.c = x - 27;
|
|
237
|
+
bfg.d = buf;
|
|
238
|
+
bfg.e = x * 27;
|
|
239
|
+
bfg.inner.f = (float)y * x;
|
|
240
|
+
bfg.inner.g = (double)y - x;
|
|
241
|
+
*p = bfg;
|
|
242
|
+
|
|
243
|
+
return bfg;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
EXPORT const char *ReturnBigString(const char *str)
|
|
247
|
+
{
|
|
248
|
+
static char buf[16 * 1024 * 1024];
|
|
249
|
+
|
|
250
|
+
size_t len = strlen(str);
|
|
251
|
+
memcpy(buf, str, len + 1);
|
|
252
|
+
|
|
253
|
+
return buf;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
EXPORT const char *PrintFmt(const char *fmt, ...)
|
|
257
|
+
{
|
|
258
|
+
static char buf[256];
|
|
259
|
+
|
|
260
|
+
va_list ap;
|
|
261
|
+
va_start(ap, fmt);
|
|
262
|
+
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
263
|
+
va_end(ap);
|
|
264
|
+
|
|
265
|
+
return buf;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
size_t Length16(const char16_t *str)
|
|
269
|
+
{
|
|
270
|
+
size_t len = 0;
|
|
271
|
+
while (str[len]) {
|
|
272
|
+
len++;
|
|
273
|
+
}
|
|
274
|
+
return len;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
EXPORT const char16_t *Concat16(const char16_t *str1, const char16_t *str2)
|
|
278
|
+
{
|
|
279
|
+
static char16_t buf[1024];
|
|
280
|
+
|
|
281
|
+
size_t len1 = Length16(str1);
|
|
282
|
+
size_t len2 = Length16(str2);
|
|
283
|
+
|
|
284
|
+
memcpy(buf, str1, len1 * 2);
|
|
285
|
+
memcpy(buf + len1, str2, len2 * 2);
|
|
286
|
+
buf[(len1 + len2) * 2] = 0;
|
|
287
|
+
|
|
288
|
+
return buf;
|
|
289
|
+
}
|
package/test/misc.def
ADDED