1 /*
2 * common/ConfigManager.cpp
3 *
4 * This file is part of Leges Motus, a networked, 2D shooter set in zero gravity.
5 *
6 * Copyright 2009-2010 Andrew Ayer, Nathan Partlan, Jeffrey Pfau
7 *
8 * Leges Motus is free and open source software. You may redistribute it and/or
9 * modify it under the terms of version 2, or (at your option) version 3, of the
10 * GNU General Public License (GPL), as published by the Free Software Foundation.
11 *
12 * Leges Motus is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14 * PARTICULAR PURPOSE. See the full text of the GNU General Public License for
15 * further detail.
16 *
17 * For a full copy of the GNU General Public License, please see the COPYING file
18 * in the root of the source code tree. You may also retrieve a copy from
19 * <http://www.gnu.org/licenses/gpl-2.0.txt>, or request a copy by writing to the
20 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 * 02111-1307 USA
22 *
23 */
24
25 #include "ConfigManager.hpp"
26 #include "StringTokenizer.hpp"
27 #include "misc.hpp"
28 #include <istream>
29 #include <ostream>
30 #include <fstream>
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include <string.h>
34 #include <limits>
35 #ifdef __WIN32
36 // Necessary to get SHGFP_TYPE_CURRENT
37 #ifndef _WIN32_IE
38 #define _WIN32_IE 0x0600
39 #endif
40 #include <Windows.h>
41 #include <shlobj.h>
42 #endif
43
44 using namespace LM;
45 using namespace std;
46
write_option(ostream & out,const ConfigManager::map_type::value_type & option)47 void ConfigManager::write_option(ostream& out, const ConfigManager::map_type::value_type& option) {
48 out << option.first << ' ' << option.second << '\n'; // TODO: format more nicely
49 }
50
load(const char * filename)51 bool ConfigManager::load(const char* filename) {
52 ifstream in(filename);
53 return in && load(in);
54 }
55
load(std::istream & in)56 bool ConfigManager::load(std::istream& in) {
57 string line;
58 while (getline(in, line)) {
59 if (line.empty() || line[0] == '#' || line[0] == ';') {
60 continue;
61 }
62
63 StringTokenizer tokenize(line, " \t", true, 2);
64 string name;
65 tokenize >> name;
66
67 if (name.empty()) {
68 continue;
69 }
70
71 tokenize >> m_options[name];
72 }
73 return true;
74 }
75
save(const char * filename) const76 bool ConfigManager::save(const char* filename) const {
77 ofstream out(filename);
78 return out && save(out);
79 }
80
save(std::ostream & out) const81 bool ConfigManager::save(std::ostream& out) const {
82 map_type::const_iterator it(m_options.begin());
83 while (it != m_options.end()) {
84 write_option(out, *it++);
85 }
86 return true;
87 }
88
load_system_config()89 bool ConfigManager::load_system_config() {
90 if (const char* path = system_config_path()) {
91 return load(path);
92 }
93 return false;
94 }
95
load_personal_config()96 bool ConfigManager::load_personal_config() {
97 if (const char* path = personal_config_path()) {
98 return load(path);
99 }
100 return false;
101 }
102
save_personal_config() const103 bool ConfigManager::save_personal_config() const {
104 if (const char* path = personal_config_path()) {
105 return save(path);
106 }
107 return false;
108 }
109
110
lookup(const char * option_name) const111 const string* ConfigManager::lookup(const char* option_name) const {
112 map_type::const_iterator it(m_options.find(option_name));
113 return it != m_options.end() ? &it->second : NULL;
114 }
115
operator [](const char * option_name) const116 const string& ConfigManager::operator[](const char* option_name) const {
117 if (const string* option_value = lookup(option_name)) {
118 return *option_value;
119 } else {
120 return make_empty<string>();
121 }
122 }
123
124
get(const char * option_name) const125 template<> string ConfigManager::get(const char* option_name) const {
126 const string* raw_value = lookup(option_name);
127 return raw_value ? *raw_value : string();
128 }
129
get(const char * option_name) const130 template<> const char* ConfigManager::get(const char* option_name) const {
131 const string* raw_value = lookup(option_name);
132 return raw_value ? raw_value->c_str() : "";
133 }
134
135
get(const char * option_name) const136 template<> bool ConfigManager::get(const char* option_name) const {
137 const string* raw_value = lookup(option_name);
138
139 return raw_value &&
140 (atoi(raw_value->c_str()) > 0 ||
141 strcasecmp(raw_value->c_str(), "yes") == 0 ||
142 strcasecmp(raw_value->c_str(), "true") == 0 ||
143 strcasecmp(raw_value->c_str(), "on") == 0);
144 }
145
set(const char * option_name,const bool & option_value)146 template<> void ConfigManager::set(const char* option_name, const bool& option_value) {
147 m_options[option_name] = option_value ? "yes" : "no";
148 }
149
get(const char * option_name) const150 template<> uint64_t ConfigManager::get(const char* option_name) const {
151 uint64_t value = uint64_t();
152 const string* raw_value = lookup(option_name);
153 if (raw_value && strcasecmp(raw_value->c_str(), "forever") == 0) {
154 value = numeric_limits<uint64_t>::max();
155 } else if (raw_value) {
156 istringstream(*raw_value) >> value;
157 }
158 return value;
159 }
160
set(const char * option_name,const uint64_t & option_value)161 template<> void ConfigManager::set(const char* option_name, const uint64_t& option_value) {
162 if (option_value == numeric_limits<uint64_t>::max()) {
163 m_options[option_name] = "forever";
164 } else {
165 ostringstream out;
166 out << option_value;
167 m_options[option_name] = out.str();
168 }
169 }
170
171
set(const char * option_name,const char * const & option_value)172 template<> void ConfigManager::set(const char* option_name, const char* const& option_value) {
173 m_options[option_name] = option_value;
174 }
175
personal_config_path()176 const char* ConfigManager::personal_config_path() {
177 static string path;
178 if (path.empty()) {
179 #ifdef __WIN32
180 TCHAR appdata_path[MAX_PATH];
181 if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdata_path))) {
182 path = appdata_path;
183 path += "\\legesmotusrc.txt";
184 } else {
185 return NULL;
186 }
187 #else
188 if (const char* home_dir = getenv("HOME")) {
189 path = home_dir;
190 path += "/.legesmotusrc";
191 } else {
192 return NULL;
193 }
194 #endif
195 }
196 return path.c_str();
197 }
198
system_config_path()199 const char* ConfigManager::system_config_path() { // TODO: use PREFIX/etc/legesmotusrc on UNIX
200 #ifdef __WIN32
201 return "legesmotusrc.txt";
202 #else
203 return "/etc/legesmotusrc";
204 #endif
205 }
206
207