OGS
ConfigTree-impl.h
Go to the documentation of this file.
1
10
11// IWYU pragma: private, include "ConfigTree.h"
12
13#include <sstream>
14#include <utility>
15
16#include "ConfigTree.h"
17#include "StringTools.h"
18
19namespace BaseLib
20{
22template <typename Iterator>
23class Range
24{
25public:
26 explicit Range(Iterator begin, Iterator end)
27 : begin_(std::move(begin)), end_(std::move(end))
28 {
29 }
30
31 Iterator begin() const { return begin_; }
32 Iterator end() const { return end_; }
33 std::size_t size() const { return std::distance(begin_, end_); }
34 bool empty() const { return size() == 0; }
35
36private:
37 Iterator begin_;
38 Iterator end_;
39};
40
41template <typename T>
42T ConfigTree::getConfigParameter(std::string const& param) const
43{
44 if (auto p = getConfigParameterOptional<T>(param))
45 {
46 return *p;
47 }
48
49 error("Key <" + param + "> has not been found");
50}
51
52template <typename T>
53T ConfigTree::getConfigParameter(std::string const& param,
54 T const& default_value) const
55{
56 if (auto p = getConfigParameterOptional<T>(param))
57 {
58 return *p;
59 }
60
61 return default_value;
62}
63
64template <typename T>
66 std::string const& param) const
67{
68 checkUnique(param);
69
70 return getConfigParameterOptionalImpl(param, static_cast<T*>(nullptr));
71}
72
73template <typename T>
75 std::string const& param, T* /*unused*/) const
76{
77 if (auto p = getConfigSubtreeOptional(param))
78 {
79 return p->getValue<T>();
80 }
81
82 return std::nullopt;
83}
84
85template <typename T>
86std::optional<std::vector<T>> ConfigTree::getConfigParameterOptionalImpl(
87 std::string const& param, std::vector<T>* /*unused*/) const
88{
89 if (auto p = getConfigSubtreeOptional(param))
90 {
91 std::string const raw = p->getValue<std::string>();
92
93 std::size_t bad_idx = 0;
94 if (auto parsed = BaseLib::tryParseVector<T>(raw, &bad_idx))
95 {
96 return parsed; // OK
97 }
98
99 // preserve original error wording & token index
100 error("Value for key <" + param + "> `" + shortString(raw) +
101 "' not convertible to a vector of the desired type."
102 " Could not convert token no. " +
103 std::to_string(bad_idx) + ".");
104 return std::nullopt; // not reached
105 }
106
107 return std::nullopt;
108}
109
110template <typename T>
112 std::string const& param) const
113{
114 checkUnique(param);
115 markVisited<T>(param, Attr::TAG, true);
116
117 auto p = tree_->equal_range(param);
118 return Range<ValueIterator<T>>(ValueIterator<T>(p.first, param, *this),
119 ValueIterator<T>(p.second, param, *this));
120}
121
122template <typename T>
123T ConfigTree::peekConfigParameter(std::string const& param) const
124{
125 checkKeyname(param);
126
127 if (auto p = tree_->get_child_optional(param))
128 {
129 try
130 {
131 return p->get_value<T>();
132 }
133 catch (boost::property_tree::ptree_bad_data const&)
134 {
135 error("Value for key <" + param + "> `" + shortString(p->data()) +
136 "' not convertible to the desired type.");
137 }
138 }
139 else
140 {
141 error("Key <" + param + "> has not been found");
142 }
143}
144
145template <typename T>
147{
148 if (have_read_data_)
149 {
150 error("The data of this subtree has already been read.");
151 }
152
153 have_read_data_ = true;
154
155 if (auto v = tree_->get_value_optional<T>())
156 {
157 return *v;
158 }
159 error("Value `" + shortString(tree_->data()) +
160 "' is not convertible to the desired type.");
161}
162
163template <typename T>
164T ConfigTree::getConfigAttribute(std::string const& attr) const
165{
166 if (auto a = getConfigAttributeOptional<T>(attr))
167 {
168 return *a;
169 }
170
171 error("Did not find XML attribute with name '" + attr + "'.");
172}
173
174template <typename T>
175T ConfigTree::getConfigAttribute(std::string const& attr,
176 T const& default_value) const
177{
178 if (auto a = getConfigAttributeOptional<T>(attr))
179 {
180 return *a;
181 }
182
183 return default_value;
184}
185
186template <typename T>
188 std::string const& attr) const
189{
190 checkUniqueAttr(attr);
191 auto& ct = markVisited<T>(attr, Attr::ATTR, true);
192
193 if (auto attrs = tree_->get_child_optional("<xmlattr>"))
194 {
195 if (auto a = attrs->get_child_optional(attr))
196 {
197 ++ct.count; // count only if attribute has been found
198 if (auto v = a->get_value_optional<T>())
199 {
200 return std::make_optional(*v);
201 }
202 error("Value for XML attribute '" + attr + "' `" +
203 shortString(a->data()) +
204 "' not convertible to the desired type.");
205 }
206 }
207
208 return std::nullopt;
209}
210
211template <typename T>
213 Attr const is_attr,
214 bool const peek_only) const
215{
216 auto const type = std::type_index(typeid(T));
217
218 auto p = visited_params_.emplace(std::make_pair(is_attr, key),
219 CountType{peek_only ? 0 : 1, type});
220
221 if (!p.second)
222 { // no insertion happened
223 auto& v = p.first->second;
224 if (v.type == type)
225 {
226 if (!peek_only)
227 {
228 ++v.count;
229 }
230 }
231 else
232 {
233 error("There already was an attempt to obtain key <" + key +
234 "> with type '" + v.type.name() + "' (now: '" + type.name() +
235 "').");
236 }
237 }
238
239 return p.first->second;
240}
241
242} // namespace BaseLib
Definition of string helper functions.
T peekConfigParameter(std::string const &param) const
void checkUniqueAttr(std::string const &attr) const
Asserts that the attribute attr has not been read yet.
std::map< KeyType, CountType > visited_params_
Definition ConfigTree.h:666
static std::string shortString(std::string const &s)
returns a short string at suitable for error/warning messages
void error(std::string const &message) const
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
std::optional< T > getConfigParameterOptional(std::string const &param) const
void checkUnique(std::string const &key) const
Asserts that the key has not been read yet.
T getConfigParameter(std::string const &param) const
T getConfigAttribute(std::string const &attr) const
Attr
Used to indicate if dealing with XML tags or XML attributes.
Definition ConfigTree.h:572
CountType & markVisited(std::string const &key, Attr const is_attr, bool peek_only) const
std::optional< T > getConfigParameterOptionalImpl(std::string const &param, T *) const
Default implementation of reading a value of type T.
Range< ValueIterator< T > > getConfigParameterList(std::string const &param) const
std::optional< T > getConfigAttributeOptional(std::string const &attr) const
PTree const * tree_
The wrapped tree.
Definition ConfigTree.h:648
void checkKeyname(std::string const &key) const
Checks if key complies with the rules [a-z0-9_].
Wraps a pair of iterators for use as a range in range-based for-loops.
Range(Iterator begin, Iterator end)
bool empty() const
Iterator end() const
Iterator begin() const
std::size_t size() const
std::optional< std::vector< T > > tryParseVector(std::string const &raw, std::size_t *bad_token_idx)
Definition StringTools.h:95