diff options
-rw-r--r-- | include/BLua.h | 4 | ||||
-rw-r--r-- | include/LuaHandle.h | 14 | ||||
-rw-r--r-- | lib/LuaHandle.cc | 405 |
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; } |