1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "n_val.h"
17
18 #include <string>
19
20 #include "../log.h"
21 #include "../uni_error.h"
22
23 namespace OHOS {
24 namespace DistributedFS {
25 using namespace std;
26
NVal(napi_env nEnv,napi_value nVal=nullptr)27 NVal::NVal(napi_env nEnv, napi_value nVal = nullptr) : env_(nEnv), val_(nVal) {}
28
29 NVal::operator bool() const
30 {
31 return env_ && val_;
32 }
33
TypeIs(napi_valuetype expType) const34 bool NVal::TypeIs(napi_valuetype expType) const
35 {
36 if (!*this) {
37 return false;
38 }
39
40 napi_valuetype valueType;
41 napi_typeof(env_, val_, &valueType);
42 if (expType != valueType) {
43 return false;
44 }
45
46 return true;
47 }
48
TypeIsError(bool checkErrno) const49 bool NVal::TypeIsError(bool checkErrno) const
50 {
51 if (!*this) {
52 return false;
53 }
54
55 bool res = false;
56 napi_is_error(env_, val_, &res);
57
58 return res;
59 }
60
ToUTF8StringPath() const61 std::tuple<bool, std::unique_ptr<char[]>, size_t> NVal::ToUTF8StringPath() const
62 {
63 auto [succ, path, strLen] = ToUTF8String();
64 if (succ == false || std::strlen(path.get()) < strLen) {
65 return { false, nullptr, 0 };
66 }
67 return make_tuple(true, move(path), strLen);
68 }
69
ToUTF8String() const70 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String() const
71 {
72 size_t strLen = 0;
73 napi_status status = napi_get_value_string_utf8(env_, val_, nullptr, -1, &strLen);
74 if (status != napi_ok) {
75 return { false, nullptr, 0 };
76 }
77
78 size_t bufLen = strLen + 1;
79 unique_ptr<char[]> str = make_unique<char[]>(bufLen);
80 status = napi_get_value_string_utf8(env_, val_, str.get(), bufLen, &strLen);
81 return make_tuple(status == napi_ok, move(str), strLen);
82 }
83
ToUTF8String(string_view defaultValue) const84 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String(string_view defaultValue) const
85 {
86 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
87 auto str = make_unique<char[]>(defaultValue.size() + 1);
88 copy(defaultValue.begin(), defaultValue.end(), str.get());
89 return make_tuple(true, move(str), defaultValue.size());
90 }
91 return ToUTF8String();
92 }
93
ToUTF16String() const94 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF16String() const
95 {
96 #ifdef FILE_SUBSYSTEM_DEBUG_LOCAL
97 size_t strLen = 0;
98 napi_status status = napi_get_value_string_utf16(env_, val_, nullptr, -1, &strLen);
99 if (status != napi_ok) {
100 return { false, nullptr, 0 };
101 }
102
103 auto str = make_unique<char16_t[]>(++strLen);
104 status = napi_get_value_string_utf16(env_, val_, str.get(), strLen, nullptr);
105 if (status != napi_ok) {
106 return { false, nullptr, 0 };
107 }
108
109 strLen = reinterpret_cast<char *>(str.get() + strLen) - reinterpret_cast<char *>(str.get());
110 auto strRet = unique_ptr<char[]>(reinterpret_cast<char *>(str.release()));
111 return { true, move(strRet), strLen };
112 #else
113 // Note that quickjs doesn't support utf16
114 return ToUTF8String();
115 #endif
116 }
117
ToPointer() const118 tuple<bool, void *> NVal::ToPointer() const
119 {
120 void *res = nullptr;
121 napi_status status = napi_get_value_external(env_, val_, &res);
122 return make_tuple(status == napi_ok, res);
123 }
124
ToBool() const125 tuple<bool, bool> NVal::ToBool() const
126 {
127 bool flag = false;
128 napi_status status = napi_get_value_bool(env_, val_, &flag);
129 return make_tuple(status == napi_ok, flag);
130 }
131
ToBool(bool defaultValue) const132 tuple<bool, bool> NVal::ToBool(bool defaultValue) const
133 {
134 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
135 return make_tuple(true, defaultValue);
136 }
137 return ToBool();
138 }
139
ToInt32() const140 tuple<bool, int32_t> NVal::ToInt32() const
141 {
142 int32_t res = 0;
143 napi_status status = napi_get_value_int32(env_, val_, &res);
144 return make_tuple(status == napi_ok, res);
145 }
146
ToInt32(int32_t defaultValue) const147 tuple<bool, int32_t> NVal::ToInt32(int32_t defaultValue) const
148 {
149 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
150 return make_tuple(true, defaultValue);
151 }
152 return ToInt32();
153 }
154
ToInt64() const155 tuple<bool, int64_t> NVal::ToInt64() const
156 {
157 int64_t res = 0;
158 napi_status status = napi_get_value_int64(env_, val_, &res);
159 return make_tuple(status == napi_ok, res);
160 }
161
ToInt64(int64_t defaultValue) const162 tuple<bool, int64_t> NVal::ToInt64(int64_t defaultValue) const
163 {
164 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
165 return make_tuple(true, defaultValue);
166 }
167 return ToInt64();
168 }
169
ToDouble() const170 tuple<bool, double> NVal::ToDouble() const
171 {
172 double res = 0;
173 napi_status status = napi_get_value_double(env_, val_, &res);
174 return make_tuple(status == napi_ok, res);
175 }
176
ToUint64() const177 tuple<bool, uint64_t, bool> NVal::ToUint64() const
178 {
179 uint64_t res = 0;
180 bool lossless = false;
181 napi_status status = napi_get_value_bigint_uint64(env_, val_, &res, &lossless);
182 return make_tuple(status == napi_ok, res, lossless);
183 }
184
ToStringArray()185 tuple<bool, vector<string>, uint32_t> NVal::ToStringArray()
186 {
187 napi_status status;
188 uint32_t size;
189 status = napi_get_array_length(env_, val_, &size);
190 vector<string> stringArray;
191 napi_value result;
192 for (uint32_t i = 0; i < size; i++) {
193 status = napi_get_element(env_, val_, i, &result);
194 auto [succ, str, ignore] = NVal(env_, result).ToUTF8String();
195 stringArray.push_back(string(str.get()));
196 }
197 return make_tuple(status == napi_ok, stringArray, size);
198 }
199
ToArraybuffer() const200 tuple<bool, void *, size_t> NVal::ToArraybuffer() const
201 {
202 void *buf = nullptr;
203 size_t bufLen = 0;
204 bool status = napi_get_arraybuffer_info(env_, val_, &buf, &bufLen);
205 return make_tuple(status == napi_ok, buf, bufLen);
206 }
207
ToTypedArray() const208 tuple<bool, void *, size_t> NVal::ToTypedArray() const
209 {
210 napi_typedarray_type type;
211 napi_value in_array_buffer = nullptr;
212 size_t byte_offset;
213 size_t length;
214 void *data = nullptr;
215 napi_status status =
216 napi_get_typedarray_info(env_, val_, &type, &length, (void **)&data, &in_array_buffer, &byte_offset);
217 return make_tuple(status == napi_ok, data, length);
218 }
219
HasProp(string propName) const220 bool NVal::HasProp(string propName) const
221 {
222 bool res = false;
223
224 if (!env_ || !val_ || !TypeIs(napi_object))
225 return false;
226 napi_status status = napi_has_named_property(env_, val_, propName.c_str(), &res);
227 return (status == napi_ok) && res;
228 }
229
GetProp(string propName) const230 NVal NVal::GetProp(string propName) const
231 {
232 if (!HasProp(propName)) {
233 return { env_, nullptr };
234 }
235
236 napi_value prop = nullptr;
237 napi_status status = napi_get_named_property(env_, val_, propName.c_str(), &prop);
238 if (status != napi_ok) {
239 return { env_, nullptr };
240 }
241
242 return NVal(env_, prop);
243 }
244
AddProp(vector<napi_property_descriptor> && propVec) const245 bool NVal::AddProp(vector<napi_property_descriptor> &&propVec) const
246 {
247 if (!TypeIs(napi_valuetype::napi_object)) {
248 HILOGE("INNER BUG. Prop should only be added to objects");
249 return false;
250 }
251
252 napi_status status = napi_define_properties(env_, val_, propVec.size(), propVec.data());
253 if (status != napi_ok) {
254 HILOGE("INNER BUG. Cannot define properties because of %{public}d", status);
255 return false;
256 }
257
258 return true;
259 }
260
AddProp(string propName,napi_value val) const261 bool NVal::AddProp(string propName, napi_value val) const
262 {
263 if (!TypeIs(napi_valuetype::napi_object) || HasProp(propName)) {
264 HILOGE("INNER BUG. Prop should only be added to objects");
265 return false;
266 }
267
268 napi_status status = napi_set_named_property(env_, val_, propName.c_str(), val);
269 if (status != napi_ok) {
270 HILOGE("INNER BUG. Cannot set named property because of %{public}d", status);
271 return false;
272 }
273
274 return true;
275 }
276
CreateUndefined(napi_env env)277 NVal NVal::CreateUndefined(napi_env env)
278 {
279 napi_value res = nullptr;
280 napi_get_undefined(env, &res);
281 return { env, res };
282 }
283
CreateBigInt64(napi_env env,int64_t val)284 NVal NVal::CreateBigInt64(napi_env env, int64_t val)
285 {
286 napi_value res = nullptr;
287 napi_create_bigint_int64(env, val, &res);
288 return { env, res };
289 }
290
CreateInt64(napi_env env,int64_t val)291 NVal NVal::CreateInt64(napi_env env, int64_t val)
292 {
293 napi_value res = nullptr;
294 napi_create_int64(env, val, &res);
295 return { env, res };
296 }
297
CreateInt32(napi_env env,int32_t val)298 NVal NVal::CreateInt32(napi_env env, int32_t val)
299 {
300 napi_value res = nullptr;
301 napi_create_int32(env, val, &res);
302 return { env, res };
303 }
304
CreateObject(napi_env env)305 NVal NVal::CreateObject(napi_env env)
306 {
307 napi_value res = nullptr;
308 napi_create_object(env, &res);
309 return { env, res };
310 }
311
CreateBool(napi_env env,bool val)312 NVal NVal::CreateBool(napi_env env, bool val)
313 {
314 napi_value res = nullptr;
315 napi_get_boolean(env, val, &res);
316 return { env, res };
317 }
318
CreateUTF8String(napi_env env,std::string str)319 NVal NVal::CreateUTF8String(napi_env env, std::string str)
320 {
321 napi_value res = nullptr;
322 napi_create_string_utf8(env, str.c_str(), str.length(), &res);
323 return { env, res };
324 }
325
CreateUTF8String(napi_env env,const char * str,ssize_t len)326 NVal NVal::CreateUTF8String(napi_env env, const char* str, ssize_t len)
327 {
328 napi_value res = nullptr;
329 napi_create_string_utf8(env, str, len, &res);
330 return { env, res };
331 }
332
CreateUint8Array(napi_env env,void * buf,size_t bufLen)333 NVal NVal::CreateUint8Array(napi_env env, void *buf, size_t bufLen)
334 {
335 napi_value output_buffer = nullptr;
336 napi_create_external_arraybuffer(
337 env,
338 buf,
339 bufLen,
340 [](napi_env env, void *finalize_data, void *finalize_hint) { free(finalize_data); },
341 NULL,
342 &output_buffer);
343 napi_value output_array = nullptr;
344 napi_create_typedarray(env, napi_uint8_array, bufLen, output_buffer, 0, &output_array);
345 return { env, output_array };
346 }
347
CreateArrayString(napi_env env,vector<string> strs)348 NVal NVal::CreateArrayString(napi_env env, vector<string> strs)
349 {
350 napi_value res = nullptr;
351 napi_create_array(env, &res);
352 for (size_t i = 0; i < strs.size(); i++) {
353 napi_value filename;
354 napi_create_string_utf8(env, strs[i].c_str(), strs[i].length(), &filename);
355 napi_set_element(env, res, i, filename);
356 }
357 return {env, res};
358 }
359
CreateArrayBuffer(napi_env env,size_t len)360 tuple<NVal, void *> NVal::CreateArrayBuffer(napi_env env, size_t len)
361 {
362 napi_value val;
363 void *buf = nullptr;
364 napi_create_arraybuffer(env, len, &buf, &val);
365 return { { env, val }, { buf } };
366 }
367
DeclareNapiProperty(const char * name,napi_value val)368 napi_property_descriptor NVal::DeclareNapiProperty(const char *name, napi_value val)
369 {
370 return { (name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr };
371 }
372
DeclareNapiStaticProperty(const char * name,napi_value val)373 napi_property_descriptor NVal::DeclareNapiStaticProperty(const char *name, napi_value val)
374 {
375 return { (name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr };
376 }
377
DeclareNapiFunction(const char * name,napi_callback func)378 napi_property_descriptor NVal::DeclareNapiFunction(const char *name, napi_callback func)
379 {
380 return { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr };
381 }
382
DeclareNapiStaticFunction(const char * name,napi_callback func)383 napi_property_descriptor NVal::DeclareNapiStaticFunction(const char *name, napi_callback func)
384 {
385 return { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr };
386 }
387
DeclareNapiGetter(const char * name,napi_callback getter)388 napi_property_descriptor NVal::DeclareNapiGetter(const char *name, napi_callback getter)
389 {
390 return { (name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, nullptr };
391 }
392
DeclareNapiSetter(const char * name,napi_callback setter)393 napi_property_descriptor NVal::DeclareNapiSetter(const char *name, napi_callback setter)
394 {
395 return { (name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, nullptr };
396 }
397
DeclareNapiGetterSetter(const char * name,napi_callback getter,napi_callback setter)398 napi_property_descriptor NVal::DeclareNapiGetterSetter(const char *name, napi_callback getter, napi_callback setter)
399 {
400 return { (name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, nullptr };
401 }
402 } // namespace DistributedFS
403 } // namespace OHOS