Upload UI
[lsnes.git] / src / lua / callback.cpp
blob117c9c1e125ff1968876f88cae5c806c8e6dc1c3
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;
39 DECLARE_LUACLASS(lua_callbacks_list, "CALLBACKS_LIST");
40 DECLARE_LUACLASS(lua_callback_obj, "CALLBACK_OBJ");
42 namespace
44 lua_callbacks_list::lua_callbacks_list(lua_state& L)
46 objclass<lua_callbacks_list>().bind_multi(L, {
47 {"__index", &lua_callbacks_list::index},
48 {"__newindex", &lua_callbacks_list::newindex},
49 });
52 int lua_callbacks_list::index(lua_state& L, const std::string& fname)
54 std::string name = L.get_string(2, fname.c_str());
55 lua_class<lua_callback_obj>::create(L, name);
56 return 1;
59 int lua_callbacks_list::newindex(lua_state& L, const std::string& fname)
61 throw std::runtime_error("Writing is not allowed");
64 lua_callback_obj::lua_callback_obj(lua_state& L, const std::string& name)
66 objclass<lua_callback_obj>().bind_multi(L, {
67 {"register", &lua_callback_obj::_register},
68 {"unregister", &lua_callback_obj::_unregister},
69 {"__call", &lua_callback_obj::_call},
70 });
71 callback = NULL;
72 special = 0;
73 for(auto i : L.get_callbacks())
74 if(i->get_name() == name)
75 callback = i;
76 if(name == "register") {
77 special = 1;
78 return;
80 if(name == "unregister") {
81 special = 2;
82 return;
84 if(!callback && !special)
85 throw std::runtime_error("Unknown callback type '" + name + "' for callback.<foo>");
88 int lua_callback_obj::_register(lua_state& L, const std::string& fname)
90 if(!callback)
91 throw std::runtime_error("callback.{,un}register.register not valid");
92 if(L.type(2) != LUA_TFUNCTION)
93 throw std::runtime_error("Expected function as 2nd argument to callback.<foo>:register");
94 L.pushvalue(2);
95 callback->_register(L);
96 L.pop(1);
97 L.pushvalue(2);
98 return 1;
101 int lua_callback_obj::_unregister(lua_state& L, const std::string& fname)
103 if(!callback)
104 throw std::runtime_error("callback.{,un}register.unregister not valid");
105 if(L.type(2) != LUA_TFUNCTION)
106 throw std::runtime_error("Expected function as 2nd argument to callback.<foo>:register");
107 L.pushvalue(2);
108 callback->_unregister(L);
109 L.pop(1);
110 L.pushvalue(2);
111 return 1;
114 int lua_callback_obj::_call(lua_state& L, const std::string& fname)
116 if(!special)
117 throw std::runtime_error("Need to specify operation to do to callback");
118 std::string name = L.get_string(2, "callback.{,un}register");
119 if(L.type(3) != LUA_TFUNCTION)
120 throw std::runtime_error("Expected function as 2nd argument to callback.{,un}register");
121 bool any = false;
122 for(auto i : L.get_callbacks()) {
123 if(i->get_name() == name) {
124 L.pushvalue(3);
125 if(special == 1)
126 i->_register(L);
127 else if(special == 2)
128 i->_unregister(L);
129 L.pop(1);
130 any = true;
133 if(!any)
134 throw std::runtime_error("Unknown callback type '" + name + "' for callback.register");
135 L.pushvalue(3);
136 return 1;
139 function_ptr_luafun callback(lua_func_callback, "callback", [](lua_state& L, const std::string& fname)
140 -> int {
141 lua_class<lua_callbacks_list>::create(L);
142 return 1;