Mercurial > code
comparison C++/Ini.h @ 327:78e8f9a3b233
Ini:
- Add support for @include
- Add more tests
- Added lot of documentation
TODO:
- Add lots of test with errored files
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 03 Mar 2015 21:21:11 +0100 |
parents | d52a69f9f029 |
children |
comparison
equal
deleted
inserted
replaced
326:fb6c42173634 | 327:78e8f9a3b233 |
---|---|
17 */ | 17 */ |
18 | 18 |
19 #ifndef _INI_H_ | 19 #ifndef _INI_H_ |
20 #define _INI_H_ | 20 #define _INI_H_ |
21 | 21 |
22 /** | |
23 * @file Ini.h | |
24 * @brief Configuration file parser | |
25 */ | |
26 | |
22 #include <algorithm> | 27 #include <algorithm> |
23 #include <deque> | 28 #include <deque> |
24 #include <fstream> | |
25 #include <istream> | |
26 #include <stdexcept> | 29 #include <stdexcept> |
27 #include <string> | 30 #include <string> |
31 | |
32 /** | |
33 * @class IniError | |
34 * @brief Error in a file | |
35 */ | |
36 class IniError : public std::exception { | |
37 private: | |
38 int m_line; | |
39 int m_position; | |
40 std::string m_error; | |
41 | |
42 public: | |
43 /** | |
44 * Construct an error. | |
45 * | |
46 * @param line the line | |
47 * @param position the position | |
48 * @param error the error | |
49 */ | |
50 inline IniError(int line, int position, std::string error) | |
51 : m_line(line) | |
52 , m_position(position) | |
53 , m_error(std::move(error)) | |
54 { | |
55 } | |
56 | |
57 /** | |
58 * Return the line number. | |
59 * | |
60 * @return the line | |
61 */ | |
62 inline int line() const noexcept | |
63 { | |
64 return m_line; | |
65 } | |
66 | |
67 /** | |
68 * Return the position in the current line. | |
69 * | |
70 * @return the position | |
71 */ | |
72 inline int position() const noexcept | |
73 { | |
74 return m_position; | |
75 } | |
76 | |
77 /** | |
78 * Get the error string. | |
79 * | |
80 * @return the string | |
81 */ | |
82 inline const char *what() const noexcept | |
83 { | |
84 return m_error.c_str(); | |
85 } | |
86 }; | |
28 | 87 |
29 /** | 88 /** |
30 * @class IniOption | 89 * @class IniOption |
31 * @brief Option definition | 90 * @brief Option definition |
32 */ | 91 */ |
34 private: | 93 private: |
35 std::string m_key; | 94 std::string m_key; |
36 std::string m_value; | 95 std::string m_value; |
37 | 96 |
38 public: | 97 public: |
98 /** | |
99 * Construct an option. | |
100 * | |
101 * @param key the key | |
102 * @param value the value | |
103 */ | |
39 inline IniOption(std::string key, std::string value) | 104 inline IniOption(std::string key, std::string value) |
40 : m_key(std::move(key)) | 105 : m_key(std::move(key)) |
41 , m_value(std::move(value)) | 106 , m_value(std::move(value)) |
42 { | 107 { |
43 } | 108 } |
44 | 109 |
110 /** | |
111 * Get the option key. | |
112 * | |
113 * @return the key | |
114 */ | |
45 inline const std::string &key() const noexcept | 115 inline const std::string &key() const noexcept |
46 { | 116 { |
47 return m_key; | 117 return m_key; |
48 } | 118 } |
49 | 119 |
120 /** | |
121 * Get the option value. | |
122 * | |
123 * @return the value | |
124 */ | |
50 inline const std::string &value() const noexcept | 125 inline const std::string &value() const noexcept |
51 { | 126 { |
52 return m_value; | 127 return m_value; |
53 } | 128 } |
54 }; | 129 }; |
74 | 149 |
75 return const_cast<T>(*it); | 150 return const_cast<T>(*it); |
76 } | 151 } |
77 | 152 |
78 public: | 153 public: |
154 /** | |
155 * Default constructor has no sections and no values. | |
156 */ | |
79 IniSection() = default; | 157 IniSection() = default; |
80 | 158 |
81 inline IniSection(std::string key, std::deque<IniOption> options = {}) | 159 /** |
160 * Construct a section with a set of options. | |
161 * | |
162 * @param key the section name | |
163 * @param options the list of options | |
164 */ | |
165 inline IniSection(std::string key, std::deque<IniOption> options = {}) noexcept | |
82 : m_key(std::move(key)) | 166 : m_key(std::move(key)) |
83 , m_options(std::move(options)) | 167 , m_options(std::move(options)) |
84 { | 168 { |
85 } | 169 } |
86 | 170 |
171 /** | |
172 * Get the section key. | |
173 * | |
174 * @return the key | |
175 */ | |
87 inline const std::string &key() const noexcept | 176 inline const std::string &key() const noexcept |
88 { | 177 { |
89 return m_key; | 178 return m_key; |
90 } | 179 } |
91 | 180 |
181 /** | |
182 * Get an iterator to the beginning. | |
183 * | |
184 * @return the iterator | |
185 */ | |
92 inline auto begin() noexcept | 186 inline auto begin() noexcept |
93 { | 187 { |
94 return m_options.begin(); | 188 return m_options.begin(); |
95 } | 189 } |
96 | 190 |
191 /** | |
192 * Overloaded function. | |
193 * | |
194 * @return the iterator | |
195 */ | |
97 inline auto begin() const noexcept | 196 inline auto begin() const noexcept |
98 { | 197 { |
99 return m_options.begin(); | 198 return m_options.begin(); |
100 } | 199 } |
101 | 200 |
201 /** | |
202 * Overloaded function. | |
203 * | |
204 * @return the iterator | |
205 */ | |
102 inline auto cbegin() const noexcept | 206 inline auto cbegin() const noexcept |
103 { | 207 { |
104 return m_options.cbegin(); | 208 return m_options.cbegin(); |
105 } | 209 } |
106 | 210 |
211 /** | |
212 * Get an iterator to the end. | |
213 * | |
214 * @return the iterator | |
215 */ | |
107 inline auto end() noexcept | 216 inline auto end() noexcept |
108 { | 217 { |
109 return m_options.end(); | 218 return m_options.end(); |
110 } | 219 } |
111 | 220 |
221 /** | |
222 * Overloaded function. | |
223 * | |
224 * @return the iterator | |
225 */ | |
112 inline auto end() const noexcept | 226 inline auto end() const noexcept |
113 { | 227 { |
114 return m_options.end(); | 228 return m_options.end(); |
115 } | 229 } |
116 | 230 |
231 /** | |
232 * Overloaded function. | |
233 * | |
234 * @return the iterator | |
235 */ | |
117 inline auto cend() const noexcept | 236 inline auto cend() const noexcept |
118 { | 237 { |
119 return m_options.cend(); | 238 return m_options.cend(); |
120 } | 239 } |
121 | 240 |
241 /** | |
242 * Append an option. | |
243 * | |
244 * @param option the option to add | |
245 */ | |
122 inline void push_back(IniOption option) | 246 inline void push_back(IniOption option) |
123 { | 247 { |
124 m_options.push_back(std::move(option)); | 248 m_options.push_back(std::move(option)); |
125 } | 249 } |
126 | 250 |
251 /** | |
252 * Push an option to the beginning. | |
253 * | |
254 * @param option the option to add | |
255 */ | |
127 inline void push_front(IniOption option) | 256 inline void push_front(IniOption option) |
128 { | 257 { |
129 m_options.push_front(std::move(option)); | 258 m_options.push_front(std::move(option)); |
130 } | 259 } |
131 | 260 |
261 /** | |
262 * Get the number of options in that section. | |
263 * | |
264 * @return the size | |
265 */ | |
132 inline unsigned size() const noexcept | 266 inline unsigned size() const noexcept |
133 { | 267 { |
134 return m_options.size(); | 268 return m_options.size(); |
135 } | 269 } |
136 | 270 |
271 /** | |
272 * Access an option at the specified index. | |
273 * | |
274 * @param index the index | |
275 * @return the option | |
276 * @warning No bounds checking is performed | |
277 */ | |
137 inline IniOption &operator[](int index) noexcept | 278 inline IniOption &operator[](int index) noexcept |
138 { | 279 { |
139 return m_options[index]; | 280 return m_options[index]; |
140 } | 281 } |
141 | 282 |
283 /** | |
284 * Access an option at the specified index. | |
285 * | |
286 * @param index the index | |
287 * @return the option | |
288 * @warning No bounds checking is performed | |
289 */ | |
142 inline const IniOption &operator[](int index) const noexcept | 290 inline const IniOption &operator[](int index) const noexcept |
143 { | 291 { |
144 return m_options[index]; | 292 return m_options[index]; |
145 } | 293 } |
146 | 294 |
295 /** | |
296 * Access an option at the specified key. | |
297 * | |
298 * @param key the key | |
299 * @return the option | |
300 * @warning No bounds checking is performed | |
301 */ | |
147 inline IniOption &operator[](const std::string &key) | 302 inline IniOption &operator[](const std::string &key) |
148 { | 303 { |
149 return find<IniOption &>(key); | 304 return find<IniOption &>(key); |
150 } | 305 } |
151 | 306 |
307 /** | |
308 * Access an option at the specified key. | |
309 * | |
310 * @param key the key | |
311 * @return the option | |
312 * @warning No bounds checking is performed | |
313 */ | |
152 inline const IniOption &operator[](const std::string &key) const | 314 inline const IniOption &operator[](const std::string &key) const |
153 { | 315 { |
154 return find<const IniOption &>(key); | 316 return find<const IniOption &>(key); |
155 } | 317 } |
156 }; | 318 }; |
175 | 337 |
176 return const_cast<T>(*it); | 338 return const_cast<T>(*it); |
177 } | 339 } |
178 | 340 |
179 public: | 341 public: |
342 /** | |
343 * Default constructor with an empty configuration. | |
344 */ | |
180 Ini() = default; | 345 Ini() = default; |
181 | 346 |
182 Ini(std::istream &stream); | 347 /** |
183 | 348 * Open the path as the configuration file. |
184 inline Ini(std::istream &&stream) | 349 * |
185 : Ini(stream) | 350 * @param path the path |
186 { | 351 * @throw IniError on any error |
187 } | 352 */ |
188 | 353 Ini(const std::string &path); |
354 | |
355 /** | |
356 * Get an iterator to the beginning. | |
357 * | |
358 * @return the iterator | |
359 */ | |
189 inline auto begin() noexcept | 360 inline auto begin() noexcept |
190 { | 361 { |
191 return m_sections.begin(); | 362 return m_sections.begin(); |
192 } | 363 } |
193 | 364 |
365 /** | |
366 * Overloaded function. | |
367 * | |
368 * @return the iterator | |
369 */ | |
194 inline auto begin() const noexcept | 370 inline auto begin() const noexcept |
195 { | 371 { |
196 return m_sections.begin(); | 372 return m_sections.begin(); |
197 } | 373 } |
198 | 374 |
375 /** | |
376 * Overloaded function. | |
377 * | |
378 * @return the iterator | |
379 */ | |
199 inline auto cbegin() const noexcept | 380 inline auto cbegin() const noexcept |
200 { | 381 { |
201 return m_sections.cbegin(); | 382 return m_sections.cbegin(); |
202 } | 383 } |
203 | 384 |
385 /** | |
386 * Get an iterator to the end. | |
387 * | |
388 * @return the iterator | |
389 */ | |
204 inline auto end() noexcept | 390 inline auto end() noexcept |
205 { | 391 { |
206 return m_sections.end(); | 392 return m_sections.end(); |
207 } | 393 } |
208 | 394 |
395 /** | |
396 * Overloaded function. | |
397 * | |
398 * @return the iterator | |
399 */ | |
209 inline auto end() const noexcept | 400 inline auto end() const noexcept |
210 { | 401 { |
211 return m_sections.end(); | 402 return m_sections.end(); |
212 } | 403 } |
213 | 404 |
405 /** | |
406 * Overloaded function. | |
407 * | |
408 * @return the iterator | |
409 */ | |
214 inline auto cend() const noexcept | 410 inline auto cend() const noexcept |
215 { | 411 { |
216 return m_sections.cend(); | 412 return m_sections.cend(); |
217 } | 413 } |
218 | 414 |
415 /** | |
416 * Get the number of sections in the configuration. | |
417 * | |
418 * @return the size | |
419 */ | |
219 inline unsigned size() const noexcept | 420 inline unsigned size() const noexcept |
220 { | 421 { |
221 return m_sections.size(); | 422 return m_sections.size(); |
222 } | 423 } |
223 | 424 |
425 /** | |
426 * Append a section to the end. | |
427 * | |
428 * @param section the section to add | |
429 */ | |
224 inline void push_back(IniSection section) | 430 inline void push_back(IniSection section) |
225 { | 431 { |
226 m_sections.push_back(std::move(section)); | 432 m_sections.push_back(std::move(section)); |
227 } | 433 } |
228 | 434 |
435 /** | |
436 * Add a section to the beginning. | |
437 * | |
438 * @param section the section to add | |
439 */ | |
229 inline void push_front(IniSection section) | 440 inline void push_front(IniSection section) |
230 { | 441 { |
231 m_sections.push_front(std::move(section)); | 442 m_sections.push_front(std::move(section)); |
232 } | 443 } |
233 | 444 |
445 /** | |
446 * Access a section at the specified index. | |
447 * | |
448 * @param index the index | |
449 * @return the section | |
450 * @warning No bounds checking is performed | |
451 */ | |
234 inline IniSection &operator[](int index) noexcept | 452 inline IniSection &operator[](int index) noexcept |
235 { | 453 { |
236 return m_sections[index]; | 454 return m_sections[index]; |
237 } | 455 } |
238 | 456 |
457 /** | |
458 * Access a section at the specified index. | |
459 * | |
460 * @param index the index | |
461 * @return the section | |
462 * @warning No bounds checking is performed | |
463 */ | |
239 inline const IniSection &operator[](int index) const noexcept | 464 inline const IniSection &operator[](int index) const noexcept |
240 { | 465 { |
241 return m_sections[index]; | 466 return m_sections[index]; |
242 } | 467 } |
243 | 468 |
469 /** | |
470 * Access a section at the specified key. | |
471 * | |
472 * @param key the key | |
473 * @return the section | |
474 * @warning No bounds checking is performed | |
475 */ | |
244 inline IniSection &operator[](const std::string &key) | 476 inline IniSection &operator[](const std::string &key) |
245 { | 477 { |
246 return find<IniSection &>(key); | 478 return find<IniSection &>(key); |
247 } | 479 } |
248 | 480 |
481 /** | |
482 * Access a section at the specified key. | |
483 * | |
484 * @param key the key | |
485 * @return the section | |
486 * @warning No bounds checking is performed | |
487 */ | |
249 inline const IniSection &operator[](const std::string &key) const | 488 inline const IniSection &operator[](const std::string &key) const |
250 { | 489 { |
251 return find<IniSection &>(key); | 490 return find<IniSection &>(key); |
252 } | 491 } |
253 }; | 492 }; |