aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk')
-rw-r--r--src/FbTk/Luamm.cc101
-rw-r--r--src/FbTk/Luamm.hh109
2 files changed, 108 insertions, 102 deletions
diff --git a/src/FbTk/Luamm.cc b/src/FbTk/Luamm.cc
index d17096f..ff3669f 100644
--- a/src/FbTk/Luamm.cc
+++ b/src/FbTk/Luamm.cc
@@ -221,51 +221,56 @@ namespace lua {
221 } 221 }
222 222
223 state::state() 223 state::state()
224 : cobj(luaL_newstate())
224 { 225 {
225 if(lua_State *l = luaL_newstate()) 226 if(cobj == NULL) {
226 cobj.reset(l, &lua_close);
227 else {
228 // docs say this can happen only in case of a memory allocation error 227 // docs say this can happen only in case of a memory allocation error
229 throw std::bad_alloc(); 228 throw std::bad_alloc();
230 } 229 }
231 230
232 // set our panic function 231 try {
233 lua_atpanic(cobj.get(), panic_throw); 232 // set our panic function
234 233 lua_atpanic(cobj, panic_throw);
235 checkstack(2); 234
236 235 checkstack(2);
237 // store a pointer to ourselves 236
238 pushlightuserdata(this); 237 // store a pointer to ourselves
239 rawsetfield(REGISTRYINDEX, this_cpp_object); 238 pushlightuserdata(this);
240 239 rawsetfield(REGISTRYINDEX, this_cpp_object);
241 // a metatable for C++ exceptions travelling through lua code 240
242 newmetatable(cpp_exception_metatable); 241 // a metatable for C++ exceptions travelling through lua code
243 lua_pushcfunction(cobj.get(), &exception_to_string); 242 newmetatable(cpp_exception_metatable);
244 rawsetfield(-2, "__tostring"); 243 lua_pushcfunction(cobj, &exception_to_string);
245 pushboolean(false); 244 rawsetfield(-2, "__tostring");
246 rawsetfield(-2, "__metatable"); 245 pushboolean(false);
247 pushdestructor<std::exception_ptr>(); 246 rawsetfield(-2, "__metatable");
248 rawsetfield(-2, "__gc"); 247 pushdestructor<std::exception_ptr>();
249 pop(); 248 rawsetfield(-2, "__gc");
250 249 pop();
251 // a metatable for C++ functions callable from lua code 250
252 newmetatable(cpp_function_metatable); 251 // a metatable for C++ functions callable from lua code
253 pushboolean(false); 252 newmetatable(cpp_function_metatable);
254 rawsetfield(-2, "__metatable"); 253 pushboolean(false);
255 pushdestructor<FbTk::Slot<int, state *> >(); 254 rawsetfield(-2, "__metatable");
256 rawsetfield(-2, "__gc"); 255 pushdestructor<FbTk::Slot<int, state *> >();
257 pop(); 256 rawsetfield(-2, "__gc");
258 257 pop();
259 // while they're travelling through C++ code, lua exceptions will reside here 258
260 newtable(); 259 // while they're travelling through C++ code, lua exceptions will reside here
261 rawsetfield(REGISTRYINDEX, lua_exception_namespace); 260 newtable();
262 261 rawsetfield(REGISTRYINDEX, lua_exception_namespace);
263 luaL_openlibs(cobj.get()); 262
263 luaL_openlibs(cobj);
264 }
265 catch(...) {
266 lua_close(cobj);
267 throw;
268 }
264 } 269 }
265 270
266 void state::call(int nargs, int nresults, int errfunc) 271 void state::call(int nargs, int nresults, int errfunc)
267 { 272 {
268 int r = lua_pcall(cobj.get(), nargs, nresults, errfunc); 273 int r = lua_pcall(cobj, nargs, nresults, errfunc);
269 if(r == 0) 274 if(r == 0)
270 return; 275 return;
271 276
@@ -301,7 +306,7 @@ namespace lua {
301 306
302 void state::checkstack(int extra) throw(std::bad_alloc) 307 void state::checkstack(int extra) throw(std::bad_alloc)
303 { 308 {
304 if(not lua_checkstack(cobj.get(), extra)) 309 if(not lua_checkstack(cobj, extra))
305 throw std::bad_alloc(); 310 throw std::bad_alloc();
306 } 311 }
307 312
@@ -309,7 +314,7 @@ namespace lua {
309 { 314 {
310 assert(n>=0); 315 assert(n>=0);
311 checkstack(1); 316 checkstack(1);
312 lua_pushcfunction(cobj.get(), safe_concat_trampoline); 317 lua_pushcfunction(cobj, safe_concat_trampoline);
313 insert(-n-1); 318 insert(-n-1);
314 call(n, 1, 0); 319 call(n, 1, 0);
315 } 320 }
@@ -326,7 +331,7 @@ namespace lua {
326 int state::gc(int what, int data) 331 int state::gc(int what, int data)
327 { 332 {
328 checkstack(3); 333 checkstack(3);
329 lua_pushcfunction(cobj.get(), safe_gc_trampoline); 334 lua_pushcfunction(cobj, safe_gc_trampoline);
330 pushinteger(what); 335 pushinteger(what);
331 pushinteger(data); 336 pushinteger(data);
332 call(2, 1, 0); 337 call(2, 1, 0);
@@ -349,7 +354,7 @@ namespace lua {
349 checkstack(2); 354 checkstack(2);
350 pushvalue(index); 355 pushvalue(index);
351 insert(-2); 356 insert(-2);
352 lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_gettable, 1>)); 357 lua_pushcfunction(cobj, (&safe_misc_trampoline<&lua_gettable, 1>));
353 insert(-3); 358 insert(-3);
354 call(2, 1, 0); 359 call(2, 1, 0);
355 } 360 }
@@ -362,7 +367,7 @@ namespace lua {
362 void state::loadfile(const char *filename) 367 void state::loadfile(const char *filename)
363 throw(lua::syntax_error, lua::file_error, std::bad_alloc) 368 throw(lua::syntax_error, lua::file_error, std::bad_alloc)
364 { 369 {
365 switch(luaL_loadfile(cobj.get(), filename)) { 370 switch(luaL_loadfile(cobj, filename)) {
366 case 0: 371 case 0:
367 return; 372 return;
368 case LUA_ERRSYNTAX: 373 case LUA_ERRSYNTAX:
@@ -378,7 +383,7 @@ namespace lua {
378 383
379 void state::loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc) 384 void state::loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc)
380 { 385 {
381 switch(luaL_loadstring(cobj.get(), s)) { 386 switch(luaL_loadstring(cobj, s)) {
382 case 0: 387 case 0:
383 return; 388 return;
384 case LUA_ERRSYNTAX: 389 case LUA_ERRSYNTAX:
@@ -395,7 +400,7 @@ namespace lua {
395 checkstack(2); 400 checkstack(2);
396 pushvalue(index); 401 pushvalue(index);
397 insert(-2); 402 insert(-2);
398 lua_pushcfunction(cobj.get(), &safe_next_trampoline); 403 lua_pushcfunction(cobj, &safe_next_trampoline);
399 insert(-3); 404 insert(-3);
400 405
401 call(2, MULTRET, 0); 406 call(2, MULTRET, 0);
@@ -416,10 +421,10 @@ namespace lua {
416 } 421 }
417 422
418 void state::rawgetfield(int index, const char *k) throw(std::bad_alloc) 423 void state::rawgetfield(int index, const char *k) throw(std::bad_alloc)
419 { lua::rawgetfield(cobj.get(), index, k); } 424 { lua::rawgetfield(cobj, index, k); }
420 425
421 void state::rawsetfield(int index, const char *k) throw(std::bad_alloc) 426 void state::rawsetfield(int index, const char *k) throw(std::bad_alloc)
422 { lua::rawsetfield(cobj.get(), index, k); } 427 { lua::rawsetfield(cobj, index, k); }
423 428
424 bool state::safe_compare(lua_CFunction trampoline, int index1, int index2) 429 bool state::safe_compare(lua_CFunction trampoline, int index1, int index2)
425 { 430 {
@@ -432,7 +437,7 @@ namespace lua {
432 index2 = absindex(index2); 437 index2 = absindex(index2);
433 438
434 checkstack(3); 439 checkstack(3);
435 lua_pushcfunction(cobj.get(), trampoline); 440 lua_pushcfunction(cobj, trampoline);
436 pushvalue(index1); 441 pushvalue(index1);
437 pushvalue(index2); 442 pushvalue(index2);
438 call(2, 1, 0); 443 call(2, 1, 0);
@@ -456,7 +461,7 @@ namespace lua {
456 checkstack(2); 461 checkstack(2);
457 pushvalue(index); 462 pushvalue(index);
458 insert(-3); 463 insert(-3);
459 lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_settable, 0>)); 464 lua_pushcfunction(cobj, (&safe_misc_trampoline<&lua_settable, 0>));
460 insert(-4); 465 insert(-4);
461 call(3, 0, 0); 466 call(3, 0, 0);
462 } 467 }
@@ -464,7 +469,7 @@ namespace lua {
464 std::string state::tostring(int index) throw(lua::not_string_error) 469 std::string state::tostring(int index) throw(lua::not_string_error)
465 { 470 {
466 size_t len; 471 size_t len;
467 const char *str = lua_tolstring(cobj.get(), index, &len); 472 const char *str = lua_tolstring(cobj, index, &len);
468 if(not str) 473 if(not str)
469 throw not_string_error(); 474 throw not_string_error();
470 return std::string(str, len); 475 return std::string(str, len);
diff --git a/src/FbTk/Luamm.hh b/src/FbTk/Luamm.hh
index e173be9..6b26a17 100644
--- a/src/FbTk/Luamm.hh
+++ b/src/FbTk/Luamm.hh
@@ -130,29 +130,30 @@ namespace lua {
130 130
131 // a fancy wrapper around lua_State 131 // a fancy wrapper around lua_State
132 class state { 132 class state {
133 std::shared_ptr<lua_State> cobj; 133 lua_State *cobj;
134 134
135 // destructor for C++ objects stored as lua userdata 135 // destructor for C++ objects stored as lua userdata
136 template<typename T> 136 template<typename T>
137 static int destroy_cpp_object(lua_State *l) 137 static int destroy_cpp_object(lua_State *l)
138 { 138 {
139 T *ptr = static_cast<T *>(lua_touserdata(l, -1)); 139 T *ptr = static_cast<T *>(lua_touserdata(l, -1));
140 assert(ptr); 140 assert(ptr);
141 try { 141 try {
142 // throwing exceptions in destructors is a bad idea 142 // throwing exceptions in destructors is a bad idea
143 // but we catch (and ignore) them, just in case 143 // but we catch (and ignore) them, just in case
144 ptr->~T(); 144 ptr->~T();
145 }
146 catch(...) {
147 }
148 return 0;
149 } 145 }
146 catch(...) {
147 }
148 return 0;
149 }
150 150
151 bool safe_compare(lua_CFunction trampoline, int index1, int index2); 151 bool safe_compare(lua_CFunction trampoline, int index1, int index2);
152 void do_pushclosure(int n); 152 void do_pushclosure(int n);
153 153
154 public: 154 public:
155 state(); 155 state();
156 ~state() { lua_close(cobj); }
156 157
157 /* 158 /*
158 * Lua functions come in three flavours 159 * Lua functions come in three flavours
@@ -179,68 +180,68 @@ namespace lua {
179 180
180 // type a, never throw 181 // type a, never throw
181 int absindex(int index) throw() { return index<0 && -index<=gettop() ? gettop()+1+index : index; } 182 int absindex(int index) throw() { return index<0 && -index<=gettop() ? gettop()+1+index : index; }
182 bool getmetatable(int index) throw() { return lua_getmetatable(cobj.get(), index); } 183 bool getmetatable(int index) throw() { return lua_getmetatable(cobj, index); }
183 int gettop() throw() { return lua_gettop(cobj.get()); } 184 int gettop() throw() { return lua_gettop(cobj); }
184 void insert(int index) throw() { lua_insert(cobj.get(), index); } 185 void insert(int index) throw() { lua_insert(cobj, index); }
185 bool isboolean(int index) throw() { return lua_isboolean(cobj.get(), index); } 186 bool isboolean(int index) throw() { return lua_isboolean(cobj, index); }
186 bool isfunction(int index) throw() { return lua_isfunction(cobj.get(), index); } 187 bool isfunction(int index) throw() { return lua_isfunction(cobj, index); }
187 bool islightuserdata(int index) throw() { return lua_islightuserdata(cobj.get(), index); } 188 bool islightuserdata(int index) throw() { return lua_islightuserdata(cobj, index); }
188 bool isnil(int index) throw() { return lua_isnil(cobj.get(), index); } 189 bool isnil(int index) throw() { return lua_isnil(cobj, index); }
189 bool isnone(int index) throw() { return lua_isnone(cobj.get(), index); } 190 bool isnone(int index) throw() { return lua_isnone(cobj, index); }
190 bool isnumber(int index) throw() { return lua_isnumber(cobj.get(), index); } 191 bool isnumber(int index) throw() { return lua_isnumber(cobj, index); }
191 bool isstring(int index) throw() { return lua_isstring(cobj.get(), index); } 192 bool isstring(int index) throw() { return lua_isstring(cobj, index); }
192 void pop(int n = 1) throw() { lua_pop(cobj.get(), n); } 193 void pop(int n = 1) throw() { lua_pop(cobj, n); }
193 void pushboolean(bool b) throw() { lua_pushboolean(cobj.get(), b); } 194 void pushboolean(bool b) throw() { lua_pushboolean(cobj, b); }
194 void pushinteger(integer n) throw() { lua_pushinteger(cobj.get(), n); } 195 void pushinteger(integer n) throw() { lua_pushinteger(cobj, n); }
195 void pushlightuserdata(void *p) throw() { lua_pushlightuserdata(cobj.get(), p); } 196 void pushlightuserdata(void *p) throw() { lua_pushlightuserdata(cobj, p); }
196 void pushnil() throw() { lua_pushnil(cobj.get()); } 197 void pushnil() throw() { lua_pushnil(cobj); }
197 void pushnumber(number n) throw() { lua_pushnumber(cobj.get(), n); } 198 void pushnumber(number n) throw() { lua_pushnumber(cobj, n); }
198 void pushvalue(int index) throw() { lua_pushvalue(cobj.get(), index); } 199 void pushvalue(int index) throw() { lua_pushvalue(cobj, index); }
199 void rawget(int index) throw() { lua_rawget(cobj.get(), index); } 200 void rawget(int index) throw() { lua_rawget(cobj, index); }
200 void rawgeti(int index, int n) throw() { lua_rawgeti(cobj.get(), index, n); } 201 void rawgeti(int index, int n) throw() { lua_rawgeti(cobj, index, n); }
201 bool rawequal(int index1, int index2) throw() { return lua_rawequal(cobj.get(), index1, index2); } 202 bool rawequal(int index1, int index2) throw() { return lua_rawequal(cobj, index1, index2); }
202 void replace(int index) throw() { lua_replace(cobj.get(), index); } 203 void replace(int index) throw() { lua_replace(cobj, index); }
203 // lua_setmetatable returns int, but docs don't specify it's meaning :/ 204 // lua_setmetatable returns int, but docs don't specify it's meaning :/
204 int setmetatable(int index) throw() { return lua_setmetatable(cobj.get(), index); } 205 int setmetatable(int index) throw() { return lua_setmetatable(cobj, index); }
205 void settop(int index) throw() { return lua_settop(cobj.get(), index); } 206 void settop(int index) throw() { return lua_settop(cobj, index); }
206 bool toboolean(int index) throw() { return lua_toboolean(cobj.get(), index); } 207 bool toboolean(int index) throw() { return lua_toboolean(cobj, index); }
207 integer tointeger(int index) throw() { return lua_tointeger(cobj.get(), index); } 208 integer tointeger(int index) throw() { return lua_tointeger(cobj, index); }
208 number tonumber(int index) throw() { return lua_tonumber(cobj.get(), index); } 209 number tonumber(int index) throw() { return lua_tonumber(cobj, index); }
209 void* touserdata(int index) throw() { return lua_touserdata(cobj.get(), index); } 210 void* touserdata(int index) throw() { return lua_touserdata(cobj, index); }
210 Type type(int index) throw() { return static_cast<Type>(lua_type(cobj.get(), index)); } 211 Type type(int index) throw() { return static_cast<Type>(lua_type(cobj, index)); }
211 // typename is a reserved word :/ 212 // typename is a reserved word :/
212 const char* type_name(Type tp) throw() { return lua_typename(cobj.get(), tp); } 213 const char* type_name(Type tp) throw() { return lua_typename(cobj, tp); }
213 void unref(int t, int ref) throw() { return luaL_unref(cobj.get(), t, ref); } 214 void unref(int t, int ref) throw() { return luaL_unref(cobj, t, ref); }
214 215
215 // type b, throw only on memory allocation errors 216 // type b, throw only on memory allocation errors
216 // checkstack correctly throws bad_alloc, because lua_checkstack kindly informs us of 217 // checkstack correctly throws bad_alloc, because lua_checkstack kindly informs us of
217 // that sitution 218 // that sitution
218 void checkstack(int extra) throw(std::bad_alloc); 219 void checkstack(int extra) throw(std::bad_alloc);
219 const char* gsub(const char *s, const char *p, const char *r) { return luaL_gsub(cobj.get(), s, p, r); } 220 const char* gsub(const char *s, const char *p, const char *r) { return luaL_gsub(cobj, s, p, r); }
220 bool newmetatable(const char *tname) { return luaL_newmetatable(cobj.get(), tname); } 221 bool newmetatable(const char *tname) { return luaL_newmetatable(cobj, tname); }
221 void newtable() { lua_newtable(cobj.get()); } 222 void newtable() { lua_newtable(cobj); }
222 void *newuserdata(size_t size) { return lua_newuserdata(cobj.get(), size); } 223 void *newuserdata(size_t size) { return lua_newuserdata(cobj, size); }
223 // Functor can be anything that FbTk::Slot can handle, everything else remains 224 // Functor can be anything that FbTk::Slot can handle, everything else remains
224 // identical 225 // identical
225 template<typename Functor> 226 template<typename Functor>
226 void pushclosure(const Functor &fn, int n); 227 void pushclosure(const Functor &fn, int n);
227 template<typename Functor> 228 template<typename Functor>
228 void pushfunction(const Functor &fn) { pushclosure(fn, 0); } 229 void pushfunction(const Functor &fn) { pushclosure(fn, 0); }
229 void pushstring(const char *s) { lua_pushstring(cobj.get(), s); } 230 void pushstring(const char *s) { lua_pushstring(cobj, s); }
230 void pushstring(const char *s, size_t len) { lua_pushlstring(cobj.get(), s, len); } 231 void pushstring(const char *s, size_t len) { lua_pushlstring(cobj, s, len); }
231 void pushstring(const std::string &s) { lua_pushlstring(cobj.get(), s.c_str(), s.size()); } 232 void pushstring(const std::string &s) { lua_pushlstring(cobj, s.c_str(), s.size()); }
232 void rawgetfield(int index, const char *k) throw(std::bad_alloc); 233 void rawgetfield(int index, const char *k) throw(std::bad_alloc);
233 void rawset(int index) { lua_rawset(cobj.get(), index); } 234 void rawset(int index) { lua_rawset(cobj, index); }
234 void rawsetfield(int index, const char *k) throw(std::bad_alloc); 235 void rawsetfield(int index, const char *k) throw(std::bad_alloc);
235 int ref(int t) { return luaL_ref(cobj.get(), t); } 236 int ref(int t) { return luaL_ref(cobj, t); }
236 // len recieves length, if not null. Returned value may contain '\0' 237 // len recieves length, if not null. Returned value may contain '\0'
237 const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj.get(), index, len); } 238 const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj, index, len); }
238 // Don't use pushclosure() to create a __gc function. The problem is that lua calls them 239 // Don't use pushclosure() to create a __gc function. The problem is that lua calls them
239 // in an unspecified order, and we may end up destroying the object holding the 240 // in an unspecified order, and we may end up destroying the object holding the
240 // std::function before we get a chance to call it. This pushes a function that simply 241 // std::function before we get a chance to call it. This pushes a function that simply
241 // calls ~T when the time comes. Only set it as __gc on userdata of type T. 242 // calls ~T when the time comes. Only set it as __gc on userdata of type T.
242 template<typename T> 243 template<typename T>
243 void pushdestructor() { lua_pushcfunction(cobj.get(), &destroy_cpp_object<T>); } 244 void pushdestructor() { lua_pushcfunction(cobj, &destroy_cpp_object<T>); }
244 245
245 // type c, throw everything but the kitchen sink 246 // type c, throw everything but the kitchen sink
246 // call() is a protected mode call, we don't allow unprotected calls 247 // call() is a protected mode call, we don't allow unprotected calls