Mercurial > code
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 ¤t = m_sections.back(); | 190 Section ¤t = 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 |