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 "error_util.h"
17 #include "i18n_hilog.h"
18 #include "locale_info_addon.h"
19 #include "variable_convertor.h"
20 #include "simple_number_format_addon.h"
21
22 namespace OHOS {
23 namespace Global {
24 namespace I18n {
25 static thread_local napi_ref* g_SimpleNumberFormatConstructor = nullptr;
26
SimpleNumberFormatAddon()27 SimpleNumberFormatAddon::SimpleNumberFormatAddon() {}
28
~SimpleNumberFormatAddon()29 SimpleNumberFormatAddon::~SimpleNumberFormatAddon() {}
30
Destructor(napi_env env,void * nativeObject,void * hint)31 void SimpleNumberFormatAddon::Destructor(napi_env env, void *nativeObject, void *hint)
32 {
33 if (!nativeObject) {
34 return;
35 }
36 delete reinterpret_cast<SimpleNumberFormatAddon *>(nativeObject);
37 nativeObject = nullptr;
38 }
39
InitSimpleNumberFormat(napi_env env,napi_value exports)40 napi_value SimpleNumberFormatAddon::InitSimpleNumberFormat(napi_env env, napi_value exports)
41 {
42 napi_property_descriptor properties[] = {
43 DECLARE_NAPI_FUNCTION("format", Format),
44 };
45
46 napi_value constructor = nullptr;
47 napi_status status = napi_define_class(env, "SimpleNumberFormat", NAPI_AUTO_LENGTH,
48 SimpleNumberFormatConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor),
49 properties, &constructor);
50 if (status != napi_ok) {
51 HILOG_ERROR_I18N("InitSimpleNumberFormat: Failed to define class SimpleNumberFormat at Init.");
52 return nullptr;
53 }
54
55 g_SimpleNumberFormatConstructor = new (std::nothrow) napi_ref;
56 if (!g_SimpleNumberFormatConstructor) {
57 HILOG_ERROR_I18N("InitSimpleNumberFormat: Failed to create SimpleNumberFormat ref at init.");
58 return nullptr;
59 }
60 status = napi_create_reference(env, constructor, 1, g_SimpleNumberFormatConstructor);
61 if (status != napi_ok) {
62 HILOG_ERROR_I18N(
63 "InitSimpleNumberFormat: Failed to create reference g_SimpleNumberFormatConstructor at init.");
64 return nullptr;
65 }
66
67 status = napi_set_named_property(env, exports, "SimpleNumberFormat", constructor);
68 if (status != napi_ok) {
69 HILOG_ERROR_I18N("InitSimpleNumberFormat: Set property failed at init.");
70 return nullptr;
71 }
72 return exports;
73 }
74
GetSimpleNumberFormatBySkeleton(napi_env env,napi_callback_info info)75 napi_value SimpleNumberFormatAddon::GetSimpleNumberFormatBySkeleton(napi_env env, napi_callback_info info)
76 {
77 size_t argc = 2;
78 napi_value argv[2] = { nullptr };
79 napi_value thisVar = nullptr;
80 void *data = nullptr;
81 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
82 if (status != napi_ok) {
83 HILOG_ERROR_I18N("GetSimpleNumberFormatBySkeleton: Get cb info failed.");
84 return nullptr;
85 }
86
87 napi_value constructor = nullptr;
88 if (g_SimpleNumberFormatConstructor == nullptr) {
89 HILOG_ERROR_I18N("Failed to create g_SimpleNumberFormatConstructor");
90 return nullptr;
91 }
92 status = napi_get_reference_value(env, *g_SimpleNumberFormatConstructor, &constructor);
93 if (status != napi_ok) {
94 HILOG_ERROR_I18N("GetSimpleNumberFormatBySkeleton: Failed to create reference.");
95 return nullptr;
96 }
97
98 napi_value result = nullptr;
99 status = napi_new_instance(env, constructor, argc, argv, &result);
100 if (status != napi_ok) {
101 HILOG_ERROR_I18N("GetSimpleNumberFormatBySkeleton: Create instance failed.");
102 return nullptr;
103 }
104 return result;
105 }
106
Format(napi_env env,napi_callback_info info)107 napi_value SimpleNumberFormatAddon::Format(napi_env env, napi_callback_info info)
108 {
109 size_t argc = 1;
110 napi_value argv[1] = { 0 };
111 napi_value thisVar = nullptr;
112 void *data = nullptr;
113 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
114 if (status != napi_ok) {
115 HILOG_ERROR_I18N("SimpleNumberFormatAddon::Format: Get cb info failed.");
116 return VariableConvertor::CreateString(env, "");
117 } else if (argc < 1) {
118 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "value", "", true);
119 return VariableConvertor::CreateString(env, "");
120 }
121
122 napi_valuetype valueType = napi_valuetype::napi_undefined;
123 status = napi_typeof(env, argv[0], &valueType);
124 if (status != napi_ok) {
125 HILOG_ERROR_I18N("SimpleNumberFormatAddon::Format: Failed to get type of argv[0].");
126 return VariableConvertor::CreateString(env, "");
127 } else if (valueType != napi_valuetype::napi_number) {
128 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "value", "number", true);
129 return VariableConvertor::CreateString(env, "");
130 }
131
132 double value = 0;
133 status = napi_get_value_double(env, argv[0], &value);
134 if (status != napi_ok) {
135 HILOG_ERROR_I18N("SimpleNumberFormatAddon::Format: Failed to get value argv[0].");
136 return VariableConvertor::CreateString(env, "");
137 }
138
139 SimpleNumberFormatAddon* obj = nullptr;
140 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
141 if (status != napi_ok || !obj || !obj->simpleNumberFormat_) {
142 HILOG_ERROR_I18N("SimpleNumberFormatAddon::Format: Unwrap SimpleNumberFormatAddon failed.");
143 return VariableConvertor::CreateString(env, "");
144 }
145
146 std::string formatResult = obj->simpleNumberFormat_->Format(value);
147 if (formatResult.empty()) {
148 HILOG_ERROR_I18N("SimpleNumberFormatAddon::Format: Format result is empty.");
149 }
150 return VariableConvertor::CreateString(env, formatResult);
151 }
152
SimpleNumberFormatConstructor(napi_env env,napi_callback_info info)153 napi_value SimpleNumberFormatAddon::SimpleNumberFormatConstructor(napi_env env, napi_callback_info info)
154 {
155 size_t argc = 2;
156 napi_value argv[2] = { nullptr };
157 napi_value thisVar = nullptr;
158 void *data = nullptr;
159 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
160 if (status != napi_ok) {
161 HILOG_ERROR_I18N("SimpleNumberFormatConstructor: Get cb info failed.");
162 return nullptr;
163 } else if (argc < 1) {
164 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "skeleton", "", true);
165 return nullptr;
166 }
167
168 VariableConvertor::VerifyType(env, "skeleton", napi_valuetype::napi_string, argv[0]);
169
170 int32_t code = 0;
171 std::string skeleton = VariableConvertor::GetString(env, argv[0], code);
172 if (code != 0) {
173 HILOG_ERROR_I18N("SimpleNumberFormatConstructor: Get argv[0] failed.");
174 return nullptr;
175 }
176
177 std::unique_ptr<SimpleNumberFormatAddon> obj = std::make_unique<SimpleNumberFormatAddon>();
178 if (!obj) {
179 HILOG_ERROR_I18N("SimpleNumberFormatConstructor: create SimpleNumberFormatAddon failed.");
180 return nullptr;
181 }
182 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
183 SimpleNumberFormatAddon::Destructor, nullptr, nullptr);
184 if (status != napi_ok) {
185 HILOG_ERROR_I18N("SimpleNumberFormatConstructor: Wrap SimpleNumberFormatAddon failed.");
186 return nullptr;
187 }
188
189 I18nErrorCode errCode = I18nErrorCode::SUCCESS;
190 napi_value locale = (argc > 1) ? argv[1] : nullptr;
191 obj->simpleNumberFormat_ =
192 SimpleNumberFormatAddon::InitSimpleNumberFormatContext(env, locale, skeleton, errCode);
193 if (errCode == I18nErrorCode::INVALID_NUMBER_FORMAT_SKELETON) {
194 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "skeleton", "a valid number format skeleton", true);
195 return nullptr;
196 } else if (!obj->simpleNumberFormat_ || errCode != I18nErrorCode::SUCCESS) {
197 HILOG_ERROR_I18N("SimpleNumberFormatConstructor: Construct SimpleNumberFormat failed.");
198 return nullptr;
199 }
200 obj.release();
201 return thisVar;
202 }
203
InitSimpleNumberFormatContext(napi_env env,napi_value locale,const std::string & skeleton,I18nErrorCode & errCode)204 std::unique_ptr<SimpleNumberFormat> SimpleNumberFormatAddon::InitSimpleNumberFormatContext(napi_env env,
205 napi_value locale, const std::string& skeleton, I18nErrorCode& errCode)
206 {
207 if (locale == nullptr) {
208 std::shared_ptr<LocaleInfo> localeInfo = nullptr;
209 return std::make_unique<SimpleNumberFormat>(skeleton, localeInfo, errCode);
210 }
211
212 if (VariableConvertor::GetLocaleType(env, locale) == LocaleType::BUILTINS_LOCALE) {
213 std::string localeTag = VariableConvertor::ParseBuiltinsLocale(env, locale);
214 return std::make_unique<SimpleNumberFormat>(skeleton, localeTag, errCode);
215 } else if (VariableConvertor::GetLocaleType(env, locale) == LocaleType::LOCALE_INFO) {
216 std::shared_ptr<LocaleInfo> localeInfo = VariableConvertor::ParseLocaleInfo(env, locale);
217 return std::make_unique<SimpleNumberFormat>(skeleton, localeInfo, errCode);
218 }
219 HILOG_ERROR_I18N("SimpleNumberFormatAddon::InitSimpleNumberFormatContext: Init context failed.");
220 return nullptr;
221 }
222
CopySimpleNumberFormat()223 std::shared_ptr<SimpleNumberFormat> SimpleNumberFormatAddon::CopySimpleNumberFormat()
224 {
225 return simpleNumberFormat_;
226 }
227 } // namespace I18n
228 } // namespace Global
229 } // namespace OHOS