From 8addf3e9c6e50dc85d2a5d7840a752a56b2258da Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Thu, 7 Jul 2011 21:47:34 +0200 Subject: FbTk::Lua - a class which augments lua::state with additional features --- src/FbTk/LuaUtil.cc | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/FbTk/LuaUtil.hh | 78 ++++++++++++++++++++++++++++++++++++++ src/FbTk/Makefile.am | 1 + 3 files changed, 183 insertions(+) create mode 100644 src/FbTk/LuaUtil.cc create mode 100644 src/FbTk/LuaUtil.hh diff --git a/src/FbTk/LuaUtil.cc b/src/FbTk/LuaUtil.cc new file mode 100644 index 0000000..456abac --- /dev/null +++ b/src/FbTk/LuaUtil.cc @@ -0,0 +1,104 @@ +// LuaUtil: Various additional functions for working with lua +// Copyright (C) 2011 Pavel Labath +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "LuaUtil.hh" + +namespace { + int newindexDenyWrite(lua::state *l) { + if(l->isstring(-2)) + throw std::runtime_error("Cannot modify field '" + l->tostring(-2) + "'."); + else + throw std::runtime_error("Cannot modify this field."); + } + + int newindexDenyModify(lua::state *l) { + bool ok = false; + l->getmetatable(-1); { + l->rawgetfield(-1, "__index"); { + l->pushvalue(-4); l->rawget(-2); { + if(l->isnil(-1)) + ok = true; + } l->pop(); + } l->pop(); + } l->pop(); + + if(ok) { + l->pushvalue(-2); + l->pushvalue(-4); + l->rawset(-3); + } else + newindexDenyWrite(l); + + return 0; + } +} + +namespace FbTk { + +Lua::InitFunctions Lua::s_init_functions; + +Lua::Lua() { + InitFunctions::const_iterator it_end = s_init_functions.end(); + for(InitFunctions::const_iterator it = s_init_functions.begin(); it != it_end; ++it) + (**it)(*this); +} + +void Lua::makeReadOnly(int index, bool only_existing_fields) { + checkstack(6); + lua::stack_sentry s(*this); + index = absindex(index); + + newtable(); { + newtable(); { + pushnil(); while(next(index)) { + pushvalue(-2); pushvalue(-2); rawset(-5); + + pop(); pushnil(); rawset(index); + + pushnil(); + } + } rawsetfield(-2, "__index"); + + pushfunction(only_existing_fields ? &newindexDenyModify : &newindexDenyWrite); + rawsetfield(-2, "__newindex"); + + pushboolean(false); + rawsetfield(-2, "__metatable"); + } setmetatable(index); +} + +void Lua::readOnlySet(int index) { + checkstack(2); + lua::stack_sentry s(*this, -2); + + getmetatable(index); { + rawgetfield(-1, "__index"); insert(-4); + } pop(); + + rawset(-3); + pop(); +} + +} // namespace FbTk diff --git a/src/FbTk/LuaUtil.hh b/src/FbTk/LuaUtil.hh new file mode 100644 index 0000000..cdd1934 --- /dev/null +++ b/src/FbTk/LuaUtil.hh @@ -0,0 +1,78 @@ +// LuaUtil: Various additional functions for working with lua +// Copyright (C) 2011 Pavel Labath +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef FBTK_LUAUTIL_HH +#define FBTK_LUAUTIL_HH + +#include + +#include "Luamm.hh" + +namespace FbTk { + +/* + * This class augments lua::state with additional functions/features. Every object automatically + * calls registered init functions, which can be used to initialize/create global variables in + * the lua state. Functions can be registered by calling registerInitFunction or by creating + * objects of type RegisterInitFunction. + */ +class Lua: public lua::state { +public: + Lua(); + + /* + * makeReadOnly() makes the table at the specified index "read only". This means that any + * attempt to modify a table entry will result in an error (if only_existing_fields is + * false). If only_existing_fields is true then only fields that were present at the time of + * the call will be protected - user can add new entries and modify them afterwards. You + * should avoid raw access to "read only" tables -- it might not do what you think it will. + */ + void makeReadOnly(int index, bool only_existing_fields = false); + + /* + * readOnlySet() is the equivalent of settable, except that it works on "read only" tables. + * It can be used to modify protected entries or create new ones. + */ + void readOnlySet(int index); + + template + static void registerInitFunction(const Functor &fn) { + s_init_functions.push_back(new SlotImpl(fn)); + } + + class RegisterInitFunction { + public: + template + RegisterInitFunction(const Functor &fn) { + registerInitFunction(fn); + } + }; + +private: + typedef Slot InitFunction; + typedef std::vector InitFunctions; + + static InitFunctions s_init_functions; +}; + +} // namespace FbTk + +#endif // FBTK_LUAUTIL_HH diff --git a/src/FbTk/Makefile.am b/src/FbTk/Makefile.am index 5146810..dba4478 100644 --- a/src/FbTk/Makefile.am +++ b/src/FbTk/Makefile.am @@ -67,6 +67,7 @@ libFbTk_a_SOURCES = App.hh App.cc Color.cc Color.hh Command.hh \ Slot.hh Signal.hh MemFun.hh SelectArg.hh \ Util.hh \ Luamm.cc Luamm.hh LResource.cc LResource.hh LResourceHelper-lua.cc \ + LuaUtil.cc LuaUtil.hh \ ${xpm_SOURCE} \ ${xft_SOURCE} \ ${xmb_SOURCE} \ -- cgit v0.11.2