1 /*
2 * Copyright (c) 2025 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 "locale_info_addon.h"
17
18 #include "i18n_hilog.h"
19 #include "variable_converter.h"
20
21 using namespace OHOS;
22 using namespace Global;
23 using namespace I18n;
24
UnwrapAddon(ani_env * env,ani_object object,const std::string & name)25 LocaleInfoAddon* LocaleInfoAddon::UnwrapAddon(ani_env *env, ani_object object, const std::string &name)
26 {
27 ani_long ptr;
28 if (ANI_OK != env->Object_GetFieldByName_Long(object, name.c_str(), &ptr)) {
29 HILOG_ERROR_I18N("Get Long '%{public}s' failed", name.c_str());
30 return nullptr;
31 }
32 return reinterpret_cast<LocaleInfoAddon*>(ptr);
33 }
34
35 template<typename T>
GetLocaleProperty(ani_env * env,ani_object object,const std::string & propertyName,T (LocaleInfo::* getter)()const)36 T LocaleInfoAddon::GetLocaleProperty(ani_env *env, ani_object object,
37 const std::string &propertyName, T (LocaleInfo::*getter)() const)
38 {
39 LocaleInfoAddon* obj = UnwrapAddon(env, object, "nativeLocale");
40 if (obj == nullptr || obj->locale_ == nullptr) {
41 HILOG_ERROR_I18N("%{public}s: Get Locale object failed", propertyName.c_str());
42 return T{};
43 }
44 return (obj->locale_.get()->*getter)();
45 }
46
Locale_ToString(ani_env * env,ani_object object)47 ani_string LocaleInfoAddon::Locale_ToString(ani_env *env, ani_object object)
48 {
49 std::string value = GetLocaleProperty(env, object, "toString", &LocaleInfo::ToString);
50 return VariableConverter::StringToAniStr(env, value);
51 }
52
Locale_Maximize(ani_env * env,ani_object object)53 ani_object LocaleInfoAddon::Locale_Maximize(ani_env *env, ani_object object)
54 {
55 LocaleInfoAddon* obj = UnwrapAddon(env, object, "nativeLocale");
56 if (obj == nullptr || obj->locale_ == nullptr) {
57 HILOG_ERROR_I18N("Maximize: Get Locale object failed");
58 return nullptr;
59 }
60
61 std::string localeTag = obj->locale_->Maximize();
62 return Locale_CreateWithParam(env, nullptr, VariableConverter::StringToAniStr(env, localeTag), nullptr);
63 }
64
Locale_Minimize(ani_env * env,ani_object object)65 ani_object LocaleInfoAddon::Locale_Minimize(ani_env *env, ani_object object)
66 {
67 LocaleInfoAddon* obj = UnwrapAddon(env, object, "nativeLocale");
68 if (obj == nullptr || obj->locale_ == nullptr) {
69 HILOG_ERROR_I18N("Minimize: Get Locale object failed");
70 return nullptr;
71 }
72
73 std::string localeTag = obj->locale_->Minimize();
74 return Locale_CreateWithParam(env, nullptr, VariableConverter::StringToAniStr(env, localeTag), nullptr);
75 }
76
Locale_GetLanguage(ani_env * env,ani_object object)77 ani_string LocaleInfoAddon::Locale_GetLanguage(ani_env *env, ani_object object)
78 {
79 std::string value = GetLocaleProperty(env, object, "getLanguage", &LocaleInfo::GetLanguage);
80 return VariableConverter::StringToAniStr(env, value);
81 }
82
Locale_GetScript(ani_env * env,ani_object object)83 ani_string LocaleInfoAddon::Locale_GetScript(ani_env *env, ani_object object)
84 {
85 std::string value = GetLocaleProperty(env, object, "getScript", &LocaleInfo::GetScript);
86 return VariableConverter::StringToAniStr(env, value);
87 }
88
Locale_GetRegion(ani_env * env,ani_object object)89 ani_string LocaleInfoAddon::Locale_GetRegion(ani_env *env, ani_object object)
90 {
91 std::string value = GetLocaleProperty(env, object, "getRegion", &LocaleInfo::GetRegion);
92 return VariableConverter::StringToAniStr(env, value);
93 }
94
Locale_GetBaseName(ani_env * env,ani_object object)95 ani_string LocaleInfoAddon::Locale_GetBaseName(ani_env *env, ani_object object)
96 {
97 std::string value = GetLocaleProperty(env, object, "getBaseName", &LocaleInfo::GetBaseName);
98 return VariableConverter::StringToAniStr(env, value);
99 }
100
Locale_GetCaseFirst(ani_env * env,ani_object object)101 ani_string LocaleInfoAddon::Locale_GetCaseFirst(ani_env *env, ani_object object)
102 {
103 std::string value = GetLocaleProperty(env, object, "getCaseFirst", &LocaleInfo::GetCaseFirst);
104 return VariableConverter::StringToAniStr(env, value);
105 }
106
Locale_GetCalendar(ani_env * env,ani_object object)107 ani_string LocaleInfoAddon::Locale_GetCalendar(ani_env *env, ani_object object)
108 {
109 std::string value = GetLocaleProperty(env, object, "getCalendar", &LocaleInfo::GetCalendar);
110 return VariableConverter::StringToAniStr(env, value);
111 }
112
Locale_GetCollation(ani_env * env,ani_object object)113 ani_string LocaleInfoAddon::Locale_GetCollation(ani_env *env, ani_object object)
114 {
115 std::string value = GetLocaleProperty(env, object, "getCollation", &LocaleInfo::GetCollation);
116 return VariableConverter::StringToAniStr(env, value);
117 }
118
Locale_GetHourCycle(ani_env * env,ani_object object)119 ani_string LocaleInfoAddon::Locale_GetHourCycle(ani_env *env, ani_object object)
120 {
121 std::string value = GetLocaleProperty(env, object, "getHourCycle", &LocaleInfo::GetHourCycle);
122 return VariableConverter::StringToAniStr(env, value);
123 }
124
Locale_GetNumberingSystem(ani_env * env,ani_object object)125 ani_string LocaleInfoAddon::Locale_GetNumberingSystem(ani_env *env, ani_object object)
126 {
127 std::string value = GetLocaleProperty(env, object, "getNumberingSystem", &LocaleInfo::GetNumberingSystem);
128 return VariableConverter::StringToAniStr(env, value);
129 }
130
Locale_GetNumeric(ani_env * env,ani_object object)131 ani_boolean LocaleInfoAddon::Locale_GetNumeric(ani_env *env, ani_object object)
132 {
133 LocaleInfoAddon* obj = UnwrapAddon(env, object, "nativeLocale");
134 if (obj == nullptr || obj->locale_ == nullptr) {
135 HILOG_ERROR_I18N("getNumeric: Get Locale object failed");
136 return false;
137 }
138 return (obj->locale_->GetNumeric() == "true");
139 }
140
Locale_Create(ani_env * env,ani_object object)141 ani_object LocaleInfoAddon::Locale_Create(ani_env *env, [[maybe_unused]] ani_object object)
142 {
143 std::map<std::string, std::string> map = {};
144 std::unique_ptr<LocaleInfoAddon> obj = std::make_unique<LocaleInfoAddon>();
145 obj->locale_ = std::make_unique<LocaleInfo>("", map);
146
147 static const char *className = "L@ohos/intl/intl/Locale;";
148 ani_object localeObject = VariableConverter::CreateAniObject(env, className, obj.get());
149 obj.release();
150 return localeObject;
151 }
152
Locale_CreateWithParam(ani_env * env,ani_object object,ani_string locale,ani_object options)153 ani_object LocaleInfoAddon::Locale_CreateWithParam(ani_env *env, [[maybe_unused]] ani_object object,
154 ani_string locale, ani_object options)
155 {
156 std::map<std::string, std::string> map = {};
157 ani_boolean isUndefined;
158 if (ANI_OK != env->Reference_IsUndefined(options, &isUndefined)) {
159 HILOG_ERROR_I18N("Reference IsUndefined failed");
160 return nullptr;
161 }
162 if (!isUndefined) {
163 const std::vector<std::string> keys = {
164 "calendar", "collation", "hourCycle", "numberingSystem", "caseFirst"
165 };
166
167 for (const auto& key : keys) {
168 std::string value;
169 if (VariableConverter::GetStringMember(env, options, key, value)) {
170 map.insert(std::make_pair(key, value));
171 }
172 }
173
174 bool numeric;
175 if (VariableConverter::GetBooleanMember(env, options, "numeric", numeric)) {
176 map.insert(std::make_pair("numeric", numeric ? "true" : "false"));
177 }
178 }
179
180 std::unique_ptr<LocaleInfoAddon> obj = std::make_unique<LocaleInfoAddon>();
181 obj->locale_ = std::make_unique<LocaleInfo>(VariableConverter::AniStrToString(env, locale), map);
182 static const char *className = "L@ohos/intl/intl/Locale;";
183 ani_object localeObject = VariableConverter::CreateAniObject(env, className, obj.get());
184 obj.release();
185 return localeObject;
186 }
187
BindContext_Locale(ani_env * env)188 ani_status LocaleInfoAddon::BindContext_Locale(ani_env *env)
189 {
190 static const char *className = "L@ohos/intl/intl/Locale;";
191 ani_class cls;
192 if (ANI_OK != env->FindClass(className, &cls)) {
193 HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
194 return ANI_ERROR;
195 }
196
197 std::array methods = {
198 ani_native_function {"create", ":L@ohos/intl/intl/Locale;", reinterpret_cast<void *>(Locale_Create) },
199 ani_native_function {"create", "Lstd/core/String;L@ohos/intl/intl/LocaleOptions;:L@ohos/intl/intl/Locale;",
200 reinterpret_cast<void *>(Locale_CreateWithParam) },
201 ani_native_function {"toString", nullptr, reinterpret_cast<void *>(Locale_ToString) },
202 ani_native_function {"maximize", nullptr, reinterpret_cast<void *>(Locale_Maximize) },
203 ani_native_function {"minimize", nullptr, reinterpret_cast<void *>(Locale_Minimize) },
204 ani_native_function {"getLanguage", nullptr, reinterpret_cast<void *>(Locale_GetLanguage) },
205 ani_native_function {"getScript", nullptr, reinterpret_cast<void *>(Locale_GetScript) },
206 ani_native_function {"getRegion", nullptr, reinterpret_cast<void *>(Locale_GetRegion) },
207 ani_native_function {"getBaseName", nullptr, reinterpret_cast<void *>(Locale_GetBaseName) },
208 ani_native_function {"getCaseFirst", nullptr, reinterpret_cast<void *>(Locale_GetCaseFirst) },
209 ani_native_function {"getCalendar", nullptr, reinterpret_cast<void *>(Locale_GetCalendar) },
210 ani_native_function {"getCollation", nullptr, reinterpret_cast<void *>(Locale_GetCollation) },
211 ani_native_function {"getHourCycle", nullptr, reinterpret_cast<void *>(Locale_GetHourCycle) },
212 ani_native_function {"getNumberingSystem", nullptr, reinterpret_cast<void *>(Locale_GetNumberingSystem) },
213 ani_native_function {"getNumeric", nullptr, reinterpret_cast<void *>(Locale_GetNumeric) },
214 };
215
216 if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) {
217 HILOG_ERROR_I18N("Cannot bind native methods to '%{public}s'", className);
218 return ANI_ERROR;
219 };
220 return ANI_OK;
221 }
222