summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/BLua.h235
-rw-r--r--lib/BLua.cc32
-rw-r--r--lib/LuaHandle.cc14
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<classname>::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<classname>::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 T>
+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 <lualib.h>
@@ -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);
}