1 | /**************************************************************************/ |
2 | /* variant_construct.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 VARIANT_CONSTRUCT_H |
32 | #define VARIANT_CONSTRUCT_H |
33 | |
34 | #include "variant.h" |
35 | |
36 | #include "core/core_string_names.h" |
37 | #include "core/crypto/crypto_core.h" |
38 | #include "core/debugger/engine_debugger.h" |
39 | #include "core/io/compression.h" |
40 | #include "core/object/class_db.h" |
41 | #include "core/os/os.h" |
42 | #include "core/templates/local_vector.h" |
43 | #include "core/templates/oa_hash_map.h" |
44 | |
45 | template <class T> |
46 | struct PtrConstruct {}; |
47 | |
48 | #define MAKE_PTRCONSTRUCT(m_type) \ |
49 | template <> \ |
50 | struct PtrConstruct<m_type> { \ |
51 | _FORCE_INLINE_ static void construct(const m_type &p_value, void *p_ptr) { \ |
52 | memnew_placement(p_ptr, m_type(p_value)); \ |
53 | } \ |
54 | }; |
55 | |
56 | MAKE_PTRCONSTRUCT(bool); |
57 | MAKE_PTRCONSTRUCT(int64_t); |
58 | MAKE_PTRCONSTRUCT(double); |
59 | MAKE_PTRCONSTRUCT(String); |
60 | MAKE_PTRCONSTRUCT(Vector2); |
61 | MAKE_PTRCONSTRUCT(Vector2i); |
62 | MAKE_PTRCONSTRUCT(Rect2); |
63 | MAKE_PTRCONSTRUCT(Rect2i); |
64 | MAKE_PTRCONSTRUCT(Vector3); |
65 | MAKE_PTRCONSTRUCT(Vector3i); |
66 | MAKE_PTRCONSTRUCT(Vector4); |
67 | MAKE_PTRCONSTRUCT(Vector4i); |
68 | MAKE_PTRCONSTRUCT(Transform2D); |
69 | MAKE_PTRCONSTRUCT(Plane); |
70 | MAKE_PTRCONSTRUCT(Quaternion); |
71 | MAKE_PTRCONSTRUCT(AABB); |
72 | MAKE_PTRCONSTRUCT(Basis); |
73 | MAKE_PTRCONSTRUCT(Transform3D); |
74 | MAKE_PTRCONSTRUCT(Projection); |
75 | MAKE_PTRCONSTRUCT(Color); |
76 | MAKE_PTRCONSTRUCT(StringName); |
77 | MAKE_PTRCONSTRUCT(NodePath); |
78 | MAKE_PTRCONSTRUCT(RID); |
79 | |
80 | template <> |
81 | struct PtrConstruct<Object *> { |
82 | _FORCE_INLINE_ static void construct(Object *p_value, void *p_ptr) { |
83 | *((Object **)p_ptr) = p_value; |
84 | } |
85 | }; |
86 | |
87 | MAKE_PTRCONSTRUCT(Callable); |
88 | MAKE_PTRCONSTRUCT(Signal); |
89 | MAKE_PTRCONSTRUCT(Dictionary); |
90 | MAKE_PTRCONSTRUCT(Array); |
91 | MAKE_PTRCONSTRUCT(PackedByteArray); |
92 | MAKE_PTRCONSTRUCT(PackedInt32Array); |
93 | MAKE_PTRCONSTRUCT(PackedInt64Array); |
94 | MAKE_PTRCONSTRUCT(PackedFloat32Array); |
95 | MAKE_PTRCONSTRUCT(PackedFloat64Array); |
96 | MAKE_PTRCONSTRUCT(PackedStringArray); |
97 | MAKE_PTRCONSTRUCT(PackedVector2Array); |
98 | MAKE_PTRCONSTRUCT(PackedVector3Array); |
99 | MAKE_PTRCONSTRUCT(PackedColorArray); |
100 | MAKE_PTRCONSTRUCT(Variant); |
101 | |
102 | template <class T, class... P> |
103 | class VariantConstructor { |
104 | template <size_t... Is> |
105 | static _FORCE_INLINE_ void construct_helper(T &base, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { |
106 | r_error.error = Callable::CallError::CALL_OK; |
107 | |
108 | #ifdef DEBUG_METHODS_ENABLED |
109 | base = T(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); |
110 | #else |
111 | base = T(VariantCaster<P>::cast(*p_args[Is])...); |
112 | #endif |
113 | } |
114 | |
115 | template <size_t... Is> |
116 | static _FORCE_INLINE_ void validated_construct_helper(T &base, const Variant **p_args, IndexSequence<Is...>) { |
117 | base = T((*VariantGetInternalPtr<P>::get_ptr(p_args[Is]))...); |
118 | } |
119 | |
120 | template <size_t... Is> |
121 | static _FORCE_INLINE_ void ptr_construct_helper(void *base, const void **p_args, IndexSequence<Is...>) { |
122 | PtrConstruct<T>::construct(T(PtrToArg<P>::convert(p_args[Is])...), base); |
123 | } |
124 | |
125 | public: |
126 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
127 | r_error.error = Callable::CallError::CALL_OK; |
128 | VariantTypeChanger<T>::change(&r_ret); |
129 | construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); |
130 | } |
131 | |
132 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
133 | VariantTypeChanger<T>::change(r_ret); |
134 | validated_construct_helper(*VariantGetInternalPtr<T>::get_ptr(r_ret), p_args, BuildIndexSequence<sizeof...(P)>{}); |
135 | } |
136 | static void ptr_construct(void *base, const void **p_args) { |
137 | ptr_construct_helper(base, p_args, BuildIndexSequence<sizeof...(P)>{}); |
138 | } |
139 | |
140 | static int get_argument_count() { |
141 | return sizeof...(P); |
142 | } |
143 | |
144 | static Variant::Type get_argument_type(int p_arg) { |
145 | return call_get_argument_type<P...>(p_arg); |
146 | } |
147 | |
148 | static Variant::Type get_base_type() { |
149 | return GetTypeInfo<T>::VARIANT_TYPE; |
150 | } |
151 | }; |
152 | |
153 | class VariantConstructorObject { |
154 | public: |
155 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
156 | VariantInternal::clear(&r_ret); |
157 | if (p_args[0]->get_type() == Variant::NIL) { |
158 | VariantInternal::object_assign_null(&r_ret); |
159 | r_error.error = Callable::CallError::CALL_OK; |
160 | } else if (p_args[0]->get_type() == Variant::OBJECT) { |
161 | VariantInternal::object_assign(&r_ret, p_args[0]); |
162 | r_error.error = Callable::CallError::CALL_OK; |
163 | } else { |
164 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
165 | r_error.argument = 0; |
166 | r_error.expected = Variant::OBJECT; |
167 | } |
168 | } |
169 | |
170 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
171 | VariantInternal::clear(r_ret); |
172 | VariantInternal::object_assign(r_ret, p_args[0]); |
173 | } |
174 | static void ptr_construct(void *base, const void **p_args) { |
175 | PtrConstruct<Object *>::construct(PtrToArg<Object *>::convert(p_args[0]), base); |
176 | } |
177 | |
178 | static int get_argument_count() { |
179 | return 1; |
180 | } |
181 | |
182 | static Variant::Type get_argument_type(int p_arg) { |
183 | return Variant::OBJECT; |
184 | } |
185 | |
186 | static Variant::Type get_base_type() { |
187 | return Variant::OBJECT; |
188 | } |
189 | }; |
190 | |
191 | class VariantConstructorNilObject { |
192 | public: |
193 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
194 | if (p_args[0]->get_type() != Variant::NIL) { |
195 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
196 | r_error.argument = 0; |
197 | r_error.expected = Variant::NIL; |
198 | } |
199 | |
200 | VariantInternal::clear(&r_ret); |
201 | VariantInternal::object_assign_null(&r_ret); |
202 | } |
203 | |
204 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
205 | VariantInternal::clear(r_ret); |
206 | VariantInternal::object_assign_null(r_ret); |
207 | } |
208 | static void ptr_construct(void *base, const void **p_args) { |
209 | PtrConstruct<Object *>::construct(nullptr, base); |
210 | } |
211 | |
212 | static int get_argument_count() { |
213 | return 1; |
214 | } |
215 | |
216 | static Variant::Type get_argument_type(int p_arg) { |
217 | return Variant::NIL; |
218 | } |
219 | |
220 | static Variant::Type get_base_type() { |
221 | return Variant::OBJECT; |
222 | } |
223 | }; |
224 | |
225 | template <class T> |
226 | class VariantConstructorFromString { |
227 | public: |
228 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
229 | if (p_args[0]->get_type() != Variant::STRING) { |
230 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
231 | r_error.argument = 0; |
232 | r_error.expected = Variant::STRING; |
233 | return; |
234 | } |
235 | |
236 | VariantTypeChanger<T>::change(&r_ret); |
237 | const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]); |
238 | |
239 | if (r_ret.get_type() == Variant::Type::INT) { |
240 | r_ret = src_str.to_int(); |
241 | } else if (r_ret.get_type() == Variant::Type::FLOAT) { |
242 | r_ret = src_str.to_float(); |
243 | } |
244 | } |
245 | |
246 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
247 | VariantTypeChanger<T>::change(r_ret); |
248 | const String &src_str = *VariantGetInternalPtr<String>::get_ptr(p_args[0]); |
249 | T ret = Variant(); |
250 | if (r_ret->get_type() == Variant::Type::INT) { |
251 | ret = src_str.to_int(); |
252 | } else if (r_ret->get_type() == Variant::Type::FLOAT) { |
253 | ret = src_str.to_float(); |
254 | } |
255 | *r_ret = ret; |
256 | } |
257 | |
258 | static void ptr_construct(void *base, const void **p_args) { |
259 | String src_str = PtrToArg<String>::convert(p_args[0]); |
260 | T dst_var = Variant(); |
261 | Variant type_test = Variant(dst_var); |
262 | if (type_test.get_type() == Variant::Type::INT) { |
263 | dst_var = src_str.to_int(); |
264 | } else if (type_test.get_type() == Variant::Type::FLOAT) { |
265 | dst_var = src_str.to_float(); |
266 | } |
267 | PtrConstruct<T>::construct(dst_var, base); |
268 | } |
269 | |
270 | static int get_argument_count() { |
271 | return 1; |
272 | } |
273 | |
274 | static Variant::Type get_argument_type(int p_arg) { |
275 | return Variant::STRING; |
276 | } |
277 | |
278 | static Variant::Type get_base_type() { |
279 | return GetTypeInfo<T>::VARIANT_TYPE; |
280 | } |
281 | }; |
282 | |
283 | class VariantConstructorCallableArgs { |
284 | public: |
285 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
286 | ObjectID object_id; |
287 | StringName method; |
288 | |
289 | if (p_args[0]->get_type() == Variant::NIL) { |
290 | // leave as is |
291 | } else if (p_args[0]->get_type() == Variant::OBJECT) { |
292 | object_id = VariantInternal::get_object_id(p_args[0]); |
293 | } else { |
294 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
295 | r_error.argument = 0; |
296 | r_error.expected = Variant::OBJECT; |
297 | return; |
298 | } |
299 | |
300 | if (p_args[1]->get_type() == Variant::STRING_NAME) { |
301 | method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]); |
302 | } else if (p_args[1]->get_type() == Variant::STRING) { |
303 | method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]); |
304 | } else { |
305 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
306 | r_error.argument = 1; |
307 | r_error.expected = Variant::STRING_NAME; |
308 | return; |
309 | } |
310 | |
311 | VariantTypeChanger<Callable>::change(&r_ret); |
312 | *VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(object_id, method); |
313 | } |
314 | |
315 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
316 | VariantTypeChanger<Callable>::change(r_ret); |
317 | *VariantGetInternalPtr<Callable>::get_ptr(r_ret) = Callable(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1])); |
318 | } |
319 | static void ptr_construct(void *base, const void **p_args) { |
320 | PtrConstruct<Callable>::construct(Callable(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base); |
321 | } |
322 | |
323 | static int get_argument_count() { |
324 | return 2; |
325 | } |
326 | |
327 | static Variant::Type get_argument_type(int p_arg) { |
328 | if (p_arg == 0) { |
329 | return Variant::OBJECT; |
330 | } else { |
331 | return Variant::STRING_NAME; |
332 | } |
333 | } |
334 | |
335 | static Variant::Type get_base_type() { |
336 | return Variant::CALLABLE; |
337 | } |
338 | }; |
339 | |
340 | class VariantConstructorSignalArgs { |
341 | public: |
342 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
343 | ObjectID object_id; |
344 | StringName method; |
345 | |
346 | if (p_args[0]->get_type() == Variant::NIL) { |
347 | // leave as is |
348 | } else if (p_args[0]->get_type() == Variant::OBJECT) { |
349 | object_id = VariantInternal::get_object_id(p_args[0]); |
350 | } else { |
351 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
352 | r_error.argument = 0; |
353 | r_error.expected = Variant::OBJECT; |
354 | return; |
355 | } |
356 | |
357 | if (p_args[1]->get_type() == Variant::STRING_NAME) { |
358 | method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]); |
359 | } else if (p_args[1]->get_type() == Variant::STRING) { |
360 | method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]); |
361 | } else { |
362 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
363 | r_error.argument = 1; |
364 | r_error.expected = Variant::STRING_NAME; |
365 | return; |
366 | } |
367 | |
368 | VariantTypeChanger<Signal>::change(&r_ret); |
369 | *VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(object_id, method); |
370 | } |
371 | |
372 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
373 | VariantTypeChanger<Signal>::change(r_ret); |
374 | *VariantGetInternalPtr<Signal>::get_ptr(r_ret) = Signal(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1])); |
375 | } |
376 | static void ptr_construct(void *base, const void **p_args) { |
377 | PtrConstruct<Signal>::construct(Signal(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base); |
378 | } |
379 | |
380 | static int get_argument_count() { |
381 | return 2; |
382 | } |
383 | |
384 | static Variant::Type get_argument_type(int p_arg) { |
385 | if (p_arg == 0) { |
386 | return Variant::OBJECT; |
387 | } else { |
388 | return Variant::STRING_NAME; |
389 | } |
390 | } |
391 | |
392 | static Variant::Type get_base_type() { |
393 | return Variant::SIGNAL; |
394 | } |
395 | }; |
396 | |
397 | class VariantConstructorTypedArray { |
398 | public: |
399 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
400 | if (p_args[0]->get_type() != Variant::ARRAY) { |
401 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
402 | r_error.argument = 0; |
403 | r_error.expected = Variant::ARRAY; |
404 | return; |
405 | } |
406 | |
407 | if (p_args[1]->get_type() != Variant::INT) { |
408 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
409 | r_error.argument = 1; |
410 | r_error.expected = Variant::INT; |
411 | return; |
412 | } |
413 | |
414 | if (p_args[2]->get_type() != Variant::STRING_NAME) { |
415 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
416 | r_error.argument = 2; |
417 | r_error.expected = Variant::STRING_NAME; |
418 | return; |
419 | } |
420 | |
421 | const Array &base_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]); |
422 | const uint32_t type = p_args[1]->operator uint32_t(); |
423 | const StringName &class_name = *VariantGetInternalPtr<StringName>::get_ptr(p_args[2]); |
424 | r_ret = Array(base_arr, type, class_name, *p_args[3]); |
425 | } |
426 | |
427 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
428 | const Array &base_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]); |
429 | const uint32_t type = p_args[1]->operator uint32_t(); |
430 | const StringName &class_name = *VariantGetInternalPtr<StringName>::get_ptr(p_args[2]); |
431 | *r_ret = Array(base_arr, type, class_name, *p_args[3]); |
432 | } |
433 | |
434 | static void ptr_construct(void *base, const void **p_args) { |
435 | const Array &base_arr = PtrToArg<Array>::convert(p_args[0]); |
436 | const uint32_t type = PtrToArg<uint32_t>::convert(p_args[1]); |
437 | const StringName &class_name = PtrToArg<StringName>::convert(p_args[2]); |
438 | const Variant &script = PtrToArg<Variant>::convert(p_args[3]); |
439 | Array dst_arr = Array(base_arr, type, class_name, script); |
440 | |
441 | PtrConstruct<Array>::construct(dst_arr, base); |
442 | } |
443 | |
444 | static int get_argument_count() { |
445 | return 4; |
446 | } |
447 | |
448 | static Variant::Type get_argument_type(int p_arg) { |
449 | switch (p_arg) { |
450 | case 0: { |
451 | return Variant::ARRAY; |
452 | } break; |
453 | case 1: { |
454 | return Variant::INT; |
455 | } break; |
456 | case 2: { |
457 | return Variant::STRING_NAME; |
458 | } break; |
459 | case 3: { |
460 | return Variant::NIL; |
461 | } break; |
462 | default: { |
463 | return Variant::NIL; |
464 | } break; |
465 | } |
466 | } |
467 | |
468 | static Variant::Type get_base_type() { |
469 | return Variant::ARRAY; |
470 | } |
471 | }; |
472 | |
473 | template <class T> |
474 | class VariantConstructorToArray { |
475 | public: |
476 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
477 | if (p_args[0]->get_type() != GetTypeInfo<T>::VARIANT_TYPE) { |
478 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
479 | r_error.argument = 0; |
480 | r_error.expected = GetTypeInfo<T>::VARIANT_TYPE; |
481 | return; |
482 | } |
483 | |
484 | r_ret = Array(); |
485 | Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret); |
486 | const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]); |
487 | |
488 | int size = src_arr.size(); |
489 | dst_arr.resize(size); |
490 | for (int i = 0; i < size; i++) { |
491 | dst_arr[i] = src_arr[i]; |
492 | } |
493 | } |
494 | |
495 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
496 | *r_ret = Array(); |
497 | Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(r_ret); |
498 | const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]); |
499 | |
500 | int size = src_arr.size(); |
501 | dst_arr.resize(size); |
502 | for (int i = 0; i < size; i++) { |
503 | dst_arr[i] = src_arr[i]; |
504 | } |
505 | } |
506 | static void ptr_construct(void *base, const void **p_args) { |
507 | Array dst_arr; |
508 | T src_arr = PtrToArg<T>::convert(p_args[0]); |
509 | |
510 | int size = src_arr.size(); |
511 | dst_arr.resize(size); |
512 | for (int i = 0; i < size; i++) { |
513 | dst_arr[i] = src_arr[i]; |
514 | } |
515 | |
516 | PtrConstruct<Array>::construct(dst_arr, base); |
517 | } |
518 | |
519 | static int get_argument_count() { |
520 | return 1; |
521 | } |
522 | |
523 | static Variant::Type get_argument_type(int p_arg) { |
524 | return GetTypeInfo<T>::VARIANT_TYPE; |
525 | } |
526 | |
527 | static Variant::Type get_base_type() { |
528 | return Variant::ARRAY; |
529 | } |
530 | }; |
531 | |
532 | template <class T> |
533 | class VariantConstructorFromArray { |
534 | public: |
535 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
536 | if (p_args[0]->get_type() != Variant::ARRAY) { |
537 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
538 | r_error.argument = 0; |
539 | r_error.expected = Variant::ARRAY; |
540 | return; |
541 | } |
542 | |
543 | VariantTypeChanger<T>::change(&r_ret); |
544 | const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]); |
545 | T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret); |
546 | |
547 | int size = src_arr.size(); |
548 | dst_arr.resize(size); |
549 | for (int i = 0; i < size; i++) { |
550 | dst_arr.write[i] = src_arr[i]; |
551 | } |
552 | } |
553 | |
554 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
555 | VariantTypeChanger<T>::change(r_ret); |
556 | const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]); |
557 | T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(r_ret); |
558 | |
559 | int size = src_arr.size(); |
560 | dst_arr.resize(size); |
561 | for (int i = 0; i < size; i++) { |
562 | dst_arr.write[i] = src_arr[i]; |
563 | } |
564 | } |
565 | static void ptr_construct(void *base, const void **p_args) { |
566 | Array src_arr = PtrToArg<Array>::convert(p_args[0]); |
567 | T dst_arr; |
568 | |
569 | int size = src_arr.size(); |
570 | dst_arr.resize(size); |
571 | for (int i = 0; i < size; i++) { |
572 | dst_arr.write[i] = src_arr[i]; |
573 | } |
574 | |
575 | PtrConstruct<T>::construct(dst_arr, base); |
576 | } |
577 | |
578 | static int get_argument_count() { |
579 | return 1; |
580 | } |
581 | |
582 | static Variant::Type get_argument_type(int p_arg) { |
583 | return Variant::ARRAY; |
584 | } |
585 | |
586 | static Variant::Type get_base_type() { |
587 | return GetTypeInfo<T>::VARIANT_TYPE; |
588 | } |
589 | }; |
590 | |
591 | class VariantConstructorNil { |
592 | public: |
593 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
594 | if (p_args[0]->get_type() != Variant::NIL) { |
595 | r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; |
596 | r_error.argument = 0; |
597 | r_error.expected = Variant::NIL; |
598 | return; |
599 | } |
600 | |
601 | r_error.error = Callable::CallError::CALL_OK; |
602 | VariantInternal::clear(&r_ret); |
603 | } |
604 | |
605 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
606 | VariantInternal::clear(r_ret); |
607 | } |
608 | static void ptr_construct(void *base, const void **p_args) { |
609 | PtrConstruct<Variant>::construct(Variant(), base); |
610 | } |
611 | |
612 | static int get_argument_count() { |
613 | return 1; |
614 | } |
615 | |
616 | static Variant::Type get_argument_type(int p_arg) { |
617 | return Variant::NIL; |
618 | } |
619 | |
620 | static Variant::Type get_base_type() { |
621 | return Variant::NIL; |
622 | } |
623 | }; |
624 | |
625 | template <class T> |
626 | class VariantConstructNoArgs { |
627 | public: |
628 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
629 | VariantTypeChanger<T>::change_and_reset(&r_ret); |
630 | r_error.error = Callable::CallError::CALL_OK; |
631 | } |
632 | |
633 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
634 | VariantTypeChanger<T>::change_and_reset(r_ret); |
635 | } |
636 | static void ptr_construct(void *base, const void **p_args) { |
637 | PtrConstruct<T>::construct(T(), base); |
638 | } |
639 | |
640 | static int get_argument_count() { |
641 | return 0; |
642 | } |
643 | |
644 | static Variant::Type get_argument_type(int p_arg) { |
645 | return Variant::NIL; |
646 | } |
647 | |
648 | static Variant::Type get_base_type() { |
649 | return GetTypeInfo<T>::VARIANT_TYPE; |
650 | } |
651 | }; |
652 | |
653 | class VariantConstructNoArgsNil { |
654 | public: |
655 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
656 | VariantInternal::clear(&r_ret); |
657 | r_error.error = Callable::CallError::CALL_OK; |
658 | } |
659 | |
660 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
661 | VariantInternal::clear(r_ret); |
662 | } |
663 | static void ptr_construct(void *base, const void **p_args) { |
664 | ERR_FAIL_MSG("can't ptrcall nil constructor" ); |
665 | } |
666 | |
667 | static int get_argument_count() { |
668 | return 0; |
669 | } |
670 | |
671 | static Variant::Type get_argument_type(int p_arg) { |
672 | return Variant::NIL; |
673 | } |
674 | |
675 | static Variant::Type get_base_type() { |
676 | return Variant::NIL; |
677 | } |
678 | }; |
679 | |
680 | class VariantConstructNoArgsObject { |
681 | public: |
682 | static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { |
683 | r_ret = (Object *)nullptr; // Must construct a TYPE_OBJECT containing nullptr. |
684 | r_error.error = Callable::CallError::CALL_OK; |
685 | } |
686 | |
687 | static inline void validated_construct(Variant *r_ret, const Variant **p_args) { |
688 | *r_ret = (Object *)nullptr; // Must construct a TYPE_OBJECT containing nullptr. |
689 | } |
690 | static void ptr_construct(void *base, const void **p_args) { |
691 | PtrConstruct<Object *>::construct(nullptr, base); |
692 | } |
693 | |
694 | static int get_argument_count() { |
695 | return 0; |
696 | } |
697 | |
698 | static Variant::Type get_argument_type(int p_arg) { |
699 | return Variant::NIL; |
700 | } |
701 | |
702 | static Variant::Type get_base_type() { |
703 | return Variant::OBJECT; |
704 | } |
705 | }; |
706 | |
707 | #endif // VARIANT_CONSTRUCT_H |
708 | |