1 /*
2 * Copyright (c) 2022-2023 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 "file_utils.h"
21 #include "filemgmt_libhilog.h"
22 #include "n_error.h"
23
24 namespace OHOS {
25 namespace FileManagement {
26 namespace LibN {
27 using namespace std;
28
NVal(napi_env nEnv,napi_value nVal=nullptr)29 NVal::NVal(napi_env nEnv, napi_value nVal = nullptr) : env_(nEnv), val_(nVal) {}
30
operator bool() const31 NVal::operator bool() const
32 {
33 return env_ && val_;
34 }
35
TypeIs(napi_valuetype expType) const36 bool NVal::TypeIs(napi_valuetype expType) const
37 {
38 if (!*this) {
39 return false;
40 }
41 napi_valuetype valueType;
42 napi_typeof(env_, val_, &valueType);
43
44 if (expType != valueType) {
45 return false;
46 }
47 return true;
48 }
49
TypeIsError(bool checkErrno) const50 bool NVal::TypeIsError(bool checkErrno) const
51 {
52 if (!*this) {
53 return false;
54 }
55
56 bool res = false;
57 napi_is_error(env_, val_, &res);
58
59 return res;
60 }
61
ToUTF8String() const62 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String() const
63 {
64 size_t strLen = 0;
65 napi_status status = napi_get_value_string_utf8(env_, val_, nullptr, -1, &strLen);
66 if (status != napi_ok) {
67 return { false, nullptr, 0 };
68 }
69
70 size_t bufLen = strLen + 1;
71 auto str = CreateUniquePtr<char[]>(bufLen);
72 if (str == nullptr) {
73 return { false, nullptr, 0 };
74 }
75 status = napi_get_value_string_utf8(env_, val_, str.get(), bufLen, &strLen);
76 return make_tuple(status == napi_ok, move(str), strLen);
77 }
78
ToUTF8String(string defaultValue) const79 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String(string defaultValue) const
80 {
81 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
82 auto str = CreateUniquePtr<char[]>(defaultValue.size() + 1);
83 if (str == nullptr) {
84 return { false, nullptr, 0 };
85 }
86 copy(defaultValue.begin(), defaultValue.end(), str.get());
87 str[defaultValue.size()] = '\0';
88 return make_tuple(true, move(str), defaultValue.size());
89 }
90 return ToUTF8String();
91 }
92
ToUTF16String() const93 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF16String() const
94 {
95 #ifdef FILE_SUBSYSTEM_DEBUG_LOCAL
96 size_t strLen = 0;
97 napi_status status = napi_get_value_string_utf16(env_, val_, nullptr, -1, &strLen);
98 if (status != napi_ok) {
99 return { false, nullptr, 0 };
100 }
101
102 auto str = CreateUniquePtr<char16_t[]>(++strLen);
103 if (str == nullptr) {
104 return { false, nullptr, 0 };
105 }
106 status = napi_get_value_string_utf16(env_, val_, str.get(), strLen, nullptr);
107 if (status != napi_ok) {
108 return { false, nullptr, 0 };
109 }
110
111 strLen = reinterpret_cast<char *>(str.get() + strLen) - reinterpret_cast<char *>(str.get());
112 auto strRet = unique_ptr<char[]>(reinterpret_cast<char *>(str.release()));
113 return {true, move(strRet), strLen};
114 #else
115 // Note that quickjs doesn't support utf16
116 return ToUTF8String();
117 #endif
118 }
119
ToPointer() const120 tuple<bool, void *> NVal::ToPointer() const
121 {
122 void *res = nullptr;
123 napi_status status = napi_get_value_external(env_, val_, &res);
124 return make_tuple(status == napi_ok, res);
125 }
126
ToBool() const127 tuple<bool, bool> NVal::ToBool() const
128 {
129 bool flag = false;
130 napi_status status = napi_get_value_bool(env_, val_, &flag);
131 return make_tuple(status == napi_ok, flag);
132 }
133
ToBool(bool defaultValue) const134 tuple<bool, bool> NVal::ToBool(bool defaultValue) const
135 {
136 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
137 return make_tuple(true, defaultValue);
138 }
139 return ToBool();
140 }
141
ToInt32() const142 tuple<bool, int32_t> NVal::ToInt32() const
143 {
144 int32_t res = 0;
145 napi_status status = napi_get_value_int32(env_, val_, &res);
146 return make_tuple(status == napi_ok, res);
147 }
148
ToInt32(int32_t defaultValue) const149 tuple<bool, int32_t> NVal::ToInt32(int32_t defaultValue) const
150 {
151 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
152 return make_tuple(true, defaultValue);
153 }
154 return ToInt32();
155 }
156
ToInt64() const157 tuple<bool, int64_t> NVal::ToInt64() const
158 {
159 int64_t res = 0;
160 napi_status status = napi_get_value_int64(env_, val_, &res);
161 return make_tuple(status == napi_ok, res);
162 }
163
ToInt64(int64_t defaultValue) const164 tuple<bool, int64_t> NVal::ToInt64(int64_t defaultValue) const
165 {
166 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
167 return make_tuple(true, defaultValue);
168 }
169 return ToInt64();
170 }
171
ToDouble() const172 tuple<bool, double> NVal::ToDouble() const
173 {
174 double res = 0;
175 napi_status status = napi_get_value_double(env_, val_, &res);
176 return make_tuple(status == napi_ok, res);
177 }
178
ToUint32() const179 tuple<bool, uint32_t> NVal::ToUint32() const
180 {
181 uint32_t res = 0;
182 napi_status status = napi_get_value_uint32(env_, val_, &res);
183 return make_tuple(status == napi_ok, res);
184 }
185
ToUint64() const186 tuple<bool, uint64_t, bool> NVal::ToUint64() const
187 {
188 uint64_t res = 0;
189 bool lossless = false;
190 napi_status status = napi_get_value_bigint_uint64(env_, val_, &res, &lossless);
191 return make_tuple(status == napi_ok, res, lossless);
192 }
193
ToStringArray()194 tuple<bool, vector<string>, uint32_t> NVal::ToStringArray()
195 {
196 napi_status status;
197 uint32_t size = 0;
198 status = napi_get_array_length(env_, val_, &size);
199 vector<string> stringArray;
200 napi_value result;
201 for (uint32_t i = 0; i < size; i++) {
202 status = napi_get_element(env_, val_, i, &result);
203 auto [succ, str, ignore] = NVal(env_, result).ToUTF8String();
204 stringArray.push_back(string(str.get()));
205 }
206 return make_tuple(status == napi_ok, stringArray, size);
207 }
208
ToArraybuffer() const209 tuple<bool, void *, size_t> NVal::ToArraybuffer() const
210 {
211 void *buf = nullptr;
212 size_t bufLen = 0;
213 bool status = napi_get_arraybuffer_info(env_, val_, &buf, &bufLen);
214 return make_tuple(status == napi_ok, buf, bufLen);
215 }
216
ToTypedArray() const217 tuple<bool, void *, size_t> NVal::ToTypedArray() const
218 {
219 napi_typedarray_type type;
220 napi_value in_array_buffer = nullptr;
221 size_t byte_offset;
222 size_t length;
223 void *data = nullptr;
224 napi_status status =
225 napi_get_typedarray_info(env_, val_, &type, &length, (void **)&data, &in_array_buffer, &byte_offset);
226 return make_tuple(status == napi_ok, data, length);
227 }
228
HasProp(string propName) const229 bool NVal::HasProp(string propName) const
230 {
231 bool res = false;
232
233 if (!env_ || !val_ || !TypeIs(napi_object)) {
234 return false;
235 }
236
237 napi_status status = napi_has_named_property(env_, val_, propName.c_str(), &res);
238 return (status == napi_ok) && res;
239 }
240
241 #ifdef WIN_PLATFORM
GetPropValue(string propName) const242 NVal NVal::GetPropValue(string propName) const
243 #else
244 NVal NVal::GetProp(string propName) const
245 #endif
246 {
247 if (!HasProp(propName)) {
248 return {env_, nullptr};
249 }
250
251 napi_value prop = nullptr;
252 napi_status status = napi_get_named_property(env_, val_, propName.c_str(), &prop);
253 if (status != napi_ok) {
254 return {env_, nullptr};
255 }
256 return NVal(env_, prop);
257 }
258
AddProp(vector<napi_property_descriptor> && propVec) const259 bool NVal::AddProp(vector<napi_property_descriptor> &&propVec) const
260 {
261 if (!TypeIs(napi_valuetype::napi_object)) {
262 HILOGE("INNER BUG. Prop should only be added to objects");
263 return false;
264 }
265
266 napi_status status = napi_define_properties(env_, val_, propVec.size(), propVec.data());
267 if (status != napi_ok) {
268 HILOGE("INNER BUG. Cannot define properties because of %{public}d", status);
269 return false;
270 }
271 return true;
272 }
273
AddProp(string propName,napi_value val) const274 bool NVal::AddProp(string propName, napi_value val) const
275 {
276 if (!TypeIs(napi_valuetype::napi_object) || HasProp(propName)) {
277 HILOGE("INNER BUG. Prop should only be added to objects");
278 return false;
279 }
280
281 napi_status status = napi_set_named_property(env_, val_, propName.c_str(), val);
282 if (status != napi_ok) {
283 HILOGE("INNER BUG. Cannot set named property because of %{public}d", status);
284 return false;
285 }
286 return true;
287 }
288
CreateUndefined(napi_env env)289 NVal NVal::CreateUndefined(napi_env env)
290 {
291 napi_value res = nullptr;
292 napi_get_undefined(env, &res);
293 return {env, res};
294 }
295
CreateBigInt64(napi_env env,int64_t val)296 NVal NVal::CreateBigInt64(napi_env env, int64_t val)
297 {
298 napi_value res = nullptr;
299 napi_create_bigint_int64(env, val, &res);
300 return { env, res };
301 }
302
CreateInt64(napi_env env,int64_t val)303 NVal NVal::CreateInt64(napi_env env, int64_t val)
304 {
305 napi_value res = nullptr;
306 napi_create_int64(env, val, &res);
307 return {env, res};
308 }
309
CreateInt32(napi_env env,int32_t val)310 NVal NVal::CreateInt32(napi_env env, int32_t val)
311 {
312 napi_value res = nullptr;
313 napi_create_int32(env, val, &res);
314 return {env, res};
315 }
316
CreateUint32(napi_env env,int32_t val)317 NVal NVal::CreateUint32(napi_env env, int32_t val)
318 {
319 napi_value res = nullptr;
320 napi_create_uint32(env, val, &res);
321 return {env, res};
322 }
323
CreateObject(napi_env env)324 NVal NVal::CreateObject(napi_env env)
325 {
326 napi_value res = nullptr;
327 napi_create_object(env, &res);
328 return {env, res};
329 }
330
CreateBool(napi_env env,bool val)331 NVal NVal::CreateBool(napi_env env, bool val)
332 {
333 napi_value res = nullptr;
334 napi_get_boolean(env, val, &res);
335 return {env, res};
336 }
337
CreateUTF8String(napi_env env,std::string str)338 NVal NVal::CreateUTF8String(napi_env env, std::string str)
339 {
340 napi_value res = nullptr;
341 napi_create_string_utf8(env, str.c_str(), str.length(), &res);
342 return {env, res};
343 }
344
CreateUTF8String(napi_env env,const char * str,ssize_t len)345 NVal NVal::CreateUTF8String(napi_env env, const char *str, ssize_t len)
346 {
347 napi_value res = nullptr;
348 napi_create_string_utf8(env, str, len, &res);
349 return {env, res};
350 }
351
CreateUint8Array(napi_env env,void * buf,size_t bufLen)352 NVal NVal::CreateUint8Array(napi_env env, void *buf, size_t bufLen)
353 {
354 napi_value output_buffer = nullptr;
355 napi_create_external_arraybuffer(
356 env, buf, bufLen, [](napi_env env, void *finalize_data, void *finalize_hint) { free(finalize_data); }, NULL,
357 &output_buffer);
358 napi_value output_array = nullptr;
359 napi_create_typedarray(env, napi_uint8_array, bufLen, output_buffer, 0, &output_array);
360 return {env, output_array};
361 }
362
CreateArrayString(napi_env env,vector<string> strs)363 NVal NVal::CreateArrayString(napi_env env, vector<string> strs)
364 {
365 napi_value res = nullptr;
366 napi_create_array(env, &res);
367 for (size_t i = 0; i < strs.size(); i++) {
368 napi_value filename;
369 napi_create_string_utf8(env, strs[i].c_str(), strs[i].length(), &filename);
370 napi_set_element(env, res, i, filename);
371 }
372 return {env, res};
373 }
374
CreateArrayBuffer(napi_env env,size_t len)375 tuple<NVal, void *> NVal::CreateArrayBuffer(napi_env env, size_t len)
376 {
377 napi_value val;
378 void *buf = nullptr;
379 napi_create_arraybuffer(env, len, &buf, &val);
380 return {{env, val}, {buf}};
381 }
382
DeclareNapiProperty(const char * name,napi_value val)383 napi_property_descriptor NVal::DeclareNapiProperty(const char *name, napi_value val)
384 {
385 return {(name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr};
386 }
387
DeclareNapiStaticProperty(const char * name,napi_value val)388 napi_property_descriptor NVal::DeclareNapiStaticProperty(const char *name, napi_value val)
389 {
390 return {(name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr};
391 }
392
DeclareNapiFunction(const char * name,napi_callback func)393 napi_property_descriptor NVal::DeclareNapiFunction(const char *name, napi_callback func)
394 {
395 return {(name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr};
396 }
397
DeclareNapiStaticFunction(const char * name,napi_callback func)398 napi_property_descriptor NVal::DeclareNapiStaticFunction(const char *name, napi_callback func)
399 {
400 return {(name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr};
401 }
402
DeclareNapiGetter(const char * name,napi_callback getter)403 napi_property_descriptor NVal::DeclareNapiGetter(const char *name, napi_callback getter)
404 {
405 return {(name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, nullptr};
406 }
407
DeclareNapiSetter(const char * name,napi_callback setter)408 napi_property_descriptor NVal::DeclareNapiSetter(const char *name, napi_callback setter)
409 {
410 return {(name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, nullptr};
411 }
412
DeclareNapiGetterSetter(const char * name,napi_callback getter,napi_callback setter)413 napi_property_descriptor NVal::DeclareNapiGetterSetter(const char *name, napi_callback getter, napi_callback setter)
414 {
415 return {(name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, nullptr};
416 }
417 } // namespace LibN
418 } // namespace FileManagement
419 } // namespace OHOS
420