comparison C++/Parser.cpp @ 180:2bcdee0fe8d4

Update parser
author David Demelier <markand@malikania.fr>
date Thu, 26 Sep 2013 19:39:24 +0200
parents 3648e9e6935b
children 600754c27c88
comparison
equal deleted inserted replaced
179:3648e9e6935b 180:2bcdee0fe8d4
34 /* -------------------------------------------------------- 34 /* --------------------------------------------------------
35 * Section public members 35 * Section public members
36 * -------------------------------------------------------- */ 36 * -------------------------------------------------------- */
37 37
38 Section::Section() 38 Section::Section()
39 :m_allowed(true) 39 : m_allowed(true)
40 { 40 {
41 } 41 }
42 42
43 Section::~Section() 43 const std::string &Section::getName() const
44 { 44 {
45 } 45 return m_name;
46
47 Section::Section(const Section &s)
48 {
49 m_name = s.m_name;
50 m_options = s.m_options;
51 m_allowed = s.m_allowed;
52 } 46 }
53 47
54 const std::string Section::findOption(const std::string &name) const 48 const std::string Section::findOption(const std::string &name) const
55 { 49 {
56 std::string ret; 50 std::string ret;
57 51
58 for (const Option &o : m_options) 52 for (const Option &o : m_options)
59 if (o.m_key == name) { 53 if (o.m_key == name)
54 {
60 ret = o.m_value; 55 ret = o.m_value;
61 break; 56 break;
62 } 57 }
63 58
64 return ret; 59 return ret;
65 } 60 }
66 61
67 template <> bool Section::getOption(const std::string &name) const 62 template <>
63 bool Section::getValue(const std::string &name) const
68 { 64 {
69 bool result = false; 65 bool result = false;
70 66
71 if (hasOption(name)) { 67 if (hasOption(name))
68 {
72 std::string value = findOption(name); 69 std::string value = findOption(name);
73 70
74 if (value == "yes" || value == "true"|| value == "1") 71 if (value == "yes" || value == "true"|| value == "1")
75 result = true; 72 result = true;
76 else if (value == "no" || value == "false" || value == "0") 73 else if (value == "no" || value == "false" || value == "0")
78 } 75 }
79 76
80 return result; 77 return result;
81 } 78 }
82 79
83 template <> int Section::getOption(const std::string &name) const 80 template <>
81 int Section::getValue(const std::string &name) const
84 { 82 {
85 int result = -1; 83 int result = -1;
86 84
87 if (hasOption(name)) { 85 if (hasOption(name))
88 result = atoi(findOption(name).c_str()); 86 result = atoi(findOption(name).c_str());
89 }
90 87
91 return result; 88 return result;
92 } 89 }
93 90
94 template <> std::string Section::getOption(const std::string &name) const 91 template <>
92 std::string Section::getValue(const std::string &name) const
95 { 93 {
96 std::string result; 94 std::string result;
97 95
98 if (hasOption(name)) 96 if (hasOption(name))
99 result = findOption(name); 97 result = findOption(name);
100 98
101 return result; 99 return result;
102 } 100 }
103 101
104 const std::string & Section::getName() const 102 const std::vector<Option> &Section::getOptions() const
105 {
106 return m_name;
107 }
108
109 const std::vector<Option> & Section::getOptions() const
110 { 103 {
111 return m_options; 104 return m_options;
112 } 105 }
113 106
114 bool Section::hasOption(const std::string &name) const 107 bool Section::hasOption(const std::string &name) const
155 148
156 void Parser::readSection(int lineno, const std::string &line) 149 void Parser::readSection(int lineno, const std::string &line)
157 { 150 {
158 size_t end; 151 size_t end;
159 152
160 if ((end = line.find_first_of(']')) != std::string::npos) { 153 if ((end = line.find_first_of(']')) != std::string::npos)
161 if (end > 1) { 154 {
155 if (end > 1)
156 {
162 std::string name = line.substr(1, end - 1); 157 std::string name = line.substr(1, end - 1);
163 158
164 /* 159 /*
165 * Check if we can add a section, if redefinition is 160 * Check if we can add a section, if redefinition is
166 * disabled, we must disable the previous section so the 161 * disabled, we must disable the previous section so the
167 * further read options should not be enabled until 162 * further read options should not be enabled until
168 * a correct section is found again. 163 * a correct section is found again.
169 */ 164 */
170 if (hasSection(name) && (m_tuning & DisableRedefinition)) { 165 if (hasSection(name) && (m_tuning & DisableRedefinition))
166 {
171 if (!(m_tuning & DisableVerbosity)) 167 if (!(m_tuning & DisableVerbosity))
172 log(lineno, name, "redefinition not allowed"); 168 log(lineno, name, "redefinition not allowed");
173 m_sections.back().m_allowed = false; 169 m_sections.back().m_allowed = false;
174 } else { 170 }
171 else
175 addSection(name); 172 addSection(name);
176 } 173 }
177 } else if (!(m_tuning & DisableVerbosity)) { 174 else if (!(m_tuning & DisableVerbosity))
175 {
178 /* 176 /*
179 * Do not add options at this step because it will 177 * Do not add options at this step because it will
180 * corrupt the previous one. 178 * corrupt the previous one.
181 */ 179 */
182 m_sections.back().m_allowed = false; 180 m_sections.back().m_allowed = false;
190 size_t epos; 188 size_t epos;
191 std::string key, value; 189 std::string key, value;
192 Section &current = m_sections.back(); 190 Section &current = m_sections.back();
193 191
194 // Error on last section? 192 // Error on last section?
195 if (!current.m_allowed) { 193 if (!current.m_allowed)
194 {
196 /* 195 /*
197 * If it is the root section, this has been probably set by 196 * If it is the root section, this has been probably set by
198 * DisableRootSection flag, otherwise an error has occured 197 * DisableRootSection flag, otherwise an error has occured
199 * so no need to log. 198 * so no need to log.
200 */ 199 */
202 log(lineno, "", "option not allowed in that scope"); 201 log(lineno, "", "option not allowed in that scope");
203 202
204 return; 203 return;
205 } 204 }
206 205
207 if ((epos = line.find_first_of('=')) == std::string::npos) { 206 if ((epos = line.find_first_of('=')) == std::string::npos)
207 {
208 if (!(m_tuning & DisableVerbosity)) 208 if (!(m_tuning & DisableVerbosity))
209 log(lineno, current.m_name, "missing `=' keyword"); 209 log(lineno, current.m_name, "missing `=' keyword");
210 return; 210 return;
211 } 211 }
212 212
213 if (epos > 0) { 213 if (epos > 0)
214 {
214 size_t i, begin, last; 215 size_t i, begin, last;
215 char c; 216 char c;
216 217
217 key = line.substr(0, epos - 1); 218 key = line.substr(0, epos - 1);
218 value = line.substr(epos + 1); 219 value = line.substr(epos + 1);
227 continue; 228 continue;
228 value = value.substr(begin); 229 value = value.substr(begin);
229 230
230 c = value[0]; 231 c = value[0];
231 begin = 0; 232 begin = 0;
232 if (c == '\'' || c == '"') { 233 if (c == '\'' || c == '"')
234 {
233 for (last = begin = 1; value[last] != c && last < value.length(); ++last) 235 for (last = begin = 1; value[last] != c && last < value.length(); ++last)
234 continue; 236 continue;
235 if (value[last] != c && !(m_tuning & DisableVerbosity)) 237 if (value[last] != c && !(m_tuning & DisableVerbosity))
236 if (!(m_tuning & DisableVerbosity)) 238 if (!(m_tuning & DisableVerbosity))
237 log(lineno, current.m_name, "undisclosed std::string"); 239 log(lineno, current.m_name, "undisclosed std::string");
238 } else { 240 }
241 else
242 {
239 for (last = begin; !isspace(value[last]) && last < value.length(); ++last) 243 for (last = begin; !isspace(value[last]) && last < value.length(); ++last)
240 continue; 244 continue;
241 } 245 }
242 246
243 if (last - begin > 0) 247 if (last - begin > 0)
259 // Skip default spaces 263 // Skip default spaces
260 for (i = 0; isspace(line[i]) && i < line.length(); ++i) 264 for (i = 0; isspace(line[i]) && i < line.length(); ++i)
261 continue; 265 continue;
262 266
263 buffer = line.substr(i); 267 buffer = line.substr(i);
264 if (buffer.length() > 0) { 268 if (buffer.length() > 0)
265 if (buffer[0] != m_commentChar) { 269 {
270 if (buffer[0] != m_commentChar)
271 {
266 if (buffer[0] == '[') 272 if (buffer[0] == '[')
267 readSection(lineno, buffer); 273 readSection(lineno, buffer);
268 else 274 else
269 readOption(lineno, buffer); 275 readOption(lineno, buffer);
270 } 276 }
275 * Parser public methods 281 * Parser public methods
276 * -------------------------------------------------------- */ 282 * -------------------------------------------------------- */
277 283
278 const char Parser::DEFAULT_COMMENT_CHAR = '#'; 284 const char Parser::DEFAULT_COMMENT_CHAR = '#';
279 285
286 Parser::Parser()
287 {
288 }
289
280 Parser::Parser(const std::string &path, int tuning, char commentToken) 290 Parser::Parser(const std::string &path, int tuning, char commentToken)
281 :m_path(path), m_tuning(tuning), m_commentChar(commentToken) 291 : m_path(path)
292 , m_tuning(tuning)
293 , m_commentChar(commentToken)
282 { 294 {
283 Section root; 295 Section root;
284 296
285 // Add a default root section 297 // Add a default root section
286 root.m_name = ""; 298 root.m_name = "";
287 root.m_allowed = (tuning & DisableRootSection) ? false : true; 299 root.m_allowed = (tuning & DisableRootSection) ? false : true;
288 300
289 m_sections.push_back(root); 301 m_sections.push_back(root);
290 } 302 }
291 303
292 Parser::Parser()
293 {
294 }
295
296 Parser::~Parser() 304 Parser::~Parser()
297 { 305 {
298 } 306 }
299 307
300 bool Parser::open() 308 bool Parser::open()
302 std::ifstream file; 310 std::ifstream file;
303 std::string line; 311 std::string line;
304 int lineno = 1; 312 int lineno = 1;
305 313
306 file.open(m_path.c_str()); 314 file.open(m_path.c_str());
307 if (!file.is_open()) { 315 if (!file.is_open())
316 {
308 m_error = "could not open file " + m_path; // XXX: add a real error 317 m_error = "could not open file " + m_path; // XXX: add a real error
309 return false; 318 return false;
310 } 319 }
311 320
312 // Avoid use of C getline 321 // Avoid use of C getline
313 while (std::getline(file, line)) { 322 while (std::getline(file, line))
314 readLine(lineno++, line); 323 readLine(lineno++, line);
315 }
316 324
317 file.close(); 325 file.close();
318 326
319 return true; 327 return true;
320 } 328 }
321 329
322 const std::string & Parser::getError() const 330 const std::string &Parser::getError() const
323 { 331 {
324 return m_error; 332 return m_error;
325 } 333 }
326 334
327 const std::vector<Section> & Parser::getSections() const 335 const std::vector<Section> &Parser::getSections() const
328 { 336 {
329 return m_sections; 337 return m_sections;
330 } 338 }
331 339
332 std::vector<Section> Parser::findSections(const std::string &name) const 340 void Parser::findSections(const std::string &name, FindFunc func) const
333 { 341 {
334 std::vector<Section> list; 342 for (const Section &s : m_sections)
335 343 if (s.m_name == name)
336 for (const Section &s : m_sections) { 344 func(s);
337 if (s.m_name == name) {
338 Section copy = s;
339 list.push_back(copy);
340 }
341 }
342
343 return list;
344 } 345 }
345 346
346 bool Parser::hasSection(const std::string &name) const 347 bool Parser::hasSection(const std::string &name) const
347 { 348 {
348 for (const Section &s : m_sections) 349 for (const Section &s : m_sections)
350 return true; 351 return true;
351 352
352 return false; 353 return false;
353 } 354 }
354 355
355 Section Parser::getSection(const std::string &name) const 356 const Section &Parser::getSection(const std::string &name) const
356 { 357 {
357 Section ret;
358
359 for (const Section &s : m_sections) 358 for (const Section &s : m_sections)
360 if (s.m_name == name) 359 if (s.m_name == name)
361 ret = s; 360 return s;
362 361
363 return ret; 362 throw NotFoundException(name);
364 } 363 }
365 364
366 Section Parser::requireSection(const std::string &name) const 365 const Section &Parser::requireSection(const std::string &name) const
367 { 366 {
368 if (!hasSection(name)) 367 if (!hasSection(name))
369 throw NotFoundException(name); 368 throw NotFoundException(name);
370 369
371 return getSection(name); 370 return getSection(name);
376 std::cout << "line " << number << ": " << message << std::endl; 375 std::cout << "line " << number << ": " << message << std::endl;
377 } 376 }
378 377
379 void Parser::dump() 378 void Parser::dump()
380 { 379 {
381 for (auto s : m_sections) { 380 for (auto s : m_sections)
381 {
382 dumpSection(s); 382 dumpSection(s);
383
383 for (auto o : s.m_options) 384 for (auto o : s.m_options)
384 dumpOption(o); 385 dumpOption(o);
385 } 386 }
386 } 387 }
387 388