Pioneer
LuaPushPull.h
Go to the documentation of this file.
1 // Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #ifndef _LUAPUSHPULL_H
5 #define _LUAPUSHPULL_H
6 
7 #include "Lua.h"
8 #include "buildopts.h"
9 #include <lua.hpp>
10 
11 #include <cstddef>
12 #include <string>
13 #include <tuple>
14 
15 inline void pi_lua_generic_push(lua_State *l, bool value) { lua_pushboolean(l, value); }
16 inline void pi_lua_generic_push(lua_State *l, int value) { lua_pushinteger(l, value); }
17 inline void pi_lua_generic_push(lua_State *l, int64_t value) { lua_pushinteger(l, value); }
18 inline void pi_lua_generic_push(lua_State *l, unsigned int value) { lua_pushinteger(l, value); }
19 #if SIZE_T_AND_UNSIGNED_INT_ARE_DIFFERENT_TYPES
20 inline void pi_lua_generic_push(lua_State *l, size_t value) { lua_pushinteger(l, value); }
21 #endif
22 inline void pi_lua_generic_push(lua_State *l, double value) { lua_pushnumber(l, value); }
23 inline void pi_lua_generic_push(lua_State *l, const char *value) { lua_pushstring(l, value); }
24 inline void pi_lua_generic_push(lua_State *l, const std::string &value)
25 {
26  lua_pushlstring(l, value.c_str(), value.size());
27 }
28 inline void pi_lua_generic_push(lua_State *l, std::string_view &value)
29 {
30  lua_pushlstring(l, value.data(), value.size());
31 }
32 inline void pi_lua_generic_push(lua_State *l, const std::nullptr_t &value) { lua_pushnil(l); }
33 
34 inline void pi_lua_generic_pull(lua_State *l, int index, bool &out) { out = lua_toboolean(l, index); }
35 inline void pi_lua_generic_pull(lua_State *l, int index, int &out) { out = luaL_checkinteger(l, index); }
36 inline void pi_lua_generic_pull(lua_State *l, int index, int64_t &out) { out = luaL_checkinteger(l, index); }
37 inline void pi_lua_generic_pull(lua_State *l, int index, unsigned int &out) { out = luaL_checkunsigned(l, index); }
38 #if SIZE_T_AND_UNSIGNED_INT_ARE_DIFFERENT_TYPES
39 inline void pi_lua_generic_pull(lua_State *l, int index, size_t &out) { out = luaL_checkunsigned(l, index); }
40 #endif
41 inline void pi_lua_generic_pull(lua_State *l, int index, float &out) { out = luaL_checknumber(l, index); }
42 inline void pi_lua_generic_pull(lua_State *l, int index, double &out) { out = luaL_checknumber(l, index); }
43 inline void pi_lua_generic_pull(lua_State *l, int index, const char *&out) { out = luaL_checkstring(l, index); }
44 inline void pi_lua_generic_pull(lua_State *l, int index, std::string &out)
45 {
46  size_t len;
47  const char *buf = luaL_checklstring(l, index, &len);
48  std::string(buf, len).swap(out);
49 }
50 // the returned string view is only valid until the lua object is removed from the stack
51 inline void pi_lua_generic_pull(lua_State *l, int index, std::string_view &out)
52 {
53  size_t len;
54  const char *buf = luaL_checklstring(l, index, &len);
55  out = { buf, len };
56 }
57 
58 template <typename Type>
59 inline void LuaPush(lua_State *l, Type value)
60 {
61  pi_lua_generic_push(l, value);
62 }
63 
64 template <typename Type>
65 inline std::remove_reference_t<Type> LuaPull(lua_State *l, int index)
66 {
67  std::decay_t<Type> value;
68  pi_lua_generic_pull(l, index, value);
69  return value;
70 }
71 
72 // Pull a value with an optional default.
73 template <typename Type>
74 inline Type LuaPull(lua_State *l, int index, Type defaultVal)
75 {
76  Type value = defaultVal;
77  if (lua_gettop(l) >= index && !lua_isnil(l, index))
78  pi_lua_generic_pull(l, index, value);
79  return value;
80 }
81 
82 inline bool pi_lua_strict_pull(lua_State *l, int index, bool &out)
83 {
84  if (lua_type(l, index) == LUA_TBOOLEAN) {
85  out = lua_toboolean(l, index);
86  return true;
87  }
88  return false;
89 }
90 inline bool pi_lua_strict_pull(lua_State *l, int index, int &out)
91 {
92  if (lua_type(l, index) == LUA_TNUMBER) {
93  out = lua_tointeger(l, index);
94  return true;
95  }
96  return false;
97 }
98 inline bool pi_lua_strict_pull(lua_State *l, int index, float &out)
99 {
100  if (lua_type(l, index) == LUA_TNUMBER) {
101  out = lua_tonumber(l, index);
102  return true;
103  }
104  return false;
105 }
106 inline bool pi_lua_strict_pull(lua_State *l, int index, double &out)
107 {
108  if (lua_type(l, index) == LUA_TNUMBER) {
109  out = lua_tonumber(l, index);
110  return true;
111  }
112  return false;
113 }
114 inline bool pi_lua_strict_pull(lua_State *l, int index, const char *&out)
115 {
116  if (lua_type(l, index) == LUA_TSTRING) {
117  out = lua_tostring(l, index);
118  return true;
119  }
120  return false;
121 }
122 inline bool pi_lua_strict_pull(lua_State *l, int index, std::string &out)
123 {
124  if (lua_type(l, index) == LUA_TSTRING) {
125  size_t len;
126  const char *buf = lua_tolstring(l, index, &len);
127  std::string(buf, len).swap(out);
128  return true;
129  }
130  return false;
131 }
132 template <typename... Types>
133 inline void pi_lua_multiple_push(lua_State *l, Types... args);
134 
135 #if defined(_MSC_VER) // Non-variadic version for MSVC
136 template <typename Arg1>
137 inline void pi_lua_multiple_push(lua_State *l, Arg1 arg1)
138 {
139  pi_lua_generic_push(l, arg1);
140 }
141 
142 template <typename Arg1, typename Arg2>
143 inline void pi_lua_multiple_push(lua_State *l, Arg1 arg1, Arg2 arg2)
144 {
145  pi_lua_generic_push(l, arg1);
146  pi_lua_generic_push(l, arg2);
147 }
148 
149 template <typename Arg1, typename Arg2, typename Arg3>
150 inline void pi_lua_multiple_push(lua_State *l, Arg1 arg1, Arg2 arg2, Arg3 arg3)
151 {
152  pi_lua_generic_push(l, arg1);
153  pi_lua_generic_push(l, arg2);
154  pi_lua_generic_push(l, arg3);
155 }
156 
157 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
158 inline void pi_lua_multiple_push(lua_State *l, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
159 {
160  pi_lua_generic_push(l, arg1);
161  pi_lua_generic_push(l, arg2);
162  pi_lua_generic_push(l, arg3);
163  pi_lua_generic_push(l, arg4);
164 }
165 #else // Just use the normal variadic version
166 template <typename Head, typename... Tail>
167 inline void pi_lua_multiple_push(lua_State *l, Head arg1, Tail... rest)
168 {
169  pi_lua_generic_push(l, arg1);
170  pi_lua_multiple_push(l, rest...);
171 }
172 #endif
173 
174 inline void pi_lua_multiple_push(lua_State *l)
175 {
176  return;
177 }
178 
179 #if defined(_MSC_VER)
180 template <typename Arg1, typename Arg2>
181 inline std::tuple<Arg1, Arg2> pi_lua_multiple_pull(lua_State *l, int beg)
182 {
183  beg = lua_absindex(l, beg);
184  Arg1 arg1;
185  Arg2 arg2;
186  pi_lua_generic_pull(l, beg, arg1);
187  pi_lua_generic_pull(l, beg + 1, arg2);
188  return std::make_tuple(arg1, arg2);
189 }
190 template <typename Arg1, typename Arg2, typename Arg3>
191 inline std::tuple<Arg1, Arg2, Arg3> pi_lua_multiple_pull(lua_State *l, int beg)
192 {
193  beg = lua_absindex(l, beg);
194  Arg1 arg1;
195  Arg2 arg2;
196  Arg3 arg3;
197  pi_lua_generic_pull(l, beg, arg1);
198  pi_lua_generic_pull(l, beg + 1, arg2);
199  pi_lua_generic_pull(l, beg + 2, arg3);
200  return std::make_tuple(arg1, arg2, arg3);
201 }
202 template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
203 inline std::tuple<Arg1, Arg2, Arg3, Arg4> pi_lua_multiple_pull(lua_State *l, int beg)
204 {
205  beg = lua_absindex(l, beg);
206  Arg1 arg1;
207  Arg2 arg2;
208  Arg3 arg3;
209  Arg4 arg4;
210  pi_lua_generic_pull(l, beg, arg1);
211  pi_lua_generic_pull(l, beg + 1, arg2);
212  pi_lua_generic_pull(l, beg + 2, arg3);
213  pi_lua_generic_pull(l, beg + 3, arg4);
214  return std::make_tuple(arg1, arg2, arg3, arg4);
215 }
216 #else
217 // The _bogus parameter is used to bring the empty type list case into the template world
218 // to solve name resolution problems.
219 template <int _bogus, typename Head, typename... Tail>
220 inline std::tuple<Head, Tail...> __helper_pi_lua_multiple_pull(lua_State *l, int beg)
221 {
222  beg = lua_absindex(l, beg);
223  std::tuple<Tail...> rest = __helper_pi_lua_multiple_pull<_bogus, Tail...>(l, beg + 1);
224  Head hd;
225  pi_lua_generic_pull(l, beg, hd);
226  std::tuple<Head> first(hd);
227  return std::tuple_cat(first, rest);
228 }
229 
230 template <int _bogus>
231 inline std::tuple<> __helper_pi_lua_multiple_pull(lua_State *l, int beg)
232 {
233  return std::tuple<>();
234 }
235 
236 template <typename... Types>
237 inline std::tuple<Types...> pi_lua_multiple_pull(lua_State *l, int beg)
238 {
239  return __helper_pi_lua_multiple_pull<0, Types...>(l, beg);
240 }
241 #endif
242 
243 #endif
void LuaPush(lua_State *l, Type value)
Definition: LuaPushPull.h:59
std::tuple< Head, Tail... > __helper_pi_lua_multiple_pull(lua_State *l, int beg)
Definition: LuaPushPull.h:220
bool pi_lua_strict_pull(lua_State *l, int index, bool &out)
Definition: LuaPushPull.h:82
std::tuple< Types... > pi_lua_multiple_pull(lua_State *l, int beg)
Definition: LuaPushPull.h:237
std::remove_reference_t< Type > LuaPull(lua_State *l, int index)
Definition: LuaPushPull.h:65
void pi_lua_multiple_push(lua_State *l, Types... args)
void pi_lua_generic_push(lua_State *l, bool value)
Definition: LuaPushPull.h:15
void pi_lua_generic_pull(lua_State *l, int index, bool &out)
Definition: LuaPushPull.h:34