• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "variable_converter.h"
17 
18 #include "entity_recognizer_addon.h"
19 #include "holiday_manager_addon.h"
20 #include "i18n_addon.h"
21 #include "i18n_calendar_addon.h"
22 #include "i18n_hilog.h"
23 #include "i18n_normalizer_addon.h"
24 #include "i18n_timezone_addon.h"
25 #include "intl_addon.h"
26 #include "locale_info_addon.h"
27 #include "number_format_addon.h"
28 #include "simple_date_time_format_addon.h"
29 #include "simple_number_format_addon.h"
30 #include "system_locale_manager_addon.h"
31 
32 using namespace OHOS;
33 using namespace Global;
34 using namespace I18n;
35 
AniStrToString(ani_env * env,ani_ref aniStr)36 std::string VariableConverter::AniStrToString(ani_env *env, ani_ref aniStr)
37 {
38     ani_string ani_str = static_cast<ani_string>(aniStr);
39     ani_size strSize;
40     if (ANI_OK != env->String_GetUTF8Size(ani_str, &strSize)) {
41         HILOG_ERROR_I18N("Get utf8 size failed");
42         return "";
43     }
44 
45     std::vector<char> buffer(strSize + 1);
46     ani_size bytes_written = 0;
47 
48     if (ANI_OK != env->String_GetUTF8(ani_str, buffer.data(), buffer.size(), &bytes_written)) {
49         HILOG_ERROR_I18N("Create string failed");
50         return "";
51     }
52     return std::string(buffer.data(), bytes_written);
53 }
54 
StringToAniStr(ani_env * env,const std::string & str)55 ani_string VariableConverter::StringToAniStr(ani_env *env, const std::string &str)
56 {
57     ani_string ret;
58     if (ANI_OK != env->String_NewUTF8(str.c_str(), str.size(), &ret)) {
59         HILOG_ERROR_I18N("Create ani string failed");
60         return nullptr;
61     }
62     return ret;
63 }
64 
SetBooleanMember(ani_env * env,ani_object obj,const std::string & name,const std::string & value)65 void VariableConverter::SetBooleanMember(ani_env *env, ani_object obj,
66     const std::string &name, const std::string &value)
67 {
68     if (value.empty()) {
69         return;
70     }
71 
72     static const char *className = "Lstd/core/Boolean;";
73     ani_class cls;
74     if (ANI_OK != env->FindClass(className, &cls)) {
75         HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
76         return;
77     }
78 
79     ani_method ctor;
80     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "Z:V", &ctor)) {
81         HILOG_ERROR_I18N("Find method '<ctor>' failed");
82         return;
83     }
84 
85     ani_boolean valueBool = value == "true";
86     ani_object boolObj;
87     if (ANI_OK != env->Object_New(cls, ctor, &boolObj, valueBool)) {
88         HILOG_ERROR_I18N("New object '%{public}s' failed", className);
89         return;
90     }
91 
92     if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, name.c_str(), boolObj)) {
93         HILOG_ERROR_I18N("Set property '%{public}s' failed", name.c_str());
94         return;
95     }
96 }
97 
GetBooleanMember(ani_env * env,ani_object options,const std::string & name,bool & value)98 bool VariableConverter::GetBooleanMember(ani_env *env, ani_object options, const std::string &name, bool& value)
99 {
100     ani_ref ref;
101     if (ANI_OK != env->Object_GetPropertyByName_Ref(options, name.c_str(), &ref)) {
102         HILOG_ERROR_I18N("Get property '%{public}s' failed", name.c_str());
103         return false;
104     }
105 
106     ani_boolean isUndefined;
107     if (ANI_OK != env->Reference_IsUndefined(ref, &isUndefined)) {
108         HILOG_ERROR_I18N("Reference IsUndefined failed");
109         return false;
110     }
111     if (isUndefined) {
112         return false;
113     }
114 
115     ani_boolean ret;
116     if (ANI_OK != env->Object_CallMethodByName_Boolean(static_cast<ani_object>(ref), "unboxed", ":Z", &ret)) {
117         HILOG_ERROR_I18N("Call method by name failed");
118         return false;
119     }
120     value = ret;
121     return true;
122 }
123 
SetNumberMember(ani_env * env,ani_object obj,const std::string & name,const ani_int value)124 void VariableConverter::SetNumberMember(ani_env *env, ani_object obj, const std::string &name, const ani_int value)
125 {
126     static const char *className = "Lstd/core/Int;";
127     ani_class cls;
128     if (ANI_OK != env->FindClass(className, &cls)) {
129         HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
130         return;
131     }
132 
133     ani_method ctor;
134     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "I:V", &ctor)) {
135         HILOG_ERROR_I18N("Find method '<ctor>' failed");
136         return;
137     }
138 
139     ani_object intObj;
140     if (ANI_OK != env->Object_New(cls, ctor, &intObj, value)) {
141         HILOG_ERROR_I18N("New object '%{public}s' failed", className);
142         return;
143     }
144 
145     if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, name.c_str(), intObj)) {
146         HILOG_ERROR_I18N("Set property '%{public}s' failed", name.c_str());
147         return;
148     }
149 }
150 
SetNumberMember(ani_env * env,ani_object obj,const std::string & name,const std::string & value)151 void VariableConverter::SetNumberMember(ani_env *env, ani_object obj, const std::string &name, const std::string &value)
152 {
153     if (value.empty()) {
154         return;
155     }
156 
157     static const char *className = "Lstd/core/Int;";
158     ani_class cls;
159     if (ANI_OK != env->FindClass(className, &cls)) {
160         HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
161         return;
162     }
163 
164     ani_method ctor;
165     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "I:V", &ctor)) {
166         HILOG_ERROR_I18N("Find method '<ctor>' failed");
167         return;
168     }
169 
170     int32_t status = 0;
171     ani_int digits = ConvertString2Int(value, status);
172     if (status != 0) {
173         return;
174     }
175 
176     ani_object intObj;
177     if (ANI_OK != env->Object_New(cls, ctor, &intObj, digits)) {
178         HILOG_ERROR_I18N("New object '%{public}s' failed", className);
179         return;
180     }
181 
182     if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, name.c_str(), intObj)) {
183         HILOG_ERROR_I18N("Set property '%{public}s' failed", name.c_str());
184         return;
185     }
186 }
187 
GetNumberMember(ani_env * env,ani_object options,const std::string & name,int & value)188 bool VariableConverter::GetNumberMember(ani_env *env, ani_object options, const std::string &name, int& value)
189 {
190     ani_ref ref;
191     if (ANI_OK != env->Object_GetPropertyByName_Ref(options, name.c_str(), &ref)) {
192         HILOG_ERROR_I18N("Get property '%{public}s' failed", name.c_str());
193         return false;
194     }
195 
196     ani_boolean isUndefined;
197     if (ANI_OK != env->Reference_IsUndefined(ref, &isUndefined)) {
198         HILOG_ERROR_I18N("Reference IsUndefined failed");
199         return false;
200     }
201     if (isUndefined) {
202         return false;
203     }
204 
205     ani_double valueDouble;
206     if (ANI_OK != env->Object_CallMethodByName_Double(static_cast<ani_object>(ref), "unboxed", ":D", &valueDouble)) {
207         HILOG_ERROR_I18N("Unboxed Double failed");
208         return false;
209     }
210     value = static_cast<int>(valueDouble);
211     return true;
212 }
213 
SetStringMember(ani_env * env,ani_object obj,const std::string & name,const std::string & value)214 void VariableConverter::SetStringMember(ani_env *env, ani_object obj, const std::string &name, const std::string &value)
215 {
216     if (value.empty()) {
217         return;
218     }
219 
220     if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, name.c_str(), VariableConverter::StringToAniStr(env, value))) {
221         HILOG_ERROR_I18N("Set property '%{public}s' failed", name.c_str());
222         return;
223     }
224 }
225 
GetStringMember(ani_env * env,ani_object options,const std::string & name,std::string & value)226 bool VariableConverter::GetStringMember(ani_env *env, ani_object options, const std::string &name, std::string &value)
227 {
228     ani_ref ref;
229     if (ANI_OK != env->Object_GetPropertyByName_Ref(options, name.c_str(), &ref)) {
230         HILOG_ERROR_I18N("Get property '%{public}s' failed", name.c_str());
231         return false;
232     }
233 
234     ani_boolean isUndefined;
235     if (ANI_OK != env->Reference_IsUndefined(ref, &isUndefined)) {
236         HILOG_ERROR_I18N("Reference IsUndefined failed");
237         return false;
238     }
239     if (isUndefined) {
240         return false;
241     }
242 
243     value = VariableConverter::AniStrToString(env, ref);
244     return true;
245 }
246 
CreateArray(ani_env * env,const std::vector<std::string> & strs)247 ani_object VariableConverter::CreateArray(ani_env *env, const std::vector<std::string> &strs)
248 {
249     static const char *className = "Lescompat/Array;";
250     ani_class cls;
251     if (ANI_OK != env->FindClass(className, &cls)) {
252         HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
253         return nullptr;
254     }
255 
256     ani_method ctor;
257     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "I:V", &ctor)) {
258         HILOG_ERROR_I18N("Find method '<ctor>' failed");
259         return nullptr;
260     }
261 
262     ani_object ret;
263     if (ANI_OK != env->Object_New(cls, ctor, &ret, strs.size())) {
264         HILOG_ERROR_I18N("New object '%{public}s' failed", className);
265         return nullptr;
266     }
267 
268     ani_method set;
269     if (ANI_OK != env->Class_FindMethod(cls, "$_set", "ILstd/core/Object;:V", &set)) {
270         HILOG_ERROR_I18N("Find method '$_set' failed");
271         return ret;
272     }
273 
274     for (size_t i = 0; i < strs.size(); ++i) {
275         if (ANI_OK != env->Object_CallMethod_Void(ret, set, i, VariableConverter::StringToAniStr(env, strs[i]))) {
276             HILOG_ERROR_I18N("Call method '$_set' failed");
277             return ret;
278         }
279     }
280     return ret;
281 }
282 
ParseStringArray(ani_env * env,ani_object obj,std::vector<std::string> & strs)283 bool VariableConverter::ParseStringArray(ani_env *env, ani_object obj, std::vector<std::string> &strs)
284 {
285     static const char *className = "Lescompat/Array;";
286     ani_class cls;
287     if (ANI_OK != env->FindClass(className, &cls)) {
288         HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
289         return false;
290     }
291 
292     ani_method getLengthMethod;
293     if (ANI_OK != env->Class_FindGetter(cls, "length", &getLengthMethod)) {
294         HILOG_ERROR_I18N("Find getter 'length' failed");
295         return false;
296     }
297 
298     ani_double length;
299     if (ANI_OK != env->Object_CallMethod_Double(obj, getLengthMethod, &length)) {
300         HILOG_ERROR_I18N("Get 'length' failed");
301         return false;
302     }
303 
304     ani_method get;
305     if (ANI_OK != env->Class_FindMethod(cls, "$_get", "I:Lstd/core/Object;", &get)) {
306         HILOG_ERROR_I18N("Find method '$_get' failed");
307         return false;
308     }
309 
310     for (int i = 0; i < static_cast<int>(length); ++i) {
311         ani_ref value;
312         if (ANI_OK != env->Object_CallMethod_Ref(obj, get, &value, i)) {
313             HILOG_ERROR_I18N("Call method '$_get' failed");
314             return false;
315         }
316         strs.push_back(VariableConverter::AniStrToString(env, static_cast<ani_string>(value)));
317     }
318     return true;
319 }
320 
GetEnumItemByIndex(ani_env * env,const char * enumClassName,const int index)321 ani_enum_item VariableConverter::GetEnumItemByIndex(ani_env* env, const char* enumClassName, const int index)
322 {
323     ani_enum aniEnum;
324     if (ANI_OK != env->FindEnum(enumClassName, &aniEnum)) {
325         HILOG_ERROR_I18N("Find enum '%{public}s' failed", enumClassName);
326         return nullptr;
327     }
328 
329     ani_enum_item enumItem;
330     if (ANI_OK != env->Enum_GetEnumItemByIndex(aniEnum, index, &enumItem)) {
331         HILOG_ERROR_I18N("Get enumItem '%{public}s' failed", enumClassName);
332         return nullptr;
333     }
334     return enumItem;
335 }
336 
GetDateValue(ani_env * env,ani_object date,const std::string & method)337 ani_double VariableConverter::GetDateValue(ani_env *env, ani_object date, const std::string &method)
338 {
339     static const char* className = "Lescompat/Date;";
340     ani_class cls;
341     if (ANI_OK != env->FindClass(className, &cls)) {
342         HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
343         return -1;
344     }
345 
346     ani_method get;
347     if (ANI_OK != env->Class_FindMethod(cls, method.c_str(), nullptr, &get)) {
348         HILOG_ERROR_I18N("Find method '%{public}s' failed", method.c_str());
349         return -1;
350     }
351 
352     ani_double ret;
353     if (ANI_OK != env->Object_CallMethod_Double(date, get, &ret)) {
354         HILOG_ERROR_I18N("Call method '%{public}s' failed", method.c_str());
355         return -1;
356     }
357     return ret;
358 }
359 
GetLocaleTags(ani_env * env,ani_object locale)360 std::vector<std::string> VariableConverter::GetLocaleTags(ani_env *env, ani_object locale)
361 {
362     std::vector<std::string> localeTags;
363     ani_class stringClass;
364     if (ANI_OK != env->FindClass("Lstd/core/String;", &stringClass)) {
365         HILOG_ERROR_I18N("Find class 'Lstd/core/String' failed");
366         return localeTags;
367     }
368 
369     ani_boolean isString;
370     if (ANI_OK != env->Object_InstanceOf(locale, stringClass, &isString)) {
371         HILOG_ERROR_I18N("Get Instance failed");
372         return localeTags;
373     }
374     if (isString) {
375         localeTags.push_back(AniStrToString(env, locale));
376         return localeTags;
377     }
378     static const char *className = "Lescompat/Array;";
379     ani_class cls;
380     if (ANI_OK != env->FindClass(className, &cls)) {
381         HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
382         return localeTags;
383     }
384 
385     ani_method getLengthMethod;
386     if (ANI_OK != env->Class_FindGetter(cls, "length", &getLengthMethod)) {
387         HILOG_ERROR_I18N("Find getter 'length' failed");
388         return localeTags;
389     }
390 
391     ani_double length;
392     if (ANI_OK != env->Object_CallMethod_Double(locale, getLengthMethod, &length)) {
393         HILOG_ERROR_I18N("Get 'length' failed");
394         return localeTags;
395     }
396 
397     ani_method get;
398     if (ANI_OK != env->Class_FindMethod(cls, "$_get", "I:Lstd/core/Object;", &get)) {
399         HILOG_ERROR_I18N("Find method '$_get' failed");
400         return localeTags;
401     }
402 
403     for (int i = 0; i < static_cast<int>(length); ++i) {
404         ani_ref value;
405         if (ANI_OK != env->Object_CallMethod_Ref(locale, get, &value, i)) {
406             HILOG_ERROR_I18N("Call method '$_get' failed");
407             return localeTags;
408         }
409         localeTags.push_back(AniStrToString(env, value));
410     }
411     return localeTags;
412 }
413 
414 template<typename T>
CreateAniObject(ani_env * env,const char * className,T * ptr)415 ani_object VariableConverter::CreateAniObject(ani_env* env, const char* className, T* ptr)
416 {
417     ani_class cls;
418     if (ANI_OK != env->FindClass(className, &cls)) {
419         HILOG_ERROR_I18N("Find class '%{public}s' failed", className);
420         return nullptr;
421     }
422 
423     ani_method ctor;
424     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "J:V", &ctor)) {
425         HILOG_ERROR_I18N("Find method '<ctor>' failed");
426         return nullptr;
427     }
428 
429     ani_object obj;
430     if (ANI_OK != env->Object_New(cls, ctor, &obj, reinterpret_cast<ani_long>(ptr))) {
431         HILOG_ERROR_I18N("New object '%{public}s' failed", className);
432         return nullptr;
433     }
434     return obj;
435 }
436 
437 template ani_object VariableConverter::CreateAniObject<I18nBreakIteratorAddon>(
438     ani_env*, const char*, I18nBreakIteratorAddon*);
439 template ani_object VariableConverter::CreateAniObject<I18nCalendarAddon>(ani_env*, const char*, I18nCalendarAddon*);
440 template ani_object VariableConverter::CreateAniObject<I18nEntityRecognizerAddon>(
441     ani_env*, const char*, I18nEntityRecognizerAddon*);
442 template ani_object VariableConverter::CreateAniObject<I18nHolidayManagerAddon>(
443     ani_env*, const char*, I18nHolidayManagerAddon*);
444 template ani_object VariableConverter::CreateAniObject<I18nIndexUtilAddon>(ani_env*, const char*, I18nIndexUtilAddon*);
445 template ani_object VariableConverter::CreateAniObject<I18nNormalizerAddon>(
446     ani_env*, const char*, I18nNormalizerAddon*);
447 template ani_object VariableConverter::CreateAniObject<I18nPhoneNumberFormatAddon>(
448     ani_env*, const char*, I18nPhoneNumberFormatAddon*);
449 template ani_object VariableConverter::CreateAniObject<I18nSimpleDateTimeFormatAddon>(
450     ani_env*, const char*, I18nSimpleDateTimeFormatAddon*);
451 template ani_object VariableConverter::CreateAniObject<I18nSimpleNumberFormatAddon>(
452     ani_env*, const char*, I18nSimpleNumberFormatAddon*);
453 template ani_object VariableConverter::CreateAniObject<I18nSysLocaleMgrAddon>(
454     ani_env*, const char*, I18nSysLocaleMgrAddon*);
455 template ani_object VariableConverter::CreateAniObject<I18nTimeZoneAddon>(ani_env*, const char*, I18nTimeZoneAddon*);
456 template ani_object VariableConverter::CreateAniObject<I18nTransliteratorAddon>(
457     ani_env*, const char*, I18nTransliteratorAddon*);
458 template ani_object VariableConverter::CreateAniObject<IntlAddon>(ani_env*, const char*, IntlAddon*);
459 template ani_object VariableConverter::CreateAniObject<LocaleInfoAddon>(ani_env*, const char*, LocaleInfoAddon*);
460 template ani_object VariableConverter::CreateAniObject<NumberFormatAddon>(ani_env*, const char*, NumberFormatAddon*);
461