/* * Baltisot * Copyright (C) 1999-2003 Nicolas "Pixel" Noble * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: LuaHandle.cc,v 1.14 2004-11-27 21:35:19 pixel Exp $ */ #include "LuaHandle.h" LuaInput::LuaInput(Input * h) : LuaHandle(h) { } LuaOutput::LuaOutput(Output * h) : LuaHandle(h) { } LuaBuffer::LuaBuffer(Buffer * h) : LuaHandle(h) { } LuaHandle::LuaHandle(Handle * _h) : h(_h) { } class sLuaHandle : public Base { public: static int newinput(lua_State * L); static int newoutput(lua_State * L); static int newbuffer(lua_State * L); static int read(lua_State * L); static int readstring(lua_State * L); static int readU8(lua_State * L); static int readU16(lua_State * L); static int readU32(lua_State * L); static int write(lua_State * L); static int writestring(lua_State * L); static int writeU8(lua_State * L); static int writeU16(lua_State * L); static int writeU32(lua_State * L); static int copyfrom(lua_State * L); static int copyto(lua_State * L); static int isclosed(lua_State * L); static int isnonblock(lua_State * L); static int canread(lua_State * L); static int canwrite(lua_State * L); static int canseek(lua_State * L); static int canwatch(lua_State * L); static int setnonblock(lua_State * L); static int tell(lua_State * L); static int getname(lua_State * L); static int getsize(lua_State * L); static int getmodif(lua_State * L); static int close(lua_State * L); static int flush(lua_State * L); static int seek(lua_State * L); static int setz(lua_State * L); static int bindex(lua_State * L); static int bnewindex(lua_State * L); static int bseek(lua_State * L); static int btell(lua_State * L); static int exists(lua_State * L); private: static int read(lua_State * L, int); static int write(lua_State * L, int); static int copy(lua_State * L, int); static int getcaps(lua_State * L, int); static int action(lua_State * L, int); enum { U8, U16, U32 }; enum { from, to }; enum { capisclosed, capisnonblock, capcanread, capcanwrite, capcanseek, capcanwatch }; enum { Asetnonblock, Atell, Agetname, Agetsize, Agetmodif, Aclose, Aflush }; }; void LuaInput::pushconstruct(Lua * L) { L->declarefunc("Input", sLuaHandle::newinput); } void LuaOutput::pushconstruct(Lua * L) { L->declarefunc("Output", sLuaHandle::newoutput); } void LuaBuffer::pushconstruct(Lua * L) { L->declarefunc("Buffer", sLuaHandle::newbuffer); } int sLuaHandle::newinput(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); if ((n != 1) || !L->isstring()) { L->error("Incorrect arguments to constructor `Input'"); } LuaInput i(new Input(L->tostring())); i.pushdestruct(L); return 1; } int sLuaHandle::newoutput(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); if ((n != 1) || !L->isstring()) { L->error("Incorrect arguments to constructor `Input'"); } LuaOutput o(new Output(L->tostring())); o.pushdestruct(L); return 1; } int sLuaHandle::newbuffer(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); bool seekable = false; if ((n > 1) || ((n == 1) && (!L->isboolean()))) { L->error("Incorrect arguments to constructor `Buffer'"); } if (n == 1) seekable = L->toboolean(); LuaBuffer o(new Buffer(seekable)); o.pushdestruct(L); return 1; } int sLuaHandle::read(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(), i; size_t t; ssize_t r; Handle * h; Byte * b; if (n == 1) { return readstring(_L); } if ((n != 2) || !L->isnumber()) { L->error("Incorrect arguments to method `Headle::read'"); } t = L->tonumber(); b = (Byte *) malloc(t); h = (Handle *) LuaObject::getme(L); L->newtable(); r = h->read(b, t); for (i = 0; i < r; i++) { L->push((lua_Number) i); L->push((lua_Number) b[i]); L->settable(); } free(b); L->push((lua_Number) r); return 2; } int sLuaHandle::readstring(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(), i; Handle * h; String r; if (n != 1) { L->error("Incorrect arguments to method `Headle::readstring'"); } h = (Handle *) LuaObject::getme(L); (*h) >> r; L->push(r); return 1; } int sLuaHandle::readU8(lua_State * L) { return read(L, U8); } int sLuaHandle::readU16(lua_State * L) { return read(L, U16); } int sLuaHandle::readU32(lua_State * L) { return read(L, U32); } int sLuaHandle::write(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(), i; size_t t; ssize_t r; Handle * h; Byte * b; if ((n == 2) && L->isstring()) { return writestring(_L); } if ((n != 3) || !L->isnumber() || !L->istable(2)) { L->error("Incorrect arguments to method `Headle::write'"); } t = L->tonumber(); b = (Byte *) malloc(t); h = (Handle *) LuaObject::getme(L); 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); L->push((lua_Number) r); return 1; } int sLuaHandle::writestring(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(), i; Handle * h; String r; if ((n != 2) || !L->isstring()) { L->error("Incorrect arguments to method `Headle::writestring'"); } h = (Handle *) LuaObject::getme(L); r = L->tostring(); (*h) << r; return 0; } int sLuaHandle::writeU8(lua_State * L) { return write(L, U8); } int sLuaHandle::writeU16(lua_State * L) { return write(L, U16); } int sLuaHandle::writeU32(lua_State * L) { return write(L, U32); } int sLuaHandle::read(lua_State * _L, int t) { Lua * L = Lua::find(_L); int n = L->gettop(); lua_Number r; Handle * h; if (n != 1) { L->error("Incorrect arguments to method `Headle::readUx'"); } h = (Handle *) LuaObject::getme(L); switch (t) { case U8: r = h->readU8(); break; case U16: r = h->readU16(); break; case U32: r = h->readU32(); break; } L->push(r); return 1; } int sLuaHandle::write(lua_State * _L, int t) { Lua * L = Lua::find(_L); int n = L->gettop(); lua_Number r; Handle * h; if ((n != 2) || !L->isnumber()) { L->error("Incorrect arguments to method `Headle::writeUx'"); } h = (Handle *) LuaObject::getme(L); r = L->tonumber(); switch (t) { case U8: h->writeU8(r); break; case U16: h->writeU16(r); break; case U32: h->writeU32(r); break; } return 0; } int sLuaHandle::copyfrom(lua_State * L) { return copy(L, from); } int sLuaHandle::copyto(lua_State * L) { return copy(L, to); } int sLuaHandle::copy(lua_State * _L, int dir) { Lua * L = Lua::find(_L); int n = L->gettop(); lua_Number r; Handle * s, * d; if ((n < 2) || (n > 3) || ((n == 3) && !L->isnumber(3))) { L->error("Incorrect arguments to function `handlecopy'"); } s = (Handle *) LuaObject::getme(L, 1); d = (Handle *) LuaObject::getme(L, 2); if (n == 3) { r = L->tonumber(); } else { r = -1; } if (dir == from) { SWAP(s, d); } s->copyto(d, r); return 0; } int sLuaHandle::isclosed(lua_State * L) { return getcaps(L, capisclosed); } int sLuaHandle::isnonblock(lua_State * L) { return getcaps(L, capisnonblock); } int sLuaHandle::canread(lua_State * L) { return getcaps(L, capcanread); } int sLuaHandle::canwrite(lua_State * L) { return getcaps(L, capcanwrite); } int sLuaHandle::canseek(lua_State * L) { return getcaps(L, capcanseek); } int sLuaHandle::canwatch(lua_State * L) { return getcaps(L, capcanwatch); } int sLuaHandle::getcaps(lua_State * _L, int cap) { Lua * L = Lua::find(_L); int n = L->gettop(); bool r; Handle * h; if (n != 1) { L->error("Incorrect arguments to method `Handle::getcaps'"); } h = (Handle *) LuaObject::getme(L); switch (cap) { case capisclosed: r = h->IsClosed(); break; case capisnonblock: r = h->IsNonBlock(); break; case capcanread: r = h->CanRead(); break; case capcanwrite: r = h->CanWrite(); break; case capcanseek: r = h->CanSeek(); break; case capcanwatch: r = h->CanWatch(); break; } L->push(r); return 1; } int sLuaHandle::setnonblock(lua_State * L) { return action(L, Asetnonblock); } int sLuaHandle::tell(lua_State * L) { return action(L, Atell); } int sLuaHandle::getname(lua_State * L) { return action(L, Agetname); } int sLuaHandle::getsize(lua_State * L) { return action(L, Agetsize); } int sLuaHandle::getmodif(lua_State * L) { return action(L, Agetmodif); } int sLuaHandle::close(lua_State * L) { return action(L, Aclose); } int sLuaHandle::flush(lua_State * L) { return action(L, Aflush); } int sLuaHandle::action(lua_State * _L, int act) { Lua * L = Lua::find(_L); int n = L->gettop(); int r = 1; Handle * h; if (n != 1) { L->error("Incorrect arguments to method `Handle::action'"); } h = (Handle *) LuaObject::getme(L); switch (act) { case Asetnonblock: r = 0; h->SetNonBlock(); break; case Atell: L->push((lua_Number) h->tell()); break; case Agetname: L->push(h->GetName()); break; case Agetsize: L->push((lua_Number) h->GetSize()); break; case Agetmodif: L->push((lua_Number) h->GetModif()); break; case Aclose: r = 0; h->close(); break; case Aflush: r = 0; h->Flush(); break; } return r; } int sLuaHandle::setz(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); int z = 9; Handle * h; if ((n < 1) || (n > 2) || ((n == 2) && !L->isnumber(2))) { L->error("Incorrect arguments to method `Handle::setz'"); } h = (Handle *) LuaObject::getme(L); if (n == 2) { z = L->tonumber(2); } h->SetZ(z); return 0; } int sLuaHandle::seek(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); off_t off; int wheel; Handle * h; if ((n < 2) || (n > 3) || !L->isnumber(2) || ((n == 3) && !L->isnumber(3))) { L->error("Incorrect arguments to method `Handle::seek'"); } h = (Handle *) LuaObject::getme(L); off = L->tonumber(2); if (n == 3) { wheel = L->tonumber(3); } else { wheel = SEEK_SET; } L->push((lua_Number) h->seek(off, wheel)); return 1; } int sLuaHandle::bindex(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); const Buffer * b; if (n != 2) { L->error("Inconsistant call to metamethod Buffer::index"); } if (!L->isnumber()) { L->push(); return 1; } b = (Buffer *) LuaObject::getme(L); L->push((lua_Number) (*b)[L->tonumber()]); return 1; } int sLuaHandle::bnewindex(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); Buffer * b; if (n != 3) { L->error("Inconsistant call to metamethod Buffer::newindex"); } if (!L->isnumber(2)) { L->settable(1, true); return 0; } if (!L->isnumber(3)) { L->error("Can't write a non-number to buffer"); } b = (Buffer *) LuaObject::getme(L); (*b)[L->tonumber(2)] = L->tonumber(3); return 0; } int sLuaHandle::btell(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); Buffer * h; if (n != 1) { L->error("Incorrect arguments to method `Buffer::wtell'"); } h = (Buffer *) LuaObject::getme(L); L->push((lua_Number) h->wtell()); return 1; } int sLuaHandle::bseek(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); off_t off; int wheel; Buffer * h; if ((n < 2) || (n > 3) || !L->isnumber(2) || ((n == 3) && !L->isnumber(3))) { L->error("Incorrect arguments to method `Buffer::wseek'"); } h = (Buffer *) LuaObject::getme(L); off = L->tonumber(2); if (n == 3) { wheel = L->tonumber(3); } else { wheel = SEEK_SET; } L->push((lua_Number) h->wseek(off, wheel)); return 1; } int sLuaHandle::exists(lua_State * _L) { Lua * L = Lua::find(_L); int n = L->gettop(); bool r = true; if (n != 1) { L->error("Incorrect number of arguments to function exists"); } try { Input testing(L->tostring()); } catch (IOGeneral & e) { r = false; } L->push(r); return 1; } void LuaInput::pushmembers(Lua * L) { LuaHandle::pushmembers(L); } void LuaOutput::pushmembers(Lua * L) { LuaHandle::pushmembers(L); } void LuaBuffer::pushmembers(Lua * L) { LuaHandle::pushmembers(L); pushmeta(L, "__index", sLuaHandle::bindex); pushmeta(L, "__newindex", sLuaHandle::bnewindex); pushit(L, "wtell", sLuaHandle::btell); pushit(L, "wseek", sLuaHandle::bseek); } void LuaHandle::pushmembers(Lua * L) { pushme(L, h); pushit(L, "read", &sLuaHandle::read); pushit(L, "write", &sLuaHandle::write); pushit(L, "readU8", sLuaHandle::readU8); pushit(L, "readU16", sLuaHandle::readU16); pushit(L, "readU32", sLuaHandle::readU32); pushit(L, "writeU8", sLuaHandle::writeU8); pushit(L, "writeU16", sLuaHandle::writeU16); pushit(L, "writeU32", sLuaHandle::writeU32); pushit(L, "copyfrom", sLuaHandle::copyfrom); pushit(L, "copyto", sLuaHandle::copyto); L->declarefunc("handlecopy", sLuaHandle::copyfrom); pushit(L, "isclosed", sLuaHandle::isclosed); pushit(L, "isnonblock", sLuaHandle::isnonblock); pushit(L, "canread", sLuaHandle::canread); pushit(L, "canwrite", sLuaHandle::canwatch); pushit(L, "canseek", sLuaHandle::canseek); pushit(L, "canwatch", sLuaHandle::canwatch); pushit(L, "setnonblock", sLuaHandle::setnonblock); pushit(L, "tell", sLuaHandle::tell); pushit(L, "getname", sLuaHandle::getname); pushit(L, "getsize", sLuaHandle::getsize); pushit(L, "getmodif", sLuaHandle::getmodif); pushit(L, "close", sLuaHandle::close); pushit(L, "flush", sLuaHandle::flush); pushit(L, "seek", sLuaHandle::seek); pushit(L, "setz", sLuaHandle::setz); L->declarefunc("exists", sLuaHandle::exists); L->push("SEEK_SET"); L->push((lua_Number) SEEK_SET); L->settable(LUA_GLOBALSINDEX); L->push("SEEK_CUR"); L->push((lua_Number) SEEK_CUR); L->settable(LUA_GLOBALSINDEX); L->push("SEEK_END"); L->push((lua_Number) SEEK_END); L->settable(LUA_GLOBALSINDEX); }