Lua: Add on_idle() and on_timer()
[lsnes.git] / include / core / lua-int.hpp
blob329fdfaa715c6913f9f4a861b524b0e16b109014
1 #ifndef _lua_int__hpp__included__
2 #define _lua_int__hpp__included__
4 #include "lua.hpp"
5 #include <cstdio>
6 #include <cstdlib>
7 extern "C"
9 #include <lua.h>
12 std::string get_string_argument(lua_State* LS, unsigned argindex, const char* fname);
13 bool get_boolean_argument(lua_State* LS, unsigned argindex, const char* fname);
14 void push_keygroup_parameters(lua_State* LS, const struct keygroup::parameters& p);
15 extern lua_render_context* lua_render_ctx;
16 extern controller_frame* lua_input_controllerdata;
17 extern bool lua_booted_flag;
18 extern uint64_t lua_idle_hook_time;
19 extern uint64_t lua_timer_hook_time;
21 template<typename T>
22 T get_numeric_argument(lua_State* LS, unsigned argindex, const char* fname)
24 if(lua_isnone(LS, argindex) || !lua_isnumber(LS, argindex)) {
25 char buffer[1024];
26 sprintf(buffer, "argument #%i to %s must be numeric", argindex, fname);
27 lua_pushstring(LS, buffer);
28 lua_error(LS);
30 return static_cast<T>(lua_tonumber(LS, argindex));
33 template<typename T>
34 void get_numeric_argument(lua_State* LS, unsigned argindex, T& value, const char* fname)
36 if(lua_isnoneornil(LS, argindex))
37 return;
38 if(lua_isnone(LS, argindex) || !lua_isnumber(LS, argindex)) {
39 char buffer[1024];
40 sprintf(buffer, "argument #%i to %s must be numeric if present", argindex, fname);
41 lua_pushstring(LS, buffer);
42 lua_error(LS);
44 value = static_cast<T>(lua_tonumber(LS, argindex));
48 template<typename T> struct lua_obj_pin
50 lua_obj_pin(lua_State* LS, T* _object)
52 lua_pushlightuserdata(LS, this);
53 lua_pushvalue(LS, -2);
54 lua_rawset(LS, LUA_REGISTRYINDEX);
55 state = LS;
56 obj = _object;
58 ~lua_obj_pin()
60 lua_pushlightuserdata(state, this);
61 lua_pushnil(state);
62 lua_rawset(state, LUA_REGISTRYINDEX);
64 T* object() { return obj; }
65 private:
66 T* obj;
67 lua_State* state;
68 lua_obj_pin(const lua_obj_pin&);
69 lua_obj_pin& operator=(const lua_obj_pin&);
72 template<class T> class lua_class;
74 template<class T> lua_class<T>& objclass();
76 template<class T> class lua_class
78 public:
79 lua_class(const std::string& _name)
81 name = _name;
84 template<typename... U> T* _create(lua_State* LS, U... args)
86 void* obj = lua_newuserdata(LS, sizeof(T));
87 load_metatable(LS);
88 lua_setmetatable(LS, -2);
89 T* _obj = reinterpret_cast<T*>(obj);
90 new(_obj) T(args...);
91 return _obj;
94 template<typename... U> static T* create(lua_State* LS, U... args)
96 return objclass<T>()._create(LS, args...);
99 void bind(lua_State* LS)
101 load_metatable(LS);
102 lua_pushvalue(LS, -3);
103 lua_pushvalue(LS, -3);
104 lua_rawset(LS, -3);
107 void bind(lua_State* LS, const char* keyname)
109 load_metatable(LS);
110 lua_pushstring(LS, keyname);
111 lua_pushvalue(LS, -3);
112 lua_rawset(LS, -3);
115 T* _get(lua_State* LS, int arg, const char* fname, bool optional = false)
117 if(lua_type(LS, arg) == LUA_TNONE || lua_type(LS, arg) == LUA_TNIL) {
118 if(optional)
119 return NULL;
120 else
121 goto badtype;
123 load_metatable(LS);
124 if(!lua_getmetatable(LS, arg))
125 goto badtype;
126 if(!lua_rawequal(LS, -1, -2))
127 goto badtype;
128 lua_pop(LS, 2);
129 return reinterpret_cast<T*>(lua_touserdata(LS, arg));
130 badtype:
131 char buffer[2048];
132 sprintf(buffer, "argument #%i to %s must be %s", arg, fname, name.c_str());
133 lua_pushstring(LS, buffer);
134 lua_error(LS);
137 static T* get(lua_State* LS, int arg, const char* fname, bool optional = false)
139 return objclass<T>()._get(LS, arg, fname, optional);
142 bool _is(lua_State* LS, int arg)
144 if(lua_type(LS, arg) != LUA_TUSERDATA)
145 return false;
146 load_metatable(LS);
147 if(!lua_getmetatable(LS, arg)) {
148 lua_pop(LS, 1);
149 return false;
151 bool ret = lua_rawequal(LS, -1, -2);
152 lua_pop(LS, 2);
153 return ret;
156 static bool is(lua_State* LS, int arg)
158 return objclass<T>()._is(LS, arg);
161 lua_obj_pin<T>* _pin(lua_State* LS, int arg, const char* fname)
163 T* obj = get(LS, arg, fname);
164 lua_pushvalue(LS, arg);
165 return new lua_obj_pin<T>(LS, obj);
168 static lua_obj_pin<T>* pin(lua_State* LS, int arg, const char* fname)
170 return objclass<T>()._pin(LS, arg, fname);
172 private:
173 static int dogc(lua_State* LS)
175 T* obj = reinterpret_cast<T*>(lua_touserdata(LS, 1));
176 obj->~T();
179 void load_metatable(lua_State* LS)
181 again:
182 lua_pushlightuserdata(LS, this);
183 lua_rawget(LS, LUA_REGISTRYINDEX);
184 if(lua_type(LS, -1) == LUA_TNIL) {
185 lua_pop(LS, 1);
186 lua_pushlightuserdata(LS, this);
187 lua_newtable(LS);
188 lua_pushstring(LS, "__gc");
189 lua_pushcfunction(LS, &lua_class<T>::dogc);
190 lua_rawset(LS, -3);
191 lua_rawset(LS, LUA_REGISTRYINDEX);
192 goto again;
195 std::string name;
196 lua_class(const lua_class<T>&);
197 lua_class& operator=(const lua_class<T>&);
200 #define DECLARE_LUACLASS(x, X) template<> lua_class< x >& objclass() { static lua_class< x > clazz( X ); \
201 return clazz; }
205 #endif