1 /*
2 script/lua_api/l_settings.cpp
3 Copyright (C) 2013 PilzAdam <pilzadam@minetest.net>
4 */
5
6 /*
7 This file is part of Freeminer.
8
9 Freeminer is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Freeminer is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "lua_api/l_settings.h"
24 #include "lua_api/l_internal.h"
25 #include "settings.h"
26 #include "log.h"
27
28 // garbage collector
gc_object(lua_State * L)29 int LuaSettings::gc_object(lua_State* L)
30 {
31 LuaSettings* o = *(LuaSettings **)(lua_touserdata(L, 1));
32 delete o;
33 return 0;
34 }
35
36 // get(self, key) -> value
l_get(lua_State * L)37 int LuaSettings::l_get(lua_State* L)
38 {
39 NO_MAP_LOCK_REQUIRED;
40 LuaSettings* o = checkobject(L, 1);
41
42 std::string key = std::string(luaL_checkstring(L, 2));
43 if (o->m_settings->exists(key)) {
44 std::string value = o->m_settings->get(key);
45 lua_pushstring(L, value.c_str());
46 } else {
47 lua_pushnil(L);
48 }
49
50 return 1;
51 }
52
53 // get_bool(self, key) -> boolean
l_get_bool(lua_State * L)54 int LuaSettings::l_get_bool(lua_State* L)
55 {
56 NO_MAP_LOCK_REQUIRED;
57 LuaSettings* o = checkobject(L, 1);
58
59 std::string key = std::string(luaL_checkstring(L, 2));
60 if (o->m_settings->exists(key)) {
61 bool value = o->m_settings->getBool(key);
62 lua_pushboolean(L, value);
63 } else {
64 lua_pushnil(L);
65 }
66
67 return 1;
68 }
69
70 // set(self, key, value)
l_set(lua_State * L)71 int LuaSettings::l_set(lua_State* L)
72 {
73 NO_MAP_LOCK_REQUIRED;
74 LuaSettings* o = checkobject(L, 1);
75
76 std::string key = std::string(luaL_checkstring(L, 2));
77 const char* value = luaL_checkstring(L, 3);
78
79 o->m_settings->set(key, value);
80
81 return 1;
82 }
83
84 // remove(self, key) -> success
l_remove(lua_State * L)85 int LuaSettings::l_remove(lua_State* L)
86 {
87 NO_MAP_LOCK_REQUIRED;
88 LuaSettings* o = checkobject(L, 1);
89
90 std::string key = std::string(luaL_checkstring(L, 2));
91
92 bool success = o->m_settings->remove(key);
93 lua_pushboolean(L, success);
94
95 return 1;
96 }
97
98 // get_names(self) -> {key1, ...}
l_get_names(lua_State * L)99 int LuaSettings::l_get_names(lua_State* L)
100 {
101 NO_MAP_LOCK_REQUIRED;
102 LuaSettings* o = checkobject(L, 1);
103
104 std::vector<std::string> keys = o->m_settings->getNames();
105
106 lua_newtable(L);
107 for (unsigned int i=0; i < keys.size(); i++)
108 {
109 lua_pushstring(L, keys[i].c_str());
110 lua_rawseti(L, -2, i + 1);
111 }
112
113 return 1;
114 }
115
116 // write(self) -> success
l_write(lua_State * L)117 int LuaSettings::l_write(lua_State* L)
118 {
119 NO_MAP_LOCK_REQUIRED;
120 LuaSettings* o = checkobject(L, 1);
121
122 bool success = o->m_settings->updateConfigFile(o->m_filename.c_str());
123 lua_pushboolean(L, success);
124
125 return 1;
126 }
127
128 // to_table(self) -> {[key1]=value1,...}
l_to_table(lua_State * L)129 int LuaSettings::l_to_table(lua_State* L)
130 {
131 NO_MAP_LOCK_REQUIRED;
132 LuaSettings* o = checkobject(L, 1);
133
134 std::vector<std::string> keys = o->m_settings->getNames();
135
136 lua_newtable(L);
137 for (unsigned int i=0; i < keys.size(); i++)
138 {
139 lua_pushstring(L, o->m_settings->get(keys[i]).c_str());
140 lua_setfield(L, -2, keys[i].c_str());
141 }
142
143 return 1;
144 }
145
LuaSettings(const char * filename)146 LuaSettings::LuaSettings(const char* filename)
147 {
148 m_filename = std::string(filename);
149
150 m_settings = new Settings();
151 m_settings->readConfigFile(m_filename.c_str());
152 }
153
~LuaSettings()154 LuaSettings::~LuaSettings()
155 {
156 delete m_settings;
157 }
158
Register(lua_State * L)159 void LuaSettings::Register(lua_State* L)
160 {
161 lua_newtable(L);
162 int methodtable = lua_gettop(L);
163 luaL_newmetatable(L, className);
164 int metatable = lua_gettop(L);
165
166 lua_pushliteral(L, "__metatable");
167 lua_pushvalue(L, methodtable);
168 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
169
170 lua_pushliteral(L, "__index");
171 lua_pushvalue(L, methodtable);
172 lua_settable(L, metatable);
173
174 lua_pushliteral(L, "__gc");
175 lua_pushcfunction(L, gc_object);
176 lua_settable(L, metatable);
177
178 lua_pop(L, 1); // drop metatable
179
180 luaL_openlib(L, 0, methods, 0); // fill methodtable
181 lua_pop(L, 1); // drop methodtable
182
183 // Can be created from Lua (Settings(filename))
184 lua_register(L, className, create_object);
185 }
186
187 // LuaSettings(filename)
188 // Creates an LuaSettings and leaves it on top of stack
create_object(lua_State * L)189 int LuaSettings::create_object(lua_State* L)
190 {
191 NO_MAP_LOCK_REQUIRED;
192 const char* filename = luaL_checkstring(L, 1);
193 LuaSettings* o = new LuaSettings(filename);
194 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
195 luaL_getmetatable(L, className);
196 lua_setmetatable(L, -2);
197 return 1;
198 }
199
checkobject(lua_State * L,int narg)200 LuaSettings* LuaSettings::checkobject(lua_State* L, int narg)
201 {
202 NO_MAP_LOCK_REQUIRED;
203 luaL_checktype(L, narg, LUA_TUSERDATA);
204 void *ud = luaL_checkudata(L, narg, className);
205 if(!ud) luaL_typerror(L, narg, className);
206 return *(LuaSettings**)ud; // unbox pointer
207 }
208
209 const char LuaSettings::className[] = "Settings";
210 const luaL_reg LuaSettings::methods[] = {
211 luamethod(LuaSettings, get),
212 luamethod(LuaSettings, get_bool),
213 luamethod(LuaSettings, set),
214 luamethod(LuaSettings, remove),
215 luamethod(LuaSettings, get_names),
216 luamethod(LuaSettings, write),
217 luamethod(LuaSettings, to_table),
218 {0,0}
219 };
220