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