1 /*
2 * Copyright (c) 2023-2024 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 "locale_info_addon.h"
19 #include "variable_convertor.h"
20
21 namespace OHOS {
22 namespace Global {
23 namespace I18n {
24 const std::map<napi_valuetype, std::string> VariableConvertor::NAPI_TYPE_MAP {
25 {napi_valuetype::napi_boolean, "boolean"},
26 {napi_valuetype::napi_number, "number"},
27 {napi_valuetype::napi_string, "string"},
28 {napi_valuetype::napi_bigint, "bigint"},
29 {napi_valuetype::napi_symbol, "symbol"},
30 {napi_valuetype::napi_object, "object"},
31 {napi_valuetype::napi_null, "null"},
32 {napi_valuetype::napi_undefined, "undefined"},
33 };
CheckNapiIsNull(napi_env env,napi_value value)34 bool VariableConvertor::CheckNapiIsNull(napi_env env, napi_value value)
35 {
36 if (value != nullptr) {
37 napi_valuetype valueType = napi_valuetype::napi_undefined;
38 napi_typeof(env, value, &valueType);
39 if (valueType != napi_valuetype::napi_undefined && valueType != napi_valuetype::napi_null) {
40 return true;
41 }
42 }
43 return false;
44 }
45
GetOptionValue(napi_env env,napi_value options,const std::string & optionName,std::string & value)46 void VariableConvertor::GetOptionValue(napi_env env, napi_value options, const std::string &optionName,
47 std::string &value)
48 {
49 napi_value optionValue = nullptr;
50 napi_valuetype type = napi_undefined;
51 napi_status status = napi_typeof(env, options, &type);
52 if (status != napi_ok && type != napi_object) {
53 HILOG_ERROR_I18N("GetOptionValue: Get option failed, option is not an object");
54 return;
55 }
56 bool hasProperty = false;
57 napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
58 if (propStatus == napi_ok && hasProperty) {
59 status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
60 if (status == napi_ok) {
61 size_t len;
62 napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len);
63 std::vector<char> optionBuf(len + 1);
64 status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len);
65 if (status != napi_ok) {
66 HILOG_ERROR_I18N("GetOptionValue: Failed to get string item");
67 return;
68 }
69 value = optionBuf.data();
70 }
71 }
72 }
73
GetBoolOptionValue(napi_env env,napi_value & options,const std::string & optionName,bool & boolVal)74 bool VariableConvertor::GetBoolOptionValue(napi_env env, napi_value &options, const std::string &optionName,
75 bool &boolVal)
76 {
77 napi_valuetype type = napi_undefined;
78 napi_status status = napi_typeof(env, options, &type);
79 if (status != napi_ok && type != napi_object) {
80 HILOG_ERROR_I18N("option is not an object");
81 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, optionName, "a valid object", true);
82 return false;
83 }
84 bool hasProperty = false;
85 status = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
86 if (status != napi_ok || !hasProperty) {
87 HILOG_INFO_I18N("option don't have property %{public}s", optionName.c_str());
88 return false;
89 }
90 napi_value optionValue = nullptr;
91 status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
92 if (status != napi_ok) {
93 HILOG_INFO_I18N("get option %{public}s failed", optionName.c_str());
94 return false;
95 }
96 napi_get_value_bool(env, optionValue, &boolVal);
97 return true;
98 }
99
GetString(napi_env & env,napi_value & value,int32_t & code)100 std::string VariableConvertor::GetString(napi_env &env, napi_value &value, int32_t &code)
101 {
102 size_t len = 0;
103 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
104 if (status != napi_ok) {
105 HILOG_ERROR_I18N("Get string failed");
106 code = 1;
107 return "";
108 }
109 std::vector<char> buf(len + 1);
110 status = napi_get_value_string_utf8(env, value, buf.data(), len + 1, &len);
111 if (status != napi_ok) {
112 HILOG_ERROR_I18N("Create string failed");
113 code = 1;
114 return "";
115 }
116 std::string result(buf.data());
117 return result;
118 }
119
GetStringArrayFromJsParam(napi_env env,napi_value & jsArray,const std::string & valueName,std::vector<std::string> & strArray)120 bool VariableConvertor::GetStringArrayFromJsParam(napi_env env, napi_value &jsArray, const std::string& valueName,
121 std::vector<std::string> &strArray)
122 {
123 if (jsArray == nullptr) {
124 ErrorUtil::NapiNotFoundError(env, I18N_NOT_FOUND, valueName, true);
125 return false;
126 }
127 bool isArray = false;
128 napi_status status = napi_is_array(env, jsArray, &isArray);
129 if (status != napi_ok) {
130 return false;
131 } else if (!isArray) {
132 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, valueName, "an Array", true);
133 return false;
134 }
135 uint32_t arrayLength = 0;
136 napi_get_array_length(env, jsArray, &arrayLength);
137 napi_value element = nullptr;
138 int32_t code = 0;
139 for (uint32_t i = 0; i < arrayLength; ++i) {
140 napi_get_element(env, jsArray, i, &element);
141 std::string str = GetString(env, element, code);
142 if (code != 0) {
143 HILOG_ERROR_I18N("GetStringArrayFromJsParam: Failed to obtain the parameter.");
144 return false;
145 }
146 strArray.push_back(str);
147 }
148 return true;
149 }
150
CreateString(napi_env env,const std::string & str)151 napi_value VariableConvertor::CreateString(napi_env env, const std::string &str)
152 {
153 napi_value result;
154 napi_status status = napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &result);
155 if (status != napi_ok) {
156 HILOG_ERROR_I18N("create string js variable failed.");
157 return nullptr;
158 }
159 return result;
160 }
161
CreateNumber(napi_env env,const int32_t & num)162 napi_value VariableConvertor::CreateNumber(napi_env env, const int32_t &num)
163 {
164 napi_value result;
165 napi_status status = napi_create_int32(env, num, &result);
166 if (status != napi_ok) {
167 HILOG_ERROR_I18N("create number js variable failed.");
168 return nullptr;
169 }
170 return result;
171 }
172
VerifyType(napi_env env,const std::string & valueName,napi_valuetype napiType,napi_value argv)173 void VariableConvertor::VerifyType(napi_env env, const std::string& valueName, napi_valuetype napiType,
174 napi_value argv)
175 {
176 napi_valuetype valueType = napi_valuetype::napi_undefined;
177 napi_status status = napi_typeof(env, argv, &valueType);
178 if (status != napi_ok || valueType != napiType) {
179 auto iter = NAPI_TYPE_MAP.find(napiType);
180 std::string type = iter != NAPI_TYPE_MAP.end() ? iter->second : "";
181 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, valueName, type, true);
182 }
183 }
184
SetEnumValue(napi_env env,napi_value enumObj,const std::string & enumName,int32_t enumVal)185 napi_status VariableConvertor::SetEnumValue(napi_env env, napi_value enumObj, const std::string& enumName,
186 int32_t enumVal)
187 {
188 napi_value name = nullptr;
189 napi_status status = napi_create_string_utf8(env, enumName.c_str(), NAPI_AUTO_LENGTH, &name);
190 if (status != napi_ok) {
191 HILOG_ERROR_I18N("VariableConvertor::SetEnumValue: create string %{public}s failed.", enumName.c_str());
192 return status;
193 }
194 napi_value value = nullptr;
195 status = napi_create_int32(env, enumVal, &value);
196 if (status != napi_ok) {
197 HILOG_ERROR_I18N("VariableConvertor::SetEnumValue: create int32 %{public}d failed.", enumVal);
198 return status;
199 }
200 status = napi_set_property(env, enumObj, name, value);
201 if (status != napi_ok) {
202 HILOG_ERROR_I18N("VariableConvertor::SetEnumValue: set property %{public}s failed.", enumName.c_str());
203 return status;
204 }
205 status = napi_set_property(env, enumObj, value, name);
206 if (status != napi_ok) {
207 HILOG_ERROR_I18N("VariableConvertor::SetEnumValue: set property %{public}d failed.", enumVal);
208 return status;
209 }
210 return napi_ok;
211 }
212
ParseIntlLocale(napi_env env,napi_value intlLocale)213 std::shared_ptr<LocaleInfo> VariableConvertor::ParseIntlLocale(napi_env env, napi_value intlLocale)
214 {
215 napi_valuetype valueType = napi_valuetype::napi_undefined;
216 napi_status status = napi_typeof(env, intlLocale, &valueType);
217 if (status != napi_ok) {
218 HILOG_ERROR_I18N("ParseIntlLocale: Failed to get type of intlLocale.");
219 return nullptr;
220 } else if (valueType != napi_valuetype::napi_object) {
221 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "intl.Locale", true);
222 return nullptr;
223 }
224
225 LocaleInfoAddon *localeInfoAddon = nullptr;
226 status = napi_unwrap(env, intlLocale, reinterpret_cast<void **>(&localeInfoAddon));
227 if (status != napi_ok) {
228 HILOG_ERROR_I18N("ParseIntlLocale: Failed to unwrap intlLocale.");
229 return nullptr;
230 } else if (!localeInfoAddon) {
231 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "intl.Locale", true);
232 return nullptr;
233 } else if (!localeInfoAddon->GetLocaleInfo()) {
234 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale", "a valid intl.Locale", true);
235 return nullptr;
236 }
237 return localeInfoAddon->GetLocaleInfo();
238 }
239 } // namespace I18n
240 } // namespace Global
241 } // namespace OHOS