OGS
ConfigTree-impl.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4// IWYU pragma: private, include "ConfigTree.h"
5
6#include <sstream>
7#include <utility>
8
9#include "ConfigTree.h"
10#include "StringTools.h"
11
12namespace BaseLib
13{
15template <typename Iterator>
16class Range
17{
18public:
19 explicit Range(Iterator begin, Iterator end)
20 : begin_(std::move(begin)), end_(std::move(end))
21 {
22 }
23
24 Iterator begin() const { return begin_; }
25 Iterator end() const { return end_; }
26 std::size_t size() const { return std::distance(begin_, end_); }
27 bool empty() const { return size() == 0; }
28
29private:
30 Iterator begin_;
31 Iterator end_;
32};
33
34template <typename T>
35T ConfigTree::getConfigParameter(std::string const& param) const
36{
37 if (auto p = getConfigParameterOptional<T>(param))
38 {
39 return *p;
40 }
41
42 error("Key <" + param + "> has not been found");
43}
44
45template <typename T>
46T ConfigTree::getConfigParameter(std::string const& param,
47 T const& default_value) const
48{
49 if (auto p = getConfigParameterOptional<T>(param))
50 {
51 return *p;
52 }
53
54 return default_value;
55}
56
57template <typename T>
59 std::string const& param) const
60{
61 checkUnique(param);
62
63 return getConfigParameterOptionalImpl(param, static_cast<T*>(nullptr));
64}
65
66template <typename T>
68 std::string const& param, T* /*unused*/) const
69{
70 if (auto p = getConfigSubtreeOptional(param))
71 {
72 return p->getValue<T>();
73 }
74
75 return std::nullopt;
76}
77
78template <typename T>
79std::optional<std::vector<T>> ConfigTree::getConfigParameterOptionalImpl(
80 std::string const& param, std::vector<T>* /*unused*/) const
81{
82 if (auto p = getConfigSubtreeOptional(param))
83 {
84 std::string const raw = p->getValue<std::string>();
85
86 std::size_t bad_idx = 0;
87 if (auto parsed = BaseLib::tryParseVector<T>(raw, &bad_idx))
88 {
89 return parsed; // OK
90 }
91
92 // preserve original error wording & token index
93 error("Value for key <" + param + "> `" + shortString(raw) +
94 "' not convertible to a vector of the desired type."
95 " Could not convert token no. " +
96 std::to_string(bad_idx) + ".");
97 return std::nullopt; // not reached
98 }
99
100 return std::nullopt;
101}
102
103template <typename T>
105 std::string const& param) const
106{
107 checkUnique(param);
108 markVisited<T>(param, Attr::TAG, true);
109
110 auto p = tree_->equal_range(param);
111 return Range<ValueIterator<T>>(ValueIterator<T>(p.first, param, *this),
112 ValueIterator<T>(p.second, param, *this));
113}
114
115template <typename T>
116T ConfigTree::peekConfigParameter(std::string const& param) const
117{
118 checkKeyname(param);
119
120 if (auto p = tree_->get_child_optional(param))
121 {
122 try
123 {
124 return p->get_value<T>();
125 }
126 catch (boost::property_tree::ptree_bad_data const&)
127 {
128 error("Value for key <" + param + "> `" + shortString(p->data()) +
129 "' not convertible to the desired type.");
130 }
131 }
132 else
133 {
134 error("Key <" + param + "> has not been found");
135 }
136}
137
138template <typename T>
140{
141 if (have_read_data_)
142 {
143 error("The data of this subtree has already been read.");
144 }
145
146 have_read_data_ = true;
147
148 if (auto v = tree_->get_value_optional<T>())
149 {
150 return *v;
151 }
152 error("Value `" + shortString(tree_->data()) +
153 "' is not convertible to the desired type.");
154}
155
156template <typename T>
157T ConfigTree::getConfigAttribute(std::string const& attr) const
158{
159 if (auto a = getConfigAttributeOptional<T>(attr))
160 {
161 return *a;
162 }
163
164 error("Did not find XML attribute with name '" + attr + "'.");
165}
166
167template <typename T>
168T ConfigTree::getConfigAttribute(std::string const& attr,
169 T const& default_value) const
170{
171 if (auto a = getConfigAttributeOptional<T>(attr))
172 {
173 return *a;
174 }
175
176 return default_value;
177}
178
179template <typename T>
181 std::string const& attr) const
182{
183 checkUniqueAttr(attr);
184 auto& ct = markVisited<T>(attr, Attr::ATTR, true);
185
186 if (auto attrs = tree_->get_child_optional("<xmlattr>"))
187 {
188 if (auto a = attrs->get_child_optional(attr))
189 {
190 ++ct.count; // count only if attribute has been found
191 if (auto v = a->get_value_optional<T>())
192 {
193 return std::make_optional(*v);
194 }
195 error("Value for XML attribute '" + attr + "' `" +
196 shortString(a->data()) +
197 "' not convertible to the desired type.");
198 }
199 }
200
201 return std::nullopt;
202}
203
204template <typename T>
206 Attr const is_attr,
207 bool const peek_only) const
208{
209 auto const type = std::type_index(typeid(T));
210
211 auto p = visited_params_.emplace(std::make_pair(is_attr, key),
212 CountType{peek_only ? 0 : 1, type});
213
214 if (!p.second)
215 { // no insertion happened
216 auto& v = p.first->second;
217 if (v.type == type)
218 {
219 if (!peek_only)
220 {
221 ++v.count;
222 }
223 }
224 else
225 {
226 error("There already was an attempt to obtain key <" + key +
227 "> with type '" + v.type.name() + "' (now: '" + type.name() +
228 "').");
229 }
230 }
231
232 return p.first->second;
233}
234
235} // namespace BaseLib
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:662
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:568
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:644
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:85