From 8978c2d4164c898565c4e154c29bca230a7ec9b4 Mon Sep 17 00:00:00 2001 From: pixel Date: Sun, 7 Dec 2003 04:44:38 +0000 Subject: LUA work work work --- include/BLua.h | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- lib/BLua.cc | 32 ++++++-- lib/LuaHandle.cc | 14 +--- 3 files changed, 261 insertions(+), 20 deletions(-) diff --git a/include/BLua.h b/include/BLua.h index 5f30199..8e4f549 100644 --- a/include/BLua.h +++ b/include/BLua.h @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: BLua.h,v 1.6 2003-12-06 04:26:16 pixel Exp $ */ +/* $Id: BLua.h,v 1.7 2003-12-07 04:44:38 pixel Exp $ */ #ifndef __BLUA_H__ #define __BLUA_H__ @@ -45,12 +45,14 @@ class Lua : public Base { void push(lua_Number); void push(const String &); void push(bool); + void push(char *, int size = -1); void push(void *); void push(lua_CFunction, int = 0); void pop(int = 1); void newtable(); void settable(int = -3, bool raw = false); void gettable(int = -2, bool raw = false); + void setvar(); int gettop(); void error(const String &); int type(int = -1); @@ -92,7 +94,238 @@ class LuaObject : public Base { virtual void pushmembers(Lua *) = 0; void pushme(Lua *, void *); static void pushit(Lua *, const String &, lua_CFunction); + static void pushmeta(Lua *, const String &, lua_CFunction); bool wantdestruct, pushed; }; +enum Lua_types_t { + LUA_ANY = 0, + LUA_OBJECT, + LUA_TABLE, + LUA_BOOLEAN, + LUA_NUMBER, + LUA_STRING, + LUA_FUNCTION, +}; + +#define MAXARGS 32 + +struct lua_functypes_t { + int number; + char * name; + int minargs, maxargs; + int argtypes[MAXARGS]; +}; + +#define DECLARE_METHOD(classname, enumvar) static int method_##enumvar(lua_State * L) { \ + return LuaHelpers::method_multiplex( \ + enumvar, \ + L, \ + sLua_##classname::##classname##_proceed, \ + 0, \ + classname##_methods, \ + true); \ + } + +#define DECLARE_FUNCTION(classname, enumvar) static int function_##enumvar(lua_State * L) { \ + return LuaHelpers::method_multiplex( \ + enumvar, \ + L, \ + 0, \ + sLua_##classname::##classname##_proceed_statics, \ + classname##_functions, \ + false); \ + } + +#define PUSH_METHOD(classname, enumvar) pushit( \ + L, \ + classname##_methods[enumvar].name, \ + sLua_##classname##::method_##enumvar) + +#define PUSH_METAMETHOD(classname, enumvar) pushmeta( \ + L, \ + String("__") + classname##_methods[enumvar].name, \ + sLua_##classname##::method_##enumvar) + +#define PUSH_FUNCTION(classname, enumvar) L->declarefunc( \ + classname##_functions[enumvar].name, \ + sLua_##classname##::function_##enumvar) + + +#define CHECK_METHODS(classname) { \ + int i = 0; \ + while (classname##_methods[i].number != -1) { \ + if (i != classname##_methods[i].number) { \ + throw GeneralException("Datas of " #classname "_methods inconsistants!"); \ + } \ + i++; \ + } \ +} + +#define CHECK_FUNCTIONS(classname) { \ + int i = 0; \ + while (classname##_functions[i].number != -1) { \ + if (i != classname##_functions[i].number) { \ + throw GeneralException("Datas of " #classname "_functions inconsistants!"); \ + } \ + i++; \ + } \ +} + +template +class LuaHelpers : public Base { + public: + static int method_multiplex(int caller, lua_State * _L, int (*proceed)(Lua * L, int n, T * obj, int caller), int (*proceed_static)(Lua * L, int n, int caller), lua_functypes_t * tab, bool method) { + Lua * L = Lua::find(_L); + int n = L->gettop() - (method ? 1 : 0); + T * obj = (T *) LuaObject::getme(L); + int i; + bool invalid = false; + + if ((n < tab[caller].minargs) || (n > tab[caller].maxargs)) { + invalid = true; + } else { + for (i = 0; i < tab[caller].maxargs && !invalid; i++) { + if (n >= (i + 1)) { + switch(tab[caller].argtypes[i]) { + case LUA_ANY: + break; + case LUA_OBJECT: + invalid = !L->istable(i + 2); + if (!invalid) { + L->push("__obj"); + L->gettable(i + 2); + invalid = L->islightuserdata(); + L->pop(); + } + break; + case LUA_TABLE: + invalid = !L->istable(i + 2); + break; + case LUA_BOOLEAN: + invalid = !L->isboolean(i + 2); + break; + case LUA_NUMBER: + invalid = !L->isnumber(i + 2); + break; + case LUA_STRING: + invalid = !L->isstring(i + 2); + break; + case LUA_FUNCTION: + invalid = !L->isfunction(i + 2); + break; + } + } + } + } + + if (invalid) { + if (method) { + L->error(String("Invalid arguments to method `") + typeid(T).name() + "::" + tab[caller].name + "'"); + } else { + L->error(String("Invalid arguments to function `") + typeid(T).name() + "::" + tab[caller].name + "'"); + } + } + + if (method) { + return proceed(L, n, obj, caller); + } else { + return proceed_static(L, n, caller); + } + } +}; + + +/*********************************\ +|** Let's have a sample of use **| +\*********************************/ + +#ifdef THIS_IS_A_SAMPLE_WHICH_DOES_NOT_COMPILE +Luacdfile::Luacdfile(cdfile * h) : LuaHandle(h) { } + +enum cdfile_methods_t { + CDFILE_XXX = 0, + CDFILE_YYY +}; + +enum cdfile_functions_t { + CDFILE_NEWCDFILE = 0, +}; + +struct lua_functypes_t cdutils_methods[] = { + { CDFILE_XXX, "xxx", 1, 1, {LUA_OBJECT} }, + { CDFILE_YYY, "yyy", 0, 2, {LUA_NUMBER, LUA_NUMBER} }, + { -1, 0, 0, 0, 0 } +}; + +struct lua_functypes_t cdfile_functions[] = { + { CDFILE_NEWCDFILE, "cdfile", 1, 4, {LUA_OBJECT, LUA_ANY, LUA_NUMBER, LUA_NUMBER} }, + { -1, 0, 0, 0, 0 } +}; + +class sLua_cdfile : public Base { + public: + static int newcdfile(lua_State * L); + DECLARE_METHOD(cdfile, CDFILE_XXX); + DECLARE_METHOD(cdfile, CDFILE_YYY); + DECLARE_FUNCTION(cdfile, CDFILE_NEWCDFILE); + private: + static int cdfile_proceed(Lua * L, int n, cdfile * obj, int caller); + static int cdfile_proceed_statics(Lua * L, int n, int caller); +}; + +void Luacdfile::pushmembers(Lua * L) { + { + LuaHandle::pushmembers(L); + or + pushme(L, SomeObject); + } + PUSH_METHOD(cdfile, CDFILE_XXX); + PUSH_METHOD(cdfile, CDFILE_YYY); +} + +void Luacdfile::pushstatics(Lua * L) { + CHECK_METHODS(cdfile); + CHECK_FUNCTIONS(cdfile); + + PUSH_FUNCTION(cdfile, CDFILE_NEWCDFILE); +} + +int sLua_cdfile::cdfile_proceed(Lua * L, int n, cdfile * cdfile, int caller) { + int r = 0; + SomeObj * obj; + int arg1 = DEFAULT1, arg2 = DEFAULT2; + + switch(caller) { + case CDFILE_XXX: + obj = (SomeObj *) LuaObject::getme(L, 2); + cdfile->xxx(obj); + break; + case CDFILE_YYY: + if (n >= 1) + arg1 = L->tonumber(2); + if (n >= 2) + arg2 = L->tonumber(3); + L->push((lua_Number) cdfile->yyy(arg1, arg2)); + r = 1; + break; + } + + return r; +} + +int sLua_cdfile::cdfile_proceed_statics(Lua * L, int n, int caller) { + int r = 0; + + switch(caller) { + case CDFILE_NEWCDFILE: + /****TODO****/ + break; + } + + return r; +} + +#endif + #endif diff --git a/lib/BLua.cc b/lib/BLua.cc index 7a4f1d9..9e5373e 100644 --- a/lib/BLua.cc +++ b/lib/BLua.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: BLua.cc,v 1.7 2003-12-04 04:09:02 pixel Exp $ */ +/* $Id: BLua.cc,v 1.8 2003-12-07 04:44:38 pixel Exp $ */ #include @@ -224,6 +224,14 @@ void Lua::push(bool b) { lua_pushboolean(L, b); } +void Lua::push(char * s, int size) { + if (size < 0) { + lua_pushstring(L, s); + } else { + lua_pushlstring(L, s, size); + } +} + void Lua::push(void * p) { lua_pushlightuserdata(L, p); } @@ -256,6 +264,10 @@ void Lua::gettable(int i, bool raw) { } } +void Lua::setvar() { + lua_settable(L, LUA_GLOBALSINDEX); +} + int Lua::gettop() { return lua_gettop(L); } @@ -486,6 +498,16 @@ void LuaObject::pushit(Lua * L, const String & s, lua_CFunction f) { L->settable(); } +void LuaObject::pushmeta(Lua * L, const String & s, lua_CFunction f) { + if (!L->getmetatable(1)) { + L->newtable(); + } + L->push(s); + L->push(f); + L->settable(); + L->setmetatable(1); +} + int LuaStatics::destructor(lua_State * _L) { Lua * L = Lua::find(_L); Base * b = (Base *) LuaObject::getme(L); @@ -502,13 +524,7 @@ void LuaObject::pushdestruct(Lua * L) throw (GeneralException) { throw GeneralException("Error: can't push destructor, object already pushed"); } push(L); - if (!L->getmetatable(1)) { - L->newtable(); - } - L->push("__gc"); - L->push(LuaStatics::destructor); - L->settable(); - L->setmetatable(1); + pushmeta(L, "__gc", LuaStatics::destructor); pushit(L, "destroy", LuaStatics::destructor); wantdestruct = true; diff --git a/lib/LuaHandle.cc b/lib/LuaHandle.cc index 487470d..373066f 100644 --- a/lib/LuaHandle.cc +++ b/lib/LuaHandle.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: LuaHandle.cc,v 1.6 2003-12-06 04:26:17 pixel Exp $ */ +/* $Id: LuaHandle.cc,v 1.7 2003-12-07 04:44:38 pixel Exp $ */ #include "LuaHandle.h" @@ -601,16 +601,8 @@ void LuaOutput::pushmembers(Lua * L) { void LuaBuffer::pushmembers(Lua * L) { LuaHandle::pushmembers(L); - if (!L->getmetatable(1)) { - L->newtable(); - } - L->push("__index"); - L->push(sLuaHandle::bindex); - L->settable(); - L->push("__newindex"); - L->push(sLuaHandle::bnewindex); - L->settable(); - L->setmetatable(1); + pushmeta(L, "__index", sLuaHandle::bindex); + pushmeta(L, "__newindex", sLuaHandle::bnewindex); pushit(L, "wtell", sLuaHandle::btell); pushit(L, "wseek", sLuaHandle::bseek); } -- cgit v1.2.3