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