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