Actually call on_reset callback
[lsnes.git] / include / library / lua-base.hpp
blob649cb081a245e094d2cd94ba251f1ec760d0c226
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 <functional>
11 #include <set>
12 #include <list>
13 #include <cassert>
14 #include "string.hpp"
15 #include "utf8.hpp"
16 #include "int24.hpp"
17 #include "lua-version.hpp"
19 namespace lua
21 class state;
22 class function;
23 class function_group;
24 class class_group;
25 class class_base;
27 /**
28 * Lua state object.
30 class state
32 public:
33 const static unsigned trampoline_upvals = 2;
34 //Auxillary type for store-tag.
35 template<typename T> struct _store_tag
37 T& addr;
38 T val;
39 _store_tag(T& a, T v) : addr(a), val(v) {}
41 //Auxillary type for vararg-tag.
42 struct vararg_tag
44 std::list<std::string> args;
45 vararg_tag(std::list<std::string>& _args) : args(_args) {}
46 int pushargs(state& L);
49 //Auxillary type for numeric-tag.
50 template<typename T> struct _numeric_tag
52 T val;
53 _numeric_tag(T v) : val(v) {}
56 //Auxillary type for fnptr-tag.
57 template<typename T> struct _fnptr_tag
59 int(*fn)(state& L, T v);
60 T val;
61 _fnptr_tag(int (*f)(state& L, T v), T v) : fn(f), val(v) {}
64 //Auxillary type for fn-tag.
65 template<typename T> struct _fn_tag
67 T fn;
68 _fn_tag(T f) : fn(f) {}
71 /**
72 * Callback parameter: Don't pass any real parameter, but instead store specified value in specified
73 * location.
75 * Parameter a: The location to store value to.
76 * Parameter v: The value to store.
77 * Returns: The parameter structure.
79 template<typename T> static struct _store_tag<T> store_tag(T& a, T v) { return _store_tag<T>(a, v); }
80 /**
81 * Callback parameter: Pass numeric value.
83 * Parameter v: The value to pass.
84 * Returns: The parameter structure.
86 template<typename T> static struct _numeric_tag<T> numeric_tag(T v) { return _numeric_tag<T>(v); }
88 /**
89 * Callback parameter: Execute function to push more parameters.
91 * Parameter f: The function to execute. The return value is number of additional parameters pushed.
92 * Parameter v: The value to pass to function.
93 * Returns: The parameter structure.
95 template<typename T> static struct _fnptr_tag<T> fnptr_tag(int (*f)(state& L, T v), T v)
97 return _fnptr_tag<T>(f, v);
101 * Callback parameter: Execute function to push more parameters.
103 * Parameter v: The functor to execute. Passed reference to the Lua state. The return value is number of
104 * additional parameters pushed.
105 * Returns: The parameter structure.
107 template<typename T> static struct _fn_tag<T> fn_tag(T v) { return _fn_tag<T>(v); }
110 * Callback parameter: Pass boolean argument.
112 * Parameter v: The boolean value to pass.
114 struct boolean_tag { bool val; boolean_tag(bool v) : val(v) {}};
117 * Callback parameter: Pass string argument.
119 * Parameter v: The string value to pass.
121 struct string_tag { std::string val; string_tag(const std::string& v) : val(v) {}};
124 * Callback parameter: Pass nil argument.
126 struct nil_tag { nil_tag() {}};
127 private:
128 template<typename U, typename... T> void _callback(int argc, _store_tag<U> tag, T... args)
130 tag.addr = tag.val;
131 _callback(argc, args...);
132 tag.addr = NULL;
135 template<typename... T> void _callback(int argc, vararg_tag tag, T... args)
137 int e = tag.pushargs(*this);
138 _callback(argc + e, args...);
141 template<typename... T> void _callback(int argc, nil_tag tag, T... args)
143 pushnil();
144 _callback(argc + 1, args...);
147 template<typename... T> void _callback(int argc, boolean_tag tag, T... args)
149 pushboolean(tag.val);
150 _callback(argc + 1, args...);
153 template<typename... T> void _callback(int argc, string_tag tag, T... args)
155 pushlstring(tag.val);
156 _callback(argc + 1, args...);
159 template<typename U, typename... T> void _callback(int argc, _numeric_tag<U> tag, T... args)
161 pushnumber(tag.val);
162 _callback(argc + 1, args...);
165 template<typename U, typename... T> void _callback(int argc, _fnptr_tag<U> tag, T... args)
167 int extra = tag.fn(*this, tag.val);
168 _callback(argc + extra, args...);
171 template<typename U, typename... T> void _callback(int argc, _fn_tag<U> tag, T... args)
173 int extra = tag.fn(*this);
174 _callback(argc + extra, args...);
177 void _callback(int argc)
179 int r = pcall(argc, 0, 0);
180 if(r == LUA_ERRRUN) {
181 (stringfmt() << "Error running Lua callback: " << tostring(-1)).throwex();
182 pop(1);
184 if(r == LUA_ERRMEM) {
185 (stringfmt() << "Error running Lua callback: Out of memory").throwex();
186 pop(1);
188 if(r == LUA_ERRERR) {
189 (stringfmt() << "Error running Lua callback: Double Fault???").throwex();
190 pop(1);
193 public:
195 * Create a new state.
197 state();
199 * Create a new state with specified master state.
201 state(state& _master, lua_State* L);
203 * Destroy a state.
205 ~state() throw();
207 * Get the internal state object.
209 * Return value: Internal state.
211 lua_State* handle() { return lua_handle; }
213 * Get the master state.
215 state& get_master() { return master ? master->get_master() : *this; }
217 * Set the internal state object.
219 void handle(lua_State* l) { lua_handle = l; }
221 * Set OOM handler.
223 void set_oom_handler(void (*oom)()) { oom_handler = oom ? oom : builtin_oom; }
225 * Set soft OOM handler.
227 void set_soft_oom_handler(void (*oom)(int status)) { soft_oom_handler = oom ? oom : builtin_soft_oom; }
229 * Set memory use change handler.
231 void set_memory_change_handler(std::function<void(ssize_t change)> cb)
233 memory_change = cb;
236 * Reset the state.
238 void reset();
240 * Deinit the state.
242 void deinit() throw();
244 * Create a trampoline.
246 * Parameter fn The function to execute.
247 * Parameter n_upvals The number of extra upvalues besides the 2 used by trampoline itself. Popped from stack.
249 void push_trampoline(int(*fn)(state& L), unsigned n_upvals);
251 * Get specified trampoline upvalue index.
253 int trampoline_upval(int val) { return lua_upvalueindex(trampoline_upvals + val); }
255 * Set value of interruptable flag.
257 * Parameter flag: The flag.
259 void set_interruptable_flag(bool flag)
261 if(master) master->set_interruptable_flag(flag); else interruptable = flag;
264 * Get interruptable flag.
266 bool get_interruptable_flag()
268 if(master) return master->get_interruptable_flag(); else return interruptable;
271 * Set memory limit.
273 void set_memory_limit(size_t limit)
275 if(master) master->set_memory_limit(limit); else memory_limit = limit;
278 * Get memory limit.
280 size_t get_memory_limit()
282 if(master) return master->get_memory_limit(); else return memory_limit;
285 * Get memory use.
287 size_t get_memory_use()
289 if(master) return master->get_memory_use(); else return memory_use;
292 * Charge against memory limit.
294 bool charge_memory(size_t amount, bool release);
296 * Execute function in interruptable mode.
298 * Parameter fn: The function to execute
299 * Parameter in: Number of slots to copy in.
300 * Parameter out: Number of slots to copy out.
302 void run_interruptable(std::function<void()> fn, unsigned in, unsigned out);
304 * Get a string argument.
306 * Parameter argindex: The stack index.
307 * Parameter fname: The name of function to use in error messages.
308 * Returns: The string.
309 * Throws std::runtime_error: The specified argument is not a string.
311 std::string get_string(int argindex, const std::string& fname)
313 if(isnone(argindex))
314 (stringfmt() << "argument #" << argindex << " to " << fname << " must be string").throwex();
315 size_t len;
316 const char* f = lua_tolstring(lua_handle, argindex, &len);
317 if(!f)
318 (stringfmt() << "argument #" << argindex << " to " << fname << " must be string").throwex();
319 return std::string(f, f + len);
322 * Read slot as string.
324 * Parameter argindex: The stack index.
325 * Returns: The string.
327 std::string as_string(int argindex)
329 if(isnone(argindex)) return "(none)";
330 size_t len;
331 const char* f = lua_tolstring(lua_handle, argindex, &len);
332 if(!f) return "(null)";
333 return std::string(f, f + len);
336 * Get a boolean argument.
338 * Parameter argindex: The stack index.
339 * Parameter fname: The name of function to use in error messages.
340 * Returns: The string.
341 * Throws std::runtime_error: The specified argument is not a boolean.
343 bool get_bool(int argindex, const std::string& fname)
345 if(isnone(argindex) || !isboolean(argindex))
346 (stringfmt() << "argument #" << argindex << " to " << fname << " must be boolean").throwex();
347 return (lua_toboolean(lua_handle, argindex) != 0);
350 * Get a mandatory numeric argument.
352 * Parameter argindex: The stack index.
353 * Parameter fname: The name of function to use in error messages.
354 * Returns: The parsed number.
355 * Throws std::runtime_error: Bad type.
357 template<typename T>
358 T get_numeric_argument(int argindex, const std::string& fname)
360 if(std::numeric_limits<T>::is_integer) {
361 if(isnone(argindex) || !isinteger(argindex))
362 (stringfmt() << "Argument #" << argindex << " to " << fname
363 << " must be integer").throwex();
364 return static_cast<T>(lua_tointeger(lua_handle, argindex));
365 } else {
366 if(isnone(argindex) || !isnumber(argindex))
367 (stringfmt() << "Argument #" << argindex << " to " << fname
368 << " must be numeric").throwex();
369 return static_cast<T>(lua_tonumber(lua_handle, argindex));
373 * Get a optional numeric argument.
375 * Parameter argindex: The stack index.
376 * Parameter value: The place to store the value.
377 * Parameter fname: The name of function to use in error messages.
378 * Throws std::runtime_error: Bad type.
380 template<typename T>
381 void get_numeric_argument(unsigned argindex, T& value, const std::string& fname)
383 if(isnoneornil(argindex))
384 return;
385 if(std::numeric_limits<T>::is_integer) {
386 if(isnone(argindex) || !isinteger(argindex))
387 (stringfmt() << "Argument #" << argindex << " to " << fname << " must be integer if "
388 "present").throwex();
389 value = static_cast<T>(lua_tointeger(lua_handle, argindex));
390 } else {
391 if(isnone(argindex) || !isnumber(argindex))
392 (stringfmt() << "Argument #" << argindex << " to " << fname << " must be numeric if "
393 "present").throwex();
394 value = static_cast<T>(lua_tonumber(lua_handle, argindex));
398 * Do a callback.
400 * Parameter name: The name of the callback.
401 * Parameter args: Arguments to pass to the callback.
403 template<typename... T>
404 bool callback(const std::string& name, T... args)
406 getglobal(name.c_str());
407 int t = type(-1);
408 if(t != LUA_TFUNCTION) {
409 pop(1);
410 return false;
412 _callback(0, args...);
413 return true;
416 * Do a callback.
418 * Parameter cblist: List of environment keys to do callbacks.
419 * Parameter args: Arguments to pass to the callback.
421 template<typename... T>
422 bool callback(std::list<char>& cblist, const char*& r_cb, bool& r_cb_f, T... args)
424 bool any = false;
425 for(auto i = cblist.begin(); i != cblist.end();) {
426 pushlightuserdata(const_cast<char*>(&*i));
427 rawget(LUA_REGISTRYINDEX);
428 int t = type(-1);
429 if(t != LUA_TFUNCTION) {
430 pop(1);
431 } else {
432 //Note the currently running CB so that unregister treats it specially if it is
433 //unrgistered.
434 r_cb = &*i;
435 _callback(0, args...);
436 r_cb = NULL;
437 any = true;
439 //Currently iterated function may be erased. The memory has to be freed in that case.
440 if(r_cb_f) {
441 r_cb_f = false;
442 i = cblist.erase(i);
443 } else {
444 i++;
447 return any;
450 * Add a group of functions.
452 void add_function_group(function_group& group);
454 * Add a group of classes.
456 void add_class_group(class_group& group);
458 * Function callback.
460 void function_callback(const std::string& name, function* func);
462 * Class callback.
464 void class_callback(const std::string& name, class_base* func);
466 * Do something just once per VM.
468 * Parameter key: The do-once key value.
469 * Returns: True if called the first time for given key on given VM, false otherwise.
471 bool do_once(void* key);
473 * Callback list.
475 class callback_list
477 public:
478 callback_list(state& L, const std::string& name, const std::string& fn_cbname = "");
479 ~callback_list();
480 void _register(state& L); //Reads callback from top of lua stack.
481 void _unregister(state& L); //Reads callback from top of lua stack.
482 template<typename... T> bool callback(T... args) {
483 bool any = L.callback(callbacks, running_cb, running_cb_f, args...);
484 if(fn_cbname != "" && L.callback(fn_cbname, args...))
485 any = true;
486 return any;
488 const std::string& get_name() { return name; }
489 void clear() { callbacks.clear(); }
490 private:
491 callback_list(const callback_list&);
492 callback_list& operator=(const callback_list&);
493 std::list<char> callbacks;
494 const char* running_cb;
495 bool running_cb_f;
496 state& L;
497 std::string name;
498 std::string fn_cbname;
501 * Enumerate all callbacks.
503 std::list<callback_list*> get_callbacks();
505 * Register/Unregister a callback list.
507 void do_register(const std::string& name, callback_list& callback);
508 void do_unregister(const std::string& name, callback_list& callback);
510 //All kinds of Lua API functions.
511 void pop(int n) { lua_pop(lua_handle, n); }
512 void* newuserdata(size_t size) { return lua_newuserdata(lua_handle, size); }
513 int setmetatable(int index) { return lua_setmetatable(lua_handle, index); }
514 int type(int index) { return lua_type(lua_handle, index); }
515 void replace(int index) { lua_replace(lua_handle, index); }
516 int getmetatable(int index) { return lua_getmetatable(lua_handle, index); }
517 int rawequal(int index1, int index2) { return lua_rawequal(lua_handle, index1, index2); }
518 void* touserdata(int index) { return lua_touserdata(lua_handle, index); }
519 const void* topointer(int index) { return lua_topointer(lua_handle, index); }
520 int gettop() { return lua_gettop(lua_handle); }
521 void pushvalue(int index) { lua_pushvalue(lua_handle, index); }
522 void pushlightuserdata(void* p) { lua_pushlightuserdata(lua_handle, p); }
523 void rawset(int index) { lua_rawset(lua_handle, index); }
524 void pushnil() { lua_pushnil(lua_handle); }
525 void pushstring(const char* s) { lua_pushstring(lua_handle, s); }
526 void rawget(int index) { lua_rawget(lua_handle, index); }
527 int isnil(int index) { return lua_isnil(lua_handle, index); }
528 void newtable() { lua_newtable(lua_handle); }
529 void pushcclosure(lua_CFunction fn, int n) { lua_pushcclosure(lua_handle, fn, n); }
530 void pushcfunction(lua_CFunction fn) { lua_pushcfunction(lua_handle, fn); }
531 void setfield(int index, const char* k) { lua_setfield(lua_handle, index, k); }
532 void getfield(int index, const char* k) { lua_getfield(lua_handle, index, k); }
533 void getglobal(const char* name) { lua_getglobal(lua_handle, name); }
534 void setglobal(const char* name) { lua_setglobal(lua_handle, name); }
535 void insert(int index) { lua_insert(lua_handle, index); }
536 void settable(int index) { lua_settable(lua_handle, index); }
537 int isnone(int index) { return lua_isnone(lua_handle, index); }
538 int isnumber(int index) { return lua_isnumber(lua_handle, index); }
539 int isinteger(int index) { return LUA_INTEGER_POSTFIX(lua_is) (lua_handle, index); }
540 int isboolean(int index) { return lua_isboolean(lua_handle, index); }
541 int toboolean(int index) { return lua_toboolean(lua_handle, index); }
542 const char* tolstring(int index, size_t *len) { return lua_tolstring(lua_handle, index, len); }
543 lua_Number tonumber(int index) { return lua_tonumber(lua_handle, index); }
544 int64_t tointeger(int index) { return LUA_INTEGER_POSTFIX(lua_to) (lua_handle, index); }
545 void gettable(int index) { lua_gettable(lua_handle, index); }
546 int load(lua_Reader reader, void* data, const char* chunkname, const char* mode) {
547 (void)mode;
548 return lua_load(lua_handle, reader, data, chunkname LUA_LOADMODE_ARG(mode) );
550 const char* tostring(int index) { return lua_tostring(lua_handle, index); }
551 const char* tolstring(int index, size_t& len) { return lua_tolstring(lua_handle, index, &len); }
552 void pushlstring(const char* s, size_t len) { lua_pushlstring(lua_handle, s, len); }
553 void pushlstring(const std::string& s) { lua_pushlstring(lua_handle, s.c_str(), s.length()); }
554 void pushlstring(const char32_t* s, size_t len) { pushlstring(utf8::to8(std::u32string(s, len))); }
555 int pcall(int nargs, int nresults, int errfunc)
557 state* master_state = this;
558 while(master_state->master) master_state = master_state->master;
559 //Upon entry to protected mode, interruptable mode is always set, and it is restored on exit
560 //from protected mode.
561 bool old_interruptable = master_state->interruptable;
562 master_state->interruptable = true;
563 auto ret = lua_pcall(lua_handle, nargs, nresults, errfunc);
564 master_state->interruptable = old_interruptable;
565 return ret;
567 int next(int index) { return lua_next(lua_handle, index); }
568 int isnoneornil(int index) { return lua_isnoneornil(lua_handle, index); }
569 void rawgeti(int index, int n) { lua_rawgeti(lua_handle, index, n); }
570 template<typename T> void pushnumber(T val)
572 if(std::numeric_limits<T>::is_integer || is_ss_int24<T>::flag)
573 return LUA_INTEGER_POSTFIX(lua_push) (lua_handle, val);
574 else
575 return lua_pushnumber(lua_handle, val);
577 void pushboolean(bool b) { lua_pushboolean(lua_handle, b); }
578 void pushglobals() { LUA_LOADGLOBALS }
579 private:
580 static void builtin_oom();
581 static void builtin_soft_oom(int status);
582 static void* builtin_alloc(void* user, void* old, size_t olds, size_t news);
583 void (*oom_handler)();
584 void (*soft_oom_handler)(int status);
585 std::function<void(ssize_t change)> memory_change;
586 state* master;
587 bool interruptable;
588 size_t memory_limit;
589 size_t memory_use;
590 lua_State* lua_handle;
591 state(state&);
592 state& operator=(state&);
597 #endif