@@ -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-
3936namespace 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