Merge pull request #204 from jhasse/android-byte-order
[openal-soft.git] / Alc / polymorphism.h
blobfa31fad255dec07b56985d1dac4e63d7c5ba25be
1 #ifndef POLYMORPHISM_H
2 #define POLYMORPHISM_H
4 /* Macros to declare inheriting types, and to (down-)cast and up-cast. */
5 #define DERIVE_FROM_TYPE(t) t t##_parent
6 #define STATIC_CAST(to, obj) (&(obj)->to##_parent)
7 #ifdef __GNUC__
8 #define STATIC_UPCAST(to, from, obj) __extension__({ \
9 static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))), \
10 "Invalid upcast object from type"); \
11 (to*)((char*)(obj) - offsetof(to, from##_parent)); \
13 #else
14 #define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent)))
15 #endif
17 /* Defines method forwards, which call the given parent's (T2's) implementation. */
18 #define DECLARE_FORWARD(T1, T2, rettype, func) \
19 rettype T1##_##func(T1 *obj) \
20 { return T2##_##func(STATIC_CAST(T2, obj)); }
22 #define DECLARE_FORWARD1(T1, T2, rettype, func, argtype1) \
23 rettype T1##_##func(T1 *obj, argtype1 a) \
24 { return T2##_##func(STATIC_CAST(T2, obj), a); }
26 #define DECLARE_FORWARD2(T1, T2, rettype, func, argtype1, argtype2) \
27 rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b) \
28 { return T2##_##func(STATIC_CAST(T2, obj), a, b); }
30 #define DECLARE_FORWARD3(T1, T2, rettype, func, argtype1, argtype2, argtype3) \
31 rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b, argtype3 c) \
32 { return T2##_##func(STATIC_CAST(T2, obj), a, b, c); }
34 /* Defines method thunks, functions that call to the child's method. */
35 #define DECLARE_THUNK(T1, T2, rettype, func) \
36 static rettype T1##_##T2##_##func(T2 *obj) \
37 { return T1##_##func(STATIC_UPCAST(T1, T2, obj)); }
39 #define DECLARE_THUNK1(T1, T2, rettype, func, argtype1) \
40 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a) \
41 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a); }
43 #define DECLARE_THUNK2(T1, T2, rettype, func, argtype1, argtype2) \
44 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b) \
45 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b); }
47 #define DECLARE_THUNK3(T1, T2, rettype, func, argtype1, argtype2, argtype3) \
48 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \
49 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); }
51 #define DECLARE_THUNK4(T1, T2, rettype, func, argtype1, argtype2, argtype3, argtype4) \
52 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c, argtype4 d) \
53 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c, d); }
55 /* Defines the default functions used to (de)allocate a polymorphic object. */
56 #define DECLARE_DEFAULT_ALLOCATORS(T) \
57 static void* T##_New(size_t size) { return al_malloc(16, size); } \
58 static void T##_Delete(void *ptr) { al_free(ptr); }
61 /* Helper to extract an argument list for virtual method calls. */
62 #define EXTRACT_VCALL_ARGS(...) __VA_ARGS__))
64 /* Call a "virtual" method on an object, with arguments. */
65 #define V(obj, func) ((obj)->vtbl->func((obj), EXTRACT_VCALL_ARGS
66 /* Call a "virtual" method on an object, with no arguments. */
67 #define V0(obj, func) ((obj)->vtbl->func((obj) EXTRACT_VCALL_ARGS
70 /* Helper to extract an argument list for NEW_OBJ calls. */
71 #define EXTRACT_NEW_ARGS(...) __VA_ARGS__); \
72 } \
73 } while(0)
75 /* Allocate and construct an object, with arguments. */
76 #define NEW_OBJ(_res, T) do { \
77 _res = T##_New(sizeof(T)); \
78 if(_res) \
79 { \
80 memset(_res, 0, sizeof(T)); \
81 T##_Construct(_res, EXTRACT_NEW_ARGS
82 /* Allocate and construct an object, with no arguments. */
83 #define NEW_OBJ0(_res, T) do { \
84 _res = T##_New(sizeof(T)); \
85 if(_res) \
86 { \
87 memset(_res, 0, sizeof(T)); \
88 T##_Construct(_res EXTRACT_NEW_ARGS
90 /* Destructs and deallocate an object. */
91 #define DELETE_OBJ(obj) do { \
92 if((obj) != NULL) \
93 { \
94 V0((obj),Destruct)(); \
95 V0((obj),Delete)(); \
96 } \
97 } while(0)
100 /* Helper to get a type's vtable thunk for a child type. */
101 #define GET_VTABLE2(T1, T2) (&(T1##_##T2##_vtable))
102 /* Helper to set an object's vtable thunk for a child type. Used when constructing an object. */
103 #define SET_VTABLE2(T1, T2, obj) (STATIC_CAST(T2, obj)->vtbl = GET_VTABLE2(T1, T2))
105 #endif /* POLYMORPHISM_H */