LOGIN / SIGN UP
Cleanup of naming in CfgParser, first go.
2008-10-02 08:47 93534..38c1d
    Start cleaning CfgParser before looking at templates in configuration.
    This code has not been tested much.

src/CfgParser.cc
 
1 @@ -1,10 +1,9 @@
1 //
2 // Copyright (C) 2005-2006 Claes Nästén <me{@}pekdon{.}net>
3 // Copyright © 2005-2008 Claes Nästén <me@pekdon.net>
4 //
5 // This program is licensed under the GNU GPL.
6 // See the LICENSE file for more information.
7 //
8 // $Id$
9 //
10
11 #include "CfgParser.hh"
...
33 @@ -34,15 +33,15 @@
33 using std::string;
34 using std::auto_ptr;
35
37 const string CfgParser::_o_root_source_name = string("");
37 const string CfgParser::_root_source_name = string("");
38 const char *CP_PARSE_BLANKS = " \t\n";
39
40 //! @brief CfgParser::Entry constructor.
42 CfgParser::Entry::Entry(const std::string &or_source_name, int i_line,
43 const std::string &or_name, const std::string &or_value)
44 : _op_entry_next(NULL), _op_section(NULL),
45 _o_name(or_name), _o_value(or_value),
46 _i_line(i_line), _or_source_name(or_source_name)
46 CfgParser::Entry::Entry(const std::string &source_name, int line,
47 const std::string &name, const std::string &value)
48 : _entry_next(0), _section(0),
49 _name(name), _value(value),
50 _line(line), _source_name(source_name)
51 {
52 }
53
...
52 @@ -53,86 +52,81 @@
52
53 //! @brief Adds Entry to the end of Entry list at current depth.
54 CfgParser::Entry*
56 CfgParser::Entry::add_entry(const std::string &or_source_name, int i_line,
57 const std::string &or_name,
58 const std::string &or_value)
58 CfgParser::Entry::add_entry(const std::string &source_name, int line,
59 const std::string &name, const std::string &value)
60 {
62 if (_op_entry_next) {
63 return _op_entry_next->add_entry(or_source_name, i_line,
64 or_name, or_value);
64 if (_entry_next) {
65 return _entry_next->add_entry(source_name, line, name, value);
66 } else {
68 _op_entry_next = new Entry(or_source_name, i_line,
69 or_name, or_value);
70 return _op_entry_next;
70 _entry_next = new Entry(source_name, line, name, value);
71 return _entry_next;
72 }
73 }
74
75 //! @brief Gets next entry that has a sub section.
76 CfgParser::Entry*
78 CfgParser::Entry::get_section_next (void)
78 CfgParser::Entry::get_section_next(void)
79 {
81 Entry *op_entry;
81 Entry *entry;
82
84 for (op_entry = _op_entry_next; op_entry;
85 op_entry = op_entry->_op_entry_next) {
86 if (op_entry->_op_section) {
87 return op_entry;
87 for (entry = _entry_next; entry; entry = entry->_entry_next) {
88 if (entry->_section) {
89 return entry;
90 }
91 }
92
94 return NULL;
94 return 0;
95 }
96
98 //! @brief Gets next entry without subsection matching the name or_name.
99 //! @param or_name Name of Entry to look for.
99 //! @brief Gets next entry without subsection matching the name name.
100 //! @param name Name of Entry to look for.
101 CfgParser::Entry*
103 CfgParser::Entry::find_entry (const std::string &or_name)
103 CfgParser::Entry::find_entry(const std::string &name)
104 {
106 CfgParser::Entry *op_it;
106 CfgParser::Entry *it;
107
109 for (op_it = _op_entry_next; op_it; op_it = op_it->_op_entry_next) {
110 if (! op_it->_op_section && (*op_it == or_name.c_str())) {
111 return op_it;
111 for (it = _entry_next; it; it = it->_entry_next) {
112 if (! it->_section && (*it == name.c_str())) {
113 return it;
114 }
115 }
116
118 return NULL;
118 return 0;
119 }
120
122 //! @brief Gets the next entry with subsection matchin the name or_name.
123 //! @param or_name Name of Entry to look for.
123 //! @brief Gets the next entry with subsection matchin the name name.
124 //! @param name Name of Entry to look for.
125 CfgParser::Entry*
127 CfgParser::Entry::find_section (const std::string &or_name)
127 CfgParser::Entry::find_section(const std::string &name)
128 {
130 CfgParser::Entry *op_it;
130 CfgParser::Entry *it;
131
133 for (op_it = _op_entry_next; op_it; op_it = op_it->_op_entry_next) {
134 if (op_it->_op_section && (*op_it == or_name.c_str ())) {
135 return op_it;
135 for (it = _entry_next; it; it = it->_entry_next) {
136 if (it->_section && (*it == name.c_str ())) {
137 return it;
138 }
139 }
140
142 return NULL;
142 return 0;
143 }
144
145
146 //! @brief Sets and validates data specified by key list.
147 void
149 CfgParser::Entry::parse_key_values (std::list<CfgParserKey*>::iterator o_begin,
150 std::list<CfgParserKey*>::iterator o_end)
150 CfgParser::Entry::parse_key_values(std::list<CfgParserKey*>::iterator begin,
151 std::list<CfgParserKey*>::iterator end)
152 {
154 CfgParser::Entry *op_value;
155 list<CfgParserKey*>::iterator o_it;
155 CfgParser::Entry *value;
156 list<CfgParserKey*>::iterator it;
157
159 for (o_it = o_begin; o_it != o_end; ++o_it) {
160 op_value = find_entry ((*o_it)->get_name());
161 if (op_value) {
161 for (it = begin; it != end; ++it) {
162 value = find_entry((*it)->get_name());
163 if (value) {
164 try {
166 (*o_it)->parse_value(op_value->get_value());
166 (*it)->parse_value(value->get_value());
167
168 } catch (string &ex) {
170 cerr << " *** WARNING " << ex << endl << " "
171 << *op_value << endl;
171 cerr << " *** WARNING " << ex << endl << " " << *value << endl;
172 }
173 }
174 }
...
136 @@ -142,140 +136,140 @@
136 void
137 CfgParser::Entry::free_tree(void)
138 {
145 Entry *op_entry, *op_entry_free;
140 Entry *entry, *entry_free;
141
148 for (op_entry = this; op_entry; ) {
143 for (entry = this; entry; ) {
144 // Delete subsection if any
151 if (op_entry->_op_section) {
152 op_entry->_op_section->free_tree();
153 delete op_entry->_op_section;
154 op_entry->_op_section = NULL;
149 if (entry->_section) {
150 entry->_section->free_tree();
151 delete entry->_section;
152 entry->_section = 0;
153 }
154
161 op_entry_free = op_entry;
162 op_entry = op_entry->_op_entry_next;
157 entry_free = entry;
158 entry = entry->_entry_next;
159
160 // Delete node if it is not ourselves
167 if (op_entry_free != this) {
168 delete op_entry_free;
163 if (entry_free != this) {
164 delete entry_free;
165 }
166 }
167 }
168
169 //! @brief Operator <<, return info on source, line, name and value.
170 std::ostream&
177 operator<<(std::ostream &or_stream, const CfgParser::Entry &or_entry)
172 operator<<(std::ostream &stream, const CfgParser::Entry &entry)
173 {
180 or_stream << or_entry.get_source_name() << "@" << or_entry.get_line()
181 << " " << or_entry.get_name() << " = " << or_entry.get_value();
182 return or_stream;
177 stream << entry.get_source_name() << "@" << entry.get_line()
178 << " " << entry.get_name() << " = " << entry.get_value();
179 return stream;
180 }
181
182 //! @brief CfgParser constructor.
189 CfgParser::CfgParser (void)
190 : _op_source(0),
191 _o_root_entry(_o_root_source_name, 0, "ROOT", ""),
192 _op_entry(&_o_root_entry)
187 CfgParser::CfgParser(void)
188 : _source(0),
189 _root_entry(_root_source_name, 0, "ROOT", ""),
190 _entry(&_root_entry)
191 {
192 }
193
194 //! @brief CfgParser destructor.
195 CfgParser::~CfgParser(void)
196 {
203 _o_root_entry.free_tree();
198 _root_entry.free_tree();
199 }
200
201 //! @brief Parses source and fills root section with data.
202 bool
209 CfgParser::parse(const std::string &or_src, CfgParserSource::Type i_type)
204 CfgParser::parse(const std::string &src, CfgParserSource::Type type)
205 {
206 // Init parse buffer and reserve memory.
213 string o_buf, o_value;
214 o_buf.reserve(PARSE_BUF_SIZE);
209 string buf, value;
210 buf.reserve(PARSE_BUF_SIZE);
211
212 // Open initial source.
219 parse_source_new(or_src, i_type);
220 if (_o_source_list.size() == 0) {
215 parse_source_new(src, type);
216 if (_source_list.size() == 0) {
217 return false;
218 }
219
226 int i_c, i_next;
227 while (_o_source_list.size()) {
228 _op_source = _o_source_list.back();
223 int c, next;
224 while (_source_list.size()) {
225 _source = _source_list.back();
226
233 while ((i_c = _op_source->getc()) != EOF) {
234 switch (i_c) {
229 while ((c = _source->getc()) != EOF) {
230 switch (c) {
231 case '\n':
232 // To be able to handle entry ends AND { after \n a check
233 // to see what comes after the newline is done. If { appears
234 // we continue as nothing happened else we finish the entry.
241 i_next = parse_skip_blank(_op_source);
242 if (i_next != '{') {
243 parse_entry_finish(o_buf, o_value);
238 next = parse_skip_blank(_source);
239 if (next != '{') {
240 parse_entry_finish(buf, value);
241 }
242 break;
243 case ';':
250 parse_entry_finish(o_buf, o_value);
245 parse_entry_finish(buf, value);
246 break;
247 case '{':
254 if (parse_name(o_buf)) {
255 parse_section_finish (o_buf, o_value);
250 if (parse_name(buf)) {
251 parse_section_finish (buf, value);
252 } else {
253 cerr << _("Ignoring section as name is empty.\n");
254 }
261 o_buf.clear();
262 o_value.clear();
257 buf.clear();
258 value.clear();
259 break;
260 case '}':
267 if (_o_entry_list.size() > 0) {
268 if (o_buf.size() && parse_name(o_buf)) {
269 parse_entry_finish(o_buf, o_value);
270 o_buf.clear();
271 o_value.clear();
266 if (_entry_list.size() > 0) {
267 if (buf.size() && parse_name(buf)) {
268 parse_entry_finish(buf, value);
269 buf.clear();
270 value.clear();
271 }
278 _op_entry = _o_entry_list.back();
279 _o_entry_list.pop_back();
274 _entry = _entry_list.back();
275 _entry_list.pop_back();
276 } else {
277 cerr << _("Extra } character found, ignoring.\n");
278 }
279 break;
280 case '=':
287 o_value.clear();
288 parse_value(_op_source, o_value);
283 value.clear();
284 parse_value(_source, value);
285 break;
286 case '#':
293 parse_comment_line(_op_source);
288 parse_comment_line(_source);
289 break;
290 case '/':
297 i_next = _op_source->getc();
298 if (i_next == '/') {
299 parse_comment_line(_op_source);
300 } else if (i_next == '*') {
301 parse_comment_c(_op_source);
296 next = _source->getc();
297 if (next == '/') {
298 parse_comment_line(_source);
299 } else if (next == '*') {
300 parse_comment_c(_source);
301 } else {
308 o_buf += i_c;
309 _op_source->ungetc(i_next);
304 buf += c;
305 _source->ungetc(next);
306 }
307 break;
308 default:
315 o_buf += i_c;
310 buf += c;
311 break;
312 }
313 }
314
315 try {
322 _op_source->close();
317 _source->close();
318
319 } catch (string &ex) {
320 cerr << ex << endl;
321 }
328 delete _op_source;
329 _o_source_list.pop_back();
330 _o_source_name_list.pop_back();
325 delete _source;
326 _source_list.pop_back();
327 _source_name_list.pop_back();
328 }
329
336 if (o_buf.size()) {
337 parse_entry_finish(o_buf, o_value);
332 if (buf.size()) {
333 parse_entry_finish(buf, value);
334 }
335
336 return true;
...
277 @@ -283,309 +277,300 @@
277
278 //! @brief Creates and opens new CfgParserSource.
279 void
286 CfgParser::parse_source_new(const std::string &or_name,
287 CfgParserSource::Type i_type)
282 CfgParser::parse_source_new(const std::string &name_orig, CfgParserSource::Type type)
283 {
290 int i_done = 0;
291 string o_name(or_name);
286 int done = 0;
287 string name(name_orig);
288
289 do {
296 CfgParserSource *op_source = source_new(o_name, i_type);
297 assert(op_source);
292 CfgParserSource *source = source_new(name, type);
293 assert(source);
294
295 // Open and set as active, delete if fails.
296 try {
303 op_source->open();
304 _op_source = op_source;
305 _o_source_list.push_back(_op_source);
306 i_done = 1;
301 source->open();
302 _source = source;
303 _source_list.push_back(_source);
304 done = 1;
305
306 } catch (string &ex) {
313 delete op_source;
308 delete source;
309 // Previously added in source_new
316 _o_source_name_list.pop_back();
311 _source_name_list.pop_back();
312
313
314 // Display error message on second try
321 if (i_done) {
316 if (done) {
317 cerr << ex << endl;
318 }
319
320 // If the open fails and we are trying to open a file, try
321 // to open the file from the current files directory.
328 if (! i_done && (i_type == CfgParserSource::SOURCE_FILE)) {
329 if (_o_source_name_list.size() && (or_name[0] != '/')) {
330 o_name = Util::getDir(_o_source_name_list.back());
331 o_name += "/" + or_name;
326 if (! done && (type == CfgParserSource::SOURCE_FILE)) {
327 if (_source_name_list.size() && (name[0] != '/')) {
328 name = Util::getDir(_source_name_list.back());
329 name += "/" + name_orig;
330 }
331 }
332 }
339 } while (! i_done++ && (i_type == CfgParserSource::SOURCE_FILE));
334 } while (! done++ && (type == CfgParserSource::SOURCE_FILE));
335 }
336
337 //! @brief Parses from beginning to first blank.
338 bool
345 CfgParser::parse_name(std::string &or_buf)
340 CfgParser::parse_name(std::string &buf)
341 {
348 if (! or_buf.size()) {
343 if (! buf.size()) {
344 cerr << _("Unable to parse empty name.\n");
345 return false;
346 }
347
348 // Identify name.
355 string::size_type o_begin, o_end;
356 o_begin = or_buf.find_first_not_of(CP_PARSE_BLANKS);
357 if (o_begin == string::npos) {
358 // FIXME: cerr << "ONLY BLANKS IN NAME" << endl;
353 string::size_type begin, end;
354 begin = buf.find_first_not_of(CP_PARSE_BLANKS);
355 if (begin == string::npos) {
356 return false;
357 }
364 o_end = or_buf.find_first_of(CP_PARSE_BLANKS, o_begin);
359 end = buf.find_first_of(CP_PARSE_BLANKS, begin);
360
361 // Check if there is any garbage after the value.
368 if (o_end != string::npos) {
369 if (or_buf.find_first_not_of(CP_PARSE_BLANKS, o_end) != string::npos) {
370 //cerr << "GARBAGE AFTER NAME" << endl;
365 if (end != string::npos) {
366 if (buf.find_first_not_of(CP_PARSE_BLANKS, end) != string::npos) {
367 // Pass, do notihng
368 }
369 }
370
371 // Set name.
378 or_buf = or_buf.substr(o_begin, o_end - o_begin);
373 buf = buf.substr(begin, end - begin);
374
375 return true;
376 }
377
378 //! @brief Parses from = to end of " pair.
379 bool
386 CfgParser::parse_value(CfgParserSource *op_source, std::string &or_value)
381 CfgParser::parse_value(CfgParserSource *source, std::string &value)
382 {
383 // Init parse buffer and reserve memory.
390 string o_buf;
391 o_buf.reserve(PARSE_BUF_SIZE);
386 string buf;
387 buf.reserve(PARSE_BUF_SIZE);
388
389 // We expect to get a " after the =, however to do proper error reporting
390 // we store the what we get between so we can show the output if it includes
391 // anything else than spaces.
398 int i_c, i_next;
399 bool b_garbage = false;
400 while ((i_c = op_source->getc()) != EOF) {
401 if (i_c == '"')
396 int c, next;
397 bool garbage = false;
398 while ((c = source->getc()) != EOF) {
399 if (c == '"') {
400 break;
401 }
402
409 o_buf += i_c;
404 buf += c;
405
412 if (! isspace(i_c))
413 b_garbage = true;
408 if (! isspace(c)) {
409 garbage = true;
410 }
411 }
412
413 // Check if we got to a " or found EOF first.
420 if (i_c == EOF) {
415 if (c == EOF) {
416 cerr << _("Reached EOF before opening \" in value.\n");
417 return false;
418 }
419
420 // Check if there was garbage between = and ".
427 if (b_garbage) {
428 //cerr << "GARBAGE between = and \", \"" << o_buf << "\"!" << endl;
423 if (garbage) {