1 #ifndef _library__lua_base__hpp__included__
2 #define _library__lua_base__hpp__included__
9 #include <unordered_map>
32 //Auxillary type for store-tag.
33 template<typename T
> struct _store_tag
37 _store_tag(T
& a
, T v
) : addr(a
), val(v
) {}
39 //Auxillary type for vararg-tag.
42 std::list
<std::string
> args
;
43 vararg_tag(std::list
<std::string
>& _args
) : args(_args
) {}
44 int pushargs(state
& L
);
47 //Auxillary type for numeric-tag.
48 template<typename T
> struct _numeric_tag
51 _numeric_tag(T v
) : val(v
) {}
54 //Auxillary type for fnptr-tag.
55 template<typename T
> struct _fnptr_tag
57 int(*fn
)(state
& L
, T v
);
59 _fnptr_tag(int (*f
)(state
& L
, T v
), T v
) : fn(f
), val(v
) {}
62 //Auxillary type for fn-tag.
63 template<typename T
> struct _fn_tag
66 _fn_tag(T f
) : fn(f
) {}
70 * Callback parameter: Don't pass any real parameter, but instead store specified value in specified
73 * Parameter a: The location to store value to.
74 * Parameter v: The value to store.
75 * Returns: The parameter structure.
77 template<typename T
> static struct _store_tag
<T
> store_tag(T
& a
, T v
) { return _store_tag
<T
>(a
, v
); }
79 * Callback parameter: Pass numeric value.
81 * Parameter v: The value to pass.
82 * Returns: The parameter structure.
84 template<typename T
> static struct _numeric_tag
<T
> numeric_tag(T v
) { return _numeric_tag
<T
>(v
); }
87 * Callback parameter: Execute function to push more parameters.
89 * Parameter f: The function to execute. The return value is number of additional parameters pushed.
90 * Parameter v: The value to pass to function.
91 * Returns: The parameter structure.
93 template<typename T
> static struct _fnptr_tag
<T
> fnptr_tag(int (*f
)(state
& L
, T v
), T v
)
95 return _fnptr_tag
<T
>(f
, v
);
99 * Callback parameter: Execute function to push more parameters.
101 * Parameter v: The functor to execute. Passed reference to the Lua state. The return value is number of
102 * additional parameters pushed.
103 * Returns: The parameter structure.
105 template<typename T
> static struct _fn_tag
<T
> fn_tag(T v
) { return _fn_tag
<T
>(v
); }
108 * Callback parameter: Pass boolean argument.
110 * Parameter v: The boolean value to pass.
112 struct boolean_tag
{ bool val
; boolean_tag(bool v
) : val(v
) {}};
115 * Callback parameter: Pass string argument.
117 * Parameter v: The string value to pass.
119 struct string_tag
{ std::string val
; string_tag(const std::string
& v
) : val(v
) {}};
122 * Callback parameter: Pass nil argument.
124 struct nil_tag
{ nil_tag() {}};
126 template<typename U
, typename
... T
> void _callback(int argc
, _store_tag
<U
> tag
, T
... args
)
129 _callback(argc
, args
...);
133 template<typename
... T
> void _callback(int argc
, vararg_tag tag
, T
... args
)
135 int e
= tag
.pushargs(*this);
136 _callback(argc
+ e
, args
...);
139 template<typename
... T
> void _callback(int argc
, nil_tag tag
, T
... args
)
142 _callback(argc
+ 1, args
...);
145 template<typename
... T
> void _callback(int argc
, boolean_tag tag
, T
... args
)
147 pushboolean(tag
.val
);
148 _callback(argc
+ 1, args
...);
151 template<typename
... T
> void _callback(int argc
, string_tag tag
, T
... args
)
153 pushlstring(tag
.val
.c_str(), tag
.val
.length());
154 _callback(argc
+ 1, args
...);
157 template<typename U
, typename
... T
> void _callback(int argc
, _numeric_tag
<U
> tag
, T
... args
)
160 _callback(argc
+ 1, args
...);
163 template<typename U
, typename
... T
> void _callback(int argc
, _fnptr_tag
<U
> tag
, T
... args
)
165 int extra
= tag
.fn(*this, tag
.val
);
166 _callback(argc
+ extra
, args
...);
169 template<typename U
, typename
... T
> void _callback(int argc
, _fn_tag
<U
> tag
, T
... args
)
171 int extra
= tag
.fn(*this);
172 _callback(argc
+ extra
, args
...);
175 void _callback(int argc
)
177 int r
= pcall(argc
, 0, 0);
178 if(r
== LUA_ERRRUN
) {
179 (stringfmt() << "Error running Lua callback: " << tostring(-1)).throwex();
182 if(r
== LUA_ERRMEM
) {
183 (stringfmt() << "Error running Lua callback: Out of memory").throwex();
186 if(r
== LUA_ERRERR
) {
187 (stringfmt() << "Error running Lua callback: Double Fault???").throwex();
193 * Create a new state.
195 state() throw(std::bad_alloc
);
197 * Create a new state with specified master state.
199 state(state
& _master
, lua_State
* L
);
205 * Get the internal state object.
207 * Return value: Internal state.
209 lua_State
* handle() { return lua_handle
; }
211 * Get the master state.
213 state
& get_master() { return master
? master
->get_master() : *this; }
215 * Set the internal state object.
217 void handle(lua_State
* l
) { lua_handle
= l
; }
221 void set_oom_handler(void (*oom
)()) { oom_handler
= oom
? oom
: builtin_oom
; }
225 void reset() throw(std::runtime_error
, std::bad_alloc
);
229 void deinit() throw();
231 * Get a string argument.
233 * Parameter argindex: The stack index.
234 * Parameter fname: The name of function to use in error messages.
235 * Returns: The string.
236 * Throws std::runtime_error: The specified argument is not a string.
238 std::string
get_string(int argindex
, const std::string
& fname
) throw(std::runtime_error
, std::bad_alloc
)
240 if(lua_isnone(lua_handle
, argindex
))
241 (stringfmt() << "argument #" << argindex
<< " to " << fname
<< " must be string").throwex();
243 const char* f
= lua_tolstring(lua_handle
, argindex
, &len
);
245 (stringfmt() << "argument #" << argindex
<< " to " << fname
<< " must be string").throwex();
246 return std::string(f
, f
+ len
);
249 * Get a boolean argument.
251 * Parameter argindex: The stack index.
252 * Parameter fname: The name of function to use in error messages.
253 * Returns: The string.
254 * Throws std::runtime_error: The specified argument is not a boolean.
256 bool get_bool(int argindex
, const std::string
& fname
) throw(std::runtime_error
, std::bad_alloc
)
258 if(lua_isnone(lua_handle
, argindex
) || !lua_isboolean(lua_handle
, argindex
))
259 (stringfmt() << "argument #" << argindex
<< " to " << fname
<< " must be boolean").throwex();
260 return (lua_toboolean(lua_handle
, argindex
) != 0);
263 * Get a mandatory numeric argument.
265 * Parameter argindex: The stack index.
266 * Parameter fname: The name of function to use in error messages.
267 * Returns: The parsed number.
268 * Throws std::runtime_error: Bad type.
271 T
get_numeric_argument(int argindex
, const std::string
& fname
)
273 if(lua_isnone(lua_handle
, argindex
) || !lua_isnumber(lua_handle
, argindex
))
274 (stringfmt() << "Argument #" << argindex
<< " to " << fname
<< " must be numeric").throwex();
275 return static_cast<T
>(lua_tonumber(lua_handle
, argindex
));
278 * Get a optional numeric argument.
280 * Parameter argindex: The stack index.
281 * Parameter value: The place to store the value.
282 * Parameter fname: The name of function to use in error messages.
283 * Throws std::runtime_error: Bad type.
286 void get_numeric_argument(unsigned argindex
, T
& value
, const std::string
& fname
)
288 if(lua_isnoneornil(lua_handle
, argindex
))
290 if(lua_isnone(lua_handle
, argindex
) || !lua_isnumber(lua_handle
, argindex
))
291 (stringfmt() << "Argument #" << argindex
<< " to " << fname
<< " must be numeric if "
292 "present").throwex();
293 value
= static_cast<T
>(lua_tonumber(lua_handle
, argindex
));
298 * Parameter name: The name of the callback.
299 * Parameter args: Arguments to pass to the callback.
301 template<typename
... T
>
302 bool callback(const std::string
& name
, T
... args
)
304 getglobal(name
.c_str());
306 if(t
!= LUA_TFUNCTION
) {
310 _callback(0, args
...);
316 * Parameter cblist: List of environment keys to do callbacks.
317 * Parameter args: Arguments to pass to the callback.
319 template<typename
... T
>
320 bool callback(const std::list
<char>& cblist
, T
... args
)
323 for(auto& i
: cblist
) {
324 pushlightuserdata(const_cast<char*>(&i
));
325 rawget(LUA_REGISTRYINDEX
);
327 if(t
!= LUA_TFUNCTION
) {
330 _callback(0, args
...);
337 * Add a group of functions.
339 void add_function_group(function_group
& group
);
343 void function_callback(const std::string
& name
, function
* func
);
345 * Do something just once per VM.
347 * Parameter key: The do-once key value.
348 * Returns: True if called the first time for given key on given VM, false otherwise.
350 bool do_once(void* key
);
357 callback_list(state
& L
, const std::string
& name
, const std::string
& fn_cbname
= "");
359 void _register(state
& L
); //Reads callback from top of lua stack.
360 void _unregister(state
& L
); //Reads callback from top of lua stack.
361 template<typename
... T
> bool callback(T
... args
) {
362 bool any
= L
.callback(callbacks
, args
...);
363 if(fn_cbname
!= "" && L
.callback(fn_cbname
, args
...))
367 const std::string
& get_name() { return name
; }
368 void clear() { callbacks
.clear(); }
370 callback_list(const callback_list
&);
371 callback_list
& operator=(const callback_list
&);
372 std::list
<char> callbacks
;
375 std::string fn_cbname
;
378 * Enumerate all callbacks.
380 std::list
<callback_list
*> get_callbacks()
383 return master
->get_callbacks();
384 std::list
<callback_list
*> r
;
385 for(auto i
: callbacks
)
386 r
.push_back(i
.second
);
390 * Register a callback.
395 callback_proxy(state
& _L
) : parent(_L
) {}
396 void do_register(const std::string
& name
, callback_list
& callback
)
398 parent
.do_register_cb(name
, callback
);
401 * Unregister a callback.
403 void do_unregister(const std::string
& name
)
405 parent
.do_unregister_cb(name
);
411 void do_register_cb(const std::string
& name
, callback_list
& callback
)
413 callbacks
[name
] = &callback
;
416 void do_unregister_cb(const std::string
& name
)
418 callbacks
.erase(name
);
421 //All kinds of Lua API functions.
422 void pop(int n
) { lua_pop(lua_handle
, n
); }
423 void* newuserdata(size_t size
) { return lua_newuserdata(lua_handle
, size
); }
424 int setmetatable(int index
) { return lua_setmetatable(lua_handle
, index
); }
425 int type(int index
) { return lua_type(lua_handle
, index
); }
426 int getmetatable(int index
) { return lua_getmetatable(lua_handle
, index
); }
427 int rawequal(int index1
, int index2
) { return lua_rawequal(lua_handle
, index1
, index2
); }
428 void* touserdata(int index
) { return lua_touserdata(lua_handle
, index
); }
429 const void* topointer(int index
) { return lua_topointer(lua_handle
, index
); }
430 int gettop() { return lua_gettop(lua_handle
); }
431 void pushvalue(int index
) { lua_pushvalue(lua_handle
, index
); }
432 void pushlightuserdata(void* p
) { lua_pushlightuserdata(lua_handle
, p
); }
433 void rawset(int index
) { lua_rawset(lua_handle
, index
); }
434 void pushnil() { lua_pushnil(lua_handle
); }
435 void pushstring(const char* s
) { lua_pushstring(lua_handle
, s
); }
436 void rawget(int index
) { lua_rawget(lua_handle
, index
); }
437 int isnil(int index
) { return lua_isnil(lua_handle
, index
); }
438 void newtable() { lua_newtable(lua_handle
); }
439 void pushcclosure(lua_CFunction fn
, int n
) { lua_pushcclosure(lua_handle
, fn
, n
); }
440 void pushcfunction(lua_CFunction fn
) { lua_pushcfunction(lua_handle
, fn
); }
441 void setfield(int index
, const char* k
) { lua_setfield(lua_handle
, index
, k
); }
442 void getfield(int index
, const char* k
) { lua_getfield(lua_handle
, index
, k
); }
443 void getglobal(const char* name
) { lua_getglobal(lua_handle
, name
); }
444 void setglobal(const char* name
) { lua_setglobal(lua_handle
, name
); }
445 void insert(int index
) { lua_insert(lua_handle
, index
); }
446 void settable(int index
) { lua_settable(lua_handle
, index
); }
447 int isnone(int index
) { return lua_isnone(lua_handle
, index
); }
448 void pushnumber(lua_Number n
) { return lua_pushnumber(lua_handle
, n
); }
449 int isnumber(int index
) { return lua_isnumber(lua_handle
, index
); }
450 int isboolean(int index
) { return lua_isboolean(lua_handle
, index
); }
451 int toboolean(int index
) { return lua_toboolean(lua_handle
, index
); }
452 const char* tolstring(int index
, size_t *len
) { return lua_tolstring(lua_handle
, index
, len
); }
453 void pushboolean(int b
) { lua_pushboolean(lua_handle
, b
); }
454 lua_Number
tonumber(int index
) { return lua_tonumber(lua_handle
, index
); }
455 void gettable(int index
) { lua_gettable(lua_handle
, index
); }
456 #if LUA_VERSION_NUM == 501
457 int load(lua_Reader reader
, void* data
, const char* chunkname
) { return lua_load(lua_handle
, reader
, data
,
460 #if LUA_VERSION_NUM == 502
461 int load(lua_Reader reader
, void* data
, const char* chunkname
, const char* mode
) { return lua_load(lua_handle
,
462 reader
, data
, chunkname
, mode
); }
464 const char* tostring(int index
) { return lua_tostring(lua_handle
, index
); }
465 const char* tolstring(int index
, size_t& len
) { return lua_tolstring(lua_handle
, index
, &len
); }
466 void pushlstring(const char* s
, size_t len
) { lua_pushlstring(lua_handle
, s
, len
); }
467 void pushlstring(const std::string
& s
) { lua_pushlstring(lua_handle
, s
.c_str(), s
.length()); }
468 void pushlstring(const char32_t
* s
, size_t len
) { pushlstring(utf8::to8(std::u32string(s
, len
))); }
469 int pcall(int nargs
, int nresults
, int errfunc
) { return lua_pcall(lua_handle
, nargs
, nresults
, errfunc
); }
470 int next(int index
) { return lua_next(lua_handle
, index
); }
471 int isnoneornil(int index
) { return lua_isnoneornil(lua_handle
, index
); }
472 lua_Integer
tointeger(int index
) { return lua_tointeger(lua_handle
, index
); }
473 void rawgeti(int index
, int n
) { lua_rawgeti(lua_handle
, index
, n
); }
474 callback_proxy cbproxy
;
476 static void builtin_oom();
477 static void* builtin_alloc(void* user
, void* old
, size_t olds
, size_t news
);
478 void (*oom_handler
)();
480 lua_State
* lua_handle
;
481 std::set
<std::pair
<function_group
*, int>> function_groups
;
482 std::map
<std::string
, callback_list
*> callbacks
;
484 state
& operator=(state
&);