1/**************************************************************************/
2/* method_ptrcall.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 METHOD_PTRCALL_H
32#define METHOD_PTRCALL_H
33
34#include "core/object/object_id.h"
35#include "core/typedefs.h"
36#include "core/variant/variant.h"
37
38template <class T>
39struct PtrToArg {};
40
41#define MAKE_PTRARG(m_type) \
42 template <> \
43 struct PtrToArg<m_type> { \
44 _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
45 return *reinterpret_cast<const m_type *>(p_ptr); \
46 } \
47 typedef m_type EncodeT; \
48 _FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
49 *((m_type *)p_ptr) = p_val; \
50 } \
51 }; \
52 template <> \
53 struct PtrToArg<const m_type &> { \
54 _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
55 return *reinterpret_cast<const m_type *>(p_ptr); \
56 } \
57 typedef m_type EncodeT; \
58 _FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
59 *((m_type *)p_ptr) = p_val; \
60 } \
61 }
62
63#define MAKE_PTRARGCONV(m_type, m_conv) \
64 template <> \
65 struct PtrToArg<m_type> { \
66 _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
67 return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
68 } \
69 typedef m_conv EncodeT; \
70 _FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
71 *((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
72 } \
73 }; \
74 template <> \
75 struct PtrToArg<const m_type &> { \
76 _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
77 return static_cast<m_type>(*reinterpret_cast<const m_conv *>(p_ptr)); \
78 } \
79 typedef m_conv EncodeT; \
80 _FORCE_INLINE_ static void encode(m_type p_val, void *p_ptr) { \
81 *((m_conv *)p_ptr) = static_cast<m_conv>(p_val); \
82 } \
83 }
84
85#define MAKE_PTRARG_BY_REFERENCE(m_type) \
86 template <> \
87 struct PtrToArg<m_type> { \
88 _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
89 return *reinterpret_cast<const m_type *>(p_ptr); \
90 } \
91 typedef m_type EncodeT; \
92 _FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
93 *((m_type *)p_ptr) = p_val; \
94 } \
95 }; \
96 template <> \
97 struct PtrToArg<const m_type &> { \
98 _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
99 return *reinterpret_cast<const m_type *>(p_ptr); \
100 } \
101 typedef m_type EncodeT; \
102 _FORCE_INLINE_ static void encode(const m_type &p_val, void *p_ptr) { \
103 *((m_type *)p_ptr) = p_val; \
104 } \
105 }
106
107MAKE_PTRARGCONV(bool, uint8_t);
108// Integer types.
109MAKE_PTRARGCONV(uint8_t, int64_t);
110MAKE_PTRARGCONV(int8_t, int64_t);
111MAKE_PTRARGCONV(uint16_t, int64_t);
112MAKE_PTRARGCONV(int16_t, int64_t);
113MAKE_PTRARGCONV(uint32_t, int64_t);
114MAKE_PTRARGCONV(int32_t, int64_t);
115MAKE_PTRARG(int64_t);
116MAKE_PTRARG(uint64_t);
117// Float types
118MAKE_PTRARGCONV(float, double);
119MAKE_PTRARG(double);
120
121MAKE_PTRARG(String);
122MAKE_PTRARG(Vector2);
123MAKE_PTRARG(Vector2i);
124MAKE_PTRARG(Rect2);
125MAKE_PTRARG(Rect2i);
126MAKE_PTRARG_BY_REFERENCE(Vector3);
127MAKE_PTRARG_BY_REFERENCE(Vector3i);
128MAKE_PTRARG_BY_REFERENCE(Vector4);
129MAKE_PTRARG_BY_REFERENCE(Vector4i);
130MAKE_PTRARG(Transform2D);
131MAKE_PTRARG(Projection);
132MAKE_PTRARG_BY_REFERENCE(Plane);
133MAKE_PTRARG(Quaternion);
134MAKE_PTRARG_BY_REFERENCE(AABB);
135MAKE_PTRARG_BY_REFERENCE(Basis);
136MAKE_PTRARG_BY_REFERENCE(Transform3D);
137MAKE_PTRARG_BY_REFERENCE(Color);
138MAKE_PTRARG(StringName);
139MAKE_PTRARG(NodePath);
140MAKE_PTRARG(RID);
141// Object doesn't need this.
142MAKE_PTRARG(Callable);
143MAKE_PTRARG(Signal);
144MAKE_PTRARG(Dictionary);
145MAKE_PTRARG(Array);
146MAKE_PTRARG(PackedByteArray);
147MAKE_PTRARG(PackedInt32Array);
148MAKE_PTRARG(PackedInt64Array);
149MAKE_PTRARG(PackedFloat32Array);
150MAKE_PTRARG(PackedFloat64Array);
151MAKE_PTRARG(PackedStringArray);
152MAKE_PTRARG(PackedVector2Array);
153MAKE_PTRARG(PackedVector3Array);
154MAKE_PTRARG(PackedColorArray);
155MAKE_PTRARG_BY_REFERENCE(Variant);
156
157// This is for Object.
158
159template <class T>
160struct PtrToArg<T *> {
161 _FORCE_INLINE_ static T *convert(const void *p_ptr) {
162 if (p_ptr == nullptr) {
163 return nullptr;
164 }
165 return const_cast<T *>(*reinterpret_cast<T *const *>(p_ptr));
166 }
167 typedef Object *EncodeT;
168 _FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
169 *((T **)p_ptr) = p_var;
170 }
171};
172
173template <class T>
174struct PtrToArg<const T *> {
175 _FORCE_INLINE_ static const T *convert(const void *p_ptr) {
176 if (p_ptr == nullptr) {
177 return nullptr;
178 }
179 return *reinterpret_cast<T *const *>(p_ptr);
180 }
181 typedef const Object *EncodeT;
182 _FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
183 *((T **)p_ptr) = p_var;
184 }
185};
186
187// This is for ObjectID.
188
189template <>
190struct PtrToArg<ObjectID> {
191 _FORCE_INLINE_ static const ObjectID convert(const void *p_ptr) {
192 return ObjectID(*reinterpret_cast<const uint64_t *>(p_ptr));
193 }
194 typedef uint64_t EncodeT;
195 _FORCE_INLINE_ static void encode(const ObjectID &p_val, void *p_ptr) {
196 *((uint64_t *)p_ptr) = p_val;
197 }
198};
199
200// This is for the special cases used by Variant.
201
202// No EncodeT because direct pointer conversion not possible.
203#define MAKE_VECARG(m_type) \
204 template <> \
205 struct PtrToArg<Vector<m_type>> { \
206 _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
207 const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \
208 Vector<m_type> ret; \
209 int len = dvs->size(); \
210 ret.resize(len); \
211 { \
212 const m_type *r = dvs->ptr(); \
213 for (int i = 0; i < len; i++) { \
214 ret.write[i] = r[i]; \
215 } \
216 } \
217 return ret; \
218 } \
219 _FORCE_INLINE_ static void encode(Vector<m_type> p_vec, void *p_ptr) { \
220 Vector<m_type> *dv = reinterpret_cast<Vector<m_type> *>(p_ptr); \
221 int len = p_vec.size(); \
222 dv->resize(len); \
223 { \
224 m_type *w = dv->ptrw(); \
225 for (int i = 0; i < len; i++) { \
226 w[i] = p_vec[i]; \
227 } \
228 } \
229 } \
230 }; \
231 template <> \
232 struct PtrToArg<const Vector<m_type> &> { \
233 _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
234 const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \
235 Vector<m_type> ret; \
236 int len = dvs->size(); \
237 ret.resize(len); \
238 { \
239 const m_type *r = dvs->ptr(); \
240 for (int i = 0; i < len; i++) { \
241 ret.write[i] = r[i]; \
242 } \
243 } \
244 return ret; \
245 } \
246 }
247
248// No EncodeT because direct pointer conversion not possible.
249#define MAKE_VECARG_ALT(m_type, m_type_alt) \
250 template <> \
251 struct PtrToArg<Vector<m_type_alt>> { \
252 _FORCE_INLINE_ static Vector<m_type_alt> convert(const void *p_ptr) { \
253 const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \
254 Vector<m_type_alt> ret; \
255 int len = dvs->size(); \
256 ret.resize(len); \
257 { \
258 const m_type *r = dvs->ptr(); \
259 for (int i = 0; i < len; i++) { \
260 ret.write[i] = r[i]; \
261 } \
262 } \
263 return ret; \
264 } \
265 _FORCE_INLINE_ static void encode(Vector<m_type_alt> p_vec, void *p_ptr) { \
266 Vector<m_type> *dv = reinterpret_cast<Vector<m_type> *>(p_ptr); \
267 int len = p_vec.size(); \
268 dv->resize(len); \
269 { \
270 m_type *w = dv->ptrw(); \
271 for (int i = 0; i < len; i++) { \
272 w[i] = p_vec[i]; \
273 } \
274 } \
275 } \
276 }; \
277 template <> \
278 struct PtrToArg<const Vector<m_type_alt> &> { \
279 _FORCE_INLINE_ static Vector<m_type_alt> convert(const void *p_ptr) { \
280 const Vector<m_type> *dvs = reinterpret_cast<const Vector<m_type> *>(p_ptr); \
281 Vector<m_type_alt> ret; \
282 int len = dvs->size(); \
283 ret.resize(len); \
284 { \
285 const m_type *r = dvs->ptr(); \
286 for (int i = 0; i < len; i++) { \
287 ret.write[i] = r[i]; \
288 } \
289 } \
290 return ret; \
291 } \
292 }
293
294MAKE_VECARG_ALT(String, StringName);
295
296// For stuff that gets converted to Array vectors.
297
298// No EncodeT because direct pointer conversion not possible.
299#define MAKE_VECARR(m_type) \
300 template <> \
301 struct PtrToArg<Vector<m_type>> { \
302 _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
303 const Array *arr = reinterpret_cast<const Array *>(p_ptr); \
304 Vector<m_type> ret; \
305 int len = arr->size(); \
306 ret.resize(len); \
307 for (int i = 0; i < len; i++) { \
308 ret.write[i] = (*arr)[i]; \
309 } \
310 return ret; \
311 } \
312 _FORCE_INLINE_ static void encode(Vector<m_type> p_vec, void *p_ptr) { \
313 Array *arr = reinterpret_cast<Array *>(p_ptr); \
314 int len = p_vec.size(); \
315 arr->resize(len); \
316 for (int i = 0; i < len; i++) { \
317 (*arr)[i] = p_vec[i]; \
318 } \
319 } \
320 }; \
321 template <> \
322 struct PtrToArg<const Vector<m_type> &> { \
323 _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
324 const Array *arr = reinterpret_cast<const Array *>(p_ptr); \
325 Vector<m_type> ret; \
326 int len = arr->size(); \
327 ret.resize(len); \
328 for (int i = 0; i < len; i++) { \
329 ret.write[i] = (*arr)[i]; \
330 } \
331 return ret; \
332 } \
333 }
334
335MAKE_VECARR(Variant);
336MAKE_VECARR(RID);
337MAKE_VECARR(Plane);
338
339// No EncodeT because direct pointer conversion not possible.
340#define MAKE_DVECARR(m_type) \
341 template <> \
342 struct PtrToArg<Vector<m_type>> { \
343 _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
344 const Array *arr = reinterpret_cast<const Array *>(p_ptr); \
345 Vector<m_type> ret; \
346 int len = arr->size(); \
347 ret.resize(len); \
348 { \
349 m_type *w = ret.ptrw(); \
350 for (int i = 0; i < len; i++) { \
351 w[i] = (*arr)[i]; \
352 } \
353 } \
354 return ret; \
355 } \
356 _FORCE_INLINE_ static void encode(Vector<m_type> p_vec, void *p_ptr) { \
357 Array *arr = reinterpret_cast<Array *>(p_ptr); \
358 int len = p_vec.size(); \
359 arr->resize(len); \
360 { \
361 const m_type *r = p_vec.ptr(); \
362 for (int i = 0; i < len; i++) { \
363 (*arr)[i] = r[i]; \
364 } \
365 } \
366 } \
367 }; \
368 template <> \
369 struct PtrToArg<const Vector<m_type> &> { \
370 _FORCE_INLINE_ static Vector<m_type> convert(const void *p_ptr) { \
371 const Array *arr = reinterpret_cast<const Array *>(p_ptr); \
372 Vector<m_type> ret; \
373 int len = arr->size(); \
374 ret.resize(len); \
375 { \
376 m_type *w = ret.ptrw(); \
377 for (int i = 0; i < len; i++) { \
378 w[i] = (*arr)[i]; \
379 } \
380 } \
381 return ret; \
382 } \
383 }
384
385// Special case for IPAddress.
386
387// No EncodeT because direct pointer conversion not possible.
388#define MAKE_STRINGCONV_BY_REFERENCE(m_type) \
389 template <> \
390 struct PtrToArg<m_type> { \
391 _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
392 m_type s = *reinterpret_cast<const String *>(p_ptr); \
393 return s; \
394 } \
395 _FORCE_INLINE_ static void encode(const m_type &p_vec, void *p_ptr) { \
396 String *arr = reinterpret_cast<String *>(p_ptr); \
397 *arr = p_vec; \
398 } \
399 }; \
400 \
401 template <> \
402 struct PtrToArg<const m_type &> { \
403 _FORCE_INLINE_ static m_type convert(const void *p_ptr) { \
404 m_type s = *reinterpret_cast<const String *>(p_ptr); \
405 return s; \
406 } \
407 }
408
409MAKE_STRINGCONV_BY_REFERENCE(IPAddress);
410
411// No EncodeT because direct pointer conversion not possible.
412template <>
413struct PtrToArg<Vector<Face3>> {
414 _FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) {
415 const Vector<Vector3> *dvs = reinterpret_cast<const Vector<Vector3> *>(p_ptr);
416 Vector<Face3> ret;
417 int len = dvs->size() / 3;
418 ret.resize(len);
419 {
420 const Vector3 *r = dvs->ptr();
421 Face3 *w = ret.ptrw();
422 for (int i = 0; i < len; i++) {
423 w[i].vertex[0] = r[i * 3 + 0];
424 w[i].vertex[1] = r[i * 3 + 1];
425 w[i].vertex[2] = r[i * 3 + 2];
426 }
427 }
428 return ret;
429 }
430 _FORCE_INLINE_ static void encode(Vector<Face3> p_vec, void *p_ptr) {
431 Vector<Vector3> *arr = reinterpret_cast<Vector<Vector3> *>(p_ptr);
432 int len = p_vec.size();
433 arr->resize(len * 3);
434 {
435 const Face3 *r = p_vec.ptr();
436 Vector3 *w = arr->ptrw();
437 for (int i = 0; i < len; i++) {
438 w[i * 3 + 0] = r[i].vertex[0];
439 w[i * 3 + 1] = r[i].vertex[1];
440 w[i * 3 + 2] = r[i].vertex[2];
441 }
442 }
443 }
444};
445
446// No EncodeT because direct pointer conversion not possible.
447template <>
448struct PtrToArg<const Vector<Face3> &> {
449 _FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) {
450 const Vector<Vector3> *dvs = reinterpret_cast<const Vector<Vector3> *>(p_ptr);
451 Vector<Face3> ret;
452 int len = dvs->size() / 3;
453 ret.resize(len);
454 {
455 const Vector3 *r = dvs->ptr();
456 Face3 *w = ret.ptrw();
457 for (int i = 0; i < len; i++) {
458 w[i].vertex[0] = r[i * 3 + 0];
459 w[i].vertex[1] = r[i * 3 + 1];
460 w[i].vertex[2] = r[i * 3 + 2];
461 }
462 }
463 return ret;
464 }
465};
466
467#endif // METHOD_PTRCALL_H
468