1 
2 #define FE_0(WHAT, _)
3 #define FE_1(WHAT, X, _) WHAT(X,1)
4 #define FE_2(WHAT, X, ...) WHAT(X,2)FE_1(WHAT, __VA_ARGS__)
5 #define FE_3(WHAT, X, ...) WHAT(X,3)FE_2(WHAT, __VA_ARGS__)
6 #define FE_4(WHAT, X, ...) WHAT(X,4)FE_3(WHAT, __VA_ARGS__)
7 #define FE_5(WHAT, X, ...) WHAT(X,5)FE_4(WHAT, __VA_ARGS__)
8 #define FE_6(WHAT, X, ...) WHAT(X,6)FE_5(WHAT, __VA_ARGS__)
9 #define FE_7(WHAT, X, ...) WHAT(X,7)FE_6(WHAT, __VA_ARGS__)
10 #define FE_8(WHAT, X, ...) WHAT(X,8)FE_7(WHAT, __VA_ARGS__)
11 #define FE_9(WHAT, X, ...) WHAT(X,9)FE_8(WHAT, __VA_ARGS__)
12 
13 #define GET_MACRO(_0_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME
14 #define FOR_EACH(action,...) \
15   GET_MACRO(__VA_ARGS__,FE_9,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)
16 #define ARG_AND_NAME(X, I) ,X _##I
17 #define NAME_ONLY(X, I) , _##I
18 #define ARG_ONLY(X, I) ,X
19 #define ARGS_AND_NAMES(...) FOR_EACH(ARG_AND_NAME,__VA_ARGS__)
20 #define NAMES_ONLY(...) FOR_EACH(NAME_ONLY,__VA_ARGS__)
21 #define ARGS_ONLY(...) FOR_EACH(ARG_ONLY,__VA_ARGS__)
22 
23 #define HXT_FUNCTION_MEMBER_ASSIGN(derivedType,member, ...) \
24 {\
25   HXTStatus(*castcheck)(HXT##derivedType* ARGS_ONLY(__VA_ARGS__)) = hxt##derivedType##member;\
26   c->member = (HXTStatus(*)(void* ARGS_ONLY(__VA_ARGS__)))castcheck;\
27 }
28 
29 #define HXT_FUNCTION_MEMBER_DECLARE(derivedType, member, ...) \
30   HXTStatus(*member)(void* ARGS_ONLY(__VA_ARGS__))
31 
32 #define HXT_FUNCTION_MEMBER_IMPLEMENT(derivedType, member, ...) \
33 HXTStatus hxt##derivedType##member(HXT##derivedType *c ARGS_AND_NAMES(__VA_ARGS__)) { \
34   return c->c->member(c->data NAMES_ONLY(__VA_ARGS__)); \
35 }
36 
37 #define HXT_DECLARE_DERIVED_CLASS(baseType, derivedType) \
38 static HXT##baseType##Class *hxt##derivedType##Class;\
39 HXTStatus hxt##derivedType##Register() \
40 { \
41   HXT_CHECK(hxtMalloc(&hxt##derivedType##Class, sizeof(HXT##baseType##Class))); \
42   HXT##baseType##Class *c = hxt##derivedType##Class; \
43   HXT##baseType##_MEMBERS(HXT_FUNCTION_MEMBER_ASSIGN, derivedType) \
44   HXTStatus(*castcheck)(HXT##derivedType**) = hxt##derivedType##Delete; \
45   c->Delete =  (HXTStatus(*)(void**))castcheck; \
46   return HXT_STATUS_OK;\
47 } \
48 \
49 HXTStatus hxt##baseType##Get##derivedType(HXT##baseType *b, HXT##derivedType **d) { \
50   if (b->c == hxt##derivedType##Class) { \
51     *d = b->data; \
52   } \
53   else { \
54     *d = NULL; \
55   } \
56   return HXT_STATUS_OK; \
57 }
58 
59 #define HXT_DECLARE_INTERFACE(baseType) \
60 typedef struct { \
61   HXT##baseType##_MEMBERS(HXT_FUNCTION_MEMBER_DECLARE,) \
62   HXTStatus (*Delete)(void **); \
63 } HXT##baseType##Class; \
64 struct HXT##baseType##Struct { \
65   HXT##baseType##Class *c;\
66   void *data; \
67 }; \
68 HXT##baseType##_MEMBERS(HXT_FUNCTION_MEMBER_IMPLEMENT,baseType) \
69 HXTStatus hxt##baseType##Delete(HXT##baseType **pp) {\
70   HXT_CHECK((*pp)->c->Delete(&(*pp)->data));\
71   HXT_CHECK(hxtFree(pp));\
72   return HXT_STATUS_OK;\
73 } \
74 HXTStatus hxt##baseType##Create(HXT##baseType **pp, HXT##baseType##Class *c, void *data) {\
75   HXT_CHECK(hxtMalloc(pp, sizeof(HXT##baseType))); \
76   (*pp)->c = c; \
77   (*pp)->data = data; \
78   return HXT_STATUS_OK;\
79 }
80