Pioneer
Loading...
Searching...
No Matches
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
15inline void pi_lua_generic_push(lua_State *l, bool value) { lua_pushboolean(l, value); }
16inline void pi_lua_generic_push(lua_State *l, int value) { lua_pushinteger(l, value); }
17inline void pi_lua_generic_push(lua_State *l, int64_t value) { lua_pushinteger(l, value); }
18inline 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
20inline void pi_lua_generic_push(lua_State *l, size_t value) { lua_pushinteger(l, value); }
21#endif
22inline void pi_lua_generic_push(lua_State *l, double value) { lua_pushnumber(l, value); }
23inline void pi_lua_generic_push(lua_State *l, const char *value) { lua_pushstring(l, value); }
24inline void pi_lua_generic_push(lua_State *l, const std::string &value)
25{
26 lua_pushlstring(l, value.c_str(), value.size());
27}
28inline void pi_lua_generic_push(lua_State *l, std::string_view &value)
29{
30 lua_pushlstring(l, value.data(), value.size());
31}
32inline void pi_lua_generic_push(lua_State *l, const std::nullptr_t &value) { lua_pushnil(l); }
33
34inline void pi_lua_generic_pull(lua_State *l, int index, bool &out) { out = lua_toboolean(l, index); }
35inline void pi_lua_generic_pull(lua_State *l, int index, int &out) { out = luaL_checkinteger(l, index); }
36inline void pi_lua_generic_pull(lua_State *l, int index, int64_t &out) { out = luaL_checkinteger(l, index); }
37inline 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
39inline void pi_lua_generic_pull(lua_State *l, int index, size_t &out) { out = luaL_checkunsigned(l, index); }
40#endif
41inline void pi_lua_generic_pull(lua_State *l, int index, float &out) { out = luaL_checknumber(l, index); }
42inline void pi_lua_generic_pull(lua_State *l, int index, double &out) { out = luaL_checknumber(l, index); }
43inline void pi_lua_generic_pull(lua_State *l, int index, const char *&out) { out = luaL_checkstring(l, index); }
44inline 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
51inline 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
58template <typename Type>
59inline void LuaPush(lua_State *l, Type value)
60{
61 pi_lua_generic_push(l, value);
62}
63
64template <typename Type>
65inline 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.
73template <typename Type>
74inline 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
82inline 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}
90inline 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}
98inline 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}
106inline 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}
114inline 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}
122inline 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}
132template <typename... Types>
133inline void pi_lua_multiple_push(lua_State *l, Types... args);
134
135#if defined(_MSC_VER) // Non-variadic version for MSVC
136template <typename Arg1>
137inline void pi_lua_multiple_push(lua_State *l, Arg1 arg1)
138{
139 pi_lua_generic_push(l, arg1);
140}
141
142template <typename Arg1, typename Arg2>
143inline 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
149template <typename Arg1, typename Arg2, typename Arg3>
150inline 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
157template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
158inline 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
166template <typename Head, typename... Tail>
167inline 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
174inline void pi_lua_multiple_push(lua_State *l)
175{
176 return;
177}
178
179#if defined(_MSC_VER)
180template <typename Arg1, typename Arg2>
181inline 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}
190template <typename Arg1, typename Arg2, typename Arg3>
191inline 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}
202template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
203inline 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.
219template <int _bogus, typename Head, typename... Tail>
220inline 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
230template <int _bogus>
231inline std::tuple<> __helper_pi_lua_multiple_pull(lua_State *l, int beg)
232{
233 return std::tuple<>();
234}
235
236template <typename... Types>
237inline 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
bool pi_lua_strict_pull(lua_State *l, int index, bool &out)
Definition LuaPushPull.h:82
std::tuple< Head, Tail... > __helper_pi_lua_multiple_pull(lua_State *l, int beg)
Definition LuaPushPull.h:220
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