forked from nodejs/node-addon-api
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtypedarray.cc
More file actions
234 lines (219 loc) · 10.2 KB
/
typedarray.cc
File metadata and controls
234 lines (219 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// Currently experimental guard with NODE_MAJOR_VERISION in which it was
// released. Once it is no longer experimental guard with the NAPI_VERSION
// in which it is released instead.
#if (NODE_MAJOR_VERSION >= 10)
#define NAPI_EXPERIMENTAL
#endif
#include "napi.h"
using namespace Napi;
#if defined(NAPI_HAS_CONSTEXPR)
#define NAPI_TYPEDARRAY_NEW(className, env, length, type) className::New(env, length)
#define NAPI_TYPEDARRAY_NEW_BUFFER(className, env, length, buffer, bufferOffset, type) \
className::New(env, length, buffer, bufferOffset)
#else
#define NAPI_TYPEDARRAY_NEW(className, env, length, type) className::New(env, length, type)
#define NAPI_TYPEDARRAY_NEW_BUFFER(className, env, length, buffer, bufferOffset, type) \
className::New(env, length, buffer, bufferOffset, type)
#endif
namespace {
Value CreateTypedArray(const CallbackInfo& info) {
std::string arrayType = info[0].As<String>();
size_t length = info[1].As<Number>().Uint32Value();
ArrayBuffer buffer = info[2].As<ArrayBuffer>();
size_t bufferOffset = info[3].IsUndefined() ? 0 : info[3].As<Number>().Uint32Value();
if (arrayType == "int8") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(Int8Array, info.Env(), length, napi_int8_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(Int8Array, info.Env(), length, buffer, bufferOffset,
napi_int8_array);
} else if (arrayType == "uint8") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(Uint8Array, info.Env(), length, napi_uint8_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(Uint8Array, info.Env(), length, buffer, bufferOffset,
napi_uint8_array);
} else if (arrayType == "uint8_clamped") {
return buffer.IsUndefined() ?
Uint8Array::New(info.Env(), length, napi_uint8_clamped_array) :
Uint8Array::New(info.Env(), length, buffer, bufferOffset, napi_uint8_clamped_array);
} else if (arrayType == "int16") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(Int16Array, info.Env(), length, napi_int16_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(Int16Array, info.Env(), length, buffer, bufferOffset,
napi_int16_array);
} else if (arrayType == "uint16") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(Uint16Array, info.Env(), length, napi_uint16_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(Uint16Array, info.Env(), length, buffer, bufferOffset,
napi_uint16_array);
} else if (arrayType == "int32") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(Int32Array, info.Env(), length, napi_int32_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(Int32Array, info.Env(), length, buffer, bufferOffset,
napi_int32_array);
} else if (arrayType == "uint32") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(Uint32Array, info.Env(), length, napi_uint32_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(Uint32Array, info.Env(), length, buffer, bufferOffset,
napi_uint32_array);
} else if (arrayType == "float32") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(Float32Array, info.Env(), length, napi_float32_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(Float32Array, info.Env(), length, buffer, bufferOffset,
napi_float32_array);
} else if (arrayType == "float64") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(Float64Array, info.Env(), length, napi_float64_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(Float64Array, info.Env(), length, buffer, bufferOffset,
napi_float64_array);
// Currently experimental guard with NODE_MAJOR_VERISION in which it was
// released. Once it is no longer experimental guard with the NAPI_VERSION
// in which it is released instead.
#if (NODE_MAJOR_VERSION >= 10)
} else if (arrayType == "bigint64") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(BigInt64Array, info.Env(), length, napi_bigint64_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(BigInt64Array, info.Env(), length, buffer, bufferOffset,
napi_bigint64_array);
} else if (arrayType == "biguint64") {
return buffer.IsUndefined() ?
NAPI_TYPEDARRAY_NEW(BigUint64Array, info.Env(), length, napi_biguint64_array) :
NAPI_TYPEDARRAY_NEW_BUFFER(BigUint64Array, info.Env(), length, buffer, bufferOffset,
napi_biguint64_array);
#endif
} else {
Error::New(info.Env(), "Invalid typed-array type.").ThrowAsJavaScriptException();
return Value();
}
}
Value CreateInvalidTypedArray(const CallbackInfo& info) {
return NAPI_TYPEDARRAY_NEW_BUFFER(Int8Array, info.Env(), 1, ArrayBuffer(), 0, napi_int8_array);
}
Value GetTypedArrayType(const CallbackInfo& info) {
TypedArray array = info[0].As<TypedArray>();
switch (array.TypedArrayType()) {
case napi_int8_array: return String::New(info.Env(), "int8");
case napi_uint8_array: return String::New(info.Env(), "uint8");
case napi_uint8_clamped_array: return String::New(info.Env(), "uint8_clamped");
case napi_int16_array: return String::New(info.Env(), "int16");
case napi_uint16_array: return String::New(info.Env(), "uint16");
case napi_int32_array: return String::New(info.Env(), "int32");
case napi_uint32_array: return String::New(info.Env(), "uint32");
case napi_float32_array: return String::New(info.Env(), "float32");
case napi_float64_array: return String::New(info.Env(), "float64");
// Currently experimental guard with NODE_MAJOR_VERISION in which it was
// released. Once it is no longer experimental guard with the NAPI_VERSION
// in which it is released instead.
#if (NODE_MAJOR_VERSION >= 10)
case napi_bigint64_array: return String::New(info.Env(), "bigint64");
case napi_biguint64_array: return String::New(info.Env(), "biguint64");
#endif
default: return String::New(info.Env(), "invalid");
}
}
Value GetTypedArrayLength(const CallbackInfo& info) {
TypedArray array = info[0].As<TypedArray>();
return Number::New(info.Env(), static_cast<double>(array.ElementLength()));
}
Value GetTypedArrayBuffer(const CallbackInfo& info) {
TypedArray array = info[0].As<TypedArray>();
return array.ArrayBuffer();
}
Value GetTypedArrayElement(const CallbackInfo& info) {
TypedArray array = info[0].As<TypedArray>();
size_t index = info[1].As<Number>().Uint32Value();
switch (array.TypedArrayType()) {
case napi_int8_array:
return Number::New(info.Env(), array.As<Int8Array>()[index]);
case napi_uint8_array:
return Number::New(info.Env(), array.As<Uint8Array>()[index]);
case napi_uint8_clamped_array:
return Number::New(info.Env(), array.As<Uint8Array>()[index]);
case napi_int16_array:
return Number::New(info.Env(), array.As<Int16Array>()[index]);
case napi_uint16_array:
return Number::New(info.Env(), array.As<Uint16Array>()[index]);
case napi_int32_array:
return Number::New(info.Env(), array.As<Int32Array>()[index]);
case napi_uint32_array:
return Number::New(info.Env(), array.As<Uint32Array>()[index]);
case napi_float32_array:
return Number::New(info.Env(), array.As<Float32Array>()[index]);
case napi_float64_array:
return Number::New(info.Env(), array.As<Float64Array>()[index]);
// Currently experimental guard with NODE_MAJOR_VERISION in which it was
// released. Once it is no longer experimental guard with the NAPI_VERSION
// in which it is released instead.
#if (NODE_MAJOR_VERSION >= 10)
case napi_bigint64_array:
return BigInt::New(info.Env(), array.As<BigInt64Array>()[index]);
case napi_biguint64_array:
return BigInt::New(info.Env(), array.As<BigUint64Array>()[index]);
#endif
default:
Error::New(info.Env(), "Invalid typed-array type.").ThrowAsJavaScriptException();
return Value();
}
}
void SetTypedArrayElement(const CallbackInfo& info) {
TypedArray array = info[0].As<TypedArray>();
size_t index = info[1].As<Number>().Uint32Value();
Number value = info[2].As<Number>();
switch (array.TypedArrayType()) {
case napi_int8_array:
array.As<Int8Array>()[index] = static_cast<int8_t>(value.Int32Value());
break;
case napi_uint8_array:
array.As<Uint8Array>()[index] = static_cast<uint8_t>(value.Uint32Value());
break;
case napi_uint8_clamped_array:
array.As<Uint8Array>()[index] = static_cast<uint8_t>(value.Uint32Value());
break;
case napi_int16_array:
array.As<Int16Array>()[index] = static_cast<int16_t>(value.Int32Value());
break;
case napi_uint16_array:
array.As<Uint16Array>()[index] = static_cast<uint16_t>(value.Uint32Value());
break;
case napi_int32_array:
array.As<Int32Array>()[index] = value.Int32Value();
break;
case napi_uint32_array:
array.As<Uint32Array>()[index] = value.Uint32Value();
break;
case napi_float32_array:
array.As<Float32Array>()[index] = value.FloatValue();
break;
case napi_float64_array:
array.As<Float64Array>()[index] = value.DoubleValue();
break;
// Currently experimental guard with NODE_MAJOR_VERISION in which it was
// released. Once it is no longer experimental guard with the NAPI_VERSION
// in which it is released instead.
#if (NODE_MAJOR_VERSION >= 10)
case napi_bigint64_array: {
bool lossless;
array.As<BigInt64Array>()[index] = value.As<BigInt>().Int64Value(&lossless);
break;
}
case napi_biguint64_array: {
bool lossless;
array.As<BigUint64Array>()[index] = value.As<BigInt>().Uint64Value(&lossless);
break;
}
#endif
default:
Error::New(info.Env(), "Invalid typed-array type.").ThrowAsJavaScriptException();
}
}
} // end anonymous namespace
Object InitTypedArray(Env env) {
Object exports = Object::New(env);
exports["createTypedArray"] = Function::New(env, CreateTypedArray);
exports["createInvalidTypedArray"] = Function::New(env, CreateInvalidTypedArray);
exports["getTypedArrayType"] = Function::New(env, GetTypedArrayType);
exports["getTypedArrayLength"] = Function::New(env, GetTypedArrayLength);
exports["getTypedArrayBuffer"] = Function::New(env, GetTypedArrayBuffer);
exports["getTypedArrayElement"] = Function::New(env, GetTypedArrayElement);
exports["setTypedArrayElement"] = Function::New(env, SetTypedArrayElement);
return exports;
}