2 #include "register-queue.hpp"
6 std::unordered_map
<std::type_index
, void*>& lua_class_types()
8 static std::unordered_map
<std::type_index
, void*> x
;
13 int lua_trampoline_function(lua_State
* L
)
15 void* ptr
= lua_touserdata(L
, lua_upvalueindex(1));
16 lua_state
* state
= reinterpret_cast<lua_state
*>(lua_touserdata(L
, lua_upvalueindex(2)));
17 lua_function
* f
= reinterpret_cast<lua_function
*>(ptr
);
18 lua_state
_L(*state
, L
);
21 } catch(std::exception
& e
) {
22 lua_pushfstring(L
, "%s", e
.what());
28 //Pushes given table to top of stack, creating if needed.
29 void recursive_lookup_table(lua_state
& L
, const std::string
& tab
)
32 #if LUA_VERSION_NUM == 501
33 L
.pushvalue(LUA_GLOBALSINDEX
);
35 #if LUA_VERSION_NUM == 502
36 L
.rawgeti(LUA_REGISTRYINDEX
, LUA_RIDX_GLOBALS
);
38 assert(L
.type(-1) == LUA_TTABLE
);
42 size_t split
= u
.find_last_of(".");
45 if(split
< u
.length()) {
46 u1
= u
.substr(0, split
);
47 u2
= u
.substr(split
+ 1);
49 recursive_lookup_table(L
, u1
);
50 L
.getfield(-1, u2
.c_str());
51 if(L
.type(-1) != LUA_TTABLE
) {
52 //Not a table, create a table.
55 L
.setfield(-2, u2
.c_str());
56 L
.getfield(-1, u2
.c_str());
58 //Get rid of previous table.
63 void register_lua_function(lua_state
& L
, const std::string
& name
, lua_function
* fun
)
66 size_t split
= u
.find_last_of(".");
69 if(split
< u
.length()) {
70 u1
= u
.substr(0, split
);
71 u2
= u
.substr(split
+ 1);
73 recursive_lookup_table(L
, u1
);
77 void* ptr
= reinterpret_cast<void*>(fun
);
78 L
.pushlightuserdata(ptr
);
79 L
.pushlightuserdata(&L
);
80 L
.pushcclosure(lua_trampoline_function
, 2);
82 L
.setfield(-2, u2
.c_str());
85 typedef register_queue
<lua_state
, lua_function
> regqueue_t
;
86 typedef register_queue
<lua_state::callback_proxy
, lua_state::lua_callback_list
> regqueue2_t
;
87 typedef register_queue
<lua_function_group
, lua_function
> regqueue3_t
;
91 lua_state::lua_state() throw(std::bad_alloc
)
96 oom_handler
= builtin_oom
;
97 regqueue2_t::do_ready(cbproxy
, true);
100 lua_state::lua_state(lua_state
& _master
, lua_State
* L
)
107 lua_state::~lua_state() throw()
111 for(auto i
: function_groups
)
112 i
.first
->drop_callback(i
.second
);
113 regqueue2_t::do_ready(cbproxy
, false);
115 lua_close(lua_handle
);
118 void lua_state::builtin_oom()
120 std::cerr
<< "PANIC: FATAL: Out of memory" << std::endl
;
124 void* lua_state::builtin_alloc(void* user
, void* old
, size_t olds
, size_t news
)
127 void* m
= realloc(old
, news
);
129 reinterpret_cast<lua_state
*>(user
)->oom_handler();
137 lua_function::lua_function(lua_function_group
& _group
, const std::string
& func
) throw(std::bad_alloc
)
140 regqueue3_t::do_register(group
, fname
= func
, *this);
143 lua_function::~lua_function() throw()
145 regqueue3_t::do_unregister(group
, fname
);
148 void lua_state::reset() throw(std::bad_alloc
, std::runtime_error
)
151 return master
->reset();
153 lua_State
* tmp
= lua_newstate(lua_state::builtin_alloc
, this);
155 throw std::runtime_error("Can't re-initialize Lua interpretter");
156 lua_close(lua_handle
);
157 for(auto& i
: callbacks
)
162 lua_handle
= lua_newstate(lua_state::builtin_alloc
, this);
164 throw std::runtime_error("Can't initialize Lua interpretter");
166 for(auto i
: function_groups
)
167 i
.first
->request_callback([this](std::string name
, lua_function
* func
) -> void {
168 register_lua_function(*this, name
, func
);
172 void lua_state::deinit() throw()
175 return master
->deinit();
177 lua_close(lua_handle
);
181 void lua_state::add_function_group(lua_function_group
& group
)
183 function_groups
.insert(std::make_pair(&group
, group
.add_callback([this](const std::string
& name
,
184 lua_function
* func
) -> void {
185 this->function_callback(name
, func
);
186 }, [this](lua_function_group
* x
) {
187 for(auto i
= this->function_groups
.begin(); i
!= this->function_groups
.end();)
189 i
= this->function_groups
.erase(i
);
195 void lua_state::function_callback(const std::string
& name
, lua_function
* func
)
198 return master
->function_callback(name
, func
);
200 register_lua_function(*this, name
, func
);
203 bool lua_state::do_once(void* key
)
206 return master
->do_once(key
);
207 pushlightuserdata(key
);
208 rawget(LUA_REGISTRYINDEX
);
209 if(type(-1) == LUA_TNIL
) {
211 pushlightuserdata(key
);
212 pushlightuserdata(key
);
213 rawset(LUA_REGISTRYINDEX
);
221 lua_state::lua_callback_list::lua_callback_list(lua_state
& _L
, const std::string
& _name
, const std::string
& fncbname
)
222 : L(_L
), name(_name
), fn_cbname(fncbname
)
224 regqueue2_t::do_register(L
.cbproxy
, name
, *this);
227 lua_state::lua_callback_list::~lua_callback_list()
229 regqueue2_t::do_unregister(L
.cbproxy
, name
);
232 for(auto& i
: callbacks
) {
233 L
.pushlightuserdata(&i
);
235 L
.rawset(LUA_REGISTRYINDEX
);
239 void lua_state::lua_callback_list::_register(lua_state
& _L
)
241 callbacks
.push_back(0);
242 _L
.pushlightuserdata(&*callbacks
.rbegin());
244 _L
.rawset(LUA_REGISTRYINDEX
);
247 void lua_state::lua_callback_list::_unregister(lua_state
& _L
)
249 for(auto i
= callbacks
.begin(); i
!= callbacks
.end();) {
250 _L
.pushlightuserdata(&*i
);
251 _L
.rawget(LUA_REGISTRYINDEX
);
252 if(_L
.rawequal(-1, -2)) {
254 _L
.pushlightuserdata(key
);
256 _L
.rawset(LUA_REGISTRYINDEX
);
257 i
= callbacks
.erase(i
);
264 lua_function_group::lua_function_group()
267 regqueue3_t::do_ready(*this, true);
270 lua_function_group::~lua_function_group()
272 for(auto i
: functions
)
273 for(auto j
: callbacks
)
274 j
.second(i
.first
, NULL
);
275 for(auto i
: dcallbacks
)
277 regqueue3_t::do_ready(*this, false);
280 void lua_function_group::request_callback(std::function
<void(std::string
, lua_function
*)> cb
)
282 for(auto i
: functions
)
283 cb(i
.first
, i
.second
);
286 int lua_function_group::add_callback(std::function
<void(std::string
, lua_function
*)> cb
,
287 std::function
<void(lua_function_group
*)> dcb
)
289 int handle
= next_handle
++;
290 callbacks
[handle
] = cb
;
291 dcallbacks
[handle
] = dcb
;
292 for(auto i
: functions
)
293 cb(i
.first
, i
.second
);
297 void lua_function_group::drop_callback(int handle
)
299 callbacks
.erase(handle
);
302 void lua_function_group::do_register(const std::string
& name
, lua_function
& fun
)
304 functions
[name
] = &fun
;
305 for(auto i
: callbacks
)
306 i
.second(name
, &fun
);
309 void lua_function_group::do_unregister(const std::string
& name
)
311 functions
.erase(name
);
312 for(auto i
: callbacks
)
313 i
.second(name
, NULL
);
316 std::list
<luaclass_methods
>& userdata_recogn_fns()
318 static std::list
<luaclass_methods
> x
;
322 std::string
try_recognize_userdata(lua_state
& state
, int index
)
324 for(auto i
: userdata_recogn_fns())
325 if(i
.is(state
, index
))
327 //Hack: Lua builtin file objects.
328 state
.pushstring("FILE*");
329 state
.rawget(LUA_REGISTRYINDEX
);
330 if(state
.getmetatable(index
)) {
331 if(state
.rawequal(-1, -2)) {
341 std::string
try_print_userdata(lua_state
& L
, int index
)
343 for(auto i
: userdata_recogn_fns())
345 return i
.print(L
, index
);
346 return "no data available";
349 int lua_state::vararg_tag::pushargs(lua_state
& L
)
357 else if(i
== "false")
358 L
.pushboolean(false);
359 else if(regex_match("[+-]?(|0|[1-9][0-9]*)(.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?", i
))
360 L
.pushnumber(strtod(i
.c_str(), NULL
));
362 L
.pushlstring(i
.substr(1));