1/*
2 * Copyright (c) 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 "error_util.h"
17#include "i18n_hilog.h"
18#include "js_utils.h"
19#include "variable_convertor.h"
20
21namespace OHOS {
22namespace Global {
23namespace I18n {
24bool VariableConvertor::CheckNapiValueType(napi_env env, napi_value value)
25{
26    if (value != nullptr) {
27        napi_valuetype valueType = napi_valuetype::napi_undefined;
28        napi_typeof(env, value, &valueType);
29        if (valueType != napi_valuetype::napi_undefined && valueType != napi_valuetype::napi_null) {
30            return true;
31        }
32    }
33    return false;
34}
35
36void VariableConvertor::GetOptionValue(napi_env env, napi_value options, const std::string &optionName,
37    std::string &value)
38{
39    napi_value optionValue = nullptr;
40    napi_valuetype type = napi_undefined;
41    napi_status status = napi_typeof(env, options, &type);
42    if (status != napi_ok && type != napi_object) {
43        HILOG_ERROR_I18N("GetOptionValue: Get option failed, option is not an object");
44        return;
45    }
46    bool hasProperty = false;
47    napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
48    if (propStatus == napi_ok && hasProperty) {
49        status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
50        if (status == napi_ok) {
51            size_t len;
52            napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len);
53            std::vector<char> optionBuf(len + 1);
54            status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len);
55            if (status != napi_ok) {
56                HILOG_ERROR_I18N("GetOptionValue: Failed to get string item");
57                return;
58            }
59            value = optionBuf.data();
60        }
61    }
62}
63
64bool VariableConvertor::GetBoolOptionValue(napi_env env, napi_value &options, const std::string &optionName,
65    bool &boolVal)
66{
67    napi_valuetype type = napi_undefined;
68    napi_status status = napi_typeof(env, options, &type);
69    if (status != napi_ok && type != napi_object) {
70        HILOG_ERROR_I18N("option is not an object");
71        ErrorUtil::NapiThrow(env, I18N_NOT_VALID, optionName, "a valid object", true);
72        return false;
73    }
74    bool hasProperty = false;
75    status = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
76    if (status != napi_ok || !hasProperty) {
77        HILOG_INFO_I18N("option don't have property %{public}s", optionName.c_str());
78        return false;
79    }
80    napi_value optionValue = nullptr;
81    status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
82    if (status != napi_ok) {
83        HILOG_INFO_I18N("get option %{public}s failed", optionName.c_str());
84        return false;
85    }
86    napi_get_value_bool(env, optionValue, &boolVal);
87    return true;
88}
89
90std::string VariableConvertor::GetString(napi_env &env, napi_value &value, int32_t &code)
91{
92    size_t len = 0;
93    napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
94    if (status != napi_ok) {
95        HILOG_ERROR_I18N("Get string failed");
96        code = 1;
97        return "";
98    }
99    std::vector<char> buf(len + 1);
100    status = napi_get_value_string_utf8(env, value, buf.data(), len + 1, &len);
101    if (status != napi_ok) {
102        HILOG_ERROR_I18N("Create string failed");
103        code = 1;
104        return "";
105    }
106    std::string result(buf.data());
107    return result;
108}
109
110bool VariableConvertor::GetStringArrayFromJsParam(napi_env env, napi_value &jsArray, const std::string& valueName,
111    std::vector<std::string> &strArray)
112{
113    if (jsArray == nullptr) {
114        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, valueName, "", true);
115        return false;
116    }
117    bool isArray = false;
118    napi_status status = napi_is_array(env, jsArray, &isArray);
119    if (status != napi_ok) {
120        return false;
121    } else if (!isArray) {
122        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, valueName, "an Array", true);
123        return false;
124    }
125    uint32_t arrayLength = 0;
126    napi_get_array_length(env, jsArray, &arrayLength);
127    napi_value element = nullptr;
128    int32_t code = 0;
129    for (uint32_t i = 0; i < arrayLength; ++i) {
130        napi_get_element(env, jsArray, i, &element);
131        std::string str = GetString(env, element, code);
132        if (code != 0) {
133            HILOG_ERROR_I18N("GetStringArrayFromJsParam: Failed to obtain the parameter.");
134            return false;
135        }
136        strArray.push_back(str);
137    }
138    return true;
139}
140
141napi_value VariableConvertor::CreateString(napi_env env, const std::string &str)
142{
143    napi_value result;
144    napi_status status = napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &result);
145    if (status != napi_ok) {
146        HILOG_ERROR_I18N("create string js variable failed.");
147        return nullptr;
148    }
149    return result;
150}
151
152napi_value VariableConvertor::CreateNumber(napi_env env, const int32_t &num)
153{
154    napi_value result;
155    napi_status status = napi_create_int32(env, num, &result);
156    if (status != napi_ok) {
157        HILOG_ERROR_I18N("create number js variable failed.");
158        return nullptr;
159    }
160    return result;
161}
162
163void VariableConvertor::VerifyType(napi_env env, const std::string& valueName, const std::string& type,
164    napi_value argv)
165{
166    napi_valuetype valueType = napi_valuetype::napi_undefined;
167    napi_typeof(env, argv, &valueType);
168    if (type == "string" && valueType != napi_valuetype::napi_string) {
169        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, valueName, type, true);
170    } else if (type == "number" && valueType != napi_valuetype::napi_number) {
171        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, valueName, type, true);
172    }
173}
174} // namespace I18n
175} // namespace Global
176} // namespace OHOS