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 #ifndef OHOS_ANI_TEXT_UTILS_H
17 #define OHOS_ANI_TEXT_UTILS_H
18 #include <ani.h>
19 #include <memory>
20 #include <string>
21 #include <vector>
22
23 #include "ani_common.h"
24 #include "utils/text_log.h"
25
26 namespace OHOS::Text::ANI {
27 class AniTextUtils final {
28 public:
29 static ani_status ThrowBusinessError(ani_env* env, TextErrorCode errorCode, const char* message);
30 static ani_status CreateBusinessError(ani_env* env, int32_t error, const char* message, ani_object& err);
31 template <typename T>
32 static T* GetNativeFromObj(ani_env* env, ani_object obj);
33
34 static ani_object CreateAniUndefined(ani_env* env);
35 template <typename... Args>
36 static ani_object CreateAniObject(ani_env* env, const std::string name, const char* signature, Args... params);
37 static ani_object CreateAniArray(ani_env* env, size_t size);
38 template <typename T, typename Converter>
39 static ani_object CreateAniArrayAndInitData(ani_env* env, const std::vector<T>& t, size_t size, Converter convert);
40 static ani_object CreateAniMap(ani_env* env);
41 static ani_enum_item CreateAniEnum(ani_env* env, const char* enum_descriptor, ani_size index);
42 static ani_object CreateAniDoubleObj(ani_env* env, double val);
43 static ani_object CreateAniIntObj(ani_env* env, int val);
44 static ani_object CreateAniBooleanObj(ani_env* env, bool val);
45 static ani_string CreateAniStringObj(ani_env* env, const std::string& str);
46 static ani_string CreateAniStringObj(ani_env* env, const std::u16string& str);
47
48 static ani_status AniToStdStringUtf8(ani_env* env, const ani_string& str, std::string& utf8Str);
49 static ani_status AniToStdStringUtf16(ani_env* env, const ani_string& str, std::u16string& utf16Str);
50 static bool ReadFile(const std::string& filePath, size_t& dataLen, std::unique_ptr<uint8_t[]>& data);
51 static bool SplitAbsoluteFontPath(std::string& absolutePath);
52
53 static ani_status ReadOptionalField(ani_env* env, ani_object obj, const char* fieldName, ani_ref& ref);
54 static ani_status ReadOptionalDoubleField(ani_env* env, ani_object obj, const char* fieldName, double& value);
55 static ani_status ReadOptionalStringField(ani_env* env, ani_object obj, const char* fieldName, std::string& str);
56 static ani_status ReadOptionalU16StringField(
57 ani_env* env, ani_object obj, const char* fieldName, std::u16string& str);
58 static ani_status ReadOptionalBoolField(ani_env* env, ani_object obj, const char* fieldName, bool& value);
59 template <typename EnumType>
60 static ani_status ReadOptionalEnumField(ani_env* env, ani_object obj, const char* fieldName, EnumType& value);
61 template <typename T, typename Converter>
62 static ani_status ReadOptionalArrayField(
63 ani_env* env, ani_object obj, const char* fieldName, std::vector<T>& array, Converter convert);
64 };
65
66 template <typename... Args>
CreateAniObject(ani_env * env,const std::string name,const char * signature,Args...params)67 ani_object AniTextUtils::CreateAniObject(ani_env* env, const std::string name, const char* signature, Args... params)
68 {
69 ani_class cls = nullptr;
70 if (env->FindClass(name.c_str(), &cls) != ANI_OK) {
71 TEXT_LOGE("Failed to found %{public}s", name.c_str());
72 return CreateAniUndefined(env);
73 }
74 ani_method ctor;
75 if (env->Class_FindMethod(cls, "<ctor>", signature, &ctor) != ANI_OK) {
76 TEXT_LOGE("Failed to get ctor %{public}s", name.c_str());
77 return CreateAniUndefined(env);
78 }
79 ani_object obj = {};
80 if (env->Object_New(cls, ctor, &obj, params...) != ANI_OK) {
81 TEXT_LOGE("Failed to create object %{public}s", name.c_str());
82 return CreateAniUndefined(env);
83 }
84 return obj;
85 }
86
87 template <typename T, typename Converter>
CreateAniArrayAndInitData(ani_env * env,const std::vector<T> & t,size_t size,Converter convert)88 ani_object AniTextUtils::CreateAniArrayAndInitData(
89 ani_env* env, const std::vector<T>& t, size_t size, Converter convert)
90 {
91 ani_object arrayObj = CreateAniArray(env, size);
92 ani_size index = 0;
93 for (const T& item : t) {
94 ani_object aniObj = convert(env, item);
95 ani_status ret = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniObj);
96 if (ret != ANI_OK) {
97 TEXT_LOGE("Array $_set failed, ret:%{public}d", ret);
98 continue;
99 }
100 index++;
101 }
102 return arrayObj;
103 }
104
105 template <typename T>
GetNativeFromObj(ani_env * env,ani_object obj)106 T* AniTextUtils::GetNativeFromObj(ani_env* env, ani_object obj)
107 {
108 ani_status ret;
109 ani_long nativeObj{};
110 if ((ret = env->Object_GetFieldByName_Long(obj, NATIVE_OBJ, &nativeObj)) != ANI_OK) {
111 TEXT_LOGE("Failed to get native obj");
112 return nullptr;
113 }
114 T* object = reinterpret_cast<T*>(nativeObj);
115 if (object == nullptr) {
116 TEXT_LOGE("object is null");
117 return nullptr;
118 }
119 return object;
120 };
121
122 template <typename EnumType>
ReadOptionalEnumField(ani_env * env,ani_object obj,const char * fieldName,EnumType & value)123 ani_status AniTextUtils::ReadOptionalEnumField(ani_env* env, ani_object obj, const char* fieldName, EnumType& value)
124 {
125 ani_ref ref = nullptr;
126 ani_status result = AniTextUtils::ReadOptionalField(env, obj, fieldName, ref);
127 if (result == ANI_OK && ref != nullptr) {
128 ani_size index;
129 result = env->EnumItem_GetIndex(reinterpret_cast<ani_enum_item>(ref), &index);
130 if (result == ANI_OK) {
131 value = static_cast<EnumType>(index);
132 }
133 }
134 return result;
135 };
136
137 template <typename T, typename Converter>
ReadOptionalArrayField(ani_env * env,ani_object obj,const char * fieldName,std::vector<T> & array,Converter convert)138 ani_status AniTextUtils::ReadOptionalArrayField(
139 ani_env* env, ani_object obj, const char* fieldName, std::vector<T>& array, Converter convert)
140 {
141 ani_ref ref = nullptr;
142 ani_status result = AniTextUtils::ReadOptionalField(env, obj, fieldName, ref);
143 if (result != ANI_OK || ref == nullptr) {
144 return result;
145 }
146
147 ani_object arrayObj = reinterpret_cast<ani_object>(ref);
148 ani_double length;
149 result = env->Object_GetPropertyByName_Double(arrayObj, "length", &length);
150 if (result != ANI_OK) {
151 TEXT_LOGE("Failed to get length,%{public}s", fieldName);
152 return result;
153 }
154
155 for (size_t i = 0; i < static_cast<size_t>(length); i++) {
156 ani_ref entryRef = nullptr;
157 result = env->Object_CallMethodByName_Ref(arrayObj, "$_get", "I:Lstd/core/Object;", &entryRef, i);
158 if (result != ANI_OK || entryRef == nullptr) {
159 TEXT_LOGE("Failed to get array object,%{public}s", fieldName);
160 continue;
161 }
162 array.emplace_back(convert(env, entryRef));
163 }
164 return ANI_OK;
165 };
166 } // namespace OHOS::Text::ANI
167 #endif // OHOS_ANI_TEXT_UTILS_H