summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/BLua.h4
-rw-r--r--include/LuaHandle.h14
-rw-r--r--lib/LuaHandle.cc405
3 files changed, 403 insertions, 20 deletions
diff --git a/include/BLua.h b/include/BLua.h
index 5d61dc1..f1401fd 100644
--- a/include/BLua.h
+++ b/include/BLua.h
@@ -70,6 +70,8 @@ class Lua : public Base {
Lua(const Lua &) throw (GeneralException);
virtual ~Lua();
typedef int (*lua_CallWrapper)(lua_State *, lua_CFunction);
+ int ref(int t = -2) { luaL_ref(L, t); }
+ void unref(int ref, int t = -1) { luaL_unref(L, t, ref); }
void open_base();
void open_table();
void open_io(bool safe = true);
@@ -102,6 +104,8 @@ class Lua : public Base {
void * newuser(size_t s) { checkstack(); return lua_newuserdata(L, s); }
void settable(int = -3, bool raw = false);
void gettable(int = -2, bool raw = false);
+ void rawseti(int i, int t = -2) { lua_rawseti(L, t, i); }
+ void rawgeti(int i, int t = -1) { lua_rawgeti(L, t, i); }
void setvar() { lua_settable(L, LUA_GLOBALSINDEX); }
int gettop() { return lua_gettop(L); }
void getglobal(const String &) throw (GeneralException);
diff --git a/include/LuaHandle.h b/include/LuaHandle.h
index 3ee7cc6..82dfc8c 100644
--- a/include/LuaHandle.h
+++ b/include/LuaHandle.h
@@ -61,7 +61,7 @@ class LuaBuffer : public LuaHandle {
class HandleLua : public Handle {
public:
- HandleLua();
+ HandleLua(Lua *, int t = -1);
virtual ~HandleLua();
virtual ssize_t read(void * buf, size_t count) throw (GeneralException);
virtual ssize_t write(const void * buf, size_t count) throw (GeneralException);
@@ -75,6 +75,18 @@ class HandleLua : public Handle {
virtual time_t GetModif() const;
virtual bool CanWatch() const;
virtual void Flush();
+ private:
+ void GetObj() const;
+ int ref;
+ mutable Lua * L;
+};
+
+class LuaHandleLua : public LuaHandle {
+ public:
+ static void pushconstruct(Lua *);
+ LuaHandleLua(HandleLua *);
+ protected:
+ virtual void pushmembers(Lua *);
};
#endif
diff --git a/lib/LuaHandle.cc b/lib/LuaHandle.cc
index 376e485..098c10d 100644
--- a/lib/LuaHandle.cc
+++ b/lib/LuaHandle.cc
@@ -22,6 +22,7 @@
LuaInput::LuaInput(Input * h) : LuaHandle(h) { }
LuaOutput::LuaOutput(Output * h) : LuaHandle(h) { }
LuaBuffer::LuaBuffer(Buffer * h) : LuaHandle(h) { }
+LuaHandleLua::LuaHandleLua(HandleLua * h) : LuaHandle(h) { }
LuaHandle::LuaHandle(Handle * _h) : h(_h) { }
class sLuaHandle : public Base {
@@ -29,6 +30,7 @@ class sLuaHandle : public Base {
static int newinput(lua_State * L);
static int newoutput(lua_State * L);
static int newbuffer(lua_State * L);
+ static int newhandlelua(lua_State * L);
static int read(lua_State * L);
static int readstring(lua_State * L);
static int readU8(lua_State * L);
@@ -78,6 +80,7 @@ class sLuaHandle : public Base {
static int ucl_overlap(lua_State * L);
#endif
static int archive(lua_State * L);
+ static int user2table(lua_State * L);
private:
static int read(lua_State * L, int);
static int write(lua_State * L, int);
@@ -110,6 +113,10 @@ void LuaBuffer::pushconstruct(Lua * L) {
L->declarefunc("Buffer", sLuaHandle::newbuffer);
}
+void LuaHandleLua::pushconstruct(Lua * L) {
+ L->declarefunc("HandleLua", sLuaHandle::newhandlelua);
+}
+
int sLuaHandle::newinput(lua_State * __L) {
Lua * L = Lua::find(__L);
int n = L->gettop();
@@ -156,6 +163,20 @@ int sLuaHandle::newbuffer(lua_State * __L) {
return 1;
}
+int sLuaHandle::newhandlelua(lua_State * __L) {
+ Lua * L = Lua::find(__L);
+ int n = L->gettop();
+
+ if ((n != 1) || !L->istable()) {
+ L->error("Incorrect arguments to constructor `HandleLua'");
+ }
+
+ LuaHandleLua o(new HandleLua(L));
+ o.pushdestruct(L);
+
+ return 1;
+}
+
int sLuaHandle::read(lua_State * __L) {
Lua * L = Lua::find(__L);
int n = L->gettop(), i;
@@ -163,22 +184,37 @@ int sLuaHandle::read(lua_State * __L) {
ssize_t r;
Handle * h;
Byte * b;
+ bool has_userdata = false;
+ bool wants_userdata = false;
if (n == 1) {
return readstring(__L);
}
- if ((n != 2) || !L->isnumber()) {
+ if (((n < 2) && (n > 3)) || !L->isnumber() || ((n == 3) && (!L->isuserdata(3) || !L->isboolean(3)))) {
L->error("Incorrect arguments to method `Headle::read'");
}
-
- t = L->tonumber();
- b = (Byte *) malloc(t);
- h = L->recast<Handle>();
-
- L->newtable();
-
+
+ t = L->tonumber(2);
+ if ((n == 3) && L->isuserdata(3)) {
+ has_userdata = true;
+ b = (Byte *) L->touserdata(3);
+ } else if ((n == 3) && L->toboolean(3)) {
+ wants_userdata = true;
+ b = (Byte *) L->newuser(t);
+ } else {
+ b = (Byte *) malloc(t);
+ }
+
+ h = L->recast<Handle>(1);
r = h->read(b, t);
+
+ if (has_userdata || wants_userdata) {
+ L->push((lua_Number) r);
+ return wants_userdata ? 2 : 1;
+ }
+
+ L->newtable();
for (i = 0; i < r; i++) {
L->push((lua_Number) i);
@@ -239,29 +275,38 @@ int sLuaHandle::write(lua_State * __L) {
ssize_t r;
Handle * h;
Byte * b;
+ bool has_userdata = false;
if ((n == 2) && L->isstring()) {
return writestring(__L);
}
- if ((n != 3) || !L->isnumber() || !L->istable(2)) {
+ if ((n != 3) || !L->isnumber(3) || !(L->istable(2) || L->isuserdata(2))) {
L->error("Incorrect arguments to method `Headle::write'");
}
- t = L->tonumber();
- b = (Byte *) malloc(t);
- h = L->recast<Handle>();
-
- for (i = 0; i < t; i++) {
- L->push((lua_Number) i);
- L->gettable(2);
- b[i] = L->tonumber();
- L->pop();
+ t = L->tonumber(3);
+ if (L->isuserdata(2)) {
+ b = (Byte *) L->touserdata(2);
+ has_userdata = true;
+ } else {
+ b = (Byte *) malloc(t);
+ }
+ h = L->recast<Handle>(1);
+
+ if (!has_userdata) {
+ for (i = 0; i < t; i++) {
+ L->push((lua_Number) i);
+ L->gettable(2);
+ b[i] = L->tonumber();
+ L->pop();
+ }
}
r = h->write(b, t);
- free(b);
+ if (!has_userdata)
+ free(b);
L->push((lua_Number) r);
@@ -672,6 +717,29 @@ int sLuaHandle::archive(lua_State * __L) {
return 0;
}
+int sLuaHandle::user2table(lua_State * __L) {
+ Lua * L = Lua::find(__L);
+ int n = L->gettop();
+ Byte * buf;
+ ssize_t count, i;
+
+ if ((n != 2) || !L->isuserdata(1) || !L->isnumber(2)) {
+ L->error("user2table needs exactly two arguments.");
+ }
+
+ buf = (Byte *) L->touserdata(1);
+ count = L->tonumber(2);
+
+ L->newtable();
+
+ for (i = 0; i < count; i++) {
+ L->push((lua_Number) buf[i]);
+ L->rawseti(i);
+ }
+
+ return 1;
+}
+
int sLuaHandle::seek(lua_State * __L) {
Lua * L = Lua::find(__L);
int n = L->gettop();
@@ -845,6 +913,13 @@ void LuaBuffer::pushmembers(Lua * L) {
L->settable(-3, true);
}
+void LuaHandleLua::pushmembers(Lua * L) {
+ LuaHandle::pushmembers(L);
+ L->push("__handletype");
+ L->push("HandleLua");
+ L->settable(-3, true);
+}
+
void LuaHandle::pushmembers(Lua * L) {
pushme(L, h, "Handle");
@@ -903,6 +978,10 @@ void LuaHandle::pushconstruct(Lua * L) {
L->push((lua_Number) SEEK_END);
L->settable(LUA_GLOBALSINDEX);
+ L->push("HANDLELUAREFS");
+ L->newtable();
+ L->settable(LUA_REGISTRYINDEX);
+
L->declarefunc("get_nb_handles", sLuaHandle::get_nb_handles);
L->declarefunc("get_nb_input", sLuaHandle::get_nb_input);
L->declarefunc("get_nb_output", sLuaHandle::get_nb_output);
@@ -917,4 +996,292 @@ void LuaHandle::pushconstruct(Lua * L) {
#endif
L->declarefunc("Archive", sLuaHandle::archive);
+
+ L->declarefunc("user2table", sLuaHandle::user2table);
+}
+
+HandleLua::HandleLua(Lua * L, int i) : Handle(-1), L(L) {
+ L->copy(i);
+ L->push("HANDLELUAREFS");
+ L->gettable(LUA_REGISTRYINDEX);
+ L->insert(-2);
+ ref = L->ref();
+ L->pop();
+}
+
+HandleLua::~HandleLua() {
+ GetObj();
+ L->push("predestroy");
+ L->gettable();
+ if (!L->isnil()) {
+ L->call(0, 0);
+ } else {
+ L->pop();
+ }
+ L->push("HANDLELUAREFS");
+ L->gettable(LUA_REGISTRYINDEX);
+ L->unref(ref);
+ L->pop();
+}
+
+void HandleLua::GetObj() const {
+ L->push("HANDLELUAREFS");
+ L->gettable(LUA_REGISTRYINDEX);
+ L->rawgeti(ref);
+}
+
+bool HandleLua::CanRead() const {
+ bool r = false;
+
+ GetObj();
+ L->push("canread");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ L->pop();
+ return false;
+ }
+
+ L->call(1, 1);
+ r = L->toboolean();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+bool HandleLua::CanWrite() const {
+ bool r = false;
+
+ GetObj();
+ L->push("canwrite");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ L->pop();
+ return false;
+ }
+
+ L->call(1, 1);
+ r = L->toboolean();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+bool HandleLua::CanSeek() const {
+ bool r = false;
+
+ GetObj();
+ L->push("canseek");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ L->pop();
+ return false;
+ }
+
+ L->call(1, 1);
+ r = L->toboolean();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+bool HandleLua::CanWatch() const {
+ bool r = false;
+
+ GetObj();
+ L->push("canwatch");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ L->pop();
+ return false;
+ }
+
+ L->call(1, 1);
+ r = L->toboolean();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+String HandleLua::GetName() const {
+ String r;
+
+ GetObj();
+ L->push("getname");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ L->pop();
+ return "LuaHandleNoName";
+ }
+
+ L->call(1, 1);
+ r = L->tostring();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+off_t HandleLua::tell() const {
+ lua_Number r;
+
+ GetObj();
+ L->push("tell");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ L->pop();
+ return -1;
+ }
+
+ L->call(1, 1);
+ r = L->tonumber();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+ssize_t HandleLua::GetSize() const {
+ lua_Number r;
+
+ GetObj();
+ L->push("getsize");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ L->pop();
+ return -1;
+ }
+
+ L->call(1, 1);
+ r = L->tonumber();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+time_t HandleLua::GetModif() const {
+ lua_Number r;
+
+ GetObj();
+ L->push("getmodif");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ L->pop();
+ return 0;
+ }
+
+ L->call(1, 1);
+ r = L->tonumber();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+void HandleLua::Flush() {
+ GetObj();
+ L->push("flush");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ return;
+ }
+
+ L->call(1, 0);
+ L->pop();
+}
+
+off_t HandleLua::seek(off_t offset, int wheel) throw (GeneralException) {
+ off_t r = -1;
+
+ GetObj();
+ L->push("seek");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ throw GeneralException("This HandleLua doesn't have any seek method (or can't seek maybe).");
+ }
+
+ L->push((lua_Number) offset);
+ L->push((lua_Number) wheel);
+ L->call(3, 1);
+
+ r = L->tonumber();
+ L->pop();
+ L->pop();
+ return r;
+}
+
+ssize_t HandleLua::read(void * buf, size_t count) throw (GeneralException) {
+ ssize_t r = -1;
+
+ GetObj();
+ L->push("read");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ throw GeneralException("This HandleLua doesn't have any read method (or can't read maybe).");
+ }
+
+ L->push(buf);
+ L->push((lua_Number) count);
+ L->call(3, 2);
+
+ r = L->tonumber(-2);
+
+ if (L->istable()) {
+ int i;
+ Byte * b = (Byte *) buf;
+ for (i = 0; i < r; i++) {
+ L->push((lua_Number) i);
+ L->gettable();
+ b[i] = L->tonumber();
+ L->pop();
+ }
+ }
+
+ L->pop();
+ L->pop();
+ L->pop();
+
+ return r;
+}
+
+ssize_t HandleLua::write(const void * buf, size_t count) throw (GeneralException) {
+ ssize_t r = -1;
+
+ GetObj();
+ L->push("write");
+ L->gettable();
+
+ if (L->isnil()) {
+ L->pop();
+ throw GeneralException("This HandleLua doesn't have any write method (or can't write maybe).");
+ }
+
+ L->push(buf);
+ L->push((lua_Number) count);
+ L->call(3, 1);
+
+ r = L->tonumber();
+
+ L->pop();
+ L->pop();
+
+ return r;
}