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
operator bool() const29 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
ToUTF8String() const61 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String() const
62 {
63 size_t strLen = 0;
64 napi_status status = napi_get_value_string_utf8(env_, val_, nullptr, -1, &strLen);
65 if (status != napi_ok) {
66 return { false, nullptr, 0 };
67 }
68
69 size_t bufLen = strLen + 1;
70 unique_ptr<char[]> str = make_unique<char[]>(bufLen);
71 status = napi_get_value_string_utf8(env_, val_, str.get(), bufLen, &strLen);
72 return make_tuple(status == napi_ok, move(str), strLen);
73 }
74
ToUTF8String(string_view defaultValue) const75 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String(string_view defaultValue) const
76 {
77 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
78 auto str = make_unique<char[]>(defaultValue.size() + 1);
79 copy(defaultValue.begin(), defaultValue.end(), str.get());
80 return make_tuple(true, move(str), defaultValue.size());
81 }
82 return ToUTF8String();
83 }
84
ToUTF16String() const85 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF16String() const
86 {
87 #ifdef FILE_SUBSYSTEM_DEBUG_LOCAL
88 size_t strLen = 0;
89 napi_status status = napi_get_value_string_utf16(env_, val_, nullptr, -1, &strLen);
90 if (status != napi_ok) {
91 return { false, nullptr, 0 };
92 }
93
94 auto str = make_unique<char16_t[]>(++strLen);
95 status = napi_get_value_string_utf16(env_, val_, str.get(), strLen, nullptr);
96 if (status != napi_ok) {
97 return { false, nullptr, 0 };
98 }
99
100 strLen = reinterpret_cast<char *>(str.get() + strLen) - reinterpret_cast<char *>(str.get());
101 auto strRet = unique_ptr<char[]>(reinterpret_cast<char *>(str.release()));
102 return { true, move(strRet), strLen };
103 #else
104 // Note that quickjs doesn't support utf16
105 return ToUTF8String();
106 #endif
107 }
108
ToPointer() const109 tuple<bool, void *> NVal::ToPointer() const
110 {
111 void *res = nullptr;
112 napi_status status = napi_get_value_external(env_, val_, &res);
113 return make_tuple(status == napi_ok, res);
114 }
115
ToBool() const116 tuple<bool, bool> NVal::ToBool() const
117 {
118 bool flag = false;
119 napi_status status = napi_get_value_bool(env_, val_, &flag);
120 return make_tuple(status == napi_ok, flag);
121 }
122
ToBool(bool defaultValue) const123 tuple<bool, bool> NVal::ToBool(bool defaultValue) const
124 {
125 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
126 return make_tuple(true, defaultValue);
127 }
128 return ToBool();
129 }
130
ToInt32() const131 tuple<bool, int32_t> NVal::ToInt32() const
132 {
133 int32_t res = 0;
134 napi_status status = napi_get_value_int32(env_, val_, &res);
135 return make_tuple(status == napi_ok, res);
136 }
137
ToInt32(int32_t defaultValue) const138 tuple<bool, int32_t> NVal::ToInt32(int32_t defaultValue) const
139 {
140 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
141 return make_tuple(true, defaultValue);
142 }
143 return ToInt32();
144 }
145
ToInt64() const146 tuple<bool, int64_t> NVal::ToInt64() const
147 {
148 int64_t res = 0;
149 napi_status status = napi_get_value_int64(env_, val_, &res);
150 return make_tuple(status == napi_ok, res);
151 }
152
ToInt64(int64_t defaultValue) const153 tuple<bool, int64_t> NVal::ToInt64(int64_t defaultValue) const
154 {
155 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
156 return make_tuple(true, defaultValue);
157 }
158 return ToInt64();
159 }
160
ToDouble() const161 tuple<bool, double> NVal::ToDouble() const
162 {
163 double res = 0;
164 napi_status status = napi_get_value_double(env_, val_, &res);
165 return make_tuple(status == napi_ok, res);
166 }
167
ToUint64() const168 tuple<bool, uint64_t, bool> NVal::ToUint64() const
169 {
170 uint64_t res = 0;
171 bool lossless = false;
172 napi_status status = napi_get_value_bigint_uint64(env_, val_, &res, &lossless);
173 return make_tuple(status == napi_ok, res, lossless);
174 }
175
ToStringArray()176 tuple<bool, vector<string>, uint32_t> NVal::ToStringArray()
177 {
178 napi_status status;
179 uint32_t size;
180 status = napi_get_array_length(env_, val_, &size);
181 vector<string> stringArray;
182 napi_value result;
183 for (uint32_t i = 0; i < size; i++) {
184 status = napi_get_element(env_, val_, i, &result);
185 auto [succ, str, ignore] = NVal(env_, result).ToUTF8String();
186 stringArray.push_back(string(str.get()));
187 }
188 return make_tuple(status == napi_ok, stringArray, size);
189 }
190
ToArraybuffer() const191 tuple<bool, void *, size_t> NVal::ToArraybuffer() const
192 {
193 void *buf = nullptr;
194 size_t bufLen = 0;
195 bool status = napi_get_arraybuffer_info(env_, val_, &buf, &bufLen);
196 return make_tuple(status == napi_ok, buf, bufLen);
197 }
198
ToTypedArray() const199 tuple<bool, void *, size_t> NVal::ToTypedArray() const
200 {
201 napi_typedarray_type type;
202 napi_value in_array_buffer = nullptr;
203 size_t byte_offset;
204 size_t length;
205 void *data = nullptr;
206 napi_status status =
207 napi_get_typedarray_info(env_, val_, &type, &length, (void **)&data, &in_array_buffer, &byte_offset);
208 return make_tuple(status == napi_ok, data, length);
209 }
210
HasProp(string propName) const211 bool NVal::HasProp(string propName) const
212 {
213 bool res = false;
214
215 if (!env_ || !val_ || !TypeIs(napi_object))
216 return false;
217 napi_status status = napi_has_named_property(env_, val_, propName.c_str(), &res);
218 return (status == napi_ok) && res;
219 }
220
GetProp(string propName) const221 NVal NVal::GetProp(string propName) const
222 {
223 if (!HasProp(propName)) {
224 return { env_, nullptr };
225 }
226
227 napi_value prop = nullptr;
228 napi_status status = napi_get_named_property(env_, val_, propName.c_str(), &prop);
229 if (status != napi_ok) {
230 return { env_, nullptr };
231 }
232
233 return NVal(env_, prop);
234 }
235
AddProp(vector<napi_property_descriptor> && propVec) const236 bool NVal::AddProp(vector<napi_property_descriptor> &&propVec) const
237 {
238 if (!TypeIs(napi_valuetype::napi_object)) {
239 HILOGE("INNER BUG. Prop should only be added to objects");
240 return false;
241 }
242
243 napi_status status = napi_define_properties(env_, val_, propVec.size(), propVec.data());
244 if (status != napi_ok) {
245 HILOGE("INNER BUG. Cannot define properties because of %{public}d", status);
246 return false;
247 }
248
249 return true;
250 }
251
AddProp(string propName,napi_value val) const252 bool NVal::AddProp(string propName, napi_value val) const
253 {
254 if (!TypeIs(napi_valuetype::napi_object) || HasProp(propName)) {
255 HILOGE("INNER BUG. Prop should only be added to objects");
256 return false;
257 }
258
259 napi_status status = napi_set_named_property(env_, val_, propName.c_str(), val);
260 if (status != napi_ok) {
261 HILOGE("INNER BUG. Cannot set named property because of %{public}d", status);
262 return false;
263 }
264
265 return true;
266 }
267
CreateUndefined(napi_env env)268 NVal NVal::CreateUndefined(napi_env env)
269 {
270 napi_value res = nullptr;
271 napi_get_undefined(env, &res);
272 return { env, res };
273 }
274
CreateBigInt64(napi_env env,int64_t val)275 NVal NVal::CreateBigInt64(napi_env env, int64_t val)
276 {
277 napi_value res = nullptr;
278 napi_create_bigint_int64(env, val, &res);
279 return { env, res };
280 }
281
CreateInt64(napi_env env,int64_t val)282 NVal NVal::CreateInt64(napi_env env, int64_t val)
283 {
284 napi_value res = nullptr;
285 napi_create_int64(env, val, &res);
286 return { env, res };
287 }
288
CreateInt32(napi_env env,int32_t val)289 NVal NVal::CreateInt32(napi_env env, int32_t val)
290 {
291 napi_value res = nullptr;
292 napi_create_int32(env, val, &res);
293 return { env, res };
294 }
295
CreateObject(napi_env env)296 NVal NVal::CreateObject(napi_env env)
297 {
298 napi_value res = nullptr;
299 napi_create_object(env, &res);
300 return { env, res };
301 }
302
CreateBool(napi_env env,bool val)303 NVal NVal::CreateBool(napi_env env, bool val)
304 {
305 napi_value res = nullptr;
306 napi_get_boolean(env, val, &res);
307 return { env, res };
308 }
309
CreateUTF8String(napi_env env,std::string str)310 NVal NVal::CreateUTF8String(napi_env env, std::string str)
311 {
312 napi_value res = nullptr;
313 napi_create_string_utf8(env, str.c_str(), str.length(), &res);
314 return { env, res };
315 }
316
CreateUTF8String(napi_env env,const char * str,ssize_t len)317 NVal NVal::CreateUTF8String(napi_env env, const char* str, ssize_t len)
318 {
319 napi_value res = nullptr;
320 napi_create_string_utf8(env, str, len, &res);
321 return { env, res };
322 }
323
CreateUint8Array(napi_env env,void * buf,size_t bufLen)324 NVal NVal::CreateUint8Array(napi_env env, void *buf, size_t bufLen)
325 {
326 napi_value output_buffer = nullptr;
327 napi_create_external_arraybuffer(
328 env,
329 buf,
330 bufLen,
331 [](napi_env env, void *finalize_data, void *finalize_hint) { free(finalize_data); },
332 NULL,
333 &output_buffer);
334 napi_value output_array = nullptr;
335 napi_create_typedarray(env, napi_uint8_array, bufLen, output_buffer, 0, &output_array);
336 return { env, output_array };
337 }
338
CreateArrayString(napi_env env,vector<string> strs)339 NVal NVal::CreateArrayString(napi_env env, vector<string> strs)
340 {
341 napi_value res = nullptr;
342 napi_create_array(env, &res);
343 for (size_t i = 0; i < strs.size(); i++) {
344 napi_value filename;
345 napi_create_string_utf8(env, strs[i].c_str(), strs[i].length(), &filename);
346 napi_set_element(env, res, i, filename);
347 }
348 return {env, res};
349 }
350
CreateArrayBuffer(napi_env env,size_t len)351 tuple<NVal, void *> NVal::CreateArrayBuffer(napi_env env, size_t len)
352 {
353 napi_value val;
354 void *buf = nullptr;
355 napi_create_arraybuffer(env, len, &buf, &val);
356 return { { env, val }, { buf } };
357 }
358
DeclareNapiProperty(const char * name,napi_value val)359 napi_property_descriptor NVal::DeclareNapiProperty(const char *name, napi_value val)
360 {
361 return { (name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr };
362 }
363
DeclareNapiStaticProperty(const char * name,napi_value val)364 napi_property_descriptor NVal::DeclareNapiStaticProperty(const char *name, napi_value val)
365 {
366 return { (name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr };
367 }
368
DeclareNapiFunction(const char * name,napi_callback func)369 napi_property_descriptor NVal::DeclareNapiFunction(const char *name, napi_callback func)
370 {
371 return { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr };
372 }
373
DeclareNapiStaticFunction(const char * name,napi_callback func)374 napi_property_descriptor NVal::DeclareNapiStaticFunction(const char *name, napi_callback func)
375 {
376 return { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr };
377 }
378
DeclareNapiGetter(const char * name,napi_callback getter)379 napi_property_descriptor NVal::DeclareNapiGetter(const char *name, napi_callback getter)
380 {
381 return { (name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, nullptr };
382 }
383
DeclareNapiSetter(const char * name,napi_callback setter)384 napi_property_descriptor NVal::DeclareNapiSetter(const char *name, napi_callback setter)
385 {
386 return { (name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, nullptr };
387 }
388
DeclareNapiGetterSetter(const char * name,napi_callback getter,napi_callback setter)389 napi_property_descriptor NVal::DeclareNapiGetterSetter(const char *name, napi_callback getter, napi_callback setter)
390 {
391 return { (name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, nullptr };
392 }
393 } // namespace DistributedFS
394 } // namespace OHOS