Get rid of DECLARE_LUACLASS
[lsnes.git] / src / lua / callback.cpp
blobada542b0c3a22dfb1ba7eec68a0abbbab2d93215
1 #include "lua/internal.hpp"
2 #include "library/minmax.hpp"
3 #include <stdexcept>
5 namespace
7 class lua_callbacks_list
9 public:
10 lua_callbacks_list(lua_state& L);
11 int index(lua_state& L, const std::string& fname);
12 int newindex(lua_state& L, const std::string& fname);
13 std::string print()
15 return "";
19 class lua_callback_obj
21 public:
22 lua_callback_obj(lua_state& L, const std::string& name);
23 int _register(lua_state& L, const std::string& fname);
24 int _unregister(lua_state& L, const std::string& fname);
25 int _call(lua_state& L, const std::string& fname);
26 std::string print()
28 if(callback)
29 return callback->get_name();
30 else
31 return "(null)";
33 private:
34 lua_state::lua_callback_list* callback;
35 int special;
38 lua_class<lua_callbacks_list> class_callbacks_list("CALLBACKS_LIST");
39 lua_class<lua_callback_obj> class_callback_obj("CALLBACK_OBJ");
41 lua_callbacks_list::lua_callbacks_list(lua_state& L)
43 objclass<lua_callbacks_list>().bind_multi(L, {
44 {"__index", &lua_callbacks_list::index},
45 {"__newindex", &lua_callbacks_list::newindex},
46 });
49 int lua_callbacks_list::index(lua_state& L, const std::string& fname)
51 std::string name = L.get_string(2, fname.c_str());
52 lua_class<lua_callback_obj>::create(L, name);
53 return 1;
56 int lua_callbacks_list::newindex(lua_state& L, const std::string& fname)
58 throw std::runtime_error("Writing is not allowed");
61 lua_callback_obj::lua_callback_obj(lua_state& L, const std::string& name)
63 objclass<lua_callback_obj>().bind_multi(L, {
64 {"register", &lua_callback_obj::_register},
65 {"unregister", &lua_callback_obj::_unregister},
66 {"__call", &lua_callback_obj::_call},
67 });
68 callback = NULL;
69 special = 0;
70 for(auto i : L.get_callbacks())
71 if(i->get_name() == name)
72 callback = i;
73 if(name == "register") {
74 special = 1;
75 return;
77 if(name == "unregister") {
78 special = 2;
79 return;
81 if(!callback && !special)
82 throw std::runtime_error("Unknown callback type '" + name + "' for callback.<foo>");
85 int lua_callback_obj::_register(lua_state& L, const std::string& fname)
87 if(!callback)
88 throw std::runtime_error("callback.{,un}register.register not valid");
89 if(L.type(2) != LUA_TFUNCTION)
90 throw std::runtime_error("Expected function as 2nd argument to callback.<foo>:register");
91 L.pushvalue(2);
92 callback->_register(L);
93 L.pop(1);
94 L.pushvalue(2);
95 return 1;
98 int lua_callback_obj::_unregister(lua_state& L, const std::string& fname)
100 if(!callback)
101 throw std::runtime_error("callback.{,un}register.unregister not valid");
102 if(L.type(2) != LUA_TFUNCTION)
103 throw std::runtime_error("Expected function as 2nd argument to callback.<foo>:register");
104 L.pushvalue(2);
105 callback->_unregister(L);
106 L.pop(1);
107 L.pushvalue(2);
108 return 1;
111 int lua_callback_obj::_call(lua_state& L, const std::string& fname)
113 if(!special)
114 throw std::runtime_error("Need to specify operation to do to callback");
115 std::string name = L.get_string(2, "callback.{,un}register");
116 if(L.type(3) != LUA_TFUNCTION)
117 throw std::runtime_error("Expected function as 2nd argument to callback.{,un}register");
118 bool any = false;
119 for(auto i : L.get_callbacks()) {
120 if(i->get_name() == name) {
121 L.pushvalue(3);
122 if(special == 1)
123 i->_register(L);
124 else if(special == 2)
125 i->_unregister(L);
126 L.pop(1);
127 any = true;
130 if(!any)
131 throw std::runtime_error("Unknown callback type '" + name + "' for callback.register");
132 L.pushvalue(3);
133 return 1;
136 function_ptr_luafun callback(lua_func_callback, "callback", [](lua_state& L, const std::string& fname)
137 -> int {
138 lua_class<lua_callbacks_list>::create(L);
139 return 1;