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