1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <marcin.kolny@gmail.com> wrote this file. As long as you retain this notice
5  * you can do whatever you want with this stuff. If we meet some day, and you
6  * think this stuff is worth it, you can buy me a beer in return. Marcin Kolny
7  * http://github.com/loganek/mkcreflect
8  * ----------------------------------------------------------------------------
9  */
10 #ifndef MKCREFLECT_H_
11 #define MKCREFLECT_H_
12 
13 #include <stddef.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 typedef enum
20 {
21     MKCREFLECT_TYPES_STRUCT = 1,
22     MKCREFLECT_TYPES_STRING = 2,
23     MKCREFLECT_TYPES_INTEGER = 3,
24     MKCREFLECT_TYPES_FLOAT = 4,
25     MKCREFLECT_TYPES_DOUBLE = 5,
26     MKCREFLECT_TYPES_POINTER = 6
27 } MKCREFLECT_Types;
28 
29 struct _MKCREFLECT_FieldInfo
30 {
31     const char* field_type;
32     const char* field_name;
33     size_t size;
34     size_t offset;
35     int is_signed;
36     int array_size;
37     MKCREFLECT_Types data_type;
38 };
39 
40 typedef struct _MKCREFLECT_FieldInfo MKCREFLECT_FieldInfo;
41 
42 struct _MKCREFLECT_TypeInfo
43 {
44     const char* name;
45     size_t fields_count;
46     size_t size;
47     size_t packed_size;
48     MKCREFLECT_FieldInfo* fields;
49 };
50 
51 typedef struct _MKCREFLECT_TypeInfo MKCREFLECT_TypeInfo;
52 
53 #define MKCREFLECT_EXPAND_(X) X
54 #define MKCREFLECT_EXPAND_VA_(...) __VA_ARGS__
55 #define MKCREFLECT_FOREACH_1_(FNC, USER_DATA, ARG) FNC(ARG, USER_DATA)
56 #define MKCREFLECT_FOREACH_2_(FNC, USER_DATA, ARG, ...) \
57     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_1_(FNC, USER_DATA, __VA_ARGS__))
58 #define MKCREFLECT_FOREACH_3_(FNC, USER_DATA, ARG, ...) \
59     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_2_(FNC, USER_DATA, __VA_ARGS__))
60 #define MKCREFLECT_FOREACH_4_(FNC, USER_DATA, ARG, ...) \
61     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_3_(FNC, USER_DATA, __VA_ARGS__))
62 #define MKCREFLECT_FOREACH_5_(FNC, USER_DATA, ARG, ...) \
63     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_4_(FNC, USER_DATA, __VA_ARGS__))
64 #define MKCREFLECT_FOREACH_6_(FNC, USER_DATA, ARG, ...) \
65     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_5_(FNC, USER_DATA, __VA_ARGS__))
66 #define MKCREFLECT_FOREACH_7_(FNC, USER_DATA, ARG, ...) \
67     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_6_(FNC, USER_DATA, __VA_ARGS__))
68 #define MKCREFLECT_FOREACH_8_(FNC, USER_DATA, ARG, ...) \
69     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_7_(FNC, USER_DATA, __VA_ARGS__))
70 #define MKCREFLECT_FOREACH_9_(FNC, USER_DATA, ARG, ...) \
71     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_8_(FNC, USER_DATA, __VA_ARGS__))
72 #define MKCREFLECT_FOREACH_10_(FNC, USER_DATA, ARG, ...) \
73     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_9_(FNC, USER_DATA, __VA_ARGS__))
74 #define MKCREFLECT_FOREACH_11_(FNC, USER_DATA, ARG, ...) \
75     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_10_(FNC, USER_DATA, __VA_ARGS__))
76 #define MKCREFLECT_FOREACH_12_(FNC, USER_DATA, ARG, ...) \
77     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_11_(FNC, USER_DATA, __VA_ARGS__))
78 #define MKCREFLECT_FOREACH_13_(FNC, USER_DATA, ARG, ...) \
79     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_12_(FNC, USER_DATA, __VA_ARGS__))
80 #define MKCREFLECT_FOREACH_14_(FNC, USER_DATA, ARG, ...) \
81     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_13_(FNC, USER_DATA, __VA_ARGS__))
82 #define MKCREFLECT_FOREACH_15_(FNC, USER_DATA, ARG, ...) \
83     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_14_(FNC, USER_DATA, __VA_ARGS__))
84 #define MKCREFLECT_FOREACH_16_(FNC, USER_DATA, ARG, ...) \
85     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_15_(FNC, USER_DATA, __VA_ARGS__))
86 #define MKCREFLECT_FOREACH_17_(FNC, USER_DATA, ARG, ...) \
87     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_16_(FNC, USER_DATA, __VA_ARGS__))
88 #define MKCREFLECT_FOREACH_18_(FNC, USER_DATA, ARG, ...) \
89     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_17_(FNC, USER_DATA, __VA_ARGS__))
90 #define MKCREFLECT_FOREACH_19_(FNC, USER_DATA, ARG, ...) \
91     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_18_(FNC, USER_DATA, __VA_ARGS__))
92 #define MKCREFLECT_FOREACH_20_(FNC, USER_DATA, ARG, ...) \
93     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_19_(FNC, USER_DATA, __VA_ARGS__))
94 #define MKCREFLECT_FOREACH_21_(FNC, USER_DATA, ARG, ...) \
95     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_20_(FNC, USER_DATA, __VA_ARGS__))
96 #define MKCREFLECT_FOREACH_22_(FNC, USER_DATA, ARG, ...) \
97     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_21_(FNC, USER_DATA, __VA_ARGS__))
98 #define MKCREFLECT_FOREACH_23_(FNC, USER_DATA, ARG, ...) \
99     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_22_(FNC, USER_DATA, __VA_ARGS__))
100 #define MKCREFLECT_FOREACH_24_(FNC, USER_DATA, ARG, ...) \
101     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_23_(FNC, USER_DATA, __VA_ARGS__))
102 #define MKCREFLECT_FOREACH_25_(FNC, USER_DATA, ARG, ...) \
103     FNC(ARG, USER_DATA) MKCREFLECT_EXPAND_(MKCREFLECT_FOREACH_24_(FNC, USER_DATA, __VA_ARGS__))
104 
105 #define MKCREFLECT_OVERRIDE_4(_1, _2, _3, _4, FNC, ...) FNC
106 #define MKCREFLECT_OVERRIDE_4_PLACEHOLDER 1, 2, 3, 4
107 #define MKCREFLECT_OVERRIDE_5(_1, _2, _3, _4, _5, FNC, ...) FNC
108 #define MKCREFLECT_OVERRIDE_5_PLACEHOLDER MKCREFLECT_OVERRIDE_4_PLACEHOLDER, 5
109 #define MKCREFLECT_OVERRIDE_14(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, FNC, ...) FNC
110 #define MKCREFLECT_OVERRIDE_14_PLACEHOLDER MKCREFLECT_OVERRIDE_5_PLACEHOLDER, 6, 7, 8, 9, 10, 11, 12, 13, 14
111 #define MKCREFLECT_OVERRIDE_20(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, FNC, ...) FNC
112 #define MKCREFLECT_OVERRIDE_20_PLACEHOLDER MKCREFLECT_OVERRIDE_14_PLACEHOLDER, 15, 16, 17, 18, 19, 20
113 #define MKCREFLECT_OVERRIDE_25(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, FNC, ...) FNC
114 #define MKCREFLECT_OVERRIDE_25_PLACEHOLDER MKCREFLECT_OVERRIDE_20_PLACEHOLDER, 21, 22, 23, 24, 25
115 
116 #define MKCREFLECT_FOREACH(FNC, USER_DATA, ...) \
117     MKCREFLECT_EXPAND_(MKCREFLECT_OVERRIDE_25( __VA_ARGS__,	\
118     MKCREFLECT_FOREACH_25_, \
119     MKCREFLECT_FOREACH_24_, \
120     MKCREFLECT_FOREACH_23_, \
121     MKCREFLECT_FOREACH_22_, \
122     MKCREFLECT_FOREACH_21_, \
123     MKCREFLECT_FOREACH_20_, \
124     MKCREFLECT_FOREACH_19_, \
125     MKCREFLECT_FOREACH_18_, \
126     MKCREFLECT_FOREACH_17_, \
127     MKCREFLECT_FOREACH_16_, \
128     MKCREFLECT_FOREACH_15_, \
129     MKCREFLECT_FOREACH_14_, \
130     MKCREFLECT_FOREACH_13_, \
131     MKCREFLECT_FOREACH_12_, \
132     MKCREFLECT_FOREACH_11_, \
133     MKCREFLECT_FOREACH_10_, \
134     MKCREFLECT_FOREACH_9_, \
135     MKCREFLECT_FOREACH_8_, \
136     MKCREFLECT_FOREACH_7_, \
137     MKCREFLECT_FOREACH_6_, \
138     MKCREFLECT_FOREACH_5_, \
139     MKCREFLECT_FOREACH_4_, \
140     MKCREFLECT_FOREACH_3_, \
141     MKCREFLECT_FOREACH_2_, \
142     MKCREFLECT_FOREACH_1_)(FNC, USER_DATA, __VA_ARGS__))
143 
144 #define MKCREFLECT_DECLARE_SIMPLE_FIELD_(IGNORE, TYPE, FIELD_NAME) \
145     TYPE FIELD_NAME;
146 #define MKCREFLECT_DECLARE_ARRAY_FIELD_(IGNORE, TYPE, FIELD_NAME, ARRAY_SIZE) \
147     TYPE FIELD_NAME[ARRAY_SIZE];
148 
149 #define MKCREFLECT_DECLARE_FIELD_(...) MKCREFLECT_EXPAND_(MKCREFLECT_OVERRIDE_4( \
150     __VA_ARGS__, \
151     MKCREFLECT_DECLARE_ARRAY_FIELD_, \
152     MKCREFLECT_DECLARE_SIMPLE_FIELD_, \
153     MKCREFLECT_OVERRIDE_4_PLACEHOLDER)(__VA_ARGS__))
154 
155 #define MKCREFLECT_DECLARE_FIELD(X, USER_DATA) MKCREFLECT_DECLARE_FIELD_ X
156 
157 #define MKCREFLECT_SIZEOF_(IGNORE, C_TYPE, ...) +sizeof(C_TYPE)
158 #define MKCREFLECT_SIZEOF(X, USER_DATA) MKCREFLECT_SIZEOF_ X
159 
160 #define MKCREFLECT_SUM(...) +1
161 
162 #define MKCREFLECT_IS_TYPE_SIGNED_(C_TYPE) (C_TYPE)-1 < (C_TYPE)1
163 #define MKCREFLECT_IS_SIGNED_STRUCT(C_TYPE) 0
164 #define MKCREFLECT_IS_SIGNED_STRING(C_TYPE) MKCREFLECT_IS_TYPE_SIGNED_(C_TYPE)
165 #define MKCREFLECT_IS_SIGNED_INTEGER(C_TYPE) MKCREFLECT_IS_TYPE_SIGNED_(C_TYPE)
166 #define MKCREFLECT_IS_SIGNED_FLOAT(C_TYPE) MKCREFLECT_IS_TYPE_SIGNED_(C_TYPE)
167 #define MKCREFLECT_IS_SIGNED_DOUBLE(C_TYPE) MKCREFLECT_IS_TYPE_SIGNED_(C_TYPE)
168 #define MKCREFLECT_IS_SIGNED_POINTER(C_TYPE) 0
169 
170 #define MKCREFLECT_IS_SIGNED_(DATA_TYPE, CTYPE) MKCREFLECT_IS_SIGNED_##DATA_TYPE(CTYPE)
171 
172 #define MKCREFLECT_ARRAY_FIELD_INFO_(TYPE_NAME, DATA_TYPE, C_TYPE, FIELD_NAME, ARRAY_SIZE) \
173     #C_TYPE, #FIELD_NAME, sizeof(C_TYPE) * ARRAY_SIZE, offsetof(TYPE_NAME, FIELD_NAME), \
174     MKCREFLECT_IS_SIGNED_(DATA_TYPE, C_TYPE), ARRAY_SIZE, MKCREFLECT_TYPES_##DATA_TYPE
175 
176 #define MKCREFLECT_SIMPLE_FIELD_INFO_(TYPE_NAME, DATA_TYPE, C_TYPE, FIELD_NAME) \
177     #C_TYPE, #FIELD_NAME, sizeof(C_TYPE), offsetof(TYPE_NAME, FIELD_NAME), \
178     MKCREFLECT_IS_SIGNED_(DATA_TYPE, C_TYPE), -1, MKCREFLECT_TYPES_##DATA_TYPE
179 
180 #define MKCREFLECT_FIELD_INFO_(...) \
181 { \
182     MKCREFLECT_EXPAND_(MKCREFLECT_OVERRIDE_5( \
183     __VA_ARGS__, \
184     MKCREFLECT_ARRAY_FIELD_INFO_, \
185     MKCREFLECT_SIMPLE_FIELD_INFO_, \
186     MKCREFLECT_OVERRIDE_5_PLACEHOLDER)(__VA_ARGS__)) \
187 },
188 
189 #define MKCREFLECT_FIELD_INFO(X, USER_DATA) \
190     MKCREFLECT_FIELD_INFO_(USER_DATA, MKCREFLECT_EXPAND_VA_ X)
191 
192 #ifdef MKCREFLECT_IMPL
193 
194 #define MKCREFLECT_DEFINE_GET_METHOD(TYPE_NAME, ...) \
195     MKCREFLECT_TypeInfo* mkcreflect_get_##TYPE_NAME##_type_info(void) \
196     { \
197         static MKCREFLECT_FieldInfo fields_info[MKCREFLECT_FOREACH(MKCREFLECT_SUM, 0, __VA_ARGS__)] = \
198         { \
199             MKCREFLECT_FOREACH(MKCREFLECT_FIELD_INFO, TYPE_NAME, __VA_ARGS__) \
200         }; \
201         static MKCREFLECT_TypeInfo type_info = \
202         { \
203             #TYPE_NAME, \
204             MKCREFLECT_FOREACH(MKCREFLECT_SUM, 0, __VA_ARGS__), \
205             sizeof(TYPE_NAME), \
206             MKCREFLECT_FOREACH(MKCREFLECT_SIZEOF, 0, __VA_ARGS__), \
207             fields_info \
208         }; \
209         return &type_info; \
210     }
211 
212 #else
213 
214 #define MKCREFLECT_DEFINE_GET_METHOD(TYPE_NAME, ...)
215 
216 #endif /* MKCREFLECT_IMPL */
217 
218 #define MKCREFLECT_DEFINE_STRUCT(TYPE_NAME, ...) \
219     typedef struct \
220     { \
221         MKCREFLECT_FOREACH(MKCREFLECT_DECLARE_FIELD, 0, __VA_ARGS__) \
222     } TYPE_NAME; \
223     MKCREFLECT_TypeInfo* mkcreflect_get_##TYPE_NAME##_type_info(void); \
224     MKCREFLECT_DEFINE_GET_METHOD(TYPE_NAME, __VA_ARGS__) \
225 
226 #ifdef __cplusplus
227 }
228 #endif
229 
230 #endif /* MKCREFLECT_H_ */
231