mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-11-18 02:55:12 +00:00
Retab luamm in line with setting we use (yeah... i know :/)
This commit is contained in:
parent
3e98e18324
commit
0ae2ba5210
728
src/luamm.cc
728
src/luamm.cc
@ -24,429 +24,429 @@
|
||||
#include "luamm.hh"
|
||||
|
||||
namespace lua {
|
||||
namespace {
|
||||
// keys for storing values in lua registry
|
||||
const char cpp_exception_metatable[] = "lua::cpp_exception_metatable";
|
||||
const char cpp_function_metatable [] = "lua::cpp_function_metatable";
|
||||
const char lua_exception_namespace[] = "lua::lua_exception_namespace";
|
||||
const char this_cpp_object [] = "lua::this_cpp_object";
|
||||
namespace {
|
||||
// keys for storing values in lua registry
|
||||
const char cpp_exception_metatable[] = "lua::cpp_exception_metatable";
|
||||
const char cpp_function_metatable [] = "lua::cpp_function_metatable";
|
||||
const char lua_exception_namespace[] = "lua::lua_exception_namespace";
|
||||
const char this_cpp_object [] = "lua::this_cpp_object";
|
||||
|
||||
// converts C++ exceptions to strings, so lua can do something with them
|
||||
int exception_to_string(lua_State *l)
|
||||
{
|
||||
std::exception_ptr *ptr = static_cast<std::exception_ptr *>(lua_touserdata(l, -1));
|
||||
assert(ptr);
|
||||
try {
|
||||
std::rethrow_exception(*ptr);
|
||||
}
|
||||
catch(std::exception &e) {
|
||||
lua_pushstring(l, e.what());
|
||||
}
|
||||
catch(...) {
|
||||
lua_pushstring(l, ptr->__cxa_exception_type()->name());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
// converts C++ exceptions to strings, so lua can do something with them
|
||||
int exception_to_string(lua_State *l)
|
||||
{
|
||||
std::exception_ptr *ptr = static_cast<std::exception_ptr *>(lua_touserdata(l, -1));
|
||||
assert(ptr);
|
||||
try {
|
||||
std::rethrow_exception(*ptr);
|
||||
}
|
||||
catch(std::exception &e) {
|
||||
lua_pushstring(l, e.what());
|
||||
}
|
||||
catch(...) {
|
||||
lua_pushstring(l, ptr->__cxa_exception_type()->name());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int absindex(lua_State *l, int index) throw()
|
||||
{ return index<0 && -index<=lua_gettop(l) ? lua_gettop(l)+1+index : index; }
|
||||
int absindex(lua_State *l, int index) throw()
|
||||
{ return index<0 && -index<=lua_gettop(l) ? lua_gettop(l)+1+index : index; }
|
||||
|
||||
// Just like getfield(), only without calling metamethods (or throwing random exceptions)
|
||||
inline void rawgetfield(lua_State *l, int index, const char *k) throw(std::bad_alloc)
|
||||
{
|
||||
index = absindex(l, index);
|
||||
if(not lua_checkstack(l, 1))
|
||||
throw std::bad_alloc();
|
||||
// Just like getfield(), only without calling metamethods (or throwing random exceptions)
|
||||
inline void rawgetfield(lua_State *l, int index, const char *k) throw(std::bad_alloc)
|
||||
{
|
||||
index = absindex(l, index);
|
||||
if(not lua_checkstack(l, 1))
|
||||
throw std::bad_alloc();
|
||||
|
||||
lua_pushstring(l, k);
|
||||
lua_rawget(l, index);
|
||||
}
|
||||
lua_pushstring(l, k);
|
||||
lua_rawget(l, index);
|
||||
}
|
||||
|
||||
// Just like setfield(), only without calling metamethods (or throwing random exceptions)
|
||||
inline void rawsetfield(lua_State *l, int index, const char *k) throw(std::bad_alloc)
|
||||
{
|
||||
index = absindex(l, index);
|
||||
if(not lua_checkstack(l, 2))
|
||||
throw std::bad_alloc();
|
||||
// Just like setfield(), only without calling metamethods (or throwing random exceptions)
|
||||
inline void rawsetfield(lua_State *l, int index, const char *k) throw(std::bad_alloc)
|
||||
{
|
||||
index = absindex(l, index);
|
||||
if(not lua_checkstack(l, 2))
|
||||
throw std::bad_alloc();
|
||||
|
||||
lua_pushstring(l, k);
|
||||
lua_insert(l, -2);
|
||||
lua_rawset(l, index);
|
||||
}
|
||||
lua_pushstring(l, k);
|
||||
lua_insert(l, -2);
|
||||
lua_rawset(l, index);
|
||||
}
|
||||
|
||||
int closure_trampoline(lua_State *l)
|
||||
{
|
||||
lua_checkstack(l, 2);
|
||||
rawgetfield(l, REGISTRYINDEX, this_cpp_object);
|
||||
assert(lua_islightuserdata(l, -1));
|
||||
state *L = static_cast<state *>( lua_touserdata(l, -1) );
|
||||
lua_pop(l, 1);
|
||||
int closure_trampoline(lua_State *l)
|
||||
{
|
||||
lua_checkstack(l, 2);
|
||||
rawgetfield(l, REGISTRYINDEX, this_cpp_object);
|
||||
assert(lua_islightuserdata(l, -1));
|
||||
state *L = static_cast<state *>( lua_touserdata(l, -1) );
|
||||
lua_pop(l, 1);
|
||||
|
||||
try {
|
||||
cpp_function *fn = static_cast<cpp_function *>( L->touserdata(lua_upvalueindex(1)) );
|
||||
assert(fn);
|
||||
return (*fn)(L);
|
||||
}
|
||||
catch(lua::exception &e) {
|
||||
// rethrow lua errors as such
|
||||
e.push_lua_error(L);
|
||||
}
|
||||
catch(...) {
|
||||
// C++ exceptions (pointers to them, actually) are stored as lua userdata and
|
||||
// then thrown
|
||||
void *ptr = L->newuserdata(sizeof(std::exception_ptr));
|
||||
L->rawgetfield(REGISTRYINDEX, cpp_exception_metatable);
|
||||
L->setmetatable(-2);
|
||||
new(ptr) std::exception_ptr(std::current_exception());
|
||||
}
|
||||
try {
|
||||
cpp_function *fn = static_cast<cpp_function *>( L->touserdata(lua_upvalueindex(1)) );
|
||||
assert(fn);
|
||||
return (*fn)(L);
|
||||
}
|
||||
catch(lua::exception &e) {
|
||||
// rethrow lua errors as such
|
||||
e.push_lua_error(L);
|
||||
}
|
||||
catch(...) {
|
||||
// C++ exceptions (pointers to them, actually) are stored as lua userdata and
|
||||
// then thrown
|
||||
void *ptr = L->newuserdata(sizeof(std::exception_ptr));
|
||||
L->rawgetfield(REGISTRYINDEX, cpp_exception_metatable);
|
||||
L->setmetatable(-2);
|
||||
new(ptr) std::exception_ptr(std::current_exception());
|
||||
}
|
||||
|
||||
// lua_error does longjmp(), so destructors for objects in this function will not be
|
||||
// called
|
||||
return lua_error(l);
|
||||
}
|
||||
// lua_error does longjmp(), so destructors for objects in this function will not be
|
||||
// called
|
||||
return lua_error(l);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when lua encounters an error outside of any protected
|
||||
* environment
|
||||
* Throwing the exception through lua code appears to work, even if it was compiled
|
||||
* without -fexceptions. If it turns out, it fails in some conditions, it could be
|
||||
* replaced with some longjmp() magic. But that shouldn't be necessary, as this function
|
||||
* will not be called under normal conditions (we execute everything in protected mode).
|
||||
*/
|
||||
int panic_throw(lua_State *l)
|
||||
{
|
||||
if(not lua_checkstack(l, 1))
|
||||
throw std::bad_alloc();
|
||||
/*
|
||||
* This function is called when lua encounters an error outside of any protected
|
||||
* environment
|
||||
* Throwing the exception through lua code appears to work, even if it was compiled
|
||||
* without -fexceptions. If it turns out, it fails in some conditions, it could be
|
||||
* replaced with some longjmp() magic. But that shouldn't be necessary, as this function
|
||||
* will not be called under normal conditions (we execute everything in protected mode).
|
||||
*/
|
||||
int panic_throw(lua_State *l)
|
||||
{
|
||||
if(not lua_checkstack(l, 1))
|
||||
throw std::bad_alloc();
|
||||
|
||||
rawgetfield(l, REGISTRYINDEX, this_cpp_object);
|
||||
assert(lua_islightuserdata(l, -1));
|
||||
state *L = static_cast<state *>( lua_touserdata(l, -1) );
|
||||
lua_pop(l, 1);
|
||||
rawgetfield(l, REGISTRYINDEX, this_cpp_object);
|
||||
assert(lua_islightuserdata(l, -1));
|
||||
state *L = static_cast<state *>( lua_touserdata(l, -1) );
|
||||
lua_pop(l, 1);
|
||||
|
||||
throw lua::exception(L);
|
||||
}
|
||||
throw lua::exception(L);
|
||||
}
|
||||
|
||||
// protected mode wrappers for various lua functions
|
||||
int safe_concat_trampoline(lua_State *l)
|
||||
{
|
||||
lua_concat(l, lua_gettop(l));
|
||||
return 1;
|
||||
}
|
||||
// protected mode wrappers for various lua functions
|
||||
int safe_concat_trampoline(lua_State *l)
|
||||
{
|
||||
lua_concat(l, lua_gettop(l));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<int (*compare)(lua_State *, int, int)>
|
||||
int safe_compare_trampoline(lua_State *l)
|
||||
{
|
||||
int r = compare(l, 1, 2);
|
||||
lua_pop(l, 2);
|
||||
lua_pushinteger(l, r);
|
||||
return 1;
|
||||
}
|
||||
template<int (*compare)(lua_State *, int, int)>
|
||||
int safe_compare_trampoline(lua_State *l)
|
||||
{
|
||||
int r = compare(l, 1, 2);
|
||||
lua_pop(l, 2);
|
||||
lua_pushinteger(l, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int safe_gc_trampoline(lua_State *l)
|
||||
{
|
||||
int what = lua_tointeger(l, -2);
|
||||
int data = lua_tointeger(l, -1);
|
||||
lua_pop(l, 2);
|
||||
lua_pushinteger(l, lua_gc(l, what, data));
|
||||
return 1;
|
||||
}
|
||||
int safe_gc_trampoline(lua_State *l)
|
||||
{
|
||||
int what = lua_tointeger(l, -2);
|
||||
int data = lua_tointeger(l, -1);
|
||||
lua_pop(l, 2);
|
||||
lua_pushinteger(l, lua_gc(l, what, data));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<void (*misc)(lua_State *, int), int nresults>
|
||||
int safe_misc_trampoline(lua_State *l)
|
||||
{
|
||||
misc(l, 1);
|
||||
return nresults;
|
||||
}
|
||||
template<void (*misc)(lua_State *, int), int nresults>
|
||||
int safe_misc_trampoline(lua_State *l)
|
||||
{
|
||||
misc(l, 1);
|
||||
return nresults;
|
||||
}
|
||||
|
||||
int safe_next_trampoline(lua_State *l)
|
||||
{
|
||||
int r = lua_next(l, 1);
|
||||
lua_checkstack(l, 1);
|
||||
lua_pushinteger(l, r);
|
||||
return r ? 3 : 1;
|
||||
}
|
||||
int safe_next_trampoline(lua_State *l)
|
||||
{
|
||||
int r = lua_next(l, 1);
|
||||
lua_checkstack(l, 1);
|
||||
lua_pushinteger(l, r);
|
||||
return r ? 3 : 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string exception::get_error_msg(state *L)
|
||||
{
|
||||
static const std::string default_msg("Unknown lua exception");
|
||||
std::string exception::get_error_msg(state *L)
|
||||
{
|
||||
static const std::string default_msg("Unknown lua exception");
|
||||
|
||||
try {
|
||||
return L->tostring(-1);
|
||||
}
|
||||
catch(not_string_error &e) {
|
||||
return default_msg;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return L->tostring(-1);
|
||||
}
|
||||
catch(not_string_error &e) {
|
||||
return default_msg;
|
||||
}
|
||||
}
|
||||
|
||||
exception::exception(state *l)
|
||||
: std::runtime_error(get_error_msg(l)), L(l)
|
||||
{
|
||||
L->checkstack(1);
|
||||
exception::exception(state *l)
|
||||
: std::runtime_error(get_error_msg(l)), L(l)
|
||||
{
|
||||
L->checkstack(1);
|
||||
|
||||
L->rawgetfield(REGISTRYINDEX, lua_exception_namespace);
|
||||
L->insert(-2);
|
||||
key = L->ref(-2);
|
||||
L->pop(1);
|
||||
}
|
||||
L->rawgetfield(REGISTRYINDEX, lua_exception_namespace);
|
||||
L->insert(-2);
|
||||
key = L->ref(-2);
|
||||
L->pop(1);
|
||||
}
|
||||
|
||||
exception::~exception() throw()
|
||||
{
|
||||
if(not L)
|
||||
return;
|
||||
L->checkstack(1);
|
||||
exception::~exception() throw()
|
||||
{
|
||||
if(not L)
|
||||
return;
|
||||
L->checkstack(1);
|
||||
|
||||
L->rawgetfield(REGISTRYINDEX, lua_exception_namespace);
|
||||
L->unref(-1, key);
|
||||
L->pop();
|
||||
}
|
||||
L->rawgetfield(REGISTRYINDEX, lua_exception_namespace);
|
||||
L->unref(-1, key);
|
||||
L->pop();
|
||||
}
|
||||
|
||||
void exception::push_lua_error(state *l)
|
||||
{
|
||||
if(l != L)
|
||||
throw std::runtime_error("Cannot transfer exceptions between different lua contexts");
|
||||
l->checkstack(2);
|
||||
void exception::push_lua_error(state *l)
|
||||
{
|
||||
if(l != L)
|
||||
throw std::runtime_error("Cannot transfer exceptions between different lua contexts");
|
||||
l->checkstack(2);
|
||||
|
||||
l->rawgetfield(REGISTRYINDEX, lua_exception_namespace);
|
||||
l->rawgeti(-1, key);
|
||||
l->replace(-2);
|
||||
}
|
||||
l->rawgetfield(REGISTRYINDEX, lua_exception_namespace);
|
||||
l->rawgeti(-1, key);
|
||||
l->replace(-2);
|
||||
}
|
||||
|
||||
state::state()
|
||||
{
|
||||
if(lua_State *l = luaL_newstate())
|
||||
cobj.reset(l, &lua_close);
|
||||
else {
|
||||
// docs say this can happen only in case of a memory allocation error
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
state::state()
|
||||
{
|
||||
if(lua_State *l = luaL_newstate())
|
||||
cobj.reset(l, &lua_close);
|
||||
else {
|
||||
// docs say this can happen only in case of a memory allocation error
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
// set our panic function
|
||||
lua_atpanic(cobj.get(), panic_throw);
|
||||
// set our panic function
|
||||
lua_atpanic(cobj.get(), panic_throw);
|
||||
|
||||
checkstack(2);
|
||||
checkstack(2);
|
||||
|
||||
// store a pointer to ourselves
|
||||
pushlightuserdata(this);
|
||||
rawsetfield(REGISTRYINDEX, this_cpp_object);
|
||||
// store a pointer to ourselves
|
||||
pushlightuserdata(this);
|
||||
rawsetfield(REGISTRYINDEX, this_cpp_object);
|
||||
|
||||
// a metatable for C++ exceptions travelling through lua code
|
||||
newmetatable(cpp_exception_metatable);
|
||||
lua_pushcfunction(cobj.get(), &exception_to_string);
|
||||
rawsetfield(-2, "__tostring");
|
||||
pushboolean(false);
|
||||
rawsetfield(-2, "__metatable");
|
||||
pushdestructor<std::exception_ptr>();
|
||||
rawsetfield(-2, "__gc");
|
||||
pop();
|
||||
// a metatable for C++ exceptions travelling through lua code
|
||||
newmetatable(cpp_exception_metatable);
|
||||
lua_pushcfunction(cobj.get(), &exception_to_string);
|
||||
rawsetfield(-2, "__tostring");
|
||||
pushboolean(false);
|
||||
rawsetfield(-2, "__metatable");
|
||||
pushdestructor<std::exception_ptr>();
|
||||
rawsetfield(-2, "__gc");
|
||||
pop();
|
||||
|
||||
// a metatable for C++ functions callable from lua code
|
||||
newmetatable(cpp_function_metatable);
|
||||
pushboolean(false);
|
||||
rawsetfield(-2, "__metatable");
|
||||
pushdestructor<cpp_function>();
|
||||
rawsetfield(-2, "__gc");
|
||||
pop();
|
||||
// a metatable for C++ functions callable from lua code
|
||||
newmetatable(cpp_function_metatable);
|
||||
pushboolean(false);
|
||||
rawsetfield(-2, "__metatable");
|
||||
pushdestructor<cpp_function>();
|
||||
rawsetfield(-2, "__gc");
|
||||
pop();
|
||||
|
||||
// while they're travelling through C++ code, lua exceptions will reside here
|
||||
newtable();
|
||||
rawsetfield(REGISTRYINDEX, lua_exception_namespace);
|
||||
// while they're travelling through C++ code, lua exceptions will reside here
|
||||
newtable();
|
||||
rawsetfield(REGISTRYINDEX, lua_exception_namespace);
|
||||
|
||||
luaL_openlibs(cobj.get());
|
||||
}
|
||||
luaL_openlibs(cobj.get());
|
||||
}
|
||||
|
||||
void state::call(int nargs, int nresults, int errfunc)
|
||||
{
|
||||
int r = lua_pcall(cobj.get(), nargs, nresults, errfunc);
|
||||
if(r == 0)
|
||||
return;
|
||||
void state::call(int nargs, int nresults, int errfunc)
|
||||
{
|
||||
int r = lua_pcall(cobj.get(), nargs, nresults, errfunc);
|
||||
if(r == 0)
|
||||
return;
|
||||
|
||||
if(r == LUA_ERRMEM) {
|
||||
// memory allocation error, cross your fingers
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
if(r == LUA_ERRMEM) {
|
||||
// memory allocation error, cross your fingers
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
checkstack(3);
|
||||
rawgetfield(REGISTRYINDEX, cpp_exception_metatable);
|
||||
if(getmetatable(-2)) {
|
||||
if(rawequal(-1, -2)) {
|
||||
// it's a C++ exception, rethrow it
|
||||
std::exception_ptr *ptr = static_cast<std::exception_ptr *>(touserdata(-3));
|
||||
assert(ptr);
|
||||
checkstack(3);
|
||||
rawgetfield(REGISTRYINDEX, cpp_exception_metatable);
|
||||
if(getmetatable(-2)) {
|
||||
if(rawequal(-1, -2)) {
|
||||
// it's a C++ exception, rethrow it
|
||||
std::exception_ptr *ptr = static_cast<std::exception_ptr *>(touserdata(-3));
|
||||
assert(ptr);
|
||||
|
||||
/*
|
||||
* we create a copy, so we can pop the object without fearing the exception will
|
||||
* be collected by lua's GC
|
||||
*/
|
||||
std::exception_ptr t(*ptr); ptr = NULL;
|
||||
pop(3);
|
||||
std::rethrow_exception(t);
|
||||
}
|
||||
pop(2);
|
||||
}
|
||||
// it's a lua exception, wrap it
|
||||
if(r == LUA_ERRERR)
|
||||
throw lua::errfunc_error(this);
|
||||
else
|
||||
throw lua::exception(this);
|
||||
}
|
||||
/*
|
||||
* we create a copy, so we can pop the object without fearing the exception will
|
||||
* be collected by lua's GC
|
||||
*/
|
||||
std::exception_ptr t(*ptr); ptr = NULL;
|
||||
pop(3);
|
||||
std::rethrow_exception(t);
|
||||
}
|
||||
pop(2);
|
||||
}
|
||||
// it's a lua exception, wrap it
|
||||
if(r == LUA_ERRERR)
|
||||
throw lua::errfunc_error(this);
|
||||
else
|
||||
throw lua::exception(this);
|
||||
}
|
||||
|
||||
void state::checkstack(int extra) throw(std::bad_alloc)
|
||||
{
|
||||
if(not lua_checkstack(cobj.get(), extra))
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
void state::checkstack(int extra) throw(std::bad_alloc)
|
||||
{
|
||||
if(not lua_checkstack(cobj.get(), extra))
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void state::concat(int n)
|
||||
{
|
||||
assert(n>=0);
|
||||
checkstack(1);
|
||||
lua_pushcfunction(cobj.get(), safe_concat_trampoline);
|
||||
insert(-n-1);
|
||||
call(n, 1, 0);
|
||||
}
|
||||
void state::concat(int n)
|
||||
{
|
||||
assert(n>=0);
|
||||
checkstack(1);
|
||||
lua_pushcfunction(cobj.get(), safe_concat_trampoline);
|
||||
insert(-n-1);
|
||||
call(n, 1, 0);
|
||||
}
|
||||
|
||||
bool state::equal(int index1, int index2)
|
||||
{
|
||||
// avoid pcall overhead in trivial cases
|
||||
if( rawequal(index1, index2) )
|
||||
return true;
|
||||
bool state::equal(int index1, int index2)
|
||||
{
|
||||
// avoid pcall overhead in trivial cases
|
||||
if( rawequal(index1, index2) )
|
||||
return true;
|
||||
|
||||
return safe_compare(&safe_compare_trampoline<lua_equal>, index1, index2);
|
||||
}
|
||||
return safe_compare(&safe_compare_trampoline<lua_equal>, index1, index2);
|
||||
}
|
||||
|
||||
int state::gc(int what, int data)
|
||||
{
|
||||
checkstack(3);
|
||||
lua_pushcfunction(cobj.get(), safe_gc_trampoline);
|
||||
pushinteger(what);
|
||||
pushinteger(data);
|
||||
call(2, 1, 0);
|
||||
assert(isnumber(-1));
|
||||
int r = tointeger(-1);
|
||||
pop();
|
||||
return r;
|
||||
}
|
||||
int state::gc(int what, int data)
|
||||
{
|
||||
checkstack(3);
|
||||
lua_pushcfunction(cobj.get(), safe_gc_trampoline);
|
||||
pushinteger(what);
|
||||
pushinteger(data);
|
||||
call(2, 1, 0);
|
||||
assert(isnumber(-1));
|
||||
int r = tointeger(-1);
|
||||
pop();
|
||||
return r;
|
||||
}
|
||||
|
||||
void state::getfield(int index, const char *k)
|
||||
{
|
||||
checkstack(1);
|
||||
index = absindex(index);
|
||||
pushstring(k);
|
||||
gettable(index);
|
||||
}
|
||||
void state::getfield(int index, const char *k)
|
||||
{
|
||||
checkstack(1);
|
||||
index = absindex(index);
|
||||
pushstring(k);
|
||||
gettable(index);
|
||||
}
|
||||
|
||||
void state::gettable(int index)
|
||||
{
|
||||
checkstack(2);
|
||||
pushvalue(index);
|
||||
insert(-2);
|
||||
lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_gettable, 1>));
|
||||
insert(-3);
|
||||
call(2, 1, 0);
|
||||
}
|
||||
void state::gettable(int index)
|
||||
{
|
||||
checkstack(2);
|
||||
pushvalue(index);
|
||||
insert(-2);
|
||||
lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_gettable, 1>));
|
||||
insert(-3);
|
||||
call(2, 1, 0);
|
||||
}
|
||||
|
||||
bool state::lessthan(int index1, int index2)
|
||||
{
|
||||
return safe_compare(&safe_compare_trampoline<&lua_lessthan>, index1, index2);
|
||||
}
|
||||
bool state::lessthan(int index1, int index2)
|
||||
{
|
||||
return safe_compare(&safe_compare_trampoline<&lua_lessthan>, index1, index2);
|
||||
}
|
||||
|
||||
void state::loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc)
|
||||
{
|
||||
switch(luaL_loadstring(cobj.get(), s)) {
|
||||
case 0:
|
||||
return;
|
||||
case LUA_ERRSYNTAX:
|
||||
throw lua::syntax_error(this);
|
||||
case LUA_ERRMEM:
|
||||
throw std::bad_alloc();
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
void state::loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc)
|
||||
{
|
||||
switch(luaL_loadstring(cobj.get(), s)) {
|
||||
case 0:
|
||||
return;
|
||||
case LUA_ERRSYNTAX:
|
||||
throw lua::syntax_error(this);
|
||||
case LUA_ERRMEM:
|
||||
throw std::bad_alloc();
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool state::next(int index)
|
||||
{
|
||||
checkstack(2);
|
||||
pushvalue(index);
|
||||
insert(-2);
|
||||
lua_pushcfunction(cobj.get(), &safe_next_trampoline);
|
||||
insert(-3);
|
||||
bool state::next(int index)
|
||||
{
|
||||
checkstack(2);
|
||||
pushvalue(index);
|
||||
insert(-2);
|
||||
lua_pushcfunction(cobj.get(), &safe_next_trampoline);
|
||||
insert(-3);
|
||||
|
||||
call(2, MULTRET, 0);
|
||||
call(2, MULTRET, 0);
|
||||
|
||||
assert(isnumber(-1));
|
||||
int r = tointeger(-1);
|
||||
pop();
|
||||
return r;
|
||||
}
|
||||
assert(isnumber(-1));
|
||||
int r = tointeger(-1);
|
||||
pop();
|
||||
return r;
|
||||
}
|
||||
|
||||
void state::pushclosure(const cpp_function &fn, int n)
|
||||
{
|
||||
checkstack(2);
|
||||
void state::pushclosure(const cpp_function &fn, int n)
|
||||
{
|
||||
checkstack(2);
|
||||
|
||||
void *ptr = newuserdata(sizeof(cpp_function));
|
||||
rawgetfield(REGISTRYINDEX, cpp_function_metatable);
|
||||
setmetatable(-2);
|
||||
new(ptr) cpp_function(fn);
|
||||
void *ptr = newuserdata(sizeof(cpp_function));
|
||||
rawgetfield(REGISTRYINDEX, cpp_function_metatable);
|
||||
setmetatable(-2);
|
||||
new(ptr) cpp_function(fn);
|
||||
|
||||
insert(-n-1);
|
||||
lua_pushcclosure(cobj.get(), &closure_trampoline, n+1);
|
||||
}
|
||||
insert(-n-1);
|
||||
lua_pushcclosure(cobj.get(), &closure_trampoline, n+1);
|
||||
}
|
||||
|
||||
void state::rawgetfield(int index, const char *k) throw(std::bad_alloc)
|
||||
{ lua::rawgetfield(cobj.get(), index, k); }
|
||||
void state::rawgetfield(int index, const char *k) throw(std::bad_alloc)
|
||||
{ lua::rawgetfield(cobj.get(), index, k); }
|
||||
|
||||
void state::rawsetfield(int index, const char *k) throw(std::bad_alloc)
|
||||
{ lua::rawsetfield(cobj.get(), index, k); }
|
||||
void state::rawsetfield(int index, const char *k) throw(std::bad_alloc)
|
||||
{ lua::rawsetfield(cobj.get(), index, k); }
|
||||
|
||||
bool state::safe_compare(lua_CFunction trampoline, int index1, int index2)
|
||||
{
|
||||
// if one of the indexes is invalid, return false
|
||||
if(isnone(index1) || isnone(index2))
|
||||
return false;
|
||||
bool state::safe_compare(lua_CFunction trampoline, int index1, int index2)
|
||||
{
|
||||
// if one of the indexes is invalid, return false
|
||||
if(isnone(index1) || isnone(index2))
|
||||
return false;
|
||||
|
||||
// convert relative indexes into absolute
|
||||
index1 = absindex(index1);
|
||||
index2 = absindex(index2);
|
||||
// convert relative indexes into absolute
|
||||
index1 = absindex(index1);
|
||||
index2 = absindex(index2);
|
||||
|
||||
checkstack(3);
|
||||
lua_pushcfunction(cobj.get(), trampoline);
|
||||
pushvalue(index1);
|
||||
pushvalue(index2);
|
||||
call(2, 1, 0);
|
||||
assert(isnumber(-1));
|
||||
int r = tointeger(-1);
|
||||
pop();
|
||||
return r;
|
||||
}
|
||||
checkstack(3);
|
||||
lua_pushcfunction(cobj.get(), trampoline);
|
||||
pushvalue(index1);
|
||||
pushvalue(index2);
|
||||
call(2, 1, 0);
|
||||
assert(isnumber(-1));
|
||||
int r = tointeger(-1);
|
||||
pop();
|
||||
return r;
|
||||
}
|
||||
|
||||
void state::setfield(int index, const char *k)
|
||||
{
|
||||
checkstack(1);
|
||||
index = absindex(index);
|
||||
pushstring(k);
|
||||
insert(-2);
|
||||
settable(index);
|
||||
}
|
||||
void state::setfield(int index, const char *k)
|
||||
{
|
||||
checkstack(1);
|
||||
index = absindex(index);
|
||||
pushstring(k);
|
||||
insert(-2);
|
||||
settable(index);
|
||||
}
|
||||
|
||||
void state::settable(int index)
|
||||
{
|
||||
checkstack(2);
|
||||
pushvalue(index);
|
||||
insert(-3);
|
||||
lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_settable, 0>));
|
||||
insert(-4);
|
||||
call(3, 0, 0);
|
||||
}
|
||||
void state::settable(int index)
|
||||
{
|
||||
checkstack(2);
|
||||
pushvalue(index);
|
||||
insert(-3);
|
||||
lua_pushcfunction(cobj.get(), (&safe_misc_trampoline<&lua_settable, 0>));
|
||||
insert(-4);
|
||||
call(3, 0, 0);
|
||||
}
|
||||
|
||||
std::string state::tostring(int index) throw(lua::not_string_error)
|
||||
{
|
||||
size_t len;
|
||||
const char *str = lua_tolstring(cobj.get(), index, &len);
|
||||
if(not str)
|
||||
throw not_string_error();
|
||||
return std::string(str, len);
|
||||
}
|
||||
std::string state::tostring(int index) throw(lua::not_string_error)
|
||||
{
|
||||
size_t len;
|
||||
const char *str = lua_tolstring(cobj.get(), index, &len);
|
||||
if(not str)
|
||||
throw not_string_error();
|
||||
return std::string(str, len);
|
||||
}
|
||||
}
|
||||
|
436
src/luamm.hh
436
src/luamm.hh
@ -29,126 +29,126 @@
|
||||
#include <lua.hpp>
|
||||
|
||||
namespace lua {
|
||||
class state;
|
||||
class state;
|
||||
|
||||
typedef lua_Integer integer;
|
||||
typedef lua_Number number;
|
||||
typedef std::function<int(state *)> cpp_function;
|
||||
typedef lua_Integer integer;
|
||||
typedef lua_Number number;
|
||||
typedef std::function<int(state *)> cpp_function;
|
||||
|
||||
enum {
|
||||
ENVIRONINDEX = LUA_ENVIRONINDEX,
|
||||
GLOBALSINDEX = LUA_GLOBALSINDEX,
|
||||
REGISTRYINDEX = LUA_REGISTRYINDEX
|
||||
};
|
||||
enum {
|
||||
ENVIRONINDEX = LUA_ENVIRONINDEX,
|
||||
GLOBALSINDEX = LUA_GLOBALSINDEX,
|
||||
REGISTRYINDEX = LUA_REGISTRYINDEX
|
||||
};
|
||||
|
||||
enum {
|
||||
GCSTOP = LUA_GCSTOP,
|
||||
GCRESTART = LUA_GCRESTART,
|
||||
GCCOLLECT = LUA_GCCOLLECT,
|
||||
GCCOUNT = LUA_GCCOUNT,
|
||||
GCCOUNTB = LUA_GCCOUNTB,
|
||||
GCSTEP = LUA_GCSTEP,
|
||||
GCSETPAUSE = LUA_GCSETPAUSE,
|
||||
GCSETSTEPMUL = LUA_GCSETSTEPMUL
|
||||
};
|
||||
enum {
|
||||
GCSTOP = LUA_GCSTOP,
|
||||
GCRESTART = LUA_GCRESTART,
|
||||
GCCOLLECT = LUA_GCCOLLECT,
|
||||
GCCOUNT = LUA_GCCOUNT,
|
||||
GCCOUNTB = LUA_GCCOUNTB,
|
||||
GCSTEP = LUA_GCSTEP,
|
||||
GCSETPAUSE = LUA_GCSETPAUSE,
|
||||
GCSETSTEPMUL = LUA_GCSETSTEPMUL
|
||||
};
|
||||
|
||||
enum {
|
||||
MULTRET = LUA_MULTRET
|
||||
};
|
||||
enum {
|
||||
MULTRET = LUA_MULTRET
|
||||
};
|
||||
|
||||
enum {
|
||||
TBOOLEAN = LUA_TBOOLEAN,
|
||||
TFUNCTION = LUA_TFUNCTION,
|
||||
TLIGHTUSERDATA = LUA_TLIGHTUSERDATA,
|
||||
TNIL = LUA_TNIL,
|
||||
TNONE = LUA_TNONE,
|
||||
TNUMBER = LUA_TNUMBER,
|
||||
TSTRING = LUA_TSTRING,
|
||||
TTABLE = LUA_TTABLE,
|
||||
TTHREAD = LUA_TTHREAD,
|
||||
TUSERDATA = LUA_TUSERDATA
|
||||
};
|
||||
enum {
|
||||
TBOOLEAN = LUA_TBOOLEAN,
|
||||
TFUNCTION = LUA_TFUNCTION,
|
||||
TLIGHTUSERDATA = LUA_TLIGHTUSERDATA,
|
||||
TNIL = LUA_TNIL,
|
||||
TNONE = LUA_TNONE,
|
||||
TNUMBER = LUA_TNUMBER,
|
||||
TSTRING = LUA_TSTRING,
|
||||
TTABLE = LUA_TTABLE,
|
||||
TTHREAD = LUA_TTHREAD,
|
||||
TUSERDATA = LUA_TUSERDATA
|
||||
};
|
||||
|
||||
// we reserve one upvalue for the function pointer
|
||||
inline int upvalueindex(int n)
|
||||
{ return lua_upvalueindex(n+1); }
|
||||
// we reserve one upvalue for the function pointer
|
||||
inline int upvalueindex(int n)
|
||||
{ return lua_upvalueindex(n+1); }
|
||||
|
||||
/*
|
||||
* Lua error()s are wrapped in this class when rethrown into C++ code. what() returns the
|
||||
* error message. push_lua_error() pushes the error onto lua stack. The error can only be
|
||||
* pushed into the same state it was generated in.
|
||||
*/
|
||||
class exception: public std::runtime_error {
|
||||
/*
|
||||
* We only allow moving, to avoid complications with multiple references. It shouldn't be
|
||||
* difficult to modify this to work with copying, if that proves unavoidable.
|
||||
*/
|
||||
state *L;
|
||||
int key;
|
||||
/*
|
||||
* Lua error()s are wrapped in this class when rethrown into C++ code. what() returns the
|
||||
* error message. push_lua_error() pushes the error onto lua stack. The error can only be
|
||||
* pushed into the same state it was generated in.
|
||||
*/
|
||||
class exception: public std::runtime_error {
|
||||
/*
|
||||
* We only allow moving, to avoid complications with multiple references. It shouldn't be
|
||||
* difficult to modify this to work with copying, if that proves unavoidable.
|
||||
*/
|
||||
state *L;
|
||||
int key;
|
||||
|
||||
static std::string get_error_msg(state *L);
|
||||
static std::string get_error_msg(state *L);
|
||||
|
||||
exception(const exception &) = delete;
|
||||
const exception& operator=(const exception &) = delete;
|
||||
exception(const exception &) = delete;
|
||||
const exception& operator=(const exception &) = delete;
|
||||
|
||||
public:
|
||||
exception(exception &&other)
|
||||
: std::runtime_error(std::move(other)), L(other.L), key(other.key)
|
||||
{ other.L = NULL; }
|
||||
public:
|
||||
exception(exception &&other)
|
||||
: std::runtime_error(std::move(other)), L(other.L), key(other.key)
|
||||
{ other.L = NULL; }
|
||||
|
||||
explicit exception(state *l);
|
||||
virtual ~exception() throw();
|
||||
explicit exception(state *l);
|
||||
virtual ~exception() throw();
|
||||
|
||||
void push_lua_error(state *l);
|
||||
};
|
||||
void push_lua_error(state *l);
|
||||
};
|
||||
|
||||
class not_string_error: public std::runtime_error {
|
||||
public:
|
||||
not_string_error()
|
||||
: std::runtime_error("Cannot convert value to a string")
|
||||
{}
|
||||
};
|
||||
class not_string_error: public std::runtime_error {
|
||||
public:
|
||||
not_string_error()
|
||||
: std::runtime_error("Cannot convert value to a string")
|
||||
{}
|
||||
};
|
||||
|
||||
// the name says it all
|
||||
class syntax_error: public lua::exception {
|
||||
syntax_error(const syntax_error &) = delete;
|
||||
const syntax_error& operator=(const syntax_error &) = delete;
|
||||
// the name says it all
|
||||
class syntax_error: public lua::exception {
|
||||
syntax_error(const syntax_error &) = delete;
|
||||
const syntax_error& operator=(const syntax_error &) = delete;
|
||||
|
||||
public:
|
||||
syntax_error(state *L)
|
||||
: lua::exception(L)
|
||||
{}
|
||||
public:
|
||||
syntax_error(state *L)
|
||||
: lua::exception(L)
|
||||
{}
|
||||
|
||||
syntax_error(syntax_error &&other)
|
||||
: lua::exception(std::move(other))
|
||||
{}
|
||||
};
|
||||
syntax_error(syntax_error &&other)
|
||||
: lua::exception(std::move(other))
|
||||
{}
|
||||
};
|
||||
|
||||
// double fault, lua encountered an error while running the error handler function
|
||||
class errfunc_error: public lua::exception {
|
||||
errfunc_error(const errfunc_error &) = delete;
|
||||
const errfunc_error& operator=(const errfunc_error &) = delete;
|
||||
// double fault, lua encountered an error while running the error handler function
|
||||
class errfunc_error: public lua::exception {
|
||||
errfunc_error(const errfunc_error &) = delete;
|
||||
const errfunc_error& operator=(const errfunc_error &) = delete;
|
||||
|
||||
public:
|
||||
errfunc_error(state *L)
|
||||
: lua::exception(L)
|
||||
{}
|
||||
public:
|
||||
errfunc_error(state *L)
|
||||
: lua::exception(L)
|
||||
{}
|
||||
|
||||
errfunc_error(errfunc_error &&other)
|
||||
: lua::exception(std::move(other))
|
||||
{}
|
||||
};
|
||||
errfunc_error(errfunc_error &&other)
|
||||
: lua::exception(std::move(other))
|
||||
{}
|
||||
};
|
||||
|
||||
// a fancy wrapper around lua_State
|
||||
class state {
|
||||
std::shared_ptr<lua_State> cobj;
|
||||
// a fancy wrapper around lua_State
|
||||
class state {
|
||||
std::shared_ptr<lua_State> cobj;
|
||||
|
||||
// destructor for C++ objects stored as lua userdata
|
||||
template<typename T>
|
||||
static int destroy_cpp_object(lua_State *l)
|
||||
{
|
||||
T *ptr = static_cast<T *>(lua_touserdata(l, -1));
|
||||
assert(ptr);
|
||||
// destructor for C++ objects stored as lua userdata
|
||||
template<typename T>
|
||||
static int destroy_cpp_object(lua_State *l)
|
||||
{
|
||||
T *ptr = static_cast<T *>(lua_touserdata(l, -1));
|
||||
assert(ptr);
|
||||
try {
|
||||
// throwing exceptions in destructors is a bad idea
|
||||
// but we catch (and ignore) them, just in case
|
||||
@ -156,85 +156,85 @@ namespace lua {
|
||||
}
|
||||
catch(...) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool safe_compare(lua_CFunction trampoline, int index1, int index2);
|
||||
public:
|
||||
state();
|
||||
bool safe_compare(lua_CFunction trampoline, int index1, int index2);
|
||||
public:
|
||||
state();
|
||||
|
||||
/*
|
||||
* Lua functions come in three flavours
|
||||
* a) functions that never throw an exception
|
||||
* b) functions that throw only in case of a memory allocation error
|
||||
* c) functions that throw other kinds of errors
|
||||
*
|
||||
* Calls to type a functions are simply forwarded to the C api.
|
||||
* Type c functions are executed in protected mode, to make sure they don't longjmp()
|
||||
* over us (and our destructors). This add a certain amount overhead. If you care about
|
||||
* performance, try using the raw versions (if possible).
|
||||
* Type b functions are not executed in protected mode atm. as memory allocation errors
|
||||
* don't happen that often (as opposed to the type c, where the user get deliberately set
|
||||
* a metamethod that throws an error). That means those errors will do something
|
||||
* undefined, but hopefully that won't be a problem.
|
||||
*
|
||||
* Semantics are mostly identical to those of the underlying C api. Any deviation is
|
||||
* noted in the respective functions comment. The most important difference is that
|
||||
* instead of return values, we use exceptions to indicate errors. The lua and C++
|
||||
* exception mechanisms are integrated. That means one can throw a C++ exception and
|
||||
* catch it in lua (with pcall). Lua error()s can be caught in C++ as exceptions of type
|
||||
* lua::exception.
|
||||
*/
|
||||
/*
|
||||
* Lua functions come in three flavours
|
||||
* a) functions that never throw an exception
|
||||
* b) functions that throw only in case of a memory allocation error
|
||||
* c) functions that throw other kinds of errors
|
||||
*
|
||||
* Calls to type a functions are simply forwarded to the C api.
|
||||
* Type c functions are executed in protected mode, to make sure they don't longjmp()
|
||||
* over us (and our destructors). This add a certain amount overhead. If you care about
|
||||
* performance, try using the raw versions (if possible).
|
||||
* Type b functions are not executed in protected mode atm. as memory allocation errors
|
||||
* don't happen that often (as opposed to the type c, where the user get deliberately set
|
||||
* a metamethod that throws an error). That means those errors will do something
|
||||
* undefined, but hopefully that won't be a problem.
|
||||
*
|
||||
* Semantics are mostly identical to those of the underlying C api. Any deviation is
|
||||
* noted in the respective functions comment. The most important difference is that
|
||||
* instead of return values, we use exceptions to indicate errors. The lua and C++
|
||||
* exception mechanisms are integrated. That means one can throw a C++ exception and
|
||||
* catch it in lua (with pcall). Lua error()s can be caught in C++ as exceptions of type
|
||||
* lua::exception.
|
||||
*/
|
||||
|
||||
// type a, never throw
|
||||
int absindex(int index) throw() { return index<0 && -index<=gettop() ? gettop()+1+index : index; }
|
||||
bool getmetatable(int index) throw() { return lua_getmetatable(cobj.get(), index); }
|
||||
int gettop() throw() { return lua_gettop(cobj.get()); }
|
||||
void insert(int index) throw() { lua_insert(cobj.get(), index); }
|
||||
bool isfunction(int index) throw() { return lua_isfunction(cobj.get(), index); }
|
||||
bool islightuserdata(int index) throw() { return lua_islightuserdata(cobj.get(), index); }
|
||||
bool isnone(int index) throw() { return lua_isnone(cobj.get(), index); }
|
||||
bool isnumber(int index) throw() { return lua_isnumber(cobj.get(), index); }
|
||||
bool isstring(int index) throw() { return lua_isstring(cobj.get(), index); }
|
||||
void pop(int n = 1) throw() { lua_pop(cobj.get(), n); }
|
||||
void pushboolean(bool b) throw() { lua_pushboolean(cobj.get(), b); }
|
||||
void pushinteger(integer n) throw() { lua_pushinteger(cobj.get(), n); }
|
||||
void pushlightuserdata(void *p) throw() { lua_pushlightuserdata(cobj.get(), p); }
|
||||
void pushnil() throw() { lua_pushnil(cobj.get()); }
|
||||
// type a, never throw
|
||||
int absindex(int index) throw() { return index<0 && -index<=gettop() ? gettop()+1+index : index; }
|
||||
bool getmetatable(int index) throw() { return lua_getmetatable(cobj.get(), index); }
|
||||
int gettop() throw() { return lua_gettop(cobj.get()); }
|
||||
void insert(int index) throw() { lua_insert(cobj.get(), index); }
|
||||
bool isfunction(int index) throw() { return lua_isfunction(cobj.get(), index); }
|
||||
bool islightuserdata(int index) throw() { return lua_islightuserdata(cobj.get(), index); }
|
||||
bool isnone(int index) throw() { return lua_isnone(cobj.get(), index); }
|
||||
bool isnumber(int index) throw() { return lua_isnumber(cobj.get(), index); }
|
||||
bool isstring(int index) throw() { return lua_isstring(cobj.get(), index); }
|
||||
void pop(int n = 1) throw() { lua_pop(cobj.get(), n); }
|
||||
void pushboolean(bool b) throw() { lua_pushboolean(cobj.get(), b); }
|
||||
void pushinteger(integer n) throw() { lua_pushinteger(cobj.get(), n); }
|
||||
void pushlightuserdata(void *p) throw() { lua_pushlightuserdata(cobj.get(), p); }
|
||||
void pushnil() throw() { lua_pushnil(cobj.get()); }
|
||||
void pushnumber(number n) throw() { lua_pushnumber(cobj.get(), n); }
|
||||
void pushvalue(int index) throw() { lua_pushvalue(cobj.get(), index); }
|
||||
void rawget(int index) throw() { lua_rawget(cobj.get(), index); }
|
||||
void rawgeti(int index, int n) throw() { lua_rawgeti(cobj.get(), index, n); }
|
||||
bool rawequal(int index1, int index2) throw() { return lua_rawequal(cobj.get(), index1, index2); }
|
||||
void replace(int index) throw() { lua_replace(cobj.get(), index); }
|
||||
// lua_setmetatable returns int, but docs don't specify it's meaning :/
|
||||
int setmetatable(int index) throw() { return lua_setmetatable(cobj.get(), index); }
|
||||
integer tointeger(int index) throw() { return lua_tointeger(cobj.get(), index); }
|
||||
number tonumber(int index) throw() { return lua_tonumber(cobj.get(), index); }
|
||||
void* touserdata(int index) throw() { return lua_touserdata(cobj.get(), index); }
|
||||
int type(int index) throw() { return lua_type(cobj.get(), index); }
|
||||
// typename is a reserved word :/
|
||||
const char* type_name(int tp) throw() { return lua_typename(cobj.get(), tp); }
|
||||
void unref(int t, int ref) throw() { return luaL_unref(cobj.get(), t, ref); }
|
||||
void pushvalue(int index) throw() { lua_pushvalue(cobj.get(), index); }
|
||||
void rawget(int index) throw() { lua_rawget(cobj.get(), index); }
|
||||
void rawgeti(int index, int n) throw() { lua_rawgeti(cobj.get(), index, n); }
|
||||
bool rawequal(int index1, int index2) throw() { return lua_rawequal(cobj.get(), index1, index2); }
|
||||
void replace(int index) throw() { lua_replace(cobj.get(), index); }
|
||||
// lua_setmetatable returns int, but docs don't specify it's meaning :/
|
||||
int setmetatable(int index) throw() { return lua_setmetatable(cobj.get(), index); }
|
||||
integer tointeger(int index) throw() { return lua_tointeger(cobj.get(), index); }
|
||||
number tonumber(int index) throw() { return lua_tonumber(cobj.get(), index); }
|
||||
void* touserdata(int index) throw() { return lua_touserdata(cobj.get(), index); }
|
||||
int type(int index) throw() { return lua_type(cobj.get(), index); }
|
||||
// typename is a reserved word :/
|
||||
const char* type_name(int tp) throw() { return lua_typename(cobj.get(), tp); }
|
||||
void unref(int t, int ref) throw() { return luaL_unref(cobj.get(), t, ref); }
|
||||
|
||||
// type b, throw only on memory allocation errors
|
||||
// checkstack correctly throws bad_alloc, because lua_checkstack kindly informs us of
|
||||
// that sitution
|
||||
void checkstack(int extra) throw(std::bad_alloc);
|
||||
bool newmetatable(const char *tname) { return luaL_newmetatable(cobj.get(), tname); }
|
||||
void newtable() { lua_newtable(cobj.get()); }
|
||||
void *newuserdata(size_t size) { return lua_newuserdata(cobj.get(), size); }
|
||||
// cpp_function can be anything that std::function can handle, everything else remains
|
||||
// identical
|
||||
void pushclosure(const cpp_function &fn, int n);
|
||||
void pushfunction(const cpp_function &fn) { pushclosure(fn, 0); }
|
||||
void pushstring(const char *s) { lua_pushstring(cobj.get(), s); }
|
||||
void rawgetfield(int index, const char *k) throw(std::bad_alloc);
|
||||
void rawset(int index) { lua_rawset(cobj.get(), index); }
|
||||
void rawsetfield(int index, const char *k) throw(std::bad_alloc);
|
||||
int ref(int t) { return luaL_ref(cobj.get(), t); }
|
||||
// len recieves length, if not null. Returned value may contain '\0'
|
||||
const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj.get(), index, len); }
|
||||
// type b, throw only on memory allocation errors
|
||||
// checkstack correctly throws bad_alloc, because lua_checkstack kindly informs us of
|
||||
// that sitution
|
||||
void checkstack(int extra) throw(std::bad_alloc);
|
||||
bool newmetatable(const char *tname) { return luaL_newmetatable(cobj.get(), tname); }
|
||||
void newtable() { lua_newtable(cobj.get()); }
|
||||
void *newuserdata(size_t size) { return lua_newuserdata(cobj.get(), size); }
|
||||
// cpp_function can be anything that std::function can handle, everything else remains
|
||||
// identical
|
||||
void pushclosure(const cpp_function &fn, int n);
|
||||
void pushfunction(const cpp_function &fn) { pushclosure(fn, 0); }
|
||||
void pushstring(const char *s) { lua_pushstring(cobj.get(), s); }
|
||||
void rawgetfield(int index, const char *k) throw(std::bad_alloc);
|
||||
void rawset(int index) { lua_rawset(cobj.get(), index); }
|
||||
void rawsetfield(int index, const char *k) throw(std::bad_alloc);
|
||||
int ref(int t) { return luaL_ref(cobj.get(), t); }
|
||||
// len recieves length, if not null. Returned value may contain '\0'
|
||||
const char* tocstring(int index, size_t *len = NULL) { return lua_tolstring(cobj.get(), index, len); }
|
||||
// Don't use pushclosure() to create a __gc function. The problem is that lua calls them
|
||||
// in an unspecified order, and we may end up destroying the object holding the
|
||||
// std::function before we get a chance to call it. This pushes a function that simply
|
||||
@ -243,54 +243,54 @@ namespace lua {
|
||||
void pushdestructor()
|
||||
{ lua_pushcfunction(cobj.get(), &destroy_cpp_object<T>); }
|
||||
|
||||
// type c, throw everything but the kitchen sink
|
||||
// call() is a protected mode call, we don't allow unprotected calls
|
||||
void call(int nargs, int nresults, int errfunc = 0);
|
||||
void concat(int n);
|
||||
bool equal(int index1, int index2);
|
||||
int gc(int what, int data);
|
||||
void getfield(int index, const char *k);
|
||||
void gettable(int index);
|
||||
void getglobal(const char *name) { getfield(GLOBALSINDEX, name); }
|
||||
bool lessthan(int index1, int index2);
|
||||
void loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc);
|
||||
bool next(int index);
|
||||
// register is a reserved word :/
|
||||
void register_fn(const char *name, const cpp_function &f) { pushfunction(f); setglobal(name); }
|
||||
void setfield(int index, const char *k);
|
||||
void setglobal(const char *name) { setfield(GLOBALSINDEX, name); }
|
||||
void settable(int index);
|
||||
// lua_tostring uses NULL to indicate conversion error, since there is no such thing as a
|
||||
// NULL std::string, we throw an exception. Returned value may contain '\0'
|
||||
std::string tostring(int index) throw(lua::not_string_error);
|
||||
};
|
||||
// type c, throw everything but the kitchen sink
|
||||
// call() is a protected mode call, we don't allow unprotected calls
|
||||
void call(int nargs, int nresults, int errfunc = 0);
|
||||
void concat(int n);
|
||||
bool equal(int index1, int index2);
|
||||
int gc(int what, int data);
|
||||
void getfield(int index, const char *k);
|
||||
void gettable(int index);
|
||||
void getglobal(const char *name) { getfield(GLOBALSINDEX, name); }
|
||||
bool lessthan(int index1, int index2);
|
||||
void loadstring(const char *s) throw(lua::syntax_error, std::bad_alloc);
|
||||
bool next(int index);
|
||||
// register is a reserved word :/
|
||||
void register_fn(const char *name, const cpp_function &f) { pushfunction(f); setglobal(name); }
|
||||
void setfield(int index, const char *k);
|
||||
void setglobal(const char *name) { setfield(GLOBALSINDEX, name); }
|
||||
void settable(int index);
|
||||
// lua_tostring uses NULL to indicate conversion error, since there is no such thing as a
|
||||
// NULL std::string, we throw an exception. Returned value may contain '\0'
|
||||
std::string tostring(int index) throw(lua::not_string_error);
|
||||
};
|
||||
|
||||
/*
|
||||
* Can be used to automatically pop temporary values off the lua stack on exit from the
|
||||
* function/block (e.g. via an exception). The constructor parameter indicates the number of
|
||||
* values to pop(). That can be later changed with the overloaded operators. The idiom is:
|
||||
* stack_sentry s(L);
|
||||
* L.an_operation_that_pushes_something(); ++s;
|
||||
* ...
|
||||
*/
|
||||
class stack_sentry {
|
||||
state *L;
|
||||
int n;
|
||||
|
||||
stack_sentry(const stack_sentry &) = delete;
|
||||
const stack_sentry& operator=(const stack_sentry &) = delete;
|
||||
public:
|
||||
explicit stack_sentry(state &l, int n_ = 0) throw()
|
||||
: L(&l), n(n_)
|
||||
{}
|
||||
/*
|
||||
* Can be used to automatically pop temporary values off the lua stack on exit from the
|
||||
* function/block (e.g. via an exception). The constructor parameter indicates the number of
|
||||
* values to pop(). That can be later changed with the overloaded operators. The idiom is:
|
||||
* stack_sentry s(L);
|
||||
* L.an_operation_that_pushes_something(); ++s;
|
||||
* ...
|
||||
*/
|
||||
class stack_sentry {
|
||||
state *L;
|
||||
int n;
|
||||
|
||||
stack_sentry(const stack_sentry &) = delete;
|
||||
const stack_sentry& operator=(const stack_sentry &) = delete;
|
||||
public:
|
||||
explicit stack_sentry(state &l, int n_ = 0) throw()
|
||||
: L(&l), n(n_)
|
||||
{}
|
||||
|
||||
~stack_sentry() throw() { L->pop(n); }
|
||||
~stack_sentry() throw() { L->pop(n); }
|
||||
|
||||
void operator++() throw() { ++n; }
|
||||
void operator--() throw() { --n; }
|
||||
void operator+=(int n_) throw() { n+=n_; }
|
||||
void operator-=(int n_) throw() { n-=n_; }
|
||||
};
|
||||
void operator++() throw() { ++n; }
|
||||
void operator--() throw() { --n; }
|
||||
void operator+=(int n_) throw() { n+=n_; }
|
||||
void operator-=(int n_) throw() { n-=n_; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* LUAMM_HH */
|
||||
|
Loading…
Reference in New Issue
Block a user