* Copyright (C) 2021-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "napi_util.h"
#include <codecvt>
#include <cstdio>
#include <climits>
#include <locale>
#include <string>
#include "hilog_wrapper.h"
#include "securec.h"
#include "usb_common.h"
#include "usb_errors.h"
#include "usb_napi_errors.h"
namespace OHOS {
namespace USB {
const int32_t MAX_STR_LENGTH = 1024;
void NapiUtil::JsValueToString(const napi_env &env, const napi_value &value, const int32_t bufLen, std::string &target)
{
if (bufLen <= 0 || bufLen > MAX_STR_LENGTH) {
USB_HILOGE(MODULE_USB_NAPI, "string too long malloc failed");
return;
}
int32_t actBufLen = bufLen + 1;
std::unique_ptr<char[]> buf = std::make_unique<char[]>(actBufLen);
errno_t ret = memset_s(buf.get(), actBufLen, 0, actBufLen);
RETURN_IF_WITH_LOG(ret != EOK, "JsValueToString memset_s failed.");
size_t result = 0;
napi_get_value_string_utf8(env, value, buf.get(), actBufLen, &result);
target = buf.get();
}
void NapiUtil::JsObjectToString(
const napi_env &env, const napi_value &object, std::string fieldStr, const int32_t bufLen, std::string &fieldRef)
{
if (bufLen <= 0) {
USB_HILOGE(MODULE_USB_NAPI, "invalid bufLen=%{public}d", bufLen);
return;
}
bool hasProperty = false;
napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
if (hasProperty) {
napi_value field;
napi_valuetype valueType;
napi_get_named_property(env, object, fieldStr.c_str(), &field);
napi_typeof(env, field, &valueType);
USB_ASSERT_RETURN_VOID(
env, valueType == napi_string, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be string.");
int32_t actBufLen = bufLen + 1;
std::unique_ptr<char[]> buf = std::make_unique<char[]>(actBufLen);
errno_t ret = memset_s(buf.get(), actBufLen, 0, actBufLen);
RETURN_IF_WITH_LOG(ret != EOK, "JsObjectToString memset_s failed.");
size_t result = 0;
napi_get_value_string_utf8(env, field, buf.get(), actBufLen, &result);
fieldRef = buf.get();
} else {
USB_HILOGW(MODULE_USB_NAPI, "js to str no property: %{public}s", fieldStr.c_str());
}
}
bool NapiUtil::JsObjectGetProperty(
const napi_env &env, const napi_value &object, std::string fieldStr, napi_value &value)
{
bool hasProperty = false;
napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
if (hasProperty) {
napi_get_named_property(env, object, fieldStr.c_str(), &value);
} else {
USB_HILOGW(MODULE_USB_NAPI, "js object has no property: %{public}s", fieldStr.c_str());
}
return hasProperty;
}
void NapiUtil::JsObjectToBool(const napi_env &env, const napi_value &object, std::string fieldStr, bool &fieldRef)
{
bool hasProperty = false;
napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
if (hasProperty) {
napi_value field;
napi_valuetype valueType;
napi_get_named_property(env, object, fieldStr.c_str(), &field);
napi_typeof(env, field, &valueType);
USB_ASSERT_RETURN_VOID(
env, valueType == napi_boolean, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be boolean.");
napi_get_value_bool(env, field, &fieldRef);
} else {
USB_HILOGW(MODULE_USB_NAPI, "js to boolean no property: %{public}s", fieldStr.c_str());
}
}
void NapiUtil::JsObjectToInt(const napi_env &env, const napi_value &object, std::string fieldStr, int32_t &fieldRef)
{
bool hasProperty = false;
napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
if (hasProperty) {
napi_value field;
napi_valuetype valueType;
napi_get_named_property(env, object, fieldStr.c_str(), &field);
napi_typeof(env, field, &valueType);
USB_ASSERT_RETURN_VOID(
env, valueType == napi_number, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be number.");
napi_get_value_int32(env, field, &fieldRef);
} else {
USB_HILOGW(MODULE_USB_NAPI, "js to int32_t no property: %{public}s", fieldStr.c_str());
}
}
void NapiUtil::JsObjectToUint(
const napi_env &env, const napi_value &object, const std::string &fieldStr, uint32_t &fieldRef)
{
bool hasProperty = false;
napi_status status = napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
if (status != napi_ok || !hasProperty) {
USB_HILOGE(MODULE_USB_NAPI, "js to uint32_t no property: %{public}s", fieldStr.c_str());
return;
}
napi_value field = nullptr;
napi_valuetype valueType;
status = napi_get_named_property(env, object, fieldStr.c_str(), &field);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "get property failed: %{public}s", fieldStr.c_str());
return;
}
status = napi_typeof(env, field, &valueType);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "type error failed: %{public}s", fieldStr.c_str());
return;
}
USB_ASSERT_RETURN_VOID(
env, valueType == napi_number, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be number.");
status = napi_get_value_uint32(env, field, &fieldRef);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "get value failed: %{public}s", fieldStr.c_str());
}
}
bool NapiUtil::JsObjectToUint32(
const napi_env &env, const napi_value &object, const std::string &fieldStr, uint32_t &fieldRef)
{
bool hasProperty = false;
napi_status status = napi_has_named_property(env, object, fieldStr.c_str(), &hasProperty);
if (status != napi_ok || !hasProperty) {
USB_HILOGE(MODULE_USB_NAPI, "js to uint32_t no property: %{public}s", fieldStr.c_str());
return false;
}
napi_value field = nullptr;
napi_valuetype valueType;
status = napi_get_named_property(env, object, fieldStr.c_str(), &field);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "get property failed: %{public}s", fieldStr.c_str());
return false;
}
status = napi_typeof(env, field, &valueType);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "type error failed: %{public}s", fieldStr.c_str());
return false;
}
USB_ASSERT_RETURN_FALSE(
env, valueType == napi_number, OHEC_COMMON_PARAM_ERROR, "The type of " + fieldStr + " must be number.");
status = napi_get_value_uint32(env, field, &fieldRef);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "get value failed: %{public}s", fieldStr.c_str());
return false;
}
return true;
}
bool NapiUtil::JsObjectToUint8(
const napi_env &env, const napi_value &object, const std::string &fieldStr, uint8_t &fieldRef)
{
uint32_t tmpValue = UINT_MAX;
JsObjectToUint(env, object, fieldStr, tmpValue);
if (tmpValue > SCHAR_MAX) {
USB_HILOGE(MODULE_USB_NAPI, "type error failed: uint32_t to uint8_t");
return false;
} else {
fieldRef = tmpValue;
return true;
}
}
bool NapiUtil::JsUint8ArrayParse(
const napi_env &env, const napi_value &object, uint8_t **uint8Buffer, size_t &bufferSize, size_t &offset)
{
bool isTypedArray = false;
if (napi_is_typedarray(env, object, &isTypedArray) != napi_ok || !isTypedArray) {
USB_ASSERT_RETURN_FALSE(env, isTypedArray, OHEC_COMMON_PARAM_ERROR, "The type of buffer must be TypedArray.");
USB_HILOGW(MODULE_USB_NAPI, "invalid type");
return false;
}
napi_typedarray_type type;
napi_value buffer;
napi_status infoStatus = napi_get_typedarray_info(
env, object, &type, &bufferSize, reinterpret_cast<void **>(uint8Buffer), &buffer, &offset);
if (infoStatus != napi_ok) {
USB_HILOGW(MODULE_USB_NAPI, "get typedarray info failed, status: %{public}d", infoStatus);
return false;
}
USB_ASSERT_RETURN_FALSE(
env, type == napi_uint8_array, OHEC_COMMON_PARAM_ERROR, "The type of buffer must be Uint8Array.");
USB_ASSERT_RETURN_FALSE(
env, bufferSize != 0, OHEC_COMMON_PARAM_ERROR, "The size of buffer must be a positive number.");
return true;
}
bool NapiUtil::JsUint8ArrayParseReserveZeroBuffer(
const napi_env &env, const napi_value &object, uint8_t **uint8Buffer, size_t &bufferSize, size_t &offset)
{
bool isTypedArray = false;
if (napi_is_typedarray(env, object, &isTypedArray) != napi_ok || !isTypedArray) {
USB_ASSERT_RETURN_FALSE(env, isTypedArray, OHEC_COMMON_PARAM_ERROR, "The type of buffer must be TypedArray.");
USB_HILOGW(MODULE_USB_NAPI, "invalid type");
return false;
}
napi_typedarray_type type;
napi_value buffer;
napi_status infoStatus = napi_get_typedarray_info(
env, object, &type, &bufferSize, reinterpret_cast<void **>(uint8Buffer), &buffer, &offset);
if (infoStatus != napi_ok) {
USB_HILOGW(MODULE_USB_NAPI, "get typedarray info failed, status: %{public}d", infoStatus);
return false;
}
USB_ASSERT_RETURN_FALSE(
env, type == napi_uint8_array, OHEC_COMMON_PARAM_ERROR, "The type of buffer must be Uint8Array.");
return true;
}
void NapiUtil::Uint8ArrayToJsValue(
const napi_env &env, std::vector<uint8_t> &uint8Buffer, size_t bufferSize, napi_value &result)
{
uint8_t *nativeArraybuffer = nullptr;
napi_value nativeValue = nullptr;
napi_create_arraybuffer(env, bufferSize, reinterpret_cast<void **>(&nativeArraybuffer), &nativeValue);
errno_t ret = memcpy_s(nativeArraybuffer, bufferSize, uint8Buffer.data(), bufferSize);
if (ret != EOK) {
USB_HILOGE(MODULE_USB_NAPI, "memcpy_s failed");
return;
}
napi_create_typedarray(env, napi_uint8_array, bufferSize, nativeValue, 0, &result);
}
void NapiUtil::SetValueUtf8String(const napi_env &env, std::string fieldStr, std::string str, napi_value &result)
{
napi_value value;
napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &value);
napi_set_named_property(env, result, fieldStr.c_str(), value);
}
void NapiUtil::SetValueInt32(const napi_env &env, std::string fieldStr, const int32_t intValue, napi_value &result)
{
napi_value value;
napi_create_int32(env, intValue, &value);
napi_set_named_property(env, result, fieldStr.c_str(), value);
}
void NapiUtil::SetValueUint32(
const napi_env &env, const std::string &fieldStr, const uint32_t uintValue, napi_value &result)
{
napi_value value = nullptr;
napi_status status = napi_create_uint32(env, uintValue, &value);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "create uint32 failed:%{public}s", fieldStr.c_str());
return;
}
status = napi_set_named_property(env, result, fieldStr.c_str(), value);
if (status != napi_ok) {
USB_HILOGE(MODULE_USB_NAPI, "set property failed:%{public}s", fieldStr.c_str());
}
}
void NapiUtil::SetValueBool(const napi_env &env, std::string fieldStr, const bool boolValue, napi_value &result)
{
napi_value value;
napi_get_boolean(env, boolValue, &value);
napi_set_named_property(env, result, fieldStr.c_str(), value);
}
}
}