• 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 #ifndef ANI_UTILS_H
17 #define ANI_UTILS_H
18 
19 #include <ani.h>
20 #include <cstdarg>
21 #include <memory>
22 #include <mutex>
23 #include <optional>
24 #include <string>
25 #include <unordered_map>
26 #include <variant>
27 #include <vector>
28 #include <iostream>
29 
30 class AniObjectUtils {
31 public:
Create(ani_env * env,const char * nsName,const char * clsName,...)32     static ani_object Create(ani_env *env, const char *nsName, const char *clsName, ...)
33     {
34         ani_object nullobj{};
35 
36         if (env == nullptr) {
37             return nullobj;
38         }
39 
40         ani_namespace ns;
41         if (ANI_OK != env->FindNamespace(nsName, &ns)) {
42             return nullobj;
43         }
44 
45         ani_class cls;
46         if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) {
47             return nullobj;
48         }
49 
50         ani_method ctor;
51         if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
52             return nullobj;
53         }
54 
55         ani_object obj;
56         va_list args;
57         va_start(args, clsName);
58         ani_status status = env->Object_New_V(cls, ctor, &obj, args);
59         va_end(args);
60         if (ANI_OK != status)  {
61             return nullobj;
62         }
63         return obj;
64     }
65 
Create(ani_env * env,const char * clsName,...)66     static ani_object Create(ani_env *env, const char *clsName, ...)
67     {
68         ani_object nullobj{};
69 
70         if (env == nullptr) {
71             return nullobj;
72         }
73 
74         ani_class cls;
75         if (ANI_OK != env->FindClass(clsName, &cls)) {
76             return nullobj;
77         }
78 
79         ani_method ctor;
80         if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
81             return nullobj;
82         }
83 
84         ani_object obj;
85         va_list args;
86         va_start(args, clsName);
87         ani_status status = env->Object_New_V(cls, ctor, &obj, args);
88         va_end(args);
89         if (ANI_OK != status) {
90             return nullobj;
91         }
92         return obj;
93     }
94 
Create(ani_env * env,ani_class cls,...)95     static ani_object Create(ani_env *env, ani_class cls, ...)
96     {
97         ani_object nullobj{};
98 
99         if (env == nullptr) {
100             return nullobj;
101         }
102 
103         ani_method ctor;
104         if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
105             return nullobj;
106         }
107 
108         ani_object obj;
109         va_list args;
110         va_start(args, cls);
111         ani_status status = env->Object_New_V(cls, ctor, &obj, args);
112         va_end(args);
113         if (ANI_OK != status) {
114             return nullobj;
115         }
116         return obj;
117     }
118 
CallObjMethod(ani_env * env,const char * ns,const char * cls,const char * method,ani_object obj)119     static ani_status CallObjMethod(ani_env *env, const char *ns, const char *cls, const char *method, ani_object obj)
120     {
121         if (env == nullptr) {
122             return ANI_ERROR;
123         }
124 
125         ani_namespace nameSpace;
126         auto status = env->FindNamespace(ns, &nameSpace);
127         if (status != ANI_OK) {
128             return status;
129         }
130 
131         ani_class clazz;
132         status = env->Namespace_FindClass(nameSpace, cls, &clazz);
133         if (status != ANI_OK) {
134             return status;
135         }
136 
137         ani_method objMethod;
138         status = env->Class_FindMethod(clazz, method, ":V", &objMethod);
139         if (status != ANI_OK) {
140             return status;
141         }
142         status = env->Object_CallMethod_Void(obj, objMethod);
143         return status;
144     }
145 
146     template<typename T>
147     static ani_status Wrap(ani_env *env, ani_object object, T *nativePtr, const char *propName = "nativePtr")
148     {
149         return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast<ani_long>(nativePtr));
150     }
151 
152     template<typename T>
153     static T* Unwrap(ani_env *env, ani_object object, const char *propName = "nativePtr")
154     {
155         ani_long nativePtr;
156         if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) {
157             return nullptr;
158         }
159         return reinterpret_cast<T*>(nativePtr);
160     }
161 };
162 
163 class AniStringUtils {
164 public:
ToStd(ani_env * env,ani_string ani_str)165     static std::string ToStd(ani_env *env, ani_string ani_str)
166     {
167         if (env == nullptr) {
168             return std::string();
169         }
170 
171         ani_size strSize = 0;
172         auto status = env->String_GetUTF8Size(ani_str, &strSize);
173         if (ANI_OK != status) {
174             return std::string();
175         }
176 
177         std::vector<char> buffer(strSize + 1); // +1 for null terminator
178         char *utf8Buffer = buffer.data();
179 
180         // String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416
181         ani_size bytesWritten = 0;
182         status = env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytesWritten);
183         if (ANI_OK != status) {
184             return std::string();
185         }
186 
187         utf8Buffer[bytesWritten] = '\0';
188         std::string content = std::string(utf8Buffer);
189         return content;
190     }
191 
ToAni(ani_env * env,const std::string & str)192     static ani_string ToAni(ani_env *env, const std::string& str)
193     {
194         if (env == nullptr) {
195             return nullptr;
196         }
197         ani_string aniStr = nullptr;
198         if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) {
199             return nullptr;
200         }
201         return aniStr;
202     }
203 };
204 
205 class UnionAccessor {
206 public:
UnionAccessor(ani_env * env,ani_object & obj)207     UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj)
208     {
209     }
210 
IsInstanceOf(const std::string & cls_name)211     bool IsInstanceOf(const std::string& cls_name)
212     {
213         ani_class cls;
214         env_->FindClass(cls_name.c_str(), &cls);
215 
216         ani_boolean ret;
217         env_->Object_InstanceOf(obj_, cls, &ret);
218         return ret;
219     }
220 
221     template<typename T>
222     bool IsInstanceOfType();
223 
224     template<typename T>
225     bool TryConvert(T &value);
226 
227     template<typename... Types>
TryConvertVariant(std::variant<Types...> & value)228     bool TryConvertVariant(std::variant<Types...> &value)
229     {
230         return GetNativeValue<decltype(value), Types...>(value);
231     }
232 
233     template<typename T>
GetNativeValue(T & value)234     bool GetNativeValue(T &value)
235     {
236         return false;
237     }
238 
239     template<typename T, typename First, typename... Types>
GetNativeValue(T & value)240     bool GetNativeValue(T &value)
241     {
242         First cValue;
243         auto ret = TryConvert(cValue);
244         if (ret == true) {
245             value = cValue;
246             return ret;
247         }
248         return GetNativeValue<T, Types...>(value);
249     }
250 
251     template<typename T>
252     bool TryConvertArray(std::vector<T> &value);
253 
254     bool GetObjectRefPropertyByName(std::string clsName, const char *name, ani_ref &val);
255     bool GetObjectStringPropertyByName(std::string clsName, const char *name, std::string &val);
256     bool GetObjectEnumValuePropertyByName(std::string clsName, const char *name, ani_int &val, bool optional = false);
257     ani_ref AniIteratorNext(ani_ref interator, bool &isSuccess);
258 
259 private:
260     ani_env *env_;
261     ani_object obj_;
262 };
263 
264 class OptionalAccessor {
265 public:
OptionalAccessor(ani_env * env,ani_object & obj)266     OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj)
267     {
268     }
269 
IsUndefined()270     bool IsUndefined()
271     {
272         ani_boolean isUndefined;
273         env_->Reference_IsUndefined(obj_, &isUndefined);
274         return isUndefined;
275     }
276 
277     template<typename T>
278     std::optional<T> Convert();
279 
280 private:
281     ani_env *env_;
282     ani_object obj_;
283 };
284 
285 class NativeObject {
286 public:
287     virtual ~NativeObject() = default;
288 };
289 
290 ani_status CleanerInit(ani_env *env);
291 #endif
292