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