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_