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 "number_format_addon.h"
16
17 #include "i18n_hilog.h"
18 #include "js_utils.h"
19
20 namespace OHOS {
21 namespace Global {
22 namespace I18n {
NumberFormatAddon()23 NumberFormatAddon::NumberFormatAddon()
24 {
25 }
26
~NumberFormatAddon()27 NumberFormatAddon::~NumberFormatAddon()
28 {
29 }
30
Destructor(napi_env env,void * nativeObject,void * hint)31 void NumberFormatAddon::Destructor(napi_env env, void *nativeObject, void *hint)
32 {
33 if (!nativeObject) {
34 return;
35 }
36 delete reinterpret_cast<NumberFormatAddon *>(nativeObject);
37 nativeObject = nullptr;
38 }
39
InitNumberFormat(napi_env env,napi_value exports)40 napi_value NumberFormatAddon::InitNumberFormat(napi_env env, napi_value exports)
41 {
42 napi_property_descriptor properties[] = {
43 DECLARE_NAPI_FUNCTION("format", FormatNumber),
44 DECLARE_NAPI_FUNCTION("formatRange", FormatRangeNumber),
45 DECLARE_NAPI_FUNCTION("resolvedOptions", GetNumberResolvedOptions)
46 };
47
48 napi_value constructor = nullptr;
49 napi_status status = napi_define_class(env, "NumberFormat", NAPI_AUTO_LENGTH, NumberFormatConstructor, nullptr,
50 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
51 if (status != napi_ok) {
52 HILOG_ERROR_I18N("Define class failed when InitNumberFormat");
53 return nullptr;
54 }
55
56 status = napi_set_named_property(env, exports, "NumberFormat", constructor);
57 if (status != napi_ok) {
58 HILOG_ERROR_I18N("Set property failed when InitNumberFormat");
59 return nullptr;
60 }
61 return exports;
62 }
63
NumberFormatConstructor(napi_env env,napi_callback_info info)64 napi_value NumberFormatAddon::NumberFormatConstructor(napi_env env, napi_callback_info info)
65 {
66 size_t argc = 2;
67 napi_value argv[2] = { nullptr };
68 napi_value thisVar = nullptr;
69 void *data = nullptr;
70 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
71 if (status != napi_ok) {
72 return nullptr;
73 }
74 std::vector<std::string> localeTags;
75 if (argc > 0) {
76 int32_t code = 0;
77 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
78 if (code != 0) {
79 return nullptr;
80 }
81 localeTags.assign(localeArray.begin(), localeArray.end());
82 }
83 std::map<std::string, std::string> map = {};
84 if (argc > 1) {
85 JSUtils::GetNumberOptionValues(env, argv[1], map);
86 }
87 std::unique_ptr<NumberFormatAddon> obj = std::make_unique<NumberFormatAddon>();
88 if (obj == nullptr) {
89 return nullptr;
90 }
91 status =
92 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), NumberFormatAddon::Destructor, nullptr, nullptr);
93 if (status != napi_ok) {
94 HILOG_ERROR_I18N("NumberFormatConstructor: Wrap NumberFormatAddon failed");
95 return nullptr;
96 }
97 if (!obj->InitNumberFormatContext(env, info, localeTags, map)) {
98 HILOG_ERROR_I18N("Init NumberFormat failed");
99 return nullptr;
100 }
101 obj.release();
102 return thisVar;
103 }
104
InitNumberFormatContext(napi_env env,napi_callback_info info,std::vector<std::string> localeTags,std::map<std::string,std::string> & map)105 bool NumberFormatAddon::InitNumberFormatContext(napi_env env, napi_callback_info info,
106 std::vector<std::string> localeTags, std::map<std::string, std::string> &map)
107 {
108 napi_value global = nullptr;
109 napi_status status = napi_get_global(env, &global);
110 if (status != napi_ok) {
111 HILOG_ERROR_I18N("InitNumberFormatContext: Get global failed");
112 return false;
113 }
114 numberfmt_ = std::make_shared<NumberFormat>(localeTags, map);
115
116 return numberfmt_ != nullptr;
117 }
118
FormatNumber(napi_env env,napi_callback_info info)119 napi_value NumberFormatAddon::FormatNumber(napi_env env, napi_callback_info info)
120 {
121 size_t argc = 1;
122 napi_value argv[1] = { 0 };
123 napi_value thisVar = nullptr;
124 void *data = nullptr;
125 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
126 if (status != napi_ok) {
127 return nullptr;
128 }
129 double number = 0;
130 status = napi_get_value_double(env, argv[0], &number);
131 if (status != napi_ok) {
132 return nullptr;
133 }
134 NumberFormatAddon *obj = nullptr;
135 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
136 if (status != napi_ok || !obj || !obj->numberfmt_) {
137 HILOG_ERROR_I18N("FormatNumber: Get NumberFormat object failed");
138 return nullptr;
139 }
140 std::string value = obj->numberfmt_->Format(number);
141 napi_value result = nullptr;
142 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
143 if (status != napi_ok) {
144 HILOG_ERROR_I18N("FormatNumber: Create format string failed");
145 return nullptr;
146 }
147 return result;
148 }
149
FormatRangeNumber(napi_env env,napi_callback_info info)150 napi_value NumberFormatAddon::FormatRangeNumber(napi_env env, napi_callback_info info)
151 {
152 size_t argc = 2;
153 napi_value argv[2] = { 0 };
154 napi_value thisVar = nullptr;
155 void *data = nullptr;
156 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
157 if (status != napi_ok) {
158 HILOG_ERROR_I18N("FormatRangeNumber: Get parameter info failed");
159 return JSUtils::CreateEmptyString(env);
160 }
161 if (argc != 2) { // 2 is parameter count
162 HILOG_ERROR_I18N("FormatRangeNumber: Insufficient parameters");
163 return JSUtils::CreateEmptyString(env);
164 }
165 double start = 0;
166 double end = 0;
167 status = napi_get_value_double(env, argv[0], &start);
168 if (status != napi_ok) {
169 HILOG_ERROR_I18N("FormatRangeNumber: Get first param value failed");
170 return JSUtils::CreateEmptyString(env);
171 }
172 status = napi_get_value_double(env, argv[1], &end);
173 if (status != napi_ok) {
174 HILOG_ERROR_I18N("FormatRangeNumber: Get second param value failed");
175 return JSUtils::CreateEmptyString(env);
176 }
177 NumberFormatAddon *obj = nullptr;
178 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
179 if (status != napi_ok || !obj || !obj->numberfmt_) {
180 HILOG_ERROR_I18N("FormatRangeNumber: Get NumberFormat object failed");
181 return JSUtils::CreateEmptyString(env);
182 }
183 std::string value = obj->numberfmt_->FormatRange(start, end);
184 napi_value result;
185 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
186 if (status != napi_ok) {
187 HILOG_ERROR_I18N("create string js variable failed.");
188 return JSUtils::CreateEmptyString(env);
189 }
190 return result;
191 }
192
GetNumberResolvedOptions(napi_env env,napi_callback_info info)193 napi_value NumberFormatAddon::GetNumberResolvedOptions(napi_env env, napi_callback_info info)
194 {
195 napi_value thisVar = nullptr;
196 void *data = nullptr;
197 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
198 if (status != napi_ok) {
199 return nullptr;
200 }
201 NumberFormatAddon *obj = nullptr;
202 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
203 if (status != napi_ok || !obj || !obj->numberfmt_) {
204 HILOG_ERROR_I18N("GetNumberResolvedOptions: Get NumberFormat object failed");
205 return nullptr;
206 }
207 napi_value result = nullptr;
208 status = napi_create_object(env, &result);
209 if (status != napi_ok) {
210 return nullptr;
211 }
212 std::map<std::string, std::string> options = {};
213 obj->numberfmt_->GetResolvedOptions(options);
214 JSUtils::SetOptionProperties(env, result, options, "locale");
215 JSUtils::SetOptionProperties(env, result, options, "currency");
216 JSUtils::SetOptionProperties(env, result, options, "currencySign");
217 JSUtils::SetOptionProperties(env, result, options, "currencyDisplay");
218 JSUtils::SetOptionProperties(env, result, options, "unit");
219 JSUtils::SetOptionProperties(env, result, options, "unitDisplay");
220 JSUtils::SetOptionProperties(env, result, options, "signDisplay");
221 JSUtils::SetOptionProperties(env, result, options, "compactDisplay");
222 JSUtils::SetOptionProperties(env, result, options, "notation");
223 JSUtils::SetOptionProperties(env, result, options, "style");
224 JSUtils::SetOptionProperties(env, result, options, "numberingSystem");
225 JSUtils::SetOptionProperties(env, result, options, "unitUsage");
226 JSUtils::SetBooleanOptionProperties(env, result, options, "useGrouping");
227 JSUtils::SetIntegerOptionProperties(env, result, options, "minimumIntegerDigits");
228 JSUtils::SetIntegerOptionProperties(env, result, options, "minimumFractionDigits");
229 JSUtils::SetIntegerOptionProperties(env, result, options, "maximumFractionDigits");
230 JSUtils::SetIntegerOptionProperties(env, result, options, "minimumSignificantDigits");
231 JSUtils::SetIntegerOptionProperties(env, result, options, "maximumSignificantDigits");
232 JSUtils::SetOptionProperties(env, result, options, "localeMatcher");
233 return result;
234 }
235
CopyNumberFormat()236 std::shared_ptr<NumberFormat> NumberFormatAddon::CopyNumberFormat()
237 {
238 return numberfmt_;
239 }
240 } // namespace I18n
241 } // namespace Global
242 } // namespace OHOS