/[pearpc]/src/configparser.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/configparser.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (11 years, 9 months ago) by dpavlin
File size: 8943 byte(s)
import upstream CVS
1 /*
2 * PearPC
3 * configparser.cc
4 *
5 * Copyright (C) 2003 Sebastian Biallas (sb@biallas.net)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <ctype.h>
22 #include "configparser.h"
23 #include "tools/except.h"
24 #include "tools/snprintf.h"
25
26 ConfigParser *gConfig;
27
28 ConfigEntry::ConfigEntry(const String &aName, bool mandatory)
29 {
30 mName = new String(aName);
31 mMandatory = mandatory;
32 mInitialized = false;
33 mSet = false;
34 }
35
36 ConfigEntry::~ConfigEntry()
37 {
38 delete mName;
39 }
40
41 ConfigType ConfigEntry::getType() const
42 {
43 throw Exception();
44 }
45
46 int ConfigEntry::asInt() const
47 {
48 throw MsgfException("cannot interprete config entry %y as integer", mName);
49 }
50
51 String &ConfigEntry::asString(String &result) const
52 {
53 throw MsgfException("cannot interprete config entry %y as string", mName);
54 }
55
56 int ConfigEntry::compareTo(const Object *obj) const
57 {
58 return mName->compareTo(((ConfigEntry *)obj)->mName);
59 }
60
61 bool ConfigEntry::isSet() const
62 {
63 return mSet;
64 }
65
66 bool ConfigEntry::isInitialized() const
67 {
68 return mInitialized;
69 }
70
71
72 class ConfigEntryInt: public ConfigEntry {
73 int value;
74 public:
75
76 ConfigEntryInt(const String &aName, bool mandatory)
77 :ConfigEntry(aName, mandatory)
78 {
79 }
80
81 ConfigEntryInt(const String &aName, int defaultvalue, int scheiss_c_plus_plus)
82 :ConfigEntry(aName, false)
83 {
84 value = defaultvalue;
85 mInitialized = true;
86 }
87
88 virtual ConfigType getType() const
89 {
90 return configTypeInt;
91 }
92
93 void set(int v)
94 {
95 value = v;
96 mInitialized = true;
97 mSet = true;
98 }
99
100 virtual int asInt() const
101 {
102 return value;
103 }
104 };
105
106 class ConfigEntryString: public ConfigEntry {
107 String *value;
108 public:
109
110 ConfigEntryString(const String &aName, bool mandatory)
111 :ConfigEntry(aName, mandatory)
112 {
113 value = new String;
114 }
115
116 ConfigEntryString(const String &aName, const String &defaultvalue)
117 :ConfigEntry(aName, false)
118 {
119 value = new String(defaultvalue);
120 mInitialized = true;
121 }
122
123 virtual ConfigType getType() const
124 {
125 return configTypeString;
126 }
127
128 void set(const String &s)
129 {
130 *value = s;
131 mInitialized = true;
132 mSet = true;
133 }
134
135 virtual String &asString(String &result) const
136 {
137 result = *value;
138 return result;
139 }
140 };
141
142 ConfigParser::ConfigParser()
143 {
144 entries = new AVLTree(true);
145 }
146
147 ConfigParser::~ConfigParser()
148 {
149 delete entries;
150 }
151
152 void ConfigParser::acceptConfigEntryInt(const String &mName, bool mandatory)
153 {
154 ConfigEntry *entry = new ConfigEntryInt(mName, mandatory);
155 if (!entries->insert(entry)) throw MsgfException("duplicate config entry '%y'", &mName);
156 }
157
158 void ConfigParser::acceptConfigEntryString(const String &mName, bool mandatory)
159 {
160 ConfigEntry *entry = new ConfigEntryString(mName, mandatory);
161 if (!entries->insert(entry)) throw MsgfException("duplicate config entry '%y'", &mName);
162 }
163
164 void ConfigParser::acceptConfigEntryIntDef(const String &mName, int d)
165 {
166 ConfigEntry *entry = new ConfigEntryInt(mName, d, 0);
167 if (!entries->insert(entry)) throw MsgfException("duplicate config entry '%y'", &mName);
168 }
169
170 void ConfigParser::acceptConfigEntryStringDef(const String &mName, const String &d)
171 {
172 ConfigEntry *entry = new ConfigEntryString(mName, d);
173 if (!entries->insert(entry)) throw MsgfException("duplicate config entry '%y'", &mName);
174 }
175
176 bool ConfigParser::skipWhite(Stream &in)
177 {
178 while (cur == ' ' || cur == '\t' || cur == '\r') {
179 if (!in.read(&cur, 1)) return false;
180 }
181 return true;
182 }
183
184 #define INV 0xff
185 byte mapchar[]={
186 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', 10,' ',' ',' ',' ',' ', // 0-15
187 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', // 16-31
188 ' ','!','"','#','$','%','&', 39,'(',')','*','+',',','-','.','/', // 32-47
189 '0','0','0','0','0','0','0','0','0','0',':',';','<','=','>','?', // 48-63
190 '@','A','A','A','A','A','A','A','A','A','A','A','A','A','A','A', // 64-79
191 'A','A','A','A','A','A','A','A','A','A','A','[', 92,']','^','_', // 80-95
192 INV,'A','A','A','A','A','A','A','A','A','A','A','A','A','A','A', // 96-111
193 'A','A','A','A','A','A','A','A','A','A','A','{','|','}','~',INV, // 112-127
194 INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
195 INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
196 INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
197 INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
198 INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
199 INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
200 INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,
201 INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV,INV
202 };
203
204 void ConfigParser::loadConfig(Stream &in)
205 {
206 read(in);
207 foreach(ConfigEntry, e, *entries, {
208 if (e->mMandatory && !e->isInitialized()) {
209 throw MsgfException("config entry '%y' is not set.", e->mName);
210 }
211 });
212 }
213
214 void ConfigParser::read(Stream &in)
215 {
216 if (!in.read(&cur, 1)) return;
217 line = 1;
218 while (true) {
219 if (!skipWhite(in)) return;
220 if (cur == '#') {
221 // skip comment
222 do {
223 if (!in.read(&cur, 1)) return;
224 } while (cur != '\n');
225 if (!in.read(&cur, 1)) return;
226 line++;
227 continue;
228 }
229 if (cur == '\r') {
230 if (!in.read(&cur, 1)) return;
231 continue;
232 }
233 if (cur == '\n') {
234 if (!in.read(&cur, 1)) return;
235 line++;
236 continue;
237 }
238 byte m = mapchar[cur];
239 String ident;
240 if (m != 'A' && m != '_') throw MsgfException("invalid character '%c' (%02x) in line %d.", cur, cur, line);
241 do {
242 ident += cur;
243 if (!in.read(&cur, 1)) throw MsgfException("syntax error in line %d.", line);
244 m = mapchar[cur];
245 } while (m == 'A' || m == '0' || m == '_');
246
247 ConfigEntry *e = getEntry(ident);
248 if (!e) throw MsgfException("unknown identifier '%y' in line %d.", &ident, line);
249 if (e->isSet()) throw MsgfException("config entry '%y' is already set in line %d.", e->mName, line);
250
251 if (!skipWhite(in)) throw MsgfException("%s expected in line %d.", "'='", line);
252 if (cur != '=') throw MsgfException("%s expected in line %d.", "'='", line);
253 if (!in.read(&cur, 1) || !skipWhite(in)) throw MsgfException("syntax error in line %d.", line);
254 m = mapchar[cur];
255
256 if (e->getType() == configTypeInt) {
257 if (m != '0') throw MsgfException("%s expected in line %d.", "integer", line);
258 String n;
259 do {
260 n += cur;
261 if (!in.read(&cur, 1)) cur = ' ';
262 m = mapchar[cur];
263 } while (m == '0' || m == 'A');
264 if (cur == '\n' || cur == '\r' || cur == ' ' || cur == '\t' || cur == '#') {
265 // nothing to do
266 } else {
267 cur = tolower(cur);
268 if (cur == 'h' || cur == 'o' || cur == 'b' || cur == 'd') {
269 n += cur;
270 if (!in.read(&cur, 1)) cur = ' ';
271 } else {
272 throw MsgfException("%s expected in line %d.", "integer", line);
273 }
274 }
275 uint64 u;
276 if (!n.toInt64(u)) throw MsgfException("%s expected in line %d.", "integer", line);
277 ((ConfigEntryInt *)e)->set(u);
278 } else {
279 if (m != '"') throw MsgfException("%s expected in line %d.", "'\"'", line);
280 String s;
281 int oldline = line;
282 do {
283 s += cur;
284 if (!in.read(&cur, 1)) throw MsgfException("unterminated string in line %d (starts in line %d).", line, oldline);
285 m = mapchar[cur];
286 if (m == '\n') line++;
287 } while (m != '"');
288 s.del(0, 1);
289 ((ConfigEntryString *)e)->set(s);
290 if (!in.read(&cur, 1)) cur = ' ';
291 }
292 if (!skipWhite(in)) return;
293 if (cur == '#') continue;
294 if (cur != '\n') throw MsgfException("syntax error in line %d.", line);
295 }
296 }
297
298 ConfigEntry *ConfigParser::getEntry(const String &name)
299 {
300 ConfigEntry empty(name, false);
301 return (ConfigEntry *)entries->get(entries->find(&empty));
302 }
303
304 int ConfigParser::getConfigInt(const String &name)
305 {
306 ConfigEntry empty(name, false);
307 ConfigEntry *entry = (ConfigEntry *)entries->get(entries->find(&empty));
308 if (!entry) throw MsgfException("unknown entry '%y'", &name);
309 if (!entry->isInitialized()) throw MsgfException("%y is not set!", &name);
310 return entry->asInt();
311 }
312
313 String &ConfigParser::getConfigString(const String &name, String &result)
314 {
315 ConfigEntry empty(name, false);
316 ConfigEntry *entry = (ConfigEntry *)entries->get(entries->find(&empty));
317 if (!entry) throw MsgfException("unknown entry '%y'", &name);
318 if (!entry->isInitialized()) throw MsgfException("%y is not set!", &name);
319 return entry->asString(result);
320 }
321
322 bool ConfigParser::haveKey(const String &name)
323 {
324 ConfigEntry empty(name, false);
325 ConfigEntry *entry = (ConfigEntry *)entries->get(entries->find(&empty));
326 return entry && entry->isSet();
327 }
328

  ViewVC Help
Powered by ViewVC 1.1.26