• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "intl_plural_rules_addon.h"
17 #include "i18n_hilog.h"
18 #include "js_utils.h"
19 
20 namespace OHOS {
21 namespace Global {
22 namespace I18n {
Destructor(napi_env env,void * nativeObject,void * finalize_hint)23 void IntlPluralRulesAddon::Destructor(napi_env env, void* nativeObject, void* finalize_hint)
24 {
25     if (!nativeObject) {
26         return;
27     }
28     delete reinterpret_cast<IntlPluralRulesAddon *>(nativeObject);
29     nativeObject = nullptr;
30 }
31 
InitIntlPluralRules(napi_env env,napi_value exports)32 napi_value IntlPluralRulesAddon::InitIntlPluralRules(napi_env env, napi_value exports)
33 {
34     napi_property_descriptor properties[] = {
35         DECLARE_NAPI_FUNCTION("select", Select),
36         DECLARE_NAPI_FUNCTION("resolvedOptions", ResolvedOptions),
37         DECLARE_NAPI_FUNCTION("toString", ToString),
38         DECLARE_NAPI_STATIC_FUNCTION("supportedLocalesOf", SupportedLocalesOf),
39     };
40 
41     napi_value constructor;
42     napi_status status = napi_define_class(env, "PluralRules", NAPI_AUTO_LENGTH, IntlPluralRulesConstructor,
43         nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
44     if (status != napi_ok) {
45         HILOG_ERROR_I18N("InitIntlPluralRules: Define class failed.");
46         return nullptr;
47     }
48 
49     status = napi_set_named_property(env, exports, "PluralRules", constructor);
50     if (status != napi_ok) {
51         HILOG_ERROR_I18N("InitIntlPluralRules: Set property failed.");
52         return nullptr;
53     }
54     return exports;
55 }
56 
IntlPluralRulesConstructor(napi_env env,napi_callback_info info)57 napi_value IntlPluralRulesAddon::IntlPluralRulesConstructor(napi_env env, napi_callback_info info)
58 {
59     size_t argc = 2;
60     napi_value argv[2] = { nullptr };
61     napi_value thisVar = nullptr;
62     void *data = nullptr;
63     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
64     if (status != napi_ok) {
65         HILOG_ERROR_I18N("IntlPluralRulesConstructor: napi get callback info failed.");
66         return nullptr;
67     }
68 
69     napi_value new_target;
70     status = napi_get_new_target(env, info, &new_target);
71     if (status == napi_pending_exception || new_target == nullptr) {
72         HILOG_ERROR_I18N("IntlPluralRulesConstructor: newTarget is undefined.");
73         napi_value exception;
74         napi_get_and_clear_last_exception(env, &exception);
75         napi_throw_type_error(env, nullptr, "newTarget is undefined");
76         return nullptr;
77     } else if (status != napi_ok) {
78         HILOG_ERROR_I18N("IntlPluralRulesConstructor: get newTarget failed.");
79         return nullptr;
80     }
81 
82     std::vector<std::string> localeTags;
83     if (argc > 0) {
84         int32_t code = 0;
85         localeTags = JSUtils::GetLocaleArray(env, argv[0], code);
86     }
87     std::unordered_map<std::string, std::string> configs;
88     if (argc > 1) {
89         configs = ParseConfigs(env, argv[1]);
90     }
91     IntlPluralRulesAddon* obj = new (std::nothrow) IntlPluralRulesAddon();
92     if (obj == nullptr) {
93         HILOG_ERROR_I18N("IntlPluralRulesConstructor: Create obj failed.");
94         return nullptr;
95     }
96     status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj), IntlPluralRulesAddon::Destructor,
97         nullptr, nullptr);
98     if (status != napi_ok) {
99         delete obj;
100         HILOG_ERROR_I18N("IntlPluralRulesConstructor: Wrap IntlPluralRulesAddon failed.");
101         return nullptr;
102     }
103     if (!obj->InitIntlPluralRulesContext(env, localeTags, configs)) {
104         HILOG_ERROR_I18N("IntlPluralRulesConstructor: Init IntlPluralRules failed.");
105         return nullptr;
106     }
107     return thisVar;
108 }
109 
InitIntlPluralRulesContext(napi_env env,const std::vector<std::string> & localeTags,const std::unordered_map<std::string,std::string> & configs)110 bool IntlPluralRulesAddon::InitIntlPluralRulesContext(napi_env env, const std::vector<std::string>& localeTags,
111     const std::unordered_map<std::string, std::string>& configs)
112 {
113     ErrorMessage errorMessage;
114     intlPluralRules = std::make_unique<IntlPluralRules>(localeTags, configs, errorMessage);
115     if (errorMessage.type != ErrorType::NO_ERROR) {
116         HILOG_ERROR_I18N("InitIntlPluralRulesContext: IntlPluralRules constructor failed.");
117         napi_throw_range_error(env, nullptr, errorMessage.message.c_str());
118         return false;
119     }
120     return intlPluralRules != nullptr;
121 }
122 
Select(napi_env env,napi_callback_info info)123 napi_value IntlPluralRulesAddon::Select(napi_env env, napi_callback_info info)
124 {
125     size_t argc = 1;
126     napi_value argv[1] = { nullptr };
127     napi_value thisVar = nullptr;
128     void *data = nullptr;
129     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
130     if (status != napi_ok) {
131         HILOG_ERROR_I18N("IntlPluralRulesAddon::Select: napi get callback info failed.");
132         return nullptr;
133     }
134     if (argc < 1) {
135         HILOG_ERROR_I18N("IntlPluralRulesAddon::Select: missing code param.");
136         return nullptr;
137     }
138     napi_valuetype valueType = napi_valuetype::napi_undefined;
139     status = napi_typeof(env, argv[0], &valueType);
140     if (status != napi_ok) {
141         HILOG_ERROR_I18N("IntlPluralRulesAddon::Select: Get parameter type failed.");
142         return nullptr;
143     }
144     int32_t errorCode = 0;
145     double number = JSUtils::GetDoubleFromNapiValue(env, argv[0], valueType, errorCode);
146     if (errorCode != 0) {
147         HILOG_ERROR_I18N("IntlPluralRulesAddon::Select: Get number value failed.");
148         return nullptr;
149     }
150 
151     IntlPluralRulesAddon *obj = nullptr;
152     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
153     if (status != napi_ok || !obj || !obj->intlPluralRules) {
154         HILOG_ERROR_I18N("IntlPluralRulesAddon::Select: Get IntlPluralRules object failed.");
155         return nullptr;
156     }
157 
158     ErrorMessage errorMessage;
159     std::string formatedValue = obj->intlPluralRules->Select(number, errorMessage);
160     if (errorMessage.type != ErrorType::NO_ERROR) {
161         HILOG_ERROR_I18N("IntlPluralRulesAddon::Select: IntlPluralRules select failed.");
162         napi_throw_range_error(env, nullptr, errorMessage.message.c_str());
163         return nullptr;
164     }
165     return JSUtils::CreateString(env, formatedValue);
166 }
167 
ResolvedOptions(napi_env env,napi_callback_info info)168 napi_value IntlPluralRulesAddon::ResolvedOptions(napi_env env, napi_callback_info info)
169 {
170     napi_value thisVar = nullptr;
171     void *data = nullptr;
172     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
173     if (status != napi_ok) {
174         HILOG_ERROR_I18N("IntlPluralRulesAddon::ResolvedOptions: get cb info failed.");
175         return nullptr;
176     }
177     IntlPluralRulesAddon *obj = nullptr;
178     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
179     if (status != napi_ok || !obj || !obj->intlPluralRules) {
180         HILOG_ERROR_I18N("IntlPluralRulesAddon::ResolvedOptions: Get IntlPluralRules object failed.");
181         return nullptr;
182     }
183     IntlPluralRules::ResolvedValue resolvedValue = obj->intlPluralRules->ResolvedOptions();
184 
185     napi_value result = nullptr;
186     status = napi_create_object(env, &result);
187     if (status != napi_ok) {
188         HILOG_ERROR_I18N("IntlPluralRulesAddon::ResolvedOptions: create object failed.");
189         return nullptr;
190     }
191     JSUtils::SetNamedStringProperties(env, result, "locale", resolvedValue.locale);
192     JSUtils::SetNamedStringProperties(env, result, "type", resolvedValue.type);
193     JSUtils::SetNamedIntegerProperties(env, result, "minimumIntegerDigits", resolvedValue.minimumIntegerDigits);
194     if (resolvedValue.roundingType == RoundingType::FRACTIONDIGITS) {
195         JSUtils::SetNamedIntegerProperties(env, result, "minimumFractionDigits", resolvedValue.minimumDigits);
196         JSUtils::SetNamedIntegerProperties(env, result, "maximumFractionDigits", resolvedValue.maximumDigits);
197     } else if (resolvedValue.roundingType == RoundingType::SIGNIFICANTDIGITS) {
198         JSUtils::SetNamedIntegerProperties(env, result, "minimumSignificantDigits", resolvedValue.minimumDigits);
199         JSUtils::SetNamedIntegerProperties(env, result, "maximumSignificantDigits", resolvedValue.maximumDigits);
200     }
201     JSUtils::SetNamedVectorProperties(env, result, "pluralCategories", resolvedValue.pluralCategories);
202     return result;
203 }
204 
ToString(napi_env env,napi_callback_info info)205 napi_value IntlPluralRulesAddon::ToString(napi_env env, napi_callback_info info)
206 {
207     napi_value thisVar = nullptr;
208     void *data = nullptr;
209     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
210     if (status != napi_ok) {
211         HILOG_ERROR_I18N("IntlPluralRulesAddon::ToString: get cb info failed.");
212         return JSUtils::CreateEmptyString(env);
213     }
214     IntlPluralRulesAddon *obj = nullptr;
215     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
216     if (status != napi_ok || !obj || !obj->intlPluralRules) {
217         HILOG_ERROR_I18N("IntlPluralRulesAddon::ToString: Get IntlPluralRules object failed.");
218         return JSUtils::CreateEmptyString(env);
219     }
220 
221     return JSUtils::CreateString(env, "[object Intl.PluralRules]");
222 }
223 
SupportedLocalesOf(napi_env env,napi_callback_info info)224 napi_value IntlPluralRulesAddon::SupportedLocalesOf(napi_env env, napi_callback_info info)
225 {
226     size_t argc = 2;
227     napi_value argv[2] = { nullptr };
228     napi_value thisVar = nullptr;
229     void *data = nullptr;
230     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
231     if (status != napi_ok) {
232         HILOG_ERROR_I18N("IntlPluralRulesAddon::SupportedLocalesOf: napi get callback info failed.");
233         return JSUtils::CreateEmptyArray(env);
234     }
235     std::vector<std::string> localeTags;
236     if (argc > 0) {
237         int32_t code = 0;
238         localeTags = JSUtils::GetLocaleArray(env, argv[0], code);
239     }
240     std::unordered_map<std::string, std::string> options = {};
241     if (argc > 1) {
242         JSUtils::GetOptionValue(env, argv[1], "localeMatcher", options);
243     }
244     ErrorMessage errorMessage;
245     std::vector<std::string> supportedLocales =
246         IntlPluralRules::SupportedLocalesOf(localeTags, options, errorMessage);
247     if (errorMessage.type != ErrorType::NO_ERROR) {
248         HILOG_ERROR_I18N("IntlPluralRulesAddon::SupportedLocalesOf failed.");
249         napi_throw_range_error(env, nullptr, errorMessage.message.c_str());
250         return nullptr;
251     }
252     return JSUtils::CreateArray(env, supportedLocales);
253 }
254 
ParseConfigs(napi_env env,napi_value options)255 std::unordered_map<std::string, std::string> IntlPluralRulesAddon::ParseConfigs(napi_env env, napi_value options)
256 {
257     std::unordered_map<std::string, std::string> configs;
258     JSUtils::GetOptionValue(env, options, "localeMatcher", configs);
259     JSUtils::GetOptionValue(env, options, "type", configs);
260     JSUtils::GetDoubleOptionValue(env, options, "minimumIntegerDigits", configs);
261     JSUtils::GetDoubleOptionValue(env, options, "minimumFractionDigits", configs);
262     JSUtils::GetDoubleOptionValue(env, options, "maximumFractionDigits", configs);
263     JSUtils::GetDoubleOptionValue(env, options, "minimumSignificantDigits", configs);
264     JSUtils::GetDoubleOptionValue(env, options, "maximumSignificantDigits", configs);
265     return configs;
266 }
267 } // namespace I18n
268 } // namespace Global
269 } // namespace OHOS