Lua: Refactor lots of stuff
[lsnes.git] / src / lua / callback.cpp
blob9880808863fda93cf781ab73f6c1d24cb59685d3
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::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 lua::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 lua::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 lua::fnptr2 callback(lua_func_callback, "callback", [](lua::state& L, lua::parameters& P) -> int {
137 lua::_class<lua_callbacks_list>::create(L);
138 return 1;