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