summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/LuaHandle.cc405
1 files changed, 386 insertions, 19 deletions
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;
}