1 /*
2 * Copyright (c) 2023-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 "js_utils.h"
19 #include "locale_config.h"
20 #include "variable_convertor.h"
21 #include "i18n_normalizer_addon.h"
22
23 namespace OHOS {
24 namespace Global {
25 namespace I18n {
26 static thread_local napi_ref* g_normalizerConstructor = nullptr;
27
28 const char *I18nNormalizerAddon::NORMALIZER_MODE_NFC_NAME = "NFC";
29 const char *I18nNormalizerAddon::NORMALIZER_MODE_NFD_NAME = "NFD";
30 const char *I18nNormalizerAddon::NORMALIZER_MODE_NFKC_NAME = "NFKC";
31 const char *I18nNormalizerAddon::NORMALIZER_MODE_NFKD_NAME = "NFKD";
32
I18nNormalizerAddon()33 I18nNormalizerAddon::I18nNormalizerAddon() {}
~I18nNormalizerAddon()34 I18nNormalizerAddon::~I18nNormalizerAddon()
35 {
36 }
37
Destructor(napi_env env,void * nativeObject,void * hint)38 void I18nNormalizerAddon::Destructor(napi_env env, void *nativeObject, void *hint)
39 {
40 if (!nativeObject) {
41 return;
42 }
43 delete reinterpret_cast<I18nNormalizerAddon *>(nativeObject);
44 nativeObject = nullptr;
45 }
46
InitI18nNormalizer(napi_env env,napi_value exports)47 napi_value I18nNormalizerAddon::InitI18nNormalizer(napi_env env, napi_value exports)
48 {
49 napi_property_descriptor properties[] = {
50 DECLARE_NAPI_FUNCTION("normalize", Normalize),
51 };
52 napi_value constructor = nullptr;
53 napi_status status = napi_define_class(env, "Normalizer", NAPI_AUTO_LENGTH, I18nNormalizerConstructor, nullptr,
54 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
55 if (status != napi_ok) {
56 HILOG_ERROR_I18N("InitI18nNormalizer: Failed to define class Normalizer at Init");
57 return nullptr;
58 }
59 exports = I18nNormalizerAddon::InitNormalizer(env, exports);
60 g_normalizerConstructor = new (std::nothrow) napi_ref;
61 if (!g_normalizerConstructor) {
62 HILOG_ERROR_I18N("InitI18nNormalizer: Failed to create Normalizer ref at init");
63 return nullptr;
64 }
65 status = napi_create_reference(env, constructor, 1, g_normalizerConstructor);
66 if (status != napi_ok) {
67 HILOG_ERROR_I18N("InitI18nNormalizer: Failed to create reference g_normalizerConstructor at init.");
68 return nullptr;
69 }
70 return exports;
71 }
72
InitNormalizer(napi_env env,napi_value exports)73 napi_value I18nNormalizerAddon::InitNormalizer(napi_env env, napi_value exports)
74 {
75 napi_property_descriptor properties[] = {
76 DECLARE_NAPI_STATIC_FUNCTION("getInstance", GetI18nNormalizerInstance)
77 };
78 napi_value constructor = nullptr;
79 napi_status status = napi_define_class(env, "I18nNormalizer", NAPI_AUTO_LENGTH, JSUtils::DefaultConstructor,
80 nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
81 if (status != napi_ok) {
82 HILOG_ERROR_I18N("InitNormalizer: Failed to define class Normalizer.");
83 return nullptr;
84 }
85 status = napi_set_named_property(env, exports, "Normalizer", constructor);
86 if (status != napi_ok) {
87 HILOG_ERROR_I18N("InitNormalizer: Set property failed When InitNormalizer.");
88 return nullptr;
89 }
90 return exports;
91 }
92
I18nNormalizerConstructor(napi_env env,napi_callback_info info)93 napi_value I18nNormalizerAddon::I18nNormalizerConstructor(napi_env env, napi_callback_info info)
94 {
95 size_t argc = 1;
96 napi_value argv[1] = { nullptr };
97 napi_value thisVar = nullptr;
98 void *data = nullptr;
99 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
100 if (status != napi_ok) {
101 return nullptr;
102 }
103 if (argc < 1) {
104 ErrorUtil::NapiNotFoundError(env, I18N_NOT_FOUND, "mode", true);
105 return nullptr;
106 }
107 napi_valuetype valueType = napi_valuetype::napi_undefined;
108 status = napi_typeof(env, argv[0], &valueType);
109 if (status != napi_ok) {
110 return nullptr;
111 }
112 if (valueType != napi_valuetype::napi_number) {
113 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "mode", "number", true);
114 return nullptr;
115 }
116 int32_t normalizerMode;
117 status = napi_get_value_int32(env, argv[0], &normalizerMode);
118 if (status != napi_ok) {
119 return nullptr;
120 }
121 if (normalizerMode != NORMALIZER_MODE_NFC && normalizerMode != NORMALIZER_MODE_NFD &&
122 normalizerMode != NORMALIZER_MODE_NFKC && normalizerMode != NORMALIZER_MODE_NFKD) {
123 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "mode", "a valid mode", true);
124 return nullptr;
125 }
126
127 std::unique_ptr<I18nNormalizerAddon> obj = std::make_unique<I18nNormalizerAddon>();
128 if (obj == nullptr) {
129 return nullptr;
130 }
131 status =
132 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nNormalizerAddon::Destructor, nullptr, nullptr);
133 if (status != napi_ok) {
134 return nullptr;
135 }
136 I18nNormalizerMode mode = I18nNormalizerMode(normalizerMode);
137 I18nErrorCode errorCode = I18nErrorCode::SUCCESS;
138 obj->normalizer_ = std::make_unique<I18nNormalizer>(mode, errorCode);
139 if (errorCode != I18nErrorCode::SUCCESS || !obj->normalizer_) {
140 return nullptr;
141 }
142 obj.release();
143 return thisVar;
144 }
145
Normalize(napi_env env,napi_callback_info info)146 napi_value I18nNormalizerAddon::Normalize(napi_env env, napi_callback_info info)
147 {
148 size_t argc = 1;
149 napi_value argv[1] = { nullptr };
150 napi_value thisVar = nullptr;
151 void *data = nullptr;
152 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
153 if (status != napi_ok) {
154 return nullptr;
155 }
156 if (argc < 1) {
157 ErrorUtil::NapiNotFoundError(env, I18N_NOT_FOUND, "text", true);
158 return nullptr;
159 }
160 napi_valuetype valueType = napi_valuetype::napi_undefined;
161 status = napi_typeof(env, argv[0], &valueType);
162 if (status != napi_ok) {
163 return nullptr;
164 }
165 if (valueType != napi_valuetype::napi_string) {
166 HILOG_ERROR_I18N("Invalid parameter type");
167 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "text", "string", true);
168 return nullptr;
169 }
170 int32_t code = 0;
171 std::string text = VariableConvertor::GetString(env, argv[0], code);
172 if (code != 0) {
173 return nullptr;
174 }
175
176 I18nNormalizerAddon *obj = nullptr;
177 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
178 if (status != napi_ok || obj == nullptr || obj->normalizer_ == nullptr) {
179 HILOG_ERROR_I18N("Get Normalizer object failed");
180 return nullptr;
181 }
182 I18nErrorCode errorCode = I18nErrorCode::SUCCESS;
183 std::string normalizedText = obj->normalizer_->Normalize(text.c_str(), static_cast<int32_t>(text.length()),
184 errorCode);
185 if (errorCode != I18nErrorCode::SUCCESS) {
186 return nullptr;
187 }
188 napi_value result = nullptr;
189 status = napi_create_string_utf8(env, normalizedText.c_str(), NAPI_AUTO_LENGTH, &result);
190 if (status != napi_ok) {
191 HILOG_ERROR_I18N("Create result failed");
192 return nullptr;
193 }
194 return result;
195 }
196
CreateI18NNormalizerModeEnum(napi_env env)197 napi_value I18nNormalizerAddon::CreateI18NNormalizerModeEnum(napi_env env)
198 {
199 napi_value i18nNormalizerModel = nullptr;
200 napi_status status = napi_create_object(env, &i18nNormalizerModel);
201 if (status != napi_ok) {
202 return nullptr;
203 }
204 status = VariableConvertor::SetEnumValue(env, i18nNormalizerModel, NORMALIZER_MODE_NFC_NAME, NORMALIZER_MODE_NFC);
205 if (status != napi_ok) {
206 return nullptr;
207 }
208 status = VariableConvertor::SetEnumValue(env, i18nNormalizerModel, NORMALIZER_MODE_NFD_NAME, NORMALIZER_MODE_NFD);
209 if (status != napi_ok) {
210 return nullptr;
211 }
212 status =
213 VariableConvertor::SetEnumValue(env, i18nNormalizerModel, NORMALIZER_MODE_NFKC_NAME, NORMALIZER_MODE_NFKC);
214 if (status != napi_ok) {
215 return nullptr;
216 }
217 status =
218 VariableConvertor::SetEnumValue(env, i18nNormalizerModel, NORMALIZER_MODE_NFKD_NAME, NORMALIZER_MODE_NFKD);
219 if (status != napi_ok) {
220 return nullptr;
221 }
222 return i18nNormalizerModel;
223 }
224
GetI18nNormalizerInstance(napi_env env,napi_callback_info info)225 napi_value I18nNormalizerAddon::GetI18nNormalizerInstance(napi_env env, napi_callback_info info)
226 {
227 size_t argc = 1;
228 napi_value argv[1] = { nullptr };
229 napi_value thisVar = nullptr;
230 void *data = nullptr;
231 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
232 if (status != napi_ok) {
233 HILOG_ERROR_I18N("Failed to get parameter of Normalizer.createInstance");
234 return nullptr;
235 }
236
237 napi_value constructor = nullptr;
238 if (g_normalizerConstructor == nullptr) {
239 HILOG_ERROR_I18N("Failed to create g_normalizerConstructor");
240 return nullptr;
241 }
242 status = napi_get_reference_value(env, *g_normalizerConstructor, &constructor);
243 if (status != napi_ok) {
244 HILOG_ERROR_I18N("Failed to create reference of normalizer Constructor");
245 return nullptr;
246 }
247
248 napi_value result = nullptr;
249 status = napi_new_instance(env, constructor, argc, argv, &result);
250 if (status != napi_ok) {
251 HILOG_ERROR_I18N("create normalizer instance failed");
252 return nullptr;
253 }
254 return result;
255 }
256 } // namespace I18n
257 } // namespace Global
258 } // namespace OHOS