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