Branch data Line data Source code
1 : : /*
2 : : * Copyright 2006-2009 Savarese Software Research Corporation
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at
7 : : *
8 : : * https://www.savarese.com/software/ApacheLicense-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : /**
18 : : * @file This header includes <lua.hpp> and places it inside of the
19 : : * Lua namespace.
20 : : */
21 : :
22 : : #ifndef __SSRC_WSPR_LUA_LUA_H
23 : : #define __SSRC_WSPR_LUA_LUA_H
24 : :
25 : : /**
26 : : * The %Lua C API from <lua.hpp> can be accessed via the %Lua namespace
27 : : * if required, but it is intended for internal use by the library to avoid
28 : : * polluting the global namespace.
29 : : */
30 : : namespace Lua {
31 : : #include <lua.hpp>
32 : : }
33 : :
34 : : #include <ssrc/wispers-packages.h>
35 : :
36 : : #include <string>
37 : : #include <stdexcept>
38 : :
39 : : __BEGIN_NS_SSRC_WSPR_LUA
40 : :
41 : : using namespace Lua;
42 : : using std::string;
43 : :
44 : : template<typename R> inline R convert(lua_State *state, int index = -1);
45 : :
46 : 19 : template<> inline bool convert<bool>(lua_State *state, int index) {
47 : 19 : return lua_toboolean(state, index);
48 : : }
49 : :
50 : 11 : template<> inline int convert<int>(lua_State *state, int index) {
51 : 11 : return lua_tointeger(state, index);
52 : : }
53 : :
54 : : template<> inline
55 : : unsigned int convert<unsigned int>(lua_State *state, int index) {
56 : : return static_cast<unsigned int>(lua_tointeger(state, index));
57 : : }
58 : :
59 : 903 : template<> inline string convert<string>(lua_State *state, int index) {
60 : 903 : const char *str = lua_tolstring(state, index, static_cast<size_t*>(0));
61 [ + - + - : 903 : return (str != 0 ? str : string());
# # + - #
# ]
62 : : }
63 : :
64 : : template<>
65 : : inline const char * convert<const char *>(lua_State *state, int index) {
66 : : return lua_tolstring(state, index, static_cast<size_t*>(0));
67 : : }
68 : :
69 : 57 : template<> inline lua_Number convert<lua_Number>(lua_State *state, int index) {
70 : 57 : return lua_tonumber(state, index);
71 : : }
72 : :
73 : 6 : inline void push_value(lua_State *state, const bool value) {
74 : 6 : lua_pushboolean(state, value);
75 : 6 : }
76 : :
77 : 6 : inline void push_value(lua_State *state, const int value) {
78 : 6 : lua_pushinteger(state, value);
79 : 6 : }
80 : :
81 : : inline void push_value(lua_State *state, const lua_Number value) {
82 : : lua_pushnumber(state, value);
83 : : }
84 : :
85 : 12 : inline void push_value(lua_State *state, const char *value) {
86 : 12 : lua_pushstring(state, value);
87 : 12 : }
88 : :
89 : 14 : inline void push_value(lua_State *state, const string & value) {
90 : 14 : lua_pushlstring(state, value.c_str(), value.size());
91 : 14 : }
92 : :
93 : 1 : inline void push_value(lua_State *state, void *value) {
94 : 1 : lua_pushlightuserdata(state, value);
95 : 1 : }
96 : :
97 : : inline void push_value(lua_State *state, const void *value) {
98 : : lua_pushlightuserdata(state, const_cast<void *>(value));
99 : : }
100 : :
101 : : // This version is in order to support zero-arg pcall.
102 : 20 : inline void push_values(lua_State *) { }
103 : :
104 : : template<typename P>
105 : 1 : inline void push_values(lua_State *state, const P & p) {
106 : 1 : push_value(state, p);
107 : 1 : }
108 : :
109 : : template<typename T, typename... P>
110 : : inline void push_values(lua_State *state, const T & t, const P & ...p) {
111 : : push_value(state, t);
112 : : push_values(state, p...);
113 : : }
114 : :
115 : : template<typename V>
116 : 20 : inline void set_field(lua_State* state, int index, const V & value,
117 : : const char * const field)
118 : : {
119 : 20 : push_value(state, value);
120 [ + - + - : 20 : lua_setfield(state, (index < 0 ? index - 1 : index), field);
+ - + - +
- ]
121 : 20 : }
122 : :
123 : : template<typename V>
124 : 2 : inline void set_field(lua_State* state, int index, const V & value,
125 : : const string & field)
126 : : {
127 : 2 : push_value(state, field);
128 : 2 : push_value(state, value);
129 [ + - ]: 2 : lua_settable(state, (index < 0 ? index - 2 : index));
130 : 2 : }
131 : :
132 : : template<typename V>
133 : : inline void set_field(lua_State* state, int index, const V & value, int n) {
134 : : push_value(state, value);
135 : : lua_rawseti(state, (index < 0 ? index - 1 : index), n);
136 : : }
137 : :
138 : : namespace detail {
139 : : inline
140 : 8 : void _get_field(lua_State* state, int index, const char * const field) {
141 : 8 : lua_getfield(state, index, field);
142 : 8 : }
143 : :
144 : : inline void _get_field(lua_State* state, int index, const string & field) {
145 : : push_value(state, field);
146 : : lua_gettable(state, (index < 0 ? index - 1 : index));
147 : : }
148 : :
149 : : template<typename V>
150 : 6 : inline void _create_value(lua_State* state, const V & value,
151 : : const char * const field)
152 : : {
153 : 6 : set_field(state, -1, value, field);
154 : 6 : }
155 : :
156 : : template<typename V>
157 : : inline void _create_value(lua_State* state, const V & value,
158 : : const string & field)
159 : : {
160 : : set_field(state, -1, value, field);
161 : : }
162 : :
163 : : template<typename V, typename... P>
164 : 12 : inline void _create_value(lua_State* state, const V & value,
165 : : const char * const field, P...p)
166 : : {
167 : 12 : lua_newtable(state);
168 : 12 : _create_value(state, value, p...);
169 : 12 : lua_setfield(state, -2, field);
170 : 12 : }
171 : :
172 : : template<typename V>
173 : 4 : inline void _set_value(lua_State* state, const V & value,
174 : : const char * const field)
175 : : {
176 : 4 : set_field(state, -1, value, field);
177 : 4 : }
178 : :
179 : : template<typename V>
180 : : inline void _set_value(lua_State* state, const V & value,
181 : : const string & field)
182 : : {
183 : : set_field(state, -1, value, field);
184 : : }
185 : :
186 : : template<typename V, typename... P>
187 : 8 : inline void _set_value(lua_State* state, const V & value,
188 : : const char * const field, P...p)
189 : : {
190 : 8 : _get_field(state, -1, field);
191 : 8 : _set_value(state, value, p...);
192 : 8 : lua_pop(state, 1);
193 : 8 : }
194 : : }
195 : :
196 : 36 : inline void get_global(lua_State* state, const char * const field) {
197 : 36 : lua_getglobal(state, field);
198 : 36 : }
199 : :
200 : : inline void get_global(lua_State* state, const string & field) {
201 : : push_value(state, field);
202 : : lua_gettable(state, LUA_GLOBALSINDEX);
203 : : }
204 : :
205 : : template<typename V>
206 : 10 : inline void set_global(lua_State* state, const V & value,
207 : : const char * const field)
208 : : {
209 : 10 : push_value(state, value);
210 : 10 : lua_setglobal(state, field);
211 : 10 : }
212 : :
213 : : template<typename V>
214 : : inline void set_global(lua_State* state, const V & value, const string & field)
215 : : {
216 : : push_value(state, field);
217 : : push_value(state, value);
218 : : lua_settable(state, LUA_GLOBALSINDEX);
219 : : }
220 : :
221 : : template<typename R>
222 : 42 : inline const R get_field(const R & default_value,
223 : : lua_State* state,
224 : : int index,
225 : : const char * const field)
226 : : {
227 : 42 : lua_getfield(state, index, field);
228 : : const R & result =
229 [ + + + + : 60 : (lua_isnoneornil(state, -1) ? default_value : convert<R>(state));
+ + ]
230 [ + - ]: 42 : lua_pop(state, 1);
231 [ + - ]: 60 : return result;
232 : : }
233 : :
234 : : template<typename R>
235 : : inline const R get_field(const R & default_value,
236 : : lua_State* state,
237 : : int index,
238 : : const string & field)
239 : : {
240 : : detail::_get_field(state, index, field);
241 : : const R & result =
242 : : (lua_isnoneornil(state, -1) ? default_value : convert<R>(state));
243 : : lua_pop(state, 1);
244 : : return result;
245 : : }
246 : :
247 : : template<typename R>
248 : 3 : inline const R get_field(const R & default_value,
249 : : lua_State* state,
250 : : int index,
251 : : int n)
252 : : {
253 : 3 : lua_rawgeti(state, index, n);
254 : : const R & result =
255 [ - + ]: 6 : (lua_isnoneornil(state, -1) ? default_value : convert<R>(state));
256 [ + - ]: 3 : lua_pop(state, 1);
257 [ + - ]: 6 : return result;
258 : : }
259 : :
260 : : template<typename R, typename... P>
261 : 46 : inline const R get_field(const R & default_value,
262 : : lua_State* state,
263 : : int index,
264 : : const char * const field,
265 : : P ...p)
266 : : {
267 : 46 : lua_getfield(state, index, field);
268 : : const R & result =
269 : : (lua_isnoneornil(state, -1) ?
270 [ + + + + : 72 : default_value : get_field<R>(default_value, state, -1, p...));
+ + - + -
+ - + - +
- + - + ]
271 [ + - + - : 46 : lua_pop(state, 1);
+ - + - ]
272 [ + - + - : 72 : return result;
+ - ]
273 : : }
274 : :
275 : : template<typename R> inline
276 : 7 : const R get_field(lua_State* state, int index, const char * const field) {
277 [ + - ]: 7 : return get_field(R(), state, index, field);
278 : : }
279 : :
280 : : template<typename R> inline
281 : : const R get_field(lua_State* state, int index, const string & field) {
282 : : return get_field(R(), state, index, field);
283 : : }
284 : :
285 : : template<typename R> inline
286 : 3 : const R get_field(lua_State* state, int index, int n) {
287 [ + - ]: 3 : return get_field(R(), state, index, n);
288 : : }
289 : :
290 : : template<typename R, typename... P>
291 : 26 : inline const R get_field(lua_State* state,
292 : : int index,
293 : : const char * const field,
294 : : P ...p)
295 : : {
296 [ + - + - : 26 : return get_field(R(), state, index, field, p...);
+ - ]
297 : : }
298 : :
299 : : template<typename R>
300 : 10 : inline const R get_value(const R & default_value,
301 : : lua_State* state,
302 : : const char * const var)
303 : : {
304 : 10 : get_global(state, var);
305 : : const R & result =
306 [ - + - + : 16 : (lua_isnoneornil(state, -1) ? default_value : convert<R>(state));
- + ]
307 [ + - ]: 10 : lua_pop(state, 1);
308 [ + - ]: 16 : return result;
309 : : }
310 : :
311 : : template<typename R>
312 : : inline const R get_value(const R & default_value,
313 : : lua_State* state,
314 : : const string & var)
315 : : {
316 : : get_global(state, var);
317 : : const R & result =
318 : : (lua_isnoneornil(state, -1) ? default_value : convert<R>(state));
319 : : lua_pop(state, 1);
320 : : return result;
321 : : }
322 : :
323 : : template<typename R, typename... P>
324 : 22 : inline const R get_value(const R & default_value,
325 : : lua_State* state,
326 : : const char * const var,
327 : : P ...p)
328 : : {
329 : 22 : get_global(state, var);
330 : : const R & result =
331 [ - + - + : 32 : (lua_isnoneornil(state, -1) ? default_value : get_field<R>(state, -1, p...));
- + + + +
+ + + ]
332 [ + - + - ]: 22 : lua_pop(state, 1);
333 [ + - + - ]: 32 : return result;
334 : : }
335 : :
336 : : template<typename R>
337 : 10 : inline const R get_value(lua_State* state, const char * const var) {
338 [ + - ]: 10 : return get_value(R(), state, var);
339 : : }
340 : :
341 : : template<typename R>
342 : : inline const R get_value(lua_State* state, const string & var) {
343 : : return get_value(R(), state, var);
344 : : }
345 : :
346 : : template<typename R, typename... P>
347 : 22 : inline const R get_value(lua_State* state, const char * const var, P ...p) {
348 [ + - + - ]: 22 : return get_value(R(), state, var, p...);
349 : : }
350 : :
351 : : template<typename V>
352 : 5 : inline void create_value(lua_State* state, const V & value,
353 : : const char * const var)
354 : : {
355 : 5 : set_global(state, value, var);
356 : 5 : }
357 : :
358 : : template<typename V>
359 : : inline void create_value(lua_State* state, const V & value,
360 : : const string & var)
361 : : {
362 : : set_global(state, value, var);
363 : : }
364 : :
365 : : template<typename V, typename... P>
366 : 6 : inline void create_value(lua_State* state, const V & value,
367 : : const char * const var, P ...p)
368 : : {
369 : 6 : lua_newtable(state);
370 : 6 : detail::_create_value(state, value, p...);
371 : 6 : lua_setglobal(state, var);
372 : 6 : }
373 : :
374 : : template<typename V, typename... P>
375 : 15 : inline void set_field(lua_State* state, int index, const V & value,
376 : : const char * const field, P ...p)
377 : : {
378 : 15 : lua_getfield(state, index, field);
379 [ - + - + : 15 : if(!lua_istable(state, -1)) {
- + - + +
- - + - +
- + - + +
- - + - +
- + - + +
- ]
380 : 3 : lua_pop(state, 1);
381 : 3 : lua_newtable(state);
382 [ # # # # : 3 : lua_setfield(state, (index < 0 ? index - 1 : index), field);
# # # # +
- # # # #
# # # # +
- # # # #
# # # # +
- ]
383 : 3 : lua_getfield(state, index, field);
384 : : }
385 : 15 : set_field(state, -1, value, p...);
386 : 15 : lua_pop(state, 1);
387 : 15 : }
388 : :
389 : : template<typename V>
390 : 5 : inline void set_value(lua_State* state, const V & value,
391 : : const char * const var)
392 : : {
393 : 5 : set_global(state, value, var);
394 : 5 : }
395 : :
396 : : template<typename V>
397 : : inline void set_value(lua_State* state, const V & value, const string & var) {
398 : : set_global(state, value, var);
399 : : }
400 : :
401 : : template<typename V, typename... P>
402 : 4 : inline void set_value(lua_State* state, const V & value,
403 : : const char * const var, P ...p)
404 : : {
405 : 4 : get_global(state, var);
406 : 4 : detail::_set_value(state, value, p...);
407 : 4 : lua_pop(state, 1);
408 : 4 : }
409 : :
410 : : template<typename I>
411 : : inline void
412 : : prepend_package_path(lua_State* state, const I & begin, const I & end) {
413 : : string lua_path_str;
414 : : lua_path_str.reserve(256);
415 : :
416 : : for(I it = begin; it != end; ++it) {
417 : : lua_path_str.append(*it).append("/?.lua;");
418 : : }
419 : :
420 : : get_global(state, "package");
421 : : lua_getfield(state, -1, "path");
422 : : lua_path_str.append(lua_tostring(state, -1));
423 : : set_field(state, -2, lua_path_str, "path");
424 : : lua_pop(state, 2);
425 : : }
426 : :
427 [ # # ]: 0 : struct LuaCallError : std::runtime_error {
428 : : int lua_error;
429 : :
430 : 0 : explicit LuaCallError(const string & message, const int lua_error) :
431 : 0 : std::runtime_error(message), lua_error(lua_error)
432 : 0 : {}
433 : : };
434 : :
435 : : /**
436 : : * Assumes function has already been pushed to top of stack. The
437 : : * nargs parameter is to allow you to pre-push values onto the stack.
438 : : */
439 : : template<typename... P>
440 : : inline
441 : 21 : void pcall_nopop(const int nargs, const int nresults, lua_State* state, P ...p)
442 : : SSRC_DECL_THROW(LuaCallError)
443 : : {
444 : 21 : push_values(state, p...);
445 : :
446 : 21 : int err = lua_pcall(state, nargs, nresults, 0);
447 : :
448 [ - + ]: 21 : if(err) {
449 [ # # # # ]: 0 : string msg(lua_tostring(state, -1));
450 [ # # ]: 0 : lua_pop(state, 1);
451 [ # # ]: 0 : throw LuaCallError(msg, err);
452 : : }
453 : 21 : }
454 : :
455 : : template<typename... P>
456 : 1 : inline void pcall_nopop(const int nresults, lua_State* state, P ...p)
457 : : SSRC_DECL_THROW(LuaCallError)
458 : : {
459 : 1 : pcall_nopop(sizeof...(P), nresults, state, p...);
460 : 1 : }
461 : :
462 : : /**
463 : : * Currently, we support only one return value, but it should be possible
464 : : * to work things out to specify multiple return values and return them
465 : : * via a tuple.
466 : : */
467 : : template<typename R, typename... P>
468 : : inline R pcall_ret(lua_State* state, const P & ...p)
469 : : SSRC_DECL_THROW(LuaCallError)
470 : : {
471 : : pcall_nopop(1, state, p...);
472 : : const R & result = convert<R>(state);
473 : : lua_pop(state, 1);
474 : : return result;
475 : : }
476 : :
477 : : template<typename... P>
478 : 1 : inline void pcall(lua_State* state, const P & ...p)
479 : : SSRC_DECL_THROW(LuaCallError)
480 : : {
481 : 1 : pcall_nopop(0, state, p...);
482 : 1 : }
483 : :
484 : : __END_NS_SSRC_WSPR_LUA
485 : :
486 : : #endif
|