wxwidgets: Hide dumper called "NULL"
[lsnes.git] / include / library / lua-base.hpp
bloba517c0a5a5113bdbe8f232c574603876e3985eb9
1 #ifndef _library__lua_base__hpp__included__
2 #define _library__lua_base__hpp__included__
4 #include <string>
5 #include <stdexcept>
6 #include <typeinfo>
7 #include <typeindex>
8 #include <map>
9 #include <unordered_map>
10 #include <set>
11 #include <list>
12 #include <cassert>
13 #include "string.hpp"
14 #include "utf8.hpp"
15 #include "lua-version.hpp"
17 namespace lua
19 class state;
20 class function;
21 class function_group;
22 class class_group;
23 class class_base;
25 /**
26 * Lua state object.
28 class state
30 public:
31 //Auxillary type for store-tag.
32 template<typename T> struct _store_tag
34 T& addr;
35 T val;
36 _store_tag(T& a, T v) : addr(a), val(v) {}
38 //Auxillary type for vararg-tag.
39 struct vararg_tag
41 std::list<std::string> args;
42 vararg_tag(std::list<std::string>& _args) : args(_args) {}
43 int pushargs(state& L);
46 //Auxillary type for numeric-tag.
47 template<typename T> struct _numeric_tag
49 T val;
50 _numeric_tag(T v) : val(v) {}
53 //Auxillary type for fnptr-tag.
54 template<typename T> struct _fnptr_tag
56 int(*fn)(state& L, T v);
57 T val;
58 _fnptr_tag(int (*f)(state& L, T v), T v) : fn(f), val(v) {}
61 //Auxillary type for fn-tag.
62 template<typename T> struct _fn_tag
64 T fn;
65 _fn_tag(T f) : fn(f) {}
68 /**
69 * Callback parameter: Don't pass any real parameter, but instead store specified value in specified
70 * location.
72 * Parameter a: The location to store value to.
73 * Parameter v: The value to store.
74 * Returns: The parameter structure.
76 template<typename T> static struct _store_tag<T> store_tag(T& a, T v) { return _store_tag<T>(a, v); }
77 /**
78 * Callback parameter: Pass numeric value.
80 * Parameter v: The value to pass.
81 * Returns: The parameter structure.
83 template<typename T> static struct _numeric_tag<T> numeric_tag(T v) { return _numeric_tag<T>(v); }
85 /**
86 * Callback parameter: Execute function to push more parameters.
88 * Parameter f: The function to execute. The return value is number of additional parameters pushed.
89 * Parameter v: The value to pass to function.
90 * Returns: The parameter structure.
92 template<typename T> static struct _fnptr_tag<T> fnptr_tag(int (*f)(state& L, T v), T v)
94 return _fnptr_tag<T>(f, v);
97 /**
98 * Callback parameter: Execute function to push more parameters.
100 * Parameter v: The functor to execute. Passed reference to the Lua state. The return value is number of
101 * additional parameters pushed.
102 * Returns: The parameter structure.
104 template<typename T> static struct _fn_tag<T> fn_tag(T v) { return _fn_tag<T>(v); }
107 * Callback parameter: Pass boolean argument.
109 * Parameter v: The boolean value to pass.
111 struct boolean_tag { bool val; boolean_tag(bool v) : val(v) {}};
114 * Callback parameter: Pass string argument.
116 * Parameter v: The string value to pass.
118 struct string_tag { std::string val; string_tag(const std::string& v) : val(v) {}};
121 * Callback parameter: Pass nil argument.
123 struct nil_tag { nil_tag() {}};
124 private:
125 template<typename U, typename... T> void _callback(int argc, _store_tag<U> tag, T... args)
127 tag.addr = tag.val;
128 _callback(argc, args...);
129 tag.addr = NULL;
132 template<typename... T> void _callback(int argc, vararg_tag tag, T... args)
134 int e = tag.pushargs(*this);
135 _callback(argc + e, args...);
138 template<typename... T> void _callback(int argc, nil_tag tag, T... args)
140 pushnil();
141 _callback(argc + 1, args...);
144 template<typename... T> void _callback(int argc, boolean_tag tag, T... args)
146 pushboolean(tag.val);
147 _callback(argc + 1, args...);
150 template<typename... T> void _callback(int argc, string_tag tag, T... args)
152 pushlstring(tag.val);
153 _callback(argc + 1, args...);
156 template<typename U, typename... T> void _callback(int argc, _numeric_tag<U> tag, T... args)
158 pushnumber(tag.val);
159 _callback(argc + 1, args...);
162 template<typename U, typename... T> void _callback(int argc, _fnptr_tag<U> tag, T... args)
164 int extra = tag.fn(*this, tag.val);
165 _callback(argc + extra, args...);
168 template<typename U, typename... T> void _callback(int argc, _fn_tag<U> tag, T... args)
170 int extra = tag.fn(*this);
171 _callback(argc + extra, args...);
174 void _callback(int argc)
176 int r = pcall(argc, 0, 0);
177 if(r == LUA_ERRRUN) {
178 (stringfmt() << "Error running Lua callback: " << tostring(-1)).throwex();
179 pop(1);
181 if(r == LUA_ERRMEM) {
182 (stringfmt() << "Error running Lua callback: Out of memory").throwex();
183 pop(1);
185 if(r == LUA_ERRERR) {
186 (stringfmt() << "Error running Lua callback: Double Fault???").throwex();
187 pop(1);
190 public:
192 * Create a new state.
194 state() throw(std::bad_alloc);
196 * Create a new state with specified master state.
198 state(state& _master, lua_State* L);
200 * Destroy a state.
202 ~state() throw();
204 * Get the internal state object.
206 * Return value: Internal state.
208 lua_State* handle() { return lua_handle; }
210 * Get the master state.
212 state& get_master() { return master ? master->get_master() : *this; }
214 * Set the internal state object.
216 void handle(lua_State* l) { lua_handle = l; }
218 * Set OOM handler.
220 void set_oom_handler(void (*oom)()) { oom_handler = oom ? oom : builtin_oom; }
222 * Reset the state.
224 void reset() throw(std::runtime_error, std::bad_alloc);
226 * Deinit the state.
228 void deinit() throw();
230 * Get a string argument.
232 * Parameter argindex: The stack index.
233 * Parameter fname: The name of function to use in error messages.
234 * Returns: The string.
235 * Throws std::runtime_error: The specified argument is not a string.
237 std::string get_string(int argindex, const std::string& fname) throw(std::runtime_error, std::bad_alloc)
239 if(isnone(argindex))
240 (stringfmt() << "argument #" << argindex << " to " << fname << " must be string").throwex();
241 size_t len;
242 const char* f = lua_tolstring(lua_handle, argindex, &len);
243 if(!f)
244 (stringfmt() << "argument #" << argindex << " to " << fname << " must be string").throwex();
245 return std::string(f, f + len);
248 * Get a boolean argument.
250 * Parameter argindex: The stack index.
251 * Parameter fname: The name of function to use in error messages.
252 * Returns: The string.
253 * Throws std::runtime_error: The specified argument is not a boolean.
255 bool get_bool(int argindex, const std::string& fname) throw(std::runtime_error, std::bad_alloc)
257 if(isnone(argindex) || !isboolean(argindex))
258 (stringfmt() << "argument #" << argindex << " to " << fname << " must be boolean").throwex();
259 return (lua_toboolean(lua_handle, argindex) != 0);
262 * Get a mandatory numeric argument.
264 * Parameter argindex: The stack index.
265 * Parameter fname: The name of function to use in error messages.
266 * Returns: The parsed number.
267 * Throws std::runtime_error: Bad type.
269 template<typename T>
270 T get_numeric_argument(int argindex, const std::string& fname)
272 if(std::numeric_limits<T>::is_integer) {
273 if(isnone(argindex) || !isinteger(argindex))
274 (stringfmt() << "Argument #" << argindex << " to " << fname
275 << " must be integer").throwex();
276 return static_cast<T>(lua_tointeger(lua_handle, argindex));
277 } else {
278 if(isnone(argindex) || !isnumber(argindex))
279 (stringfmt() << "Argument #" << argindex << " to " << fname
280 << " must be numeric").throwex();
281 return static_cast<T>(lua_tonumber(lua_handle, argindex));
285 * Get a optional numeric argument.
287 * Parameter argindex: The stack index.
288 * Parameter value: The place to store the value.
289 * Parameter fname: The name of function to use in error messages.
290 * Throws std::runtime_error: Bad type.
292 template<typename T>
293 void get_numeric_argument(unsigned argindex, T& value, const std::string& fname)
295 if(isnoneornil(argindex))
296 return;
297 if(std::numeric_limits<T>::is_integer) {
298 if(isnone(argindex) || !isinteger(argindex))
299 (stringfmt() << "Argument #" << argindex << " to " << fname << " must be integer if "
300 "present").throwex();
301 value = static_cast<T>(lua_tointeger(lua_handle, argindex));
302 } else {
303 if(isnone(argindex) || !isnumber(argindex))
304 (stringfmt() << "Argument #" << argindex << " to " << fname << " must be numeric if "
305 "present").throwex();
306 value = static_cast<T>(lua_tonumber(lua_handle, argindex));
310 * Do a callback.
312 * Parameter name: The name of the callback.
313 * Parameter args: Arguments to pass to the callback.
315 template<typename... T>
316 bool callback(const std::string& name, T... args)
318 getglobal(name.c_str());
319 int t = type(-1);
320 if(t != LUA_TFUNCTION) {
321 pop(1);
322 return false;
324 _callback(0, args...);
325 return true;
328 * Do a callback.
330 * Parameter cblist: List of environment keys to do callbacks.
331 * Parameter args: Arguments to pass to the callback.
333 template<typename... T>
334 bool callback(const std::list<char>& cblist, T... args)
336 bool any = false;
337 for(auto& i : cblist) {
338 pushlightuserdata(const_cast<char*>(&i));
339 rawget(LUA_REGISTRYINDEX);
340 int t = type(-1);
341 if(t != LUA_TFUNCTION) {
342 pop(1);
343 } else {
344 _callback(0, args...);
345 any = true;
348 return any;
351 * Add a group of functions.
353 void add_function_group(function_group& group);
355 * Add a group of classes.
357 void add_class_group(class_group& group);
359 * Function callback.
361 void function_callback(const std::string& name, function* func);
363 * Class callback.
365 void class_callback(const std::string& name, class_base* func);
367 * Do something just once per VM.
369 * Parameter key: The do-once key value.
370 * Returns: True if called the first time for given key on given VM, false otherwise.
372 bool do_once(void* key);
374 * Callback list.
376 class callback_list
378 public:
379 callback_list(state& L, const std::string& name, const std::string& fn_cbname = "");
380 ~callback_list();
381 void _register(state& L); //Reads callback from top of lua stack.
382 void _unregister(state& L); //Reads callback from top of lua stack.
383 template<typename... T> bool callback(T... args) {
384 bool any = L.callback(callbacks, args...);
385 if(fn_cbname != "" && L.callback(fn_cbname, args...))
386 any = true;
387 return any;
389 const std::string& get_name() { return name; }
390 void clear() { callbacks.clear(); }
391 private:
392 callback_list(const callback_list&);
393 callback_list& operator=(const callback_list&);
394 std::list<char> callbacks;
395 state& L;
396 std::string name;
397 std::string fn_cbname;
400 * Enumerate all callbacks.
402 std::list<callback_list*> get_callbacks();
404 * Register/Unregister a callback list.
406 void do_register(const std::string& name, callback_list& callback);
407 void do_unregister(const std::string& name, callback_list& callback);
409 //All kinds of Lua API functions.
410 void pop(int n) { lua_pop(lua_handle, n); }
411 void* newuserdata(size_t size) { return lua_newuserdata(lua_handle, size); }
412 int setmetatable(int index) { return lua_setmetatable(lua_handle, index); }
413 int type(int index) { return lua_type(lua_handle, index); }
414 int getmetatable(int index) { return lua_getmetatable(lua_handle, index); }
415 int rawequal(int index1, int index2) { return lua_rawequal(lua_handle, index1, index2); }
416 void* touserdata(int index) { return lua_touserdata(lua_handle, index); }
417 const void* topointer(int index) { return lua_topointer(lua_handle, index); }
418 int gettop() { return lua_gettop(lua_handle); }
419 void pushvalue(int index) { lua_pushvalue(lua_handle, index); }
420 void pushlightuserdata(void* p) { lua_pushlightuserdata(lua_handle, p); }
421 void rawset(int index) { lua_rawset(lua_handle, index); }
422 void pushnil() { lua_pushnil(lua_handle); }
423 void pushstring(const char* s) { lua_pushstring(lua_handle, s); }
424 void rawget(int index) { lua_rawget(lua_handle, index); }
425 int isnil(int index) { return lua_isnil(lua_handle, index); }
426 void newtable() { lua_newtable(lua_handle); }
427 void pushcclosure(lua_CFunction fn, int n) { lua_pushcclosure(lua_handle, fn, n); }
428 void pushcfunction(lua_CFunction fn) { lua_pushcfunction(lua_handle, fn); }
429 void setfield(int index, const char* k) { lua_setfield(lua_handle, index, k); }
430 void getfield(int index, const char* k) { lua_getfield(lua_handle, index, k); }
431 void getglobal(const char* name) { lua_getglobal(lua_handle, name); }
432 void setglobal(const char* name) { lua_setglobal(lua_handle, name); }
433 void insert(int index) { lua_insert(lua_handle, index); }
434 void settable(int index) { lua_settable(lua_handle, index); }
435 int isnone(int index) { return lua_isnone(lua_handle, index); }
436 int isnumber(int index) { return lua_isnumber(lua_handle, index); }
437 int isinteger(int index) { return LUA_INTEGER_POSTFIX(lua_is) (lua_handle, index); }
438 int isboolean(int index) { return lua_isboolean(lua_handle, index); }
439 int toboolean(int index) { return lua_toboolean(lua_handle, index); }
440 const char* tolstring(int index, size_t *len) { return lua_tolstring(lua_handle, index, len); }
441 lua_Number tonumber(int index) { return lua_tonumber(lua_handle, index); }
442 uint64_t tointeger(int index) { return LUA_INTEGER_POSTFIX(lua_to) (lua_handle, index); }
443 void gettable(int index) { lua_gettable(lua_handle, index); }
444 int load(lua_Reader reader, void* data, const char* chunkname, const char* mode) {
445 (void)mode;
446 return lua_load(lua_handle, reader, data, chunkname LUA_LOADMODE_ARG(mode) );
448 const char* tostring(int index) { return lua_tostring(lua_handle, index); }
449 const char* tolstring(int index, size_t& len) { return lua_tolstring(lua_handle, index, &len); }
450 void pushlstring(const char* s, size_t len) { lua_pushlstring(lua_handle, s, len); }
451 void pushlstring(const std::string& s) { lua_pushlstring(lua_handle, s.c_str(), s.length()); }
452 void pushlstring(const char32_t* s, size_t len) { pushlstring(utf8::to8(std::u32string(s, len))); }
453 int pcall(int nargs, int nresults, int errfunc) { return lua_pcall(lua_handle, nargs, nresults, errfunc); }
454 int next(int index) { return lua_next(lua_handle, index); }
455 int isnoneornil(int index) { return lua_isnoneornil(lua_handle, index); }
456 void rawgeti(int index, int n) { lua_rawgeti(lua_handle, index, n); }
457 template<typename T> void pushnumber(T val)
459 if(std::numeric_limits<T>::is_integer)
460 _pushinteger(val);
461 else
462 _pushnumber(val);
464 void pushboolean(bool b) { lua_pushboolean(lua_handle, b); }
465 void pushglobals() { LUA_LOADGLOBALS }
466 private:
467 void _pushnumber(lua_Number n) { return lua_pushnumber(lua_handle, n); }
468 void _pushinteger(uint64_t n) { return LUA_INTEGER_POSTFIX(lua_push) (lua_handle, n); }
469 static void builtin_oom();
470 static void* builtin_alloc(void* user, void* old, size_t olds, size_t news);
471 void (*oom_handler)();
472 state* master;
473 lua_State* lua_handle;
474 state(state&);
475 state& operator=(state&);
480 #endif