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