Skip to content

Commit 5aca0cc

Browse files
authored
Merge pull request #4406 from chdoc/data-funcs
remove eldritch preprocessor code from `DataFuncs.h`
2 parents f7916c0 + 999798f commit 5aca0cc

File tree

1 file changed

+76
-204
lines changed

1 file changed

+76
-204
lines changed

library/include/DataFuncs.h

Lines changed: 76 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -28,242 +28,114 @@ distribution.
2828
#include <sstream>
2929
#include <vector>
3030
#include <map>
31+
#include <type_traits>
3132

3233
#include "DataIdentity.h"
3334
#include "LuaWrapper.h"
3435

35-
namespace DFHack {
36-
class color_ostream;
37-
}
38-
3936
namespace df {
40-
// A very simple and stupid implementation of some stuff from boost
41-
template<class U, class V> struct is_same_type { static const bool value = false; };
42-
template<class T> struct is_same_type<T,T> { static const bool value = true; };
43-
template<class T> struct return_type {};
44-
45-
/*
46-
* Workaround for a msvc bug suggested by:
47-
*
48-
* http://stackoverflow.com/questions/5110529/class-template-partial-specialization-parametrized-on-member-function-return-typ
49-
*/
50-
template<class T, bool isvoid = is_same_type<typename return_type<T>::type,void>::value>
51-
struct function_wrapper {};
52-
5337
class DFHACK_EXPORT cur_lua_ostream_argument {
5438
DFHack::color_ostream *out;
5539
public:
5640
cur_lua_ostream_argument(lua_State *state);
5741
operator DFHack::color_ostream& () { return *out; }
5842
};
5943

60-
/*
61-
* Since templates can't match variable arg count,
62-
* a separate specialization is needed for every
63-
* supported count value...
64-
*
65-
* The FW_TARGS ugliness is needed because of
66-
* commas not wrapped in ()
67-
*/
68-
69-
#define INVOKE_VOID(call) \
70-
call; lua_pushnil(state);
71-
#define INVOKE_RV(call) \
72-
RT rv = call; df::identity_traits<RT>::get()->lua_read(state, UPVAL_METHOD_NAME, &rv);
73-
#define LOAD_CLASS() \
74-
CT *self = (CT*)DFHack::LuaWrapper::get_object_addr(state, base++, UPVAL_METHOD_NAME, "invoke");
75-
#define LOAD_ARG(type) \
76-
type v##type; df::identity_traits<type>::get()->lua_write(state, UPVAL_METHOD_NAME, &v##type, base++);
77-
#define OSTREAM_ARG DFHack::color_ostream&
78-
#define LOAD_OSTREAM(name) \
79-
cur_lua_ostream_argument name(state);
44+
template<class T> struct return_type {};
8045

81-
#define INSTANTIATE_RETURN_TYPE(FArgs) \
82-
template<FW_TARGSC class RT> struct return_type<RT (*) FArgs> { \
83-
typedef RT type; \
84-
static const bool is_method = false; \
85-
}; \
86-
template<FW_TARGSC class RT, class CT> struct return_type<RT (CT::*) FArgs> { \
87-
typedef RT type; \
88-
typedef CT class_type; \
89-
static const bool is_method = true; \
90-
}; \
91-
template<FW_TARGSC class RT, class CT> struct return_type<RT (CT::*) FArgs const> { \
92-
typedef RT type; \
93-
typedef CT class_type; \
94-
static const bool is_method = true; \
46+
template<typename RT, typename ...AT>
47+
struct return_type<RT (*)(AT...)>{
48+
using type = RT;
49+
static const bool is_method = false;
9550
};
9651

97-
#define INSTANTIATE_WRAPPERS2(Count, FArgs, Args, Loads) \
98-
template<FW_TARGS> struct function_wrapper<void (*) FArgs, true> { \
99-
static const int num_args = Count; \
100-
static void execute(lua_State *state, int base, void (*cb) FArgs) { Loads; INVOKE_VOID(cb Args); } \
101-
}; \
102-
template<FW_TARGSC class RT> struct function_wrapper<RT (*) FArgs, false> { \
103-
static const int num_args = Count; \
104-
static void execute(lua_State *state, int base, RT (*cb) FArgs) { Loads; INVOKE_RV(cb Args); } \
105-
}; \
106-
template<FW_TARGSC class CT> struct function_wrapper<void (CT::*) FArgs, true> { \
107-
static const int num_args = Count+1; \
108-
static void execute(lua_State *state, int base, void (CT::*cb) FArgs) { \
109-
LOAD_CLASS() Loads; INVOKE_VOID((self->*cb) Args); } \
110-
}; \
111-
template<FW_TARGSC class CT> struct function_wrapper<void (CT::*) FArgs const, true> { \
112-
static const int num_args = Count+1; \
113-
static void execute(lua_State *state, int base, void (CT::*cb) FArgs const) { \
114-
LOAD_CLASS() Loads; INVOKE_VOID((self->*cb) Args); } \
115-
}; \
116-
template<FW_TARGSC class RT, class CT> struct function_wrapper<RT (CT::*) FArgs, false> { \
117-
static const int num_args = Count+1; \
118-
static void execute(lua_State *state, int base, RT (CT::*cb) FArgs) { \
119-
LOAD_CLASS(); Loads; INVOKE_RV((self->*cb) Args); } \
120-
}; \
121-
template<FW_TARGSC class RT, class CT> struct function_wrapper<RT (CT::*) FArgs const, false> { \
122-
static const int num_args = Count+1; \
123-
static void execute(lua_State *state, int base, RT (CT::*cb) FArgs const) { \
124-
LOAD_CLASS(); Loads; INVOKE_RV((self->*cb) Args); } \
52+
template<typename RT, class CT, typename ...AT>
53+
struct return_type<RT (CT::*)(AT...)>{
54+
using type = RT;
55+
using class_type = CT;
56+
static const bool is_method = true;
12557
};
12658

127-
#define INSTANTIATE_WRAPPERS(Count, FArgs, OFArgs, Args, OArgs, Loads) \
128-
INSTANTIATE_WRAPPERS2(Count, FArgs, Args, Loads) \
129-
INSTANTIATE_WRAPPERS2(Count, OFArgs, OArgs, LOAD_OSTREAM(out); Loads)
130-
131-
#define FW_TARGSC
132-
#define FW_TARGS
133-
INSTANTIATE_RETURN_TYPE(())
134-
INSTANTIATE_WRAPPERS(0, (), (OSTREAM_ARG), (), (out), ;)
135-
#undef FW_TARGS
136-
137-
#undef FW_TARGSC
138-
#define FW_TARGSC FW_TARGS,
139-
#define FW_TARGS class A1
140-
INSTANTIATE_RETURN_TYPE((A1))
141-
INSTANTIATE_WRAPPERS(1, (A1), (OSTREAM_ARG,A1), (vA1), (out,vA1), LOAD_ARG(A1);)
142-
#undef FW_TARGS
143-
144-
#define FW_TARGS class A1, class A2
145-
INSTANTIATE_RETURN_TYPE((A1,A2))
146-
INSTANTIATE_WRAPPERS(2, (A1,A2), (OSTREAM_ARG,A1,A2), (vA1,vA2), (out,vA1,vA2),
147-
LOAD_ARG(A1); LOAD_ARG(A2);)
148-
#undef FW_TARGS
149-
150-
#define FW_TARGS class A1, class A2, class A3
151-
INSTANTIATE_RETURN_TYPE((A1,A2,A3))
152-
INSTANTIATE_WRAPPERS(3, (A1,A2,A3), (OSTREAM_ARG,A1,A2,A3), (vA1,vA2,vA3), (out,vA1,vA2,vA3),
153-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3);)
154-
#undef FW_TARGS
155-
156-
#define FW_TARGS class A1, class A2, class A3, class A4
157-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4))
158-
INSTANTIATE_WRAPPERS(4, (A1,A2,A3,A4), (OSTREAM_ARG,A1,A2,A3,A4),
159-
(vA1,vA2,vA3,vA4), (out,vA1,vA2,vA3,vA4),
160-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);)
161-
#undef FW_TARGS
162-
163-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5
164-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5))
165-
INSTANTIATE_WRAPPERS(5, (A1,A2,A3,A4,A5), (OSTREAM_ARG,A1,A2,A3,A4,A5),
166-
(vA1,vA2,vA3,vA4,vA5), (out,vA1,vA2,vA3,vA4,vA5),
167-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
168-
LOAD_ARG(A5);)
169-
#undef FW_TARGS
59+
template<typename RT, class CT, typename ...AT>
60+
struct return_type<RT (CT::*)(AT...) const>{
61+
using type = RT;
62+
using class_type = CT;
63+
static const bool is_method = true;
64+
};
17065

171-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6
172-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6))
173-
INSTANTIATE_WRAPPERS(6, (A1,A2,A3,A4,A5,A6), (OSTREAM_ARG,A1,A2,A3,A4,A5,A6),
174-
(vA1,vA2,vA3,vA4,vA5,vA6), (out,vA1,vA2,vA3,vA4,vA5,vA6),
175-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
176-
LOAD_ARG(A5); LOAD_ARG(A6);)
177-
#undef FW_TARGS
66+
template<typename T>
67+
T get_from_lua_state(lua_State* L, int idx) {
68+
T val;
69+
df::identity_traits<T>::get()->lua_write(L, UPVAL_METHOD_NAME, &val, idx);
70+
return val;
71+
}
17872

179-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7
180-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7))
181-
INSTANTIATE_WRAPPERS(7, (A1,A2,A3,A4,A5,A6,A7), (OSTREAM_ARG,A1,A2,A3,A4,A5,A6,A7),
182-
(vA1,vA2,vA3,vA4,vA5,vA6,vA7), (out,vA1,vA2,vA3,vA4,vA5,vA6,vA7),
183-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
184-
LOAD_ARG(A5); LOAD_ARG(A6); LOAD_ARG(A7);)
185-
#undef FW_TARGS
18673

187-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8
188-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7,A8))
189-
INSTANTIATE_WRAPPERS(8, (A1,A2,A3,A4,A5,A6,A7,A8), (OSTREAM_ARG,A1,A2,A3,A4,A5,A6,A7,A8),
190-
(vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8), (out,vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8),
191-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
192-
LOAD_ARG(A5); LOAD_ARG(A6); LOAD_ARG(A7); LOAD_ARG(A8);)
193-
#undef FW_TARGS
74+
template<typename RT, typename... AT, typename FT, typename... ET, std::size_t... I>
75+
requires std::is_invocable_r_v<RT, FT, ET..., AT...>
76+
void call_and_push_impl(lua_State* L, int base, std::index_sequence<I...>, FT fun, ET... extra)
77+
{
78+
if constexpr (std::is_same_v<RT, void>) {
79+
std::invoke(fun, extra..., (get_from_lua_state<AT>(L, base+I))...);
80+
lua_pushnil(L);
81+
}
82+
else
83+
{
84+
RT rv = std::invoke(fun, extra..., (get_from_lua_state<AT>(L, base+I))...);
85+
df::identity_traits<RT>::get()->lua_read(L, UPVAL_METHOD_NAME, &rv);
86+
}
87+
}
19488

195-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9
196-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7,A8,A9))
197-
INSTANTIATE_WRAPPERS(9, (A1,A2,A3,A4,A5,A6,A7,A8,A9),
198-
(OSTREAM_ARG,A1,A2,A3,A4,A5,A6,A7,A8,A9),
199-
(vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9),
200-
(out,vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9),
201-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
202-
LOAD_ARG(A5); LOAD_ARG(A6); LOAD_ARG(A7); LOAD_ARG(A8);
203-
LOAD_ARG(A9);)
204-
#undef FW_TARGS
89+
template<typename RT, typename... AT, typename FT, typename... ET, typename indices = std::index_sequence_for<AT...> >
90+
requires std::is_invocable_r_v<RT, FT, ET..., AT...>
91+
void call_and_push(lua_State* L, int base, FT fun, ET... extra)
92+
{
93+
call_and_push_impl<RT, AT...>(L, base, indices{}, fun, extra...);
94+
}
20595

206-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10
207-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7,A8,A9,A10))
208-
INSTANTIATE_WRAPPERS(10, (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10),
209-
(OSTREAM_ARG,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10),
210-
(vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9,vA10),
211-
(out,vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9,vA10),
212-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
213-
LOAD_ARG(A5); LOAD_ARG(A6); LOAD_ARG(A7); LOAD_ARG(A8);
214-
LOAD_ARG(A9); LOAD_ARG(A10);)
215-
#undef FW_TARGS
96+
template<typename T> struct function_wrapper {};
21697

217-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11
218-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11))
219-
INSTANTIATE_WRAPPERS(11, (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11),
220-
(OSTREAM_ARG,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11),
221-
(vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9,vA10,vA11),
222-
(out,vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9,vA10,vA11),
223-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
224-
LOAD_ARG(A5); LOAD_ARG(A6); LOAD_ARG(A7); LOAD_ARG(A8);
225-
LOAD_ARG(A9); LOAD_ARG(A10); LOAD_ARG(A11);)
226-
#undef FW_TARGS
98+
template<typename RT, typename ...AT>
99+
struct function_wrapper<RT(*)(DFHack::color_ostream&, AT...)> {
100+
static const int num_args = sizeof...(AT);
101+
static void execute(lua_State *L, int base, RT (fun)(DFHack::color_ostream& out, AT...)) {
102+
cur_lua_ostream_argument out(L);
103+
call_and_push<RT, AT...>(L, base, fun, out);
104+
}
105+
};
227106

228-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11, class A12
229-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12))
230-
INSTANTIATE_WRAPPERS(12, (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12),
231-
(OSTREAM_ARG,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12),
232-
(vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9,vA10,vA11,vA12),
233-
(out,vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9,vA10,vA11,vA12),
234-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
235-
LOAD_ARG(A5); LOAD_ARG(A6); LOAD_ARG(A7); LOAD_ARG(A8);
236-
LOAD_ARG(A9); LOAD_ARG(A10); LOAD_ARG(A11); LOAD_ARG(A12);)
237-
#undef FW_TARGS
107+
template<typename RT, typename ...AT>
108+
struct function_wrapper<RT(*)(AT...)> {
109+
static const int num_args = sizeof...(AT);
110+
static void execute(lua_State *L, int base, RT (fun)(AT...)) {
111+
call_and_push<RT, AT...>(L, base, fun);
112+
}
113+
};
238114

239-
#define FW_TARGS class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11, class A12, class A13
240-
INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13))
241-
INSTANTIATE_WRAPPERS(13, (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13),
242-
(OSTREAM_ARG,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13),
243-
(vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9,vA10,vA11,vA12,vA13),
244-
(out,vA1,vA2,vA3,vA4,vA5,vA6,vA7,vA8,vA9,vA10,vA11,vA12,vA13),
245-
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);
246-
LOAD_ARG(A5); LOAD_ARG(A6); LOAD_ARG(A7); LOAD_ARG(A8);
247-
LOAD_ARG(A9); LOAD_ARG(A10); LOAD_ARG(A11); LOAD_ARG(A12);
248-
LOAD_ARG(A13);)
249-
#undef FW_TARGS
115+
template<typename RT, class CT, typename ...AT>
116+
struct function_wrapper<RT(CT::*)(AT...)> {
117+
static const int num_args = sizeof...(AT)+1;
118+
static void execute(lua_State *L, int base, RT(CT::*mem_fun)(AT...)) {
119+
CT *self = (CT*)DFHack::LuaWrapper::get_object_addr(L, base++, UPVAL_METHOD_NAME, "invoke");
120+
call_and_push<RT, AT...>(L, base, mem_fun, self);
121+
};
122+
};
250123

251-
#undef FW_TARGSC
252-
#undef INSTANTIATE_WRAPPERS
253-
#undef INSTANTIATE_WRAPPERS2
254-
#undef INVOKE_VOID
255-
#undef INVOKE_RV
256-
#undef LOAD_CLASS
257-
#undef LOAD_ARG
258-
#undef OSTREAM_ARG
259-
#undef LOAD_OSTREAM
124+
template<typename RT, class CT, typename ...AT>
125+
struct function_wrapper<RT(CT::*)(AT...) const> {
126+
static const int num_args = sizeof...(AT)+1;
127+
static void execute(lua_State *L, int base, RT(CT::*mem_fun)(AT...) const) {
128+
CT *self = (CT*)DFHack::LuaWrapper::get_object_addr(L, base++, UPVAL_METHOD_NAME, "invoke");
129+
call_and_push<RT, AT...>(L, base, mem_fun, self);
130+
};
131+
};
260132

261133
template<class T>
262134
class function_identity : public function_identity_base {
263135
T ptr;
264136

265137
public:
266-
typedef function_wrapper<T> wrapper;
138+
using wrapper = function_wrapper<T>;
267139

268140
function_identity(T ptr, bool vararg)
269141
: function_identity_base(wrapper::num_args, vararg), ptr(ptr) {};

0 commit comments

Comments
 (0)