aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/LuaUtil.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/LuaUtil.cc')
-rw-r--r--src/FbTk/LuaUtil.cc104
1 files changed, 104 insertions, 0 deletions
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 @@
1// LuaUtil: Various additional functions for working with lua
2// Copyright (C) 2011 Pavel Labath
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include "LuaUtil.hh"
27
28namespace {
29 int newindexDenyWrite(lua::state *l) {
30 if(l->isstring(-2))
31 throw std::runtime_error("Cannot modify field '" + l->tostring(-2) + "'.");
32 else
33 throw std::runtime_error("Cannot modify this field.");
34 }
35
36 int newindexDenyModify(lua::state *l) {
37 bool ok = false;
38 l->getmetatable(-1); {
39 l->rawgetfield(-1, "__index"); {
40 l->pushvalue(-4); l->rawget(-2); {
41 if(l->isnil(-1))
42 ok = true;
43 } l->pop();
44 } l->pop();
45 } l->pop();
46
47 if(ok) {
48 l->pushvalue(-2);
49 l->pushvalue(-4);
50 l->rawset(-3);
51 } else
52 newindexDenyWrite(l);
53
54 return 0;
55 }
56}
57
58namespace FbTk {
59
60Lua::InitFunctions Lua::s_init_functions;
61
62Lua::Lua() {
63 InitFunctions::const_iterator it_end = s_init_functions.end();
64 for(InitFunctions::const_iterator it = s_init_functions.begin(); it != it_end; ++it)
65 (**it)(*this);
66}
67
68void Lua::makeReadOnly(int index, bool only_existing_fields) {
69 checkstack(6);
70 lua::stack_sentry s(*this);
71 index = absindex(index);
72
73 newtable(); {
74 newtable(); {
75 pushnil(); while(next(index)) {
76 pushvalue(-2); pushvalue(-2); rawset(-5);
77
78 pop(); pushnil(); rawset(index);
79
80 pushnil();
81 }
82 } rawsetfield(-2, "__index");
83
84 pushfunction(only_existing_fields ? &newindexDenyModify : &newindexDenyWrite);
85 rawsetfield(-2, "__newindex");
86
87 pushboolean(false);
88 rawsetfield(-2, "__metatable");
89 } setmetatable(index);
90}
91
92void Lua::readOnlySet(int index) {
93 checkstack(2);
94 lua::stack_sentry s(*this, -2);
95
96 getmetatable(index); {
97 rawgetfield(-1, "__index"); insert(-4);
98 } pop();
99
100 rawset(-3);
101 pop();
102}
103
104} // namespace FbTk