• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 };
34 
CheckNapiIsNull(napi_env env,napi_value value)35 bool VariableConvertor::CheckNapiIsNull(napi_env env, napi_value value)
36 {
37     if (value != nullptr) {
38         napi_valuetype valueType = napi_valuetype::napi_undefined;
39         napi_status status = napi_typeof(env, value, &valueType);
40         if (status != napi_ok) {
41             return false;
42         }
43         if (valueType != napi_valuetype::napi_undefined && valueType != napi_valuetype::napi_null) {
44             return true;
45         }
46     }
47     return false;
48 }
49 
GetOptionValue(napi_env env,napi_value options,const std::string & optionName,std::string & value)50 void VariableConvertor::GetOptionValue(napi_env env, napi_value options, const std::string &optionName,
51     std::string &value)
52 {
53     napi_value optionValue = nullptr;
54     napi_valuetype type = napi_undefined;
55     napi_status status = napi_typeof(env, options, &type);
56     if (status != napi_ok && type != napi_object) {
57         HILOG_ERROR_I18N("GetOptionValue: Get option failed, option is not an object");
58         return;
59     }
60     bool hasProperty = false;
61     napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
62     if (propStatus == napi_ok && hasProperty) {
63         status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
64         if (status == napi_ok) {
65             size_t len;
66             status = napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len);
67             if (status != napi_ok) {
68                 return;
69             }
70             std::vector<char> optionBuf(len + 1);
71             status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len);
72             if (status != napi_ok) {
73                 HILOG_ERROR_I18N("GetOptionValue: Failed to get string item");
74                 return;
75             }
76             value = optionBuf.data();
77         }
78     }
79 }
80 
GetBoolOptionValue(napi_env env,napi_value & options,const std::string & optionName,bool & boolVal)81 bool VariableConvertor::GetBoolOptionValue(napi_env env, napi_value &options, const std::string &optionName,
82     bool &boolVal)
83 {
84     napi_valuetype type = napi_undefined;
85     napi_status status = napi_typeof(env, options, &type);
86     if (status != napi_ok && type != napi_object) {
87         HILOG_ERROR_I18N("option is not an object");
88         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, optionName, "a valid object", true);
89         return false;
90     }
91     bool hasProperty = false;
92     status = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
93     if (status != napi_ok || !hasProperty) {
94         HILOG_INFO_I18N("option don't have property %{public}s", optionName.c_str());
95         return false;
96     }
97     napi_value optionValue = nullptr;
98     status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
99     if (status != napi_ok) {
100         HILOG_INFO_I18N("get option %{public}s failed", optionName.c_str());
101         return false;
102     }
103     status = napi_get_value_bool(env, optionValue, &boolVal);
104     if (status != napi_ok) {
105         return false;
106     }
107     return true;
108 }
109 
GetDouble(napi_env env,napi_value value,int32_t & code)110 double VariableConvertor::GetDouble(napi_env env, napi_value value, int32_t &code)
111 {
112     napi_valuetype valueType = napi_valuetype::napi_undefined;
113     napi_status status = napi_typeof(env, value, &valueType);
114     if (status != napi_ok) {
115         HILOG_ERROR_I18N("VariableConvertor::GetDouble Get napi_value type failed");
116         code = 1;
117         return 0;
118     }
119     if (valueType != napi_valuetype::napi_number) {
120         HILOG_ERROR_I18N("VariableConvertor::GetDouble check napi_type_number failed");
121         code = 1;
122         return 0;
123     }
124     double result = 0;
125     status = napi_get_value_double(env, value, &result);
126     if (status != napi_ok) {
127         HILOG_ERROR_I18N("VariableConvertor::GetDouble Get double failed");
128         code = 1;
129         return 0;
130     }
131     return result;
132 }
133 
GetInt(napi_env env,napi_value value,int32_t & code)134 int32_t VariableConvertor::GetInt(napi_env env, napi_value value, int32_t &code)
135 {
136     napi_valuetype valueType = napi_valuetype::napi_undefined;
137     napi_status status = napi_typeof(env, value, &valueType);
138     if (status != napi_ok) {
139         HILOG_ERROR_I18N("VariableConvertor::GetInt: Get napi_value type failed");
140         code = 1;
141         return 0;
142     }
143     if (valueType != napi_valuetype::napi_number) {
144         HILOG_ERROR_I18N("VariableConvertor::GetInt: check napi_type_number failed");
145         code = 1;
146         return 0;
147     }
148     int32_t result = 0;
149     status = napi_get_value_int32(env, value, &result);
150     if (status != napi_ok) {
151         HILOG_ERROR_I18N("VariableConvertor::GetInt: get int value failed");
152         code = 1;
153         return 0;
154     }
155     return result;
156 }
157 
GetString(napi_env env,napi_value value,int32_t & code)158 std::string VariableConvertor::GetString(napi_env env, napi_value value, int32_t &code)
159 {
160     size_t len = 0;
161     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
162     if (status != napi_ok) {
163         HILOG_ERROR_I18N("Get string failed");
164         code = 1;
165         return "";
166     }
167     std::vector<char> buf(len + 1);
168     status = napi_get_value_string_utf8(env, value, buf.data(), len + 1, &len);
169     if (status != napi_ok) {
170         HILOG_ERROR_I18N("Create string failed");
171         code = 1;
172         return "";
173     }
174     std::string result(buf.data());
175     return result;
176 }
177 
GetStringArrayFromJsParam(napi_env env,napi_value & jsArray,const std::string & valueName,std::vector<std::string> & strArray)178 bool VariableConvertor::GetStringArrayFromJsParam(napi_env env, napi_value &jsArray, const std::string& valueName,
179     std::vector<std::string> &strArray)
180 {
181     if (jsArray == nullptr) {
182         ErrorUtil::NapiNotFoundError(env, I18N_NOT_FOUND, valueName, true);
183         return false;
184     }
185     bool isArray = false;
186     napi_status status = napi_is_array(env, jsArray, &isArray);
187     if (status != napi_ok) {
188         return false;
189     } else if (!isArray) {
190         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, valueName, "an Array", true);
191         return false;
192     }
193     uint32_t arrayLength = 0;
194     status = napi_get_array_length(env, jsArray, &arrayLength);
195     if (status != napi_ok) {
196         return false;
197     }
198     napi_value element = nullptr;
199     int32_t code = 0;
200     for (uint32_t i = 0; i < arrayLength; ++i) {
201         status = napi_get_element(env, jsArray, i, &element);
202         if (status != napi_ok) {
203             return false;
204         }
205         std::string str = GetString(env, element, code);
206         if (code != 0) {
207             HILOG_ERROR_I18N("GetStringArrayFromJsParam: Failed to obtain the parameter.");
208             return false;
209         }
210         strArray.push_back(str);
211     }
212     return true;
213 }
214 
CreateString(napi_env env,const std::string & str)215 napi_value VariableConvertor::CreateString(napi_env env, const std::string &str)
216 {
217     napi_value result;
218     napi_status status = napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &result);
219     if (status != napi_ok) {
220         HILOG_ERROR_I18N("create string js variable failed.");
221         return nullptr;
222     }
223     return result;
224 }
225 
CreateNumber(napi_env env,const int32_t & num)226 napi_value VariableConvertor::CreateNumber(napi_env env, const int32_t &num)
227 {
228     napi_value result;
229     napi_status status = napi_create_int32(env, num, &result);
230     if (status != napi_ok) {
231         HILOG_ERROR_I18N("create number js variable failed.");
232         return nullptr;
233     }
234     return result;
235 }
236 
VerifyType(napi_env env,const std::string & valueName,napi_valuetype napiType,napi_value argv)237 void VariableConvertor::VerifyType(napi_env env, const std::string& valueName, napi_valuetype napiType,
238     napi_value argv)
239 {
240     napi_valuetype valueType = napi_valuetype::napi_undefined;
241     napi_status status = napi_typeof(env, argv, &valueType);
242     if (status != napi_ok || valueType != napiType) {
243         auto iter = NAPI_TYPE_MAP.find(napiType);
244         std::string type = iter != NAPI_TYPE_MAP.end() ? iter->second : "";
245         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, valueName, type, true);
246     }
247 }
248 
SetEnumValue(napi_env env,napi_value enumObj,const std::string & enumName,int32_t enumVal)249 napi_status VariableConvertor::SetEnumValue(napi_env env, napi_value enumObj, const std::string& enumName,
250     int32_t enumVal)
251 {
252     napi_value name = nullptr;
253     napi_status status = napi_create_string_utf8(env, enumName.c_str(), NAPI_AUTO_LENGTH, &name);
254     if (status != napi_ok) {
255         HILOG_ERROR_I18N("VariableConvertor::SetEnumValue: create string %{public}s failed.", enumName.c_str());
256         return status;
257     }
258     napi_value value = nullptr;
259     status = napi_create_int32(env, enumVal, &value);
260     if (status != napi_ok) {
261         HILOG_ERROR_I18N("VariableConvertor::SetEnumValue: create int32 %{public}d failed.", enumVal);
262         return status;
263     }
264     status = napi_set_property(env, enumObj, name, value);
265     if (status != napi_ok) {
266         HILOG_ERROR_I18N("VariableConvertor::SetEnumValue: set property %{public}s failed.", enumName.c_str());
267         return status;
268     }
269     status = napi_set_property(env, enumObj, value, name);
270     if (status != napi_ok) {
271         HILOG_ERROR_I18N("VariableConvertor::SetEnumValue: set property %{public}d failed.", enumVal);
272         return status;
273     }
274     return napi_ok;
275 }
276 
GetLocaleType(napi_env env,napi_value locale)277 LocaleType VariableConvertor::GetLocaleType(napi_env env, napi_value locale)
278 {
279     napi_valuetype valueType = napi_valuetype::napi_undefined;
280     napi_status status = napi_typeof(env, locale, &valueType);
281     if (status != napi_ok) {
282         HILOG_ERROR_I18N("VariableConvertor::GetLocaleType: Failed to get type of intlLocale.");
283         return LocaleType::INVALID;
284     } else if (valueType != napi_valuetype::napi_object) {
285         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "Locale", true);
286         return LocaleType::INVALID;
287     }
288     bool isBuiltinsLocale = VariableConvertor::IsBuiltinsLocale(env, locale);
289     if (isBuiltinsLocale) {
290         return LocaleType::BUILTINS_LOCALE;
291     }
292     bool isLocaleInfo = LocaleInfoAddon::IsLocaleInfo(env, locale);
293     if (isLocaleInfo) {
294         return LocaleType::LOCALE_INFO;
295     }
296     ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "Locale", true);
297     return LocaleType::INVALID;
298 }
299 
ParseLocaleInfo(napi_env env,napi_value localeInfo)300 std::shared_ptr<LocaleInfo> VariableConvertor::ParseLocaleInfo(napi_env env, napi_value localeInfo)
301 {
302     LocaleInfoAddon *localeInfoAddon = nullptr;
303     napi_status status = napi_unwrap(env, localeInfo, reinterpret_cast<void **>(&localeInfoAddon));
304     if (status != napi_ok) {
305         HILOG_ERROR_I18N("VariableConvertor::ParseLocaleInfo: Failed to unwrap localeInfo.");
306         return nullptr;
307     } else if (!localeInfoAddon) {
308         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "intl.Locale", true);
309         return nullptr;
310     } else if (!localeInfoAddon->GetLocaleInfo()) {
311         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale", "a valid intl.Locale", true);
312         return nullptr;
313     }
314     return localeInfoAddon->GetLocaleInfo();
315 }
316 
ParseBuiltinsLocale(napi_env env,napi_value builtinsLocale)317 std::string VariableConvertor::ParseBuiltinsLocale(napi_env env, napi_value builtinsLocale)
318 {
319     napi_value func = nullptr;
320     napi_status status = napi_get_named_property(env, builtinsLocale, "toString", &func);
321     if (status != napi_ok || func == nullptr) {
322         HILOG_ERROR_I18N("VariableConvertor::ParseBuiltinsLocale: Get function toString failed.");
323         return "";
324     }
325     napi_value locale = nullptr;
326     status = napi_call_function(env, builtinsLocale, func, 0, nullptr, &locale);
327     if (status != napi_ok || locale == nullptr) {
328         HILOG_ERROR_I18N("VariableConvertor::ParseBuiltinsLocale: Call function failed.");
329         return "";
330     }
331     int32_t code = 0;
332     std::string localeTag = VariableConvertor::GetString(env, locale, code);
333     if (code != 0) {
334         HILOG_ERROR_I18N("VariableConvertor::ParseBuiltinsLocale: Get string failed.");
335         return "";
336     }
337     return localeTag;
338 }
339 
CreateBuiltinsLocaleObject(napi_env env,const std::string & locale)340 napi_value VariableConvertor::CreateBuiltinsLocaleObject(napi_env env, const std::string& locale)
341 {
342     napi_value param = nullptr;
343     napi_status status = napi_create_string_utf8(env, locale.c_str(), NAPI_AUTO_LENGTH, &param);
344     if (status != napi_ok || param == nullptr) {
345         HILOG_ERROR_I18N("VariableConvertor::CreateBuiltinsLocaleObject: Create string failed.");
346         return nullptr;
347     }
348 
349     napi_value localeConstructor = VariableConvertor::GetBuiltinsLocaleConstructor(env);
350     if (localeConstructor == nullptr) {
351         HILOG_ERROR_I18N("VariableConvertor::CreateBuiltinsLocaleObject: Get constructor failed.");
352         return nullptr;
353     }
354 
355     size_t argc = 1;
356     napi_value argv[1] = { param };
357     napi_value builtinsLocale = nullptr;
358     status = napi_new_instance(env, localeConstructor, argc, argv, &builtinsLocale);
359     if (status != napi_ok || builtinsLocale == nullptr) {
360         HILOG_ERROR_I18N("VariableConvertor::CreateBuiltinsLocaleObject: Create locale failed.");
361         return nullptr;
362     }
363     return builtinsLocale;
364 }
365 
CreateMap(napi_env env,std::unordered_map<std::string,std::string> & ump)366 napi_value VariableConvertor::CreateMap(napi_env env, std::unordered_map<std::string, std::string>& ump)
367 {
368     napi_value result = nullptr;
369     napi_status status = napi_create_map(env, &result);
370     if (status != napi_ok || result == nullptr) {
371         HILOG_ERROR_I18N("VariableConvertor::CreateMap: Create map failed.");
372         return nullptr;
373     }
374     for (const auto& item : ump) {
375         std::string key = item.first;
376         napi_value JSKey = nullptr;
377         status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &JSKey);
378         if (status != napi_ok || JSKey == nullptr) {
379             HILOG_ERROR_I18N("VariableConvertor::CreateMap: Create JSKey failed.");
380             return nullptr;
381         }
382         std::string value = item.second;
383         napi_value JSValue = nullptr;
384         status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &JSValue);
385         if (status != napi_ok || JSValue == nullptr) {
386             HILOG_ERROR_I18N("VariableConvertor::CreateMap: Create JSValue failed.");
387             return nullptr;
388         }
389         status = napi_map_set_property(env, result, JSKey, JSValue);
390         if (status != napi_ok) {
391             HILOG_ERROR_I18N("VariableConvertor::CreateMap: Map set property failed.");
392             return nullptr;
393         }
394     }
395     return result;
396 }
397 
GetBuiltinsLocaleConstructor(napi_env env)398 napi_value VariableConvertor::GetBuiltinsLocaleConstructor(napi_env env)
399 {
400     napi_value global = nullptr;
401     napi_status status = napi_get_global(env, &global);
402     if (status != napi_ok || global == nullptr) {
403         HILOG_ERROR_I18N("VariableConvertor::GetBuiltinsLocaleConstructor: Get global failed.");
404         return nullptr;
405     }
406 
407     napi_value intl = nullptr;
408     status = napi_get_named_property(env, global, "Intl", &intl);
409     if (status != napi_ok || intl == nullptr) {
410         HILOG_ERROR_I18N("VariableConvertor::GetBuiltinsLocaleConstructor: Load intl failed.");
411         return nullptr;
412     }
413 
414     napi_value localeConstructor = nullptr;
415     status = napi_get_named_property(env, intl, "Locale", &localeConstructor);
416     if (status != napi_ok || localeConstructor == nullptr) {
417         HILOG_ERROR_I18N("VariableConvertor::GetBuiltinsLocaleConstructor: Get locale constructor failed.");
418         return nullptr;
419     }
420     return localeConstructor;
421 }
422 
IsBuiltinsLocale(napi_env env,napi_value locale)423 bool VariableConvertor::IsBuiltinsLocale(napi_env env, napi_value locale)
424 {
425     napi_value localeConstructor = VariableConvertor::GetBuiltinsLocaleConstructor(env);
426     if (localeConstructor == nullptr) {
427         HILOG_ERROR_I18N("VariableConvertor::IsBuiltinsLocale: Get constructor failed.");
428         return false;
429     }
430 
431     bool isBuiltinsLocale = false;
432     napi_status status = napi_instanceof(env, locale, localeConstructor, &isBuiltinsLocale);
433     if (status != napi_ok) {
434         HILOG_ERROR_I18N("VariableConvertor::IsBuiltinsLocale: Get instance of locale failed.");
435         return false;
436     }
437     return isBuiltinsLocale;
438 }
439 } // namespace I18n
440 } // namespace Global
441 } // namespace OHOS