1 | /**************************************************************************/ |
2 | /* binder_common.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef BINDER_COMMON_H |
32 | #define BINDER_COMMON_H |
33 | |
34 | #include "core/input/input_enums.h" |
35 | #include "core/object/object.h" |
36 | #include "core/os/keyboard.h" |
37 | #include "core/templates/list.h" |
38 | #include "core/templates/simple_type.h" |
39 | #include "core/typedefs.h" |
40 | #include "core/variant/method_ptrcall.h" |
41 | #include "core/variant/type_info.h" |
42 | #include "core/variant/variant.h" |
43 | #include "core/variant/variant_internal.h" |
44 | |
45 | #include <stdio.h> |
46 | |
47 | // Variant cannot define an implicit cast operator for every Object subclass, so the |
48 | // casting is done here, to allow binding methods with parameters more specific than Object * |
49 | |
50 | template <class T> |
51 | struct VariantCaster { |
52 | static _FORCE_INLINE_ T cast(const Variant &p_variant) { |
53 | using TStripped = std::remove_pointer_t<T>; |
54 | if constexpr (std::is_base_of<Object, TStripped>::value) { |
55 | return Object::cast_to<TStripped>(p_variant); |
56 | } else { |
57 | return p_variant; |
58 | } |
59 | } |
60 | }; |
61 | |
62 | template <class T> |
63 | struct VariantCaster<T &> { |
64 | static _FORCE_INLINE_ T cast(const Variant &p_variant) { |
65 | using TStripped = std::remove_pointer_t<T>; |
66 | if constexpr (std::is_base_of<Object, TStripped>::value) { |
67 | return Object::cast_to<TStripped>(p_variant); |
68 | } else { |
69 | return p_variant; |
70 | } |
71 | } |
72 | }; |
73 | |
74 | template <class T> |
75 | struct VariantCaster<const T &> { |
76 | static _FORCE_INLINE_ T cast(const Variant &p_variant) { |
77 | using TStripped = std::remove_pointer_t<T>; |
78 | if constexpr (std::is_base_of<Object, TStripped>::value) { |
79 | return Object::cast_to<TStripped>(p_variant); |
80 | } else { |
81 | return p_variant; |
82 | } |
83 | } |
84 | }; |
85 | |
86 | #define VARIANT_ENUM_CAST(m_enum) \ |
87 | MAKE_ENUM_TYPE_INFO(m_enum) \ |
88 | template <> \ |
89 | struct VariantCaster<m_enum> { \ |
90 | static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ |
91 | return (m_enum)p_variant.operator int64_t(); \ |
92 | } \ |
93 | }; \ |
94 | template <> \ |
95 | struct PtrToArg<m_enum> { \ |
96 | _FORCE_INLINE_ static m_enum convert(const void *p_ptr) { \ |
97 | return m_enum(*reinterpret_cast<const int64_t *>(p_ptr)); \ |
98 | } \ |
99 | typedef int64_t EncodeT; \ |
100 | _FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \ |
101 | *(int64_t *)p_ptr = (int64_t)p_val; \ |
102 | } \ |
103 | }; \ |
104 | template <> \ |
105 | struct ZeroInitializer<m_enum> { \ |
106 | static void initialize(m_enum &value) { value = (m_enum)0; } \ |
107 | }; \ |
108 | template <> \ |
109 | struct VariantInternalAccessor<m_enum> { \ |
110 | static _FORCE_INLINE_ m_enum get(const Variant *v) { return m_enum(*VariantInternal::get_int(v)); } \ |
111 | static _FORCE_INLINE_ void set(Variant *v, m_enum p_value) { *VariantInternal::get_int(v) = (int64_t)p_value; } \ |
112 | }; |
113 | |
114 | #define VARIANT_BITFIELD_CAST(m_enum) \ |
115 | MAKE_BITFIELD_TYPE_INFO(m_enum) \ |
116 | template <> \ |
117 | struct VariantCaster<BitField<m_enum>> { \ |
118 | static _FORCE_INLINE_ BitField<m_enum> cast(const Variant &p_variant) { \ |
119 | return BitField<m_enum>(p_variant.operator int64_t()); \ |
120 | } \ |
121 | }; \ |
122 | template <> \ |
123 | struct PtrToArg<BitField<m_enum>> { \ |
124 | _FORCE_INLINE_ static BitField<m_enum> convert(const void *p_ptr) { \ |
125 | return BitField<m_enum>(*reinterpret_cast<const int64_t *>(p_ptr)); \ |
126 | } \ |
127 | typedef int64_t EncodeT; \ |
128 | _FORCE_INLINE_ static void encode(BitField<m_enum> p_val, const void *p_ptr) { \ |
129 | *(int64_t *)p_ptr = p_val; \ |
130 | } \ |
131 | }; \ |
132 | template <> \ |
133 | struct ZeroInitializer<BitField<m_enum>> { \ |
134 | static void initialize(BitField<m_enum> &value) { value = 0; } \ |
135 | }; \ |
136 | template <> \ |
137 | struct VariantInternalAccessor<BitField<m_enum>> { \ |
138 | static _FORCE_INLINE_ BitField<m_enum> get(const Variant *v) { return BitField<m_enum>(*VariantInternal::get_int(v)); } \ |
139 | static _FORCE_INLINE_ void set(Variant *v, BitField<m_enum> p_value) { *VariantInternal::get_int(v) = p_value.operator int64_t(); } \ |
140 | }; |
141 | |
142 | // Object enum casts must go here |
143 | VARIANT_ENUM_CAST(Object::ConnectFlags); |
144 | |
145 | VARIANT_ENUM_CAST(Vector2::Axis); |
146 | VARIANT_ENUM_CAST(Vector2i::Axis); |
147 | VARIANT_ENUM_CAST(Vector3::Axis); |
148 | VARIANT_ENUM_CAST(Vector3i::Axis); |
149 | VARIANT_ENUM_CAST(Vector4::Axis); |
150 | VARIANT_ENUM_CAST(Vector4i::Axis); |
151 | VARIANT_ENUM_CAST(EulerOrder); |
152 | VARIANT_ENUM_CAST(Projection::Planes); |
153 | |
154 | VARIANT_ENUM_CAST(Error); |
155 | VARIANT_ENUM_CAST(Side); |
156 | VARIANT_ENUM_CAST(ClockDirection); |
157 | VARIANT_ENUM_CAST(Corner); |
158 | VARIANT_ENUM_CAST(HatDir); |
159 | VARIANT_BITFIELD_CAST(HatMask); |
160 | VARIANT_ENUM_CAST(JoyAxis); |
161 | VARIANT_ENUM_CAST(JoyButton); |
162 | |
163 | VARIANT_ENUM_CAST(MIDIMessage); |
164 | VARIANT_ENUM_CAST(MouseButton); |
165 | VARIANT_BITFIELD_CAST(MouseButtonMask); |
166 | VARIANT_ENUM_CAST(Orientation); |
167 | VARIANT_ENUM_CAST(HorizontalAlignment); |
168 | VARIANT_ENUM_CAST(VerticalAlignment); |
169 | VARIANT_ENUM_CAST(InlineAlignment); |
170 | VARIANT_ENUM_CAST(PropertyHint); |
171 | VARIANT_BITFIELD_CAST(PropertyUsageFlags); |
172 | VARIANT_ENUM_CAST(Variant::Type); |
173 | VARIANT_ENUM_CAST(Variant::Operator); |
174 | |
175 | // Key |
176 | |
177 | VARIANT_ENUM_CAST(Key); |
178 | VARIANT_BITFIELD_CAST(KeyModifierMask); |
179 | |
180 | static inline Key &operator|=(Key &a, BitField<KeyModifierMask> b) { |
181 | a = static_cast<Key>(static_cast<int>(a) | static_cast<int>(b.operator int64_t())); |
182 | return a; |
183 | } |
184 | |
185 | static inline Key &operator&=(Key &a, BitField<KeyModifierMask> b) { |
186 | a = static_cast<Key>(static_cast<int>(a) & static_cast<int>(b.operator int64_t())); |
187 | return a; |
188 | } |
189 | |
190 | static inline Key operator|(Key a, BitField<KeyModifierMask> b) { |
191 | return (Key)((int)a | (int)b.operator int64_t()); |
192 | } |
193 | |
194 | static inline Key operator&(Key a, BitField<KeyModifierMask> b) { |
195 | return (Key)((int)a & (int)b.operator int64_t()); |
196 | } |
197 | |
198 | static inline Key operator+(BitField<KeyModifierMask> a, Key b) { |
199 | return (Key)((int)a.operator int64_t() + (int)b); |
200 | } |
201 | |
202 | static inline Key operator|(BitField<KeyModifierMask> a, Key b) { |
203 | return (Key)((int)a.operator int64_t() | (int)b); |
204 | } |
205 | |
206 | template <> |
207 | struct VariantCaster<char32_t> { |
208 | static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) { |
209 | return (char32_t)p_variant.operator int(); |
210 | } |
211 | }; |
212 | |
213 | template <> |
214 | struct PtrToArg<char32_t> { |
215 | _FORCE_INLINE_ static char32_t convert(const void *p_ptr) { |
216 | return char32_t(*reinterpret_cast<const int *>(p_ptr)); |
217 | } |
218 | typedef int64_t EncodeT; |
219 | _FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) { |
220 | *(int *)p_ptr = p_val; |
221 | } |
222 | }; |
223 | |
224 | template <typename T> |
225 | struct VariantObjectClassChecker { |
226 | static _FORCE_INLINE_ bool check(const Variant &p_variant) { |
227 | using TStripped = std::remove_pointer_t<T>; |
228 | if constexpr (std::is_base_of<Object, TStripped>::value) { |
229 | Object *obj = p_variant; |
230 | return Object::cast_to<TStripped>(p_variant) || !obj; |
231 | } else { |
232 | return true; |
233 | } |
234 | } |
235 | }; |
236 | |
237 | template <typename T> |
238 | class Ref; |
239 | |
240 | template <typename T> |
241 | struct VariantObjectClassChecker<const Ref<T> &> { |
242 | static _FORCE_INLINE_ bool check(const Variant &p_variant) { |
243 | Object *obj = p_variant; |
244 | const Ref<T> node = p_variant; |
245 | return node.ptr() || !obj; |
246 | } |
247 | }; |
248 | |
249 | #ifdef DEBUG_METHODS_ENABLED |
250 | |
251 | template <class T> |
252 | struct VariantCasterAndValidate { |
253 | static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { |
254 | Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; |
255 | if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || |
256 | !VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) { |
257 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
258 | r_error.argument = p_arg_idx; |
259 | r_error.expected = argtype; |
260 | } |
261 | |
262 | return VariantCaster<T>::cast(*p_args[p_arg_idx]); |
263 | } |
264 | }; |
265 | |
266 | template <class T> |
267 | struct VariantCasterAndValidate<T &> { |
268 | static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { |
269 | Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; |
270 | if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || |
271 | !VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) { |
272 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
273 | r_error.argument = p_arg_idx; |
274 | r_error.expected = argtype; |
275 | } |
276 | |
277 | return VariantCaster<T>::cast(*p_args[p_arg_idx]); |
278 | } |
279 | }; |
280 | |
281 | template <class T> |
282 | struct VariantCasterAndValidate<const T &> { |
283 | static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { |
284 | Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; |
285 | if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || |
286 | !VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) { |
287 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
288 | r_error.argument = p_arg_idx; |
289 | r_error.expected = argtype; |
290 | } |
291 | |
292 | return VariantCaster<T>::cast(*p_args[p_arg_idx]); |
293 | } |
294 | }; |
295 | |
296 | #endif // DEBUG_METHODS_ENABLED |
297 | |
298 | template <class T, class... P, size_t... Is> |
299 | void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { |
300 | r_error.error = Callable::CallError::CALL_OK; |
301 | |
302 | #ifdef DEBUG_METHODS_ENABLED |
303 | (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
304 | #else |
305 | (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); |
306 | #endif |
307 | (void)(p_args); //avoid warning |
308 | } |
309 | |
310 | template <class T, class... P, size_t... Is> |
311 | void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { |
312 | r_error.error = Callable::CallError::CALL_OK; |
313 | |
314 | #ifdef DEBUG_METHODS_ENABLED |
315 | (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
316 | #else |
317 | (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); |
318 | #endif |
319 | (void)(p_args); //avoid warning |
320 | } |
321 | |
322 | template <class T, class... P, size_t... Is> |
323 | void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const void **p_args, IndexSequence<Is...>) { |
324 | (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...); |
325 | } |
326 | |
327 | template <class T, class... P, size_t... Is> |
328 | void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const void **p_args, IndexSequence<Is...>) { |
329 | (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...); |
330 | } |
331 | |
332 | template <class T, class R, class... P, size_t... Is> |
333 | void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret, IndexSequence<Is...>) { |
334 | PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret); |
335 | } |
336 | |
337 | template <class T, class R, class... P, size_t... Is> |
338 | void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret, IndexSequence<Is...>) { |
339 | PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret); |
340 | } |
341 | |
342 | template <class T, class... P, size_t... Is> |
343 | void call_with_ptr_args_static_helper(T *p_instance, void (*p_method)(T *, P...), const void **p_args, IndexSequence<Is...>) { |
344 | p_method(p_instance, PtrToArg<P>::convert(p_args[Is])...); |
345 | } |
346 | |
347 | template <class T, class R, class... P, size_t... Is> |
348 | void call_with_ptr_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret, IndexSequence<Is...>) { |
349 | PtrToArg<R>::encode(p_method(p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret); |
350 | } |
351 | |
352 | template <class R, class... P, size_t... Is> |
353 | void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const void **p_args, void *r_ret, IndexSequence<Is...>) { |
354 | PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret); |
355 | } |
356 | |
357 | template <class... P, size_t... Is> |
358 | void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const void **p_args, IndexSequence<Is...>) { |
359 | p_method(PtrToArg<P>::convert(p_args[Is])...); |
360 | } |
361 | |
362 | template <class T, class... P, size_t... Is> |
363 | void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) { |
364 | (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); |
365 | } |
366 | |
367 | template <class T, class... P, size_t... Is> |
368 | void call_with_validated_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, IndexSequence<Is...>) { |
369 | (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); |
370 | } |
371 | |
372 | template <class T, class R, class... P, size_t... Is> |
373 | void call_with_validated_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { |
374 | VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); |
375 | } |
376 | |
377 | template <class T, class R, class... P, size_t... Is> |
378 | void call_with_validated_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { |
379 | VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); |
380 | } |
381 | |
382 | template <class T, class R, class... P, size_t... Is> |
383 | void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { |
384 | VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); |
385 | } |
386 | |
387 | template <class T, class... P, size_t... Is> |
388 | void call_with_validated_variant_args_static_helper(T *p_instance, void (*p_method)(T *, P...), const Variant **p_args, IndexSequence<Is...>) { |
389 | p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); |
390 | } |
391 | |
392 | template <class R, class... P, size_t... Is> |
393 | void call_with_validated_variant_args_static_method_ret_helper(R (*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { |
394 | VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); |
395 | } |
396 | |
397 | template <class... P, size_t... Is> |
398 | void call_with_validated_variant_args_static_method_helper(void (*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) { |
399 | p_method((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); |
400 | } |
401 | |
402 | template <class T, class... P> |
403 | void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) { |
404 | #ifdef DEBUG_METHODS_ENABLED |
405 | if ((size_t)p_argcount > sizeof...(P)) { |
406 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
407 | r_error.argument = sizeof...(P); |
408 | return; |
409 | } |
410 | |
411 | if ((size_t)p_argcount < sizeof...(P)) { |
412 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
413 | r_error.argument = sizeof...(P); |
414 | return; |
415 | } |
416 | #endif |
417 | call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); |
418 | } |
419 | |
420 | template <class T, class... P> |
421 | void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) { |
422 | #ifdef DEBUG_ENABLED |
423 | if ((size_t)p_argcount > sizeof...(P)) { |
424 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
425 | r_error.argument = sizeof...(P); |
426 | return; |
427 | } |
428 | #endif |
429 | |
430 | int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; |
431 | |
432 | int32_t dvs = default_values.size(); |
433 | #ifdef DEBUG_ENABLED |
434 | if (missing > dvs) { |
435 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
436 | r_error.argument = sizeof...(P); |
437 | return; |
438 | } |
439 | #endif |
440 | |
441 | const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array |
442 | for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { |
443 | if (i < p_argcount) { |
444 | args[i] = p_args[i]; |
445 | } else { |
446 | args[i] = &default_values[i - p_argcount + (dvs - missing)]; |
447 | } |
448 | } |
449 | |
450 | call_with_variant_args_helper(p_instance, p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{}); |
451 | } |
452 | |
453 | template <class T, class... P> |
454 | void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { |
455 | #ifdef DEBUG_METHODS_ENABLED |
456 | if ((size_t)p_argcount > sizeof...(P)) { |
457 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
458 | r_error.argument = sizeof...(P); |
459 | return; |
460 | } |
461 | |
462 | if ((size_t)p_argcount < sizeof...(P)) { |
463 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
464 | r_error.argument = sizeof...(P); |
465 | return; |
466 | } |
467 | #endif |
468 | call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); |
469 | } |
470 | |
471 | template <class T, class... P> |
472 | void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) { |
473 | #ifdef DEBUG_ENABLED |
474 | if ((size_t)p_argcount > sizeof...(P)) { |
475 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
476 | r_error.argument = sizeof...(P); |
477 | return; |
478 | } |
479 | #endif |
480 | |
481 | int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; |
482 | |
483 | int32_t dvs = default_values.size(); |
484 | #ifdef DEBUG_ENABLED |
485 | if (missing > dvs) { |
486 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
487 | r_error.argument = sizeof...(P); |
488 | return; |
489 | } |
490 | #endif |
491 | |
492 | const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array |
493 | for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { |
494 | if (i < p_argcount) { |
495 | args[i] = p_args[i]; |
496 | } else { |
497 | args[i] = &default_values[i - p_argcount + (dvs - missing)]; |
498 | } |
499 | } |
500 | |
501 | call_with_variant_argsc_helper(p_instance, p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{}); |
502 | } |
503 | |
504 | template <class T, class R, class... P> |
505 | void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) { |
506 | #ifdef DEBUG_ENABLED |
507 | if ((size_t)p_argcount > sizeof...(P)) { |
508 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
509 | r_error.argument = sizeof...(P); |
510 | return; |
511 | } |
512 | #endif |
513 | |
514 | int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; |
515 | |
516 | int32_t dvs = default_values.size(); |
517 | #ifdef DEBUG_ENABLED |
518 | if (missing > dvs) { |
519 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
520 | r_error.argument = sizeof...(P); |
521 | return; |
522 | } |
523 | #endif |
524 | |
525 | const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array |
526 | for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { |
527 | if (i < p_argcount) { |
528 | args[i] = p_args[i]; |
529 | } else { |
530 | args[i] = &default_values[i - p_argcount + (dvs - missing)]; |
531 | } |
532 | } |
533 | |
534 | call_with_variant_args_ret_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); |
535 | } |
536 | |
537 | template <class T, class R, class... P> |
538 | void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) { |
539 | #ifdef DEBUG_ENABLED |
540 | if ((size_t)p_argcount > sizeof...(P)) { |
541 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
542 | r_error.argument = sizeof...(P); |
543 | return; |
544 | } |
545 | #endif |
546 | |
547 | int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; |
548 | |
549 | int32_t dvs = default_values.size(); |
550 | #ifdef DEBUG_ENABLED |
551 | if (missing > dvs) { |
552 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
553 | r_error.argument = sizeof...(P); |
554 | return; |
555 | } |
556 | #endif |
557 | |
558 | const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array |
559 | for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { |
560 | if (i < p_argcount) { |
561 | args[i] = p_args[i]; |
562 | } else { |
563 | args[i] = &default_values[i - p_argcount + (dvs - missing)]; |
564 | } |
565 | } |
566 | |
567 | call_with_variant_args_retc_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); |
568 | } |
569 | |
570 | template <class T, class... P> |
571 | void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const void **p_args) { |
572 | call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
573 | } |
574 | |
575 | template <class T, class... P> |
576 | void call_with_ptr_argsc(T *p_instance, void (T::*p_method)(P...) const, const void **p_args) { |
577 | call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
578 | } |
579 | |
580 | template <class T, class R, class... P> |
581 | void call_with_ptr_args_ret(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret) { |
582 | call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
583 | } |
584 | |
585 | template <class T, class R, class... P> |
586 | void call_with_ptr_args_retc(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret) { |
587 | call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
588 | } |
589 | |
590 | template <class T, class... P> |
591 | void call_with_ptr_args_static(T *p_instance, void (*p_method)(T *, P...), const void **p_args) { |
592 | call_with_ptr_args_static_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
593 | } |
594 | |
595 | template <class T, class R, class... P> |
596 | void call_with_ptr_args_static_retc(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret) { |
597 | call_with_ptr_args_static_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
598 | } |
599 | |
600 | template <class R, class... P> |
601 | void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const void **p_args, void *r_ret) { |
602 | call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
603 | } |
604 | |
605 | template <class... P> |
606 | void call_with_ptr_args_static_method(void (*p_method)(P...), const void **p_args) { |
607 | call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
608 | } |
609 | |
610 | // Validated |
611 | |
612 | template <class T, class... P> |
613 | void call_with_validated_variant_args(Variant *base, void (T::*p_method)(P...), const Variant **p_args) { |
614 | call_with_validated_variant_args_helper<T, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
615 | } |
616 | |
617 | template <class T, class R, class... P> |
618 | void call_with_validated_variant_args_ret(Variant *base, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret) { |
619 | call_with_validated_variant_args_ret_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
620 | } |
621 | |
622 | template <class T, class R, class... P> |
623 | void call_with_validated_variant_args_retc(Variant *base, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret) { |
624 | call_with_validated_variant_args_retc_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
625 | } |
626 | |
627 | template <class T, class... P> |
628 | void call_with_validated_variant_args_static(Variant *base, void (*p_method)(T *, P...), const Variant **p_args) { |
629 | call_with_validated_variant_args_static_helper<T, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
630 | } |
631 | |
632 | template <class T, class R, class... P> |
633 | void call_with_validated_variant_args_static_retc(Variant *base, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret) { |
634 | call_with_validated_variant_args_static_retc_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
635 | } |
636 | |
637 | template <class... P> |
638 | void call_with_validated_variant_args_static_method(void (*p_method)(P...), const Variant **p_args) { |
639 | call_with_validated_variant_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
640 | } |
641 | |
642 | template <class R, class... P> |
643 | void call_with_validated_variant_args_static_method_ret(R (*p_method)(P...), const Variant **p_args, Variant *r_ret) { |
644 | call_with_validated_variant_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
645 | } |
646 | |
647 | // Validated Object |
648 | |
649 | template <class T, class... P> |
650 | void call_with_validated_object_instance_args(T *base, void (T::*p_method)(P...), const Variant **p_args) { |
651 | call_with_validated_variant_args_helper<T, P...>(base, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
652 | } |
653 | |
654 | template <class T, class... P> |
655 | void call_with_validated_object_instance_argsc(T *base, void (T::*p_method)(P...) const, const Variant **p_args) { |
656 | call_with_validated_variant_argsc_helper<T, P...>(base, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
657 | } |
658 | |
659 | template <class T, class R, class... P> |
660 | void call_with_validated_object_instance_args_ret(T *base, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret) { |
661 | call_with_validated_variant_args_ret_helper<T, R, P...>(base, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
662 | } |
663 | |
664 | template <class T, class R, class... P> |
665 | void call_with_validated_object_instance_args_retc(T *base, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret) { |
666 | call_with_validated_variant_args_retc_helper<T, R, P...>(base, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
667 | } |
668 | |
669 | template <class T, class... P> |
670 | void call_with_validated_object_instance_args_static(T *base, void (*p_method)(T *, P...), const Variant **p_args) { |
671 | call_with_validated_variant_args_static_helper<T, P...>(base, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); |
672 | } |
673 | |
674 | template <class T, class R, class... P> |
675 | void call_with_validated_object_instance_args_static_retc(T *base, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret) { |
676 | call_with_validated_variant_args_static_retc_helper<T, R, P...>(base, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); |
677 | } |
678 | |
679 | // GCC raises "parameter 'p_args' set but not used" when P = {}, |
680 | // it's not clever enough to treat other P values as making this branch valid. |
681 | #if defined(__GNUC__) && !defined(__clang__) |
682 | #pragma GCC diagnostic push |
683 | #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" |
684 | #endif |
685 | |
686 | template <class Q> |
687 | void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) { |
688 | if (p_arg == index) { |
689 | type = GetTypeInfo<Q>::VARIANT_TYPE; |
690 | } |
691 | index++; |
692 | } |
693 | |
694 | template <class... P> |
695 | Variant::Type call_get_argument_type(int p_arg) { |
696 | Variant::Type type = Variant::NIL; |
697 | int index = 0; |
698 | // I think rocket science is simpler than modern C++. |
699 | using expand_type = int[]; |
700 | expand_type a{ 0, (call_get_argument_type_helper<P>(p_arg, index, type), 0)... }; |
701 | (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. |
702 | (void)index; // Suppress GCC warning. |
703 | return type; |
704 | } |
705 | |
706 | template <class Q> |
707 | void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) { |
708 | if (p_arg == index) { |
709 | info = GetTypeInfo<Q>::get_class_info(); |
710 | } |
711 | index++; |
712 | } |
713 | |
714 | template <class... P> |
715 | void call_get_argument_type_info(int p_arg, PropertyInfo &info) { |
716 | int index = 0; |
717 | // I think rocket science is simpler than modern C++. |
718 | using expand_type = int[]; |
719 | expand_type a{ 0, (call_get_argument_type_info_helper<P>(p_arg, index, info), 0)... }; |
720 | (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. |
721 | (void)index; // Suppress GCC warning. |
722 | } |
723 | |
724 | #ifdef DEBUG_METHODS_ENABLED |
725 | template <class Q> |
726 | void call_get_argument_metadata_helper(int p_arg, int &index, GodotTypeInfo::Metadata &md) { |
727 | if (p_arg == index) { |
728 | md = GetTypeInfo<Q>::METADATA; |
729 | } |
730 | index++; |
731 | } |
732 | |
733 | template <class... P> |
734 | GodotTypeInfo::Metadata call_get_argument_metadata(int p_arg) { |
735 | GodotTypeInfo::Metadata md = GodotTypeInfo::METADATA_NONE; |
736 | |
737 | int index = 0; |
738 | // I think rocket science is simpler than modern C++. |
739 | using expand_type = int[]; |
740 | expand_type a{ 0, (call_get_argument_metadata_helper<P>(p_arg, index, md), 0)... }; |
741 | (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. |
742 | (void)index; |
743 | return md; |
744 | } |
745 | |
746 | #endif // DEBUG_METHODS_ENABLED |
747 | |
748 | ////////////////////// |
749 | |
750 | template <class T, class R, class... P, size_t... Is> |
751 | void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) { |
752 | r_error.error = Callable::CallError::CALL_OK; |
753 | |
754 | #ifdef DEBUG_METHODS_ENABLED |
755 | r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
756 | #else |
757 | r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); |
758 | #endif |
759 | } |
760 | |
761 | template <class R, class... P, size_t... Is> |
762 | void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) { |
763 | r_error.error = Callable::CallError::CALL_OK; |
764 | |
765 | #ifdef DEBUG_METHODS_ENABLED |
766 | r_ret = (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
767 | #else |
768 | r_ret = (p_method)(VariantCaster<P>::cast(*p_args[Is])...); |
769 | #endif |
770 | } |
771 | |
772 | template <class... P, size_t... Is> |
773 | void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { |
774 | r_error.error = Callable::CallError::CALL_OK; |
775 | |
776 | #ifdef DEBUG_METHODS_ENABLED |
777 | (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
778 | #else |
779 | (p_method)(VariantCaster<P>::cast(*p_args[Is])...); |
780 | #endif |
781 | } |
782 | |
783 | template <class T, class R, class... P> |
784 | void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { |
785 | #ifdef DEBUG_METHODS_ENABLED |
786 | if ((size_t)p_argcount > sizeof...(P)) { |
787 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
788 | r_error.argument = sizeof...(P); |
789 | return; |
790 | } |
791 | |
792 | if ((size_t)p_argcount < sizeof...(P)) { |
793 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
794 | r_error.argument = sizeof...(P); |
795 | return; |
796 | } |
797 | #endif |
798 | call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); |
799 | } |
800 | |
801 | template <class T, class R, class... P, size_t... Is> |
802 | void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) { |
803 | r_error.error = Callable::CallError::CALL_OK; |
804 | |
805 | #ifdef DEBUG_METHODS_ENABLED |
806 | r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
807 | #else |
808 | r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); |
809 | #endif |
810 | (void)p_args; |
811 | } |
812 | |
813 | template <class R, class... P> |
814 | void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { |
815 | #ifdef DEBUG_METHODS_ENABLED |
816 | if ((size_t)p_argcount > sizeof...(P)) { |
817 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
818 | r_error.argument = sizeof...(P); |
819 | return; |
820 | } |
821 | |
822 | if ((size_t)p_argcount < sizeof...(P)) { |
823 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
824 | r_error.argument = sizeof...(P); |
825 | return; |
826 | } |
827 | #endif |
828 | call_with_variant_args_static_ret<R, P...>(p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); |
829 | } |
830 | |
831 | template <class... P> |
832 | void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { |
833 | #ifdef DEBUG_METHODS_ENABLED |
834 | if ((size_t)p_argcount > sizeof...(P)) { |
835 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
836 | r_error.argument = sizeof...(P); |
837 | return; |
838 | } |
839 | |
840 | if ((size_t)p_argcount < sizeof...(P)) { |
841 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
842 | r_error.argument = sizeof...(P); |
843 | return; |
844 | } |
845 | #endif |
846 | call_with_variant_args_static<P...>(p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); |
847 | } |
848 | |
849 | template <class T, class R, class... P> |
850 | void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { |
851 | #ifdef DEBUG_METHODS_ENABLED |
852 | if ((size_t)p_argcount > sizeof...(P)) { |
853 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
854 | r_error.argument = sizeof...(P); |
855 | return; |
856 | } |
857 | |
858 | if ((size_t)p_argcount < sizeof...(P)) { |
859 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
860 | r_error.argument = sizeof...(P); |
861 | return; |
862 | } |
863 | #endif |
864 | call_with_variant_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); |
865 | } |
866 | |
867 | template <class T, class R, class... P, size_t... Is> |
868 | void call_with_variant_args_retc_static_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) { |
869 | r_error.error = Callable::CallError::CALL_OK; |
870 | |
871 | #ifdef DEBUG_METHODS_ENABLED |
872 | r_ret = (p_method)(p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
873 | #else |
874 | r_ret = (p_method)(p_instance, VariantCaster<P>::cast(*p_args[Is])...); |
875 | #endif |
876 | |
877 | (void)p_args; |
878 | } |
879 | |
880 | template <class T, class R, class... P> |
881 | void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &default_values, Callable::CallError &r_error) { |
882 | #ifdef DEBUG_ENABLED |
883 | if ((size_t)p_argcount > sizeof...(P)) { |
884 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
885 | r_error.argument = sizeof...(P); |
886 | return; |
887 | } |
888 | #endif |
889 | |
890 | int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; |
891 | |
892 | int32_t dvs = default_values.size(); |
893 | #ifdef DEBUG_ENABLED |
894 | if (missing > dvs) { |
895 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
896 | r_error.argument = sizeof...(P); |
897 | return; |
898 | } |
899 | #endif |
900 | |
901 | const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array |
902 | for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { |
903 | if (i < p_argcount) { |
904 | args[i] = p_args[i]; |
905 | } else { |
906 | args[i] = &default_values[i - p_argcount + (dvs - missing)]; |
907 | } |
908 | } |
909 | |
910 | call_with_variant_args_retc_static_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); |
911 | } |
912 | |
913 | template <class T, class... P, size_t... Is> |
914 | void call_with_variant_args_static_helper(T *p_instance, void (*p_method)(T *, P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { |
915 | r_error.error = Callable::CallError::CALL_OK; |
916 | |
917 | #ifdef DEBUG_METHODS_ENABLED |
918 | (p_method)(p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
919 | #else |
920 | (p_method)(p_instance, VariantCaster<P>::cast(*p_args[Is])...); |
921 | #endif |
922 | |
923 | (void)p_args; |
924 | } |
925 | |
926 | template <class T, class... P> |
927 | void call_with_variant_args_static_helper_dv(T *p_instance, void (*p_method)(T *, P...), const Variant **p_args, int p_argcount, const Vector<Variant> &default_values, Callable::CallError &r_error) { |
928 | #ifdef DEBUG_ENABLED |
929 | if ((size_t)p_argcount > sizeof...(P)) { |
930 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
931 | r_error.argument = sizeof...(P); |
932 | return; |
933 | } |
934 | #endif |
935 | |
936 | int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; |
937 | |
938 | int32_t dvs = default_values.size(); |
939 | #ifdef DEBUG_ENABLED |
940 | if (missing > dvs) { |
941 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
942 | r_error.argument = sizeof...(P); |
943 | return; |
944 | } |
945 | #endif |
946 | |
947 | const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array |
948 | for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { |
949 | if (i < p_argcount) { |
950 | args[i] = p_args[i]; |
951 | } else { |
952 | args[i] = &default_values[i - p_argcount + (dvs - missing)]; |
953 | } |
954 | } |
955 | |
956 | call_with_variant_args_static_helper(p_instance, p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{}); |
957 | } |
958 | |
959 | template <class R, class... P> |
960 | void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) { |
961 | #ifdef DEBUG_ENABLED |
962 | if ((size_t)p_argcount > sizeof...(P)) { |
963 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
964 | r_error.argument = sizeof...(P); |
965 | return; |
966 | } |
967 | #endif |
968 | |
969 | int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; |
970 | |
971 | int32_t dvs = default_values.size(); |
972 | #ifdef DEBUG_ENABLED |
973 | if (missing > dvs) { |
974 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
975 | r_error.argument = sizeof...(P); |
976 | return; |
977 | } |
978 | #endif |
979 | |
980 | const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array |
981 | for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { |
982 | if (i < p_argcount) { |
983 | args[i] = p_args[i]; |
984 | } else { |
985 | args[i] = &default_values[i - p_argcount + (dvs - missing)]; |
986 | } |
987 | } |
988 | |
989 | call_with_variant_args_static_ret(p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); |
990 | } |
991 | |
992 | template <class... P> |
993 | void call_with_variant_args_static_dv(void (*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) { |
994 | #ifdef DEBUG_ENABLED |
995 | if ((size_t)p_argcount > sizeof...(P)) { |
996 | r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; |
997 | r_error.argument = sizeof...(P); |
998 | return; |
999 | } |
1000 | #endif |
1001 | |
1002 | int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; |
1003 | |
1004 | int32_t dvs = default_values.size(); |
1005 | #ifdef DEBUG_ENABLED |
1006 | if (missing > dvs) { |
1007 | r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; |
1008 | r_error.argument = sizeof...(P); |
1009 | return; |
1010 | } |
1011 | #endif |
1012 | |
1013 | const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array |
1014 | for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { |
1015 | if (i < p_argcount) { |
1016 | args[i] = p_args[i]; |
1017 | } else { |
1018 | args[i] = &default_values[i - p_argcount + (dvs - missing)]; |
1019 | } |
1020 | } |
1021 | |
1022 | call_with_variant_args_static(p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{}); |
1023 | } |
1024 | |
1025 | #if defined(__GNUC__) && !defined(__clang__) |
1026 | #pragma GCC diagnostic pop |
1027 | #endif |
1028 | |
1029 | #endif // BINDER_COMMON_H |
1030 | |