Mercurial > code
comparison C++/Ini.h @ 325:d52a69f9f029
Add Ini, brand new replacement for Parser
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 28 Feb 2015 18:53:27 +0100 |
parents | |
children | 78e8f9a3b233 |
comparison
equal
deleted
inserted
replaced
322:0e80e4589533 | 325:d52a69f9f029 |
---|---|
1 /* | |
2 * Ini.h -- .ini file parsing | |
3 * | |
4 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #ifndef _INI_H_ | |
20 #define _INI_H_ | |
21 | |
22 #include <algorithm> | |
23 #include <deque> | |
24 #include <fstream> | |
25 #include <istream> | |
26 #include <stdexcept> | |
27 #include <string> | |
28 | |
29 /** | |
30 * @class IniOption | |
31 * @brief Option definition | |
32 */ | |
33 class IniOption { | |
34 private: | |
35 std::string m_key; | |
36 std::string m_value; | |
37 | |
38 public: | |
39 inline IniOption(std::string key, std::string value) | |
40 : m_key(std::move(key)) | |
41 , m_value(std::move(value)) | |
42 { | |
43 } | |
44 | |
45 inline const std::string &key() const noexcept | |
46 { | |
47 return m_key; | |
48 } | |
49 | |
50 inline const std::string &value() const noexcept | |
51 { | |
52 return m_value; | |
53 } | |
54 }; | |
55 | |
56 /** | |
57 * @class IniSection | |
58 * @brief Section that contains one or more options | |
59 */ | |
60 class IniSection { | |
61 private: | |
62 std::string m_key; | |
63 std::deque<IniOption> m_options; | |
64 | |
65 template <typename T> | |
66 T find(const std::string &key) const | |
67 { | |
68 auto it = std::find_if(m_options.begin(), m_options.end(), [&] (const IniOption &o) { | |
69 return o.key() == key; | |
70 }); | |
71 | |
72 if (it == m_options.end()) | |
73 throw std::out_of_range("option " + key + " not found"); | |
74 | |
75 return const_cast<T>(*it); | |
76 } | |
77 | |
78 public: | |
79 IniSection() = default; | |
80 | |
81 inline IniSection(std::string key, std::deque<IniOption> options = {}) | |
82 : m_key(std::move(key)) | |
83 , m_options(std::move(options)) | |
84 { | |
85 } | |
86 | |
87 inline const std::string &key() const noexcept | |
88 { | |
89 return m_key; | |
90 } | |
91 | |
92 inline auto begin() noexcept | |
93 { | |
94 return m_options.begin(); | |
95 } | |
96 | |
97 inline auto begin() const noexcept | |
98 { | |
99 return m_options.begin(); | |
100 } | |
101 | |
102 inline auto cbegin() const noexcept | |
103 { | |
104 return m_options.cbegin(); | |
105 } | |
106 | |
107 inline auto end() noexcept | |
108 { | |
109 return m_options.end(); | |
110 } | |
111 | |
112 inline auto end() const noexcept | |
113 { | |
114 return m_options.end(); | |
115 } | |
116 | |
117 inline auto cend() const noexcept | |
118 { | |
119 return m_options.cend(); | |
120 } | |
121 | |
122 inline void push_back(IniOption option) | |
123 { | |
124 m_options.push_back(std::move(option)); | |
125 } | |
126 | |
127 inline void push_front(IniOption option) | |
128 { | |
129 m_options.push_front(std::move(option)); | |
130 } | |
131 | |
132 inline unsigned size() const noexcept | |
133 { | |
134 return m_options.size(); | |
135 } | |
136 | |
137 inline IniOption &operator[](int index) noexcept | |
138 { | |
139 return m_options[index]; | |
140 } | |
141 | |
142 inline const IniOption &operator[](int index) const noexcept | |
143 { | |
144 return m_options[index]; | |
145 } | |
146 | |
147 inline IniOption &operator[](const std::string &key) | |
148 { | |
149 return find<IniOption &>(key); | |
150 } | |
151 | |
152 inline const IniOption &operator[](const std::string &key) const | |
153 { | |
154 return find<const IniOption &>(key); | |
155 } | |
156 }; | |
157 | |
158 /** | |
159 * @class Ini | |
160 * @brief Ini config file loader | |
161 */ | |
162 class Ini { | |
163 private: | |
164 std::deque<IniSection> m_sections; | |
165 | |
166 template <typename T> | |
167 T find(const std::string &key) const | |
168 { | |
169 auto it = std::find_if(m_sections.begin(), m_sections.end(), [&] (const IniSection &s) { | |
170 return s.key() == key; | |
171 }); | |
172 | |
173 if (it == m_sections.end()) | |
174 throw std::out_of_range("section " + key + " not found"); | |
175 | |
176 return const_cast<T>(*it); | |
177 } | |
178 | |
179 public: | |
180 Ini() = default; | |
181 | |
182 Ini(std::istream &stream); | |
183 | |
184 inline Ini(std::istream &&stream) | |
185 : Ini(stream) | |
186 { | |
187 } | |
188 | |
189 inline auto begin() noexcept | |
190 { | |
191 return m_sections.begin(); | |
192 } | |
193 | |
194 inline auto begin() const noexcept | |
195 { | |
196 return m_sections.begin(); | |
197 } | |
198 | |
199 inline auto cbegin() const noexcept | |
200 { | |
201 return m_sections.cbegin(); | |
202 } | |
203 | |
204 inline auto end() noexcept | |
205 { | |
206 return m_sections.end(); | |
207 } | |
208 | |
209 inline auto end() const noexcept | |
210 { | |
211 return m_sections.end(); | |
212 } | |
213 | |
214 inline auto cend() const noexcept | |
215 { | |
216 return m_sections.cend(); | |
217 } | |
218 | |
219 inline unsigned size() const noexcept | |
220 { | |
221 return m_sections.size(); | |
222 } | |
223 | |
224 inline void push_back(IniSection section) | |
225 { | |
226 m_sections.push_back(std::move(section)); | |
227 } | |
228 | |
229 inline void push_front(IniSection section) | |
230 { | |
231 m_sections.push_front(std::move(section)); | |
232 } | |
233 | |
234 inline IniSection &operator[](int index) noexcept | |
235 { | |
236 return m_sections[index]; | |
237 } | |
238 | |
239 inline const IniSection &operator[](int index) const noexcept | |
240 { | |
241 return m_sections[index]; | |
242 } | |
243 | |
244 inline IniSection &operator[](const std::string &key) | |
245 { | |
246 return find<IniSection &>(key); | |
247 } | |
248 | |
249 inline const IniSection &operator[](const std::string &key) const | |
250 { | |
251 return find<IniSection &>(key); | |
252 } | |
253 }; | |
254 | |
255 #endif // !_INI_H_ |