• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "locale_info_addon.h"
16 
17 #include <vector>
18 
19 #include "error_util.h"
20 #include "i18n_hilog.h"
21 #include "js_utils.h"
22 
23 namespace OHOS {
24 namespace Global {
25 namespace I18n {
26 static thread_local napi_ref *g_constructor = nullptr;
27 
LocaleInfoAddon()28 LocaleInfoAddon::LocaleInfoAddon() : env_(nullptr) {}
29 
~LocaleInfoAddon()30 LocaleInfoAddon::~LocaleInfoAddon()
31 {
32 }
33 
Destructor(napi_env env,void * nativeObject,void * hint)34 void LocaleInfoAddon::Destructor(napi_env env, void *nativeObject, void *hint)
35 {
36     if (!nativeObject) {
37         return;
38     }
39     delete reinterpret_cast<LocaleInfoAddon *>(nativeObject);
40     nativeObject = nullptr;
41 }
42 
SetProperty(napi_env env,napi_callback_info info)43 napi_value LocaleInfoAddon::SetProperty(napi_env env, napi_callback_info info)
44 {
45     // do nothing but provided as an input parameter for DECLARE_NAPI_GETTER_SETTER;
46     napi_value result = nullptr;
47     NAPI_CALL(env, napi_get_undefined(env, &result));
48     return result;
49 }
50 
InitLocale(napi_env env,napi_value exports)51 napi_value LocaleInfoAddon::InitLocale(napi_env env, napi_value exports)
52 {
53     napi_property_descriptor properties[] = {
54         DECLARE_NAPI_GETTER_SETTER("language", GetLanguage, SetProperty),
55         DECLARE_NAPI_GETTER_SETTER("baseName", GetBaseName, SetProperty),
56         DECLARE_NAPI_GETTER_SETTER("region", GetRegion, SetProperty),
57         DECLARE_NAPI_GETTER_SETTER("script", GetScript, SetProperty),
58         DECLARE_NAPI_GETTER_SETTER("calendar", GetCalendar, SetProperty),
59         DECLARE_NAPI_GETTER_SETTER("collation", GetCollation, SetProperty),
60         DECLARE_NAPI_GETTER_SETTER("hourCycle", GetHourCycle, SetProperty),
61         DECLARE_NAPI_GETTER_SETTER("numberingSystem", GetNumberingSystem, SetProperty),
62         DECLARE_NAPI_GETTER_SETTER("numeric", GetNumeric, SetProperty),
63         DECLARE_NAPI_GETTER_SETTER("caseFirst", GetCaseFirst, SetProperty),
64         DECLARE_NAPI_FUNCTION("toString", ToString),
65         DECLARE_NAPI_FUNCTION("minimize", Minimize),
66         DECLARE_NAPI_FUNCTION("maximize", Maximize),
67     };
68     napi_value constructor = nullptr;
69     napi_status status = napi_define_class(env, "Locale", NAPI_AUTO_LENGTH, LocaleConstructor, nullptr,
70         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
71     if (status != napi_ok) {
72         HILOG_ERROR_I18N("Define class failed when InitLocale");
73         return nullptr;
74     }
75     status = napi_set_named_property(env, exports, "Locale", constructor);
76     if (status != napi_ok) {
77         HILOG_ERROR_I18N("Set property failed when InitLocale");
78         return nullptr;
79     }
80     g_constructor = new (std::nothrow) napi_ref;
81     if (!g_constructor) {
82         HILOG_ERROR_I18N("Failed to create ref at init");
83         return nullptr;
84     }
85     status = napi_create_reference(env, constructor, 1, g_constructor);
86     if (status != napi_ok) {
87         HILOG_ERROR_I18N("Failed to create reference at init");
88         return nullptr;
89     }
90     return exports;
91 }
92 
LocaleConstructor(napi_env env,napi_callback_info info)93 napi_value LocaleInfoAddon::LocaleConstructor(napi_env env, napi_callback_info info)
94 {
95     size_t argc = 2;
96     napi_value argv[2] = { nullptr };
97     napi_value thisVar = nullptr;
98     void *data = nullptr;
99     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
100     if (status != napi_ok) {
101         return nullptr;
102     }
103     std::string localeTag;
104     if (argc > 0) {
105         int32_t code = 0;
106         localeTag = JSUtils::GetString(env, argv[0], code);
107         if (code != 0) {
108             return nullptr;
109         }
110     }
111     std::map<std::string, std::string> map = {};
112     if (argc > 1) {
113         JSUtils::GetOptionValue(env, argv[1], "calendar", map);
114         JSUtils::GetOptionValue(env, argv[1], "collation", map);
115         JSUtils::GetOptionValue(env, argv[1], "hourCycle", map);
116         JSUtils::GetOptionValue(env, argv[1], "numberingSystem", map);
117         JSUtils::GetBoolOptionValue(env, argv[1], "numeric", map);
118         JSUtils::GetOptionValue(env, argv[1], "caseFirst", map);
119     }
120     std::unique_ptr<LocaleInfoAddon> obj = std::make_unique<LocaleInfoAddon>();
121     if (obj == nullptr) {
122         return nullptr;
123     }
124     status =
125         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), LocaleInfoAddon::Destructor, nullptr, nullptr);
126     if (status != napi_ok) {
127         HILOG_ERROR_I18N("LocaleConstructor: Wrap LocaleInfoAddon failed");
128         return nullptr;
129     }
130     if (!obj->InitLocaleContext(env, info, localeTag, map)) {
131         return nullptr;
132     }
133     obj.release();
134     return thisVar;
135 }
136 
InitLocaleContext(napi_env env,napi_callback_info info,const std::string localeTag,std::map<std::string,std::string> & map)137 bool LocaleInfoAddon::InitLocaleContext(napi_env env, napi_callback_info info, const std::string localeTag,
138     std::map<std::string, std::string> &map)
139 {
140     napi_value global = nullptr;
141     napi_status status = napi_get_global(env, &global);
142     if (status != napi_ok) {
143         HILOG_ERROR_I18N("InitLocaleContext: Get global failed");
144         return false;
145     }
146     env_ = env;
147     locale_ = std::make_unique<LocaleInfo>(localeTag, map);
148     return locale_ != nullptr;
149 }
150 
IsLocaleInfo(napi_env env,napi_value argv)151 bool LocaleInfoAddon::IsLocaleInfo(napi_env env, napi_value argv)
152 {
153     napi_value constructor = nullptr;
154     if (g_constructor == nullptr) {
155         HILOG_ERROR_I18N("LocaleInfoAddon::IsLocaleInfo: g_constructor is nullptr.");
156         return false;
157     }
158 
159     napi_status status = napi_get_reference_value(env, *g_constructor, &constructor);
160     if (status != napi_ok || constructor == nullptr) {
161         HILOG_ERROR_I18N("LocaleInfoAddon::IsLocaleInfo: Failed to create reference.");
162         return false;
163     }
164 
165     bool isLocaleInfo = false;
166     status = napi_instanceof(env, argv, constructor, &isLocaleInfo);
167     if (status != napi_ok) {
168         HILOG_ERROR_I18N("LocaleInfoAddon::IsLocaleInfo: Failed to get instance of argv.");
169         return false;
170     }
171     return isLocaleInfo;
172 }
173 
GetLanguageInner(std::shared_ptr<LocaleInfo> localeInfo)174 std::string LocaleInfoAddon::GetLanguageInner(std::shared_ptr<LocaleInfo> localeInfo)
175 {
176     if (localeInfo != nullptr) {
177         return localeInfo->GetLanguage();
178     }
179     return "";
180 }
181 
GetScriptInner(std::shared_ptr<LocaleInfo> localeInfo)182 std::string LocaleInfoAddon::GetScriptInner(std::shared_ptr<LocaleInfo> localeInfo)
183 {
184     if (localeInfo != nullptr) {
185         return localeInfo->GetScript();
186     }
187     return "";
188 }
189 
GetRegionInner(std::shared_ptr<LocaleInfo> localeInfo)190 std::string LocaleInfoAddon::GetRegionInner(std::shared_ptr<LocaleInfo> localeInfo)
191 {
192     if (localeInfo != nullptr) {
193         return localeInfo->GetRegion();
194     }
195     return "";
196 }
197 
GetBaseNameInner(std::shared_ptr<LocaleInfo> localeInfo)198 std::string LocaleInfoAddon::GetBaseNameInner(std::shared_ptr<LocaleInfo> localeInfo)
199 {
200     if (localeInfo != nullptr) {
201         return localeInfo->GetBaseName();
202     }
203     return "";
204 }
205 
GetCalendarInner(std::shared_ptr<LocaleInfo> localeInfo)206 std::string LocaleInfoAddon::GetCalendarInner(std::shared_ptr<LocaleInfo> localeInfo)
207 {
208     if (localeInfo != nullptr) {
209         return localeInfo->GetCalendar();
210     }
211     return "";
212 }
213 
GetCollationInner(std::shared_ptr<LocaleInfo> localeInfo)214 std::string LocaleInfoAddon::GetCollationInner(std::shared_ptr<LocaleInfo> localeInfo)
215 {
216     if (localeInfo != nullptr) {
217         return localeInfo->GetCollation();
218     }
219     return "";
220 }
221 
GetHourCycleInner(std::shared_ptr<LocaleInfo> localeInfo)222 std::string LocaleInfoAddon::GetHourCycleInner(std::shared_ptr<LocaleInfo> localeInfo)
223 {
224     if (localeInfo != nullptr) {
225         return localeInfo->GetHourCycle();
226     }
227     return "";
228 }
229 
GetNumberingSystemInner(std::shared_ptr<LocaleInfo> localeInfo)230 std::string LocaleInfoAddon::GetNumberingSystemInner(std::shared_ptr<LocaleInfo> localeInfo)
231 {
232     if (localeInfo != nullptr) {
233         return localeInfo->GetNumberingSystem();
234     }
235     return "";
236 }
237 
GetCaseFirstInner(std::shared_ptr<LocaleInfo> localeInfo)238 std::string LocaleInfoAddon::GetCaseFirstInner(std::shared_ptr<LocaleInfo> localeInfo)
239 {
240     if (localeInfo != nullptr) {
241         return localeInfo->GetCaseFirst();
242     }
243     return "";
244 }
245 
ToStringInner(std::shared_ptr<LocaleInfo> localeInfo)246 std::string LocaleInfoAddon::ToStringInner(std::shared_ptr<LocaleInfo> localeInfo)
247 {
248     if (localeInfo != nullptr) {
249         return localeInfo->ToString();
250     }
251     return "";
252 }
253 
MaximizeInner(std::shared_ptr<LocaleInfo> localeInfo)254 std::string LocaleInfoAddon::MaximizeInner(std::shared_ptr<LocaleInfo> localeInfo)
255 {
256     if (localeInfo != nullptr) {
257         return localeInfo->Maximize();
258     }
259     return "";
260 }
261 
MinimizeInner(std::shared_ptr<LocaleInfo> localeInfo)262 std::string LocaleInfoAddon::MinimizeInner(std::shared_ptr<LocaleInfo> localeInfo)
263 {
264     if (localeInfo != nullptr) {
265         return localeInfo->Minimize();
266     }
267     return "";
268 }
269 
GetLocaleInfoAttribute(napi_env env,napi_callback_info info,GetLocaleInfoProperty func)270 napi_value LocaleInfoAddon::GetLocaleInfoAttribute(napi_env env, napi_callback_info info,
271     GetLocaleInfoProperty func)
272 {
273     napi_value thisVar = nullptr;
274     void *data = nullptr;
275     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
276     if (status != napi_ok) {
277         return nullptr;
278     }
279     LocaleInfoAddon *obj = nullptr;
280     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
281     if (status != napi_ok || !obj || !obj->locale_) {
282         HILOG_ERROR_I18N("GetLocaleInfoAttribute: Get Locale object failed");
283         return nullptr;
284     }
285     std::string value = func(obj->locale_);
286     napi_value result = nullptr;
287     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
288     if (status != napi_ok) {
289         HILOG_ERROR_I18N("GetLocaleInfoAttribute: Create attribute string failed");
290         return nullptr;
291     }
292     return result;
293 }
294 
GetLanguage(napi_env env,napi_callback_info info)295 napi_value LocaleInfoAddon::GetLanguage(napi_env env, napi_callback_info info)
296 {
297     return GetLocaleInfoAttribute(env, info, GetLanguageInner);
298 }
299 
GetScript(napi_env env,napi_callback_info info)300 napi_value LocaleInfoAddon::GetScript(napi_env env, napi_callback_info info)
301 {
302     return GetLocaleInfoAttribute(env, info, GetScriptInner);
303 }
304 
GetRegion(napi_env env,napi_callback_info info)305 napi_value LocaleInfoAddon::GetRegion(napi_env env, napi_callback_info info)
306 {
307     return GetLocaleInfoAttribute(env, info, GetRegionInner);
308 }
309 
GetBaseName(napi_env env,napi_callback_info info)310 napi_value LocaleInfoAddon::GetBaseName(napi_env env, napi_callback_info info)
311 {
312     return GetLocaleInfoAttribute(env, info, GetBaseNameInner);
313 }
314 
GetCalendar(napi_env env,napi_callback_info info)315 napi_value LocaleInfoAddon::GetCalendar(napi_env env, napi_callback_info info)
316 {
317     return GetLocaleInfoAttribute(env, info, GetCalendarInner);
318 }
319 
GetCollation(napi_env env,napi_callback_info info)320 napi_value LocaleInfoAddon::GetCollation(napi_env env, napi_callback_info info)
321 {
322     return GetLocaleInfoAttribute(env, info, GetCollationInner);
323 }
324 
GetHourCycle(napi_env env,napi_callback_info info)325 napi_value LocaleInfoAddon::GetHourCycle(napi_env env, napi_callback_info info)
326 {
327     return GetLocaleInfoAttribute(env, info, GetHourCycleInner);
328 }
329 
GetNumberingSystem(napi_env env,napi_callback_info info)330 napi_value LocaleInfoAddon::GetNumberingSystem(napi_env env, napi_callback_info info)
331 {
332     return GetLocaleInfoAttribute(env, info, GetNumberingSystemInner);
333 }
334 
GetNumeric(napi_env env,napi_callback_info info)335 napi_value LocaleInfoAddon::GetNumeric(napi_env env, napi_callback_info info)
336 {
337     napi_value thisVar = nullptr;
338     void *data = nullptr;
339     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
340     if (status != napi_ok) {
341         return nullptr;
342     }
343     LocaleInfoAddon *obj = nullptr;
344     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
345     if (status != napi_ok || !obj || !obj->locale_) {
346         HILOG_ERROR_I18N("GetNumeric: Get Locale object failed");
347         return nullptr;
348     }
349     std::string value = obj->locale_->GetNumeric();
350     bool optionBoolValue = (value == "true");
351     napi_value result = nullptr;
352     status = napi_get_boolean(env, optionBoolValue, &result);
353     if (status != napi_ok) {
354         HILOG_ERROR_I18N("Create numeric boolean value failed");
355         return nullptr;
356     }
357     return result;
358 }
359 
GetCaseFirst(napi_env env,napi_callback_info info)360 napi_value LocaleInfoAddon::GetCaseFirst(napi_env env, napi_callback_info info)
361 {
362     return GetLocaleInfoAttribute(env, info, GetCaseFirstInner);
363 }
364 
ToString(napi_env env,napi_callback_info info)365 napi_value LocaleInfoAddon::ToString(napi_env env, napi_callback_info info)
366 {
367     return GetLocaleInfoAttribute(env, info, ToStringInner);
368 }
369 
GetMaximizeOrMinimize(napi_env env,napi_callback_info info,GetLocaleInfoProperty func)370 napi_value LocaleInfoAddon::GetMaximizeOrMinimize(napi_env env, napi_callback_info info,
371     GetLocaleInfoProperty func)
372 {
373     napi_value thisVar = nullptr;
374     void *data = nullptr;
375     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
376     if (status != napi_ok) {
377         return nullptr;
378     }
379     LocaleInfoAddon *obj = nullptr;
380     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
381     if (status != napi_ok || !obj || !obj->locale_) {
382         HILOG_ERROR_I18N("Maximize: Get Locale object failed");
383         return nullptr;
384     }
385     std::string localeTag = func(obj->locale_);
386 
387     napi_value constructor = nullptr;
388     if (g_constructor == nullptr) {
389         HILOG_ERROR_I18N("Maximize: g_constructor is nullptr.");
390         return nullptr;
391     }
392     status = napi_get_reference_value(env, *g_constructor, &constructor);
393     if (status != napi_ok) {
394         HILOG_ERROR_I18N("Maximize: Get locale constructor reference failed");
395         return nullptr;
396     }
397     napi_value result = nullptr;
398     napi_value arg = nullptr;
399     status = napi_create_string_utf8(env, localeTag.c_str(), NAPI_AUTO_LENGTH, &arg);
400     if (status != napi_ok) {
401         HILOG_ERROR_I18N("Maximize: Create localeTag string failed");
402         return nullptr;
403     }
404     status = napi_new_instance(env, constructor, 1, &arg, &result);
405     if (status != napi_ok) {
406         HILOG_ERROR_I18N("Maximize: Create new locale instance failed");
407         return nullptr;
408     }
409     return result;
410 }
411 
Maximize(napi_env env,napi_callback_info info)412 napi_value LocaleInfoAddon::Maximize(napi_env env, napi_callback_info info)
413 {
414     return GetMaximizeOrMinimize(env, info, MaximizeInner);
415 }
416 
Minimize(napi_env env,napi_callback_info info)417 napi_value LocaleInfoAddon::Minimize(napi_env env, napi_callback_info info)
418 {
419     return GetMaximizeOrMinimize(env, info, MinimizeInner);
420 }
421 
GetLocaleInfo()422 std::shared_ptr<LocaleInfo> LocaleInfoAddon::GetLocaleInfo()
423 {
424     if (!this->locale_) {
425         return nullptr;
426     }
427     return this->locale_;
428 }
429 } // namespace I18n
430 } // namespace Global
431 } // namespace OHOS