OGS 6.2.0-97-g4a610c866
ConfigTree-impl.h
Go to the documentation of this file.
1 
10 #include "ConfigTree.h"
11 
12 #include <sstream>
13 #include <utility>
14 
15 namespace BaseLib
16 {
17 
19 template<typename Iterator>
20 class Range
21 {
22 public:
23  explicit Range(Iterator begin, Iterator end)
24  : _begin(std::move(begin)), _end(std::move(end))
25  {}
26 
27  Iterator begin() const { return _begin; }
28  Iterator end() const { return _end; }
29  std::size_t size() const { return std::distance(_begin, _end); }
30  bool empty() const { return size() == 0; }
31 
32 private:
33  Iterator _begin;
34  Iterator _end;
35 };
36 
37 template<typename T>
38 T
40 getConfigParameter(std::string const& param) const
41 {
42  if (auto p = getConfigParameterOptional<T>(param))
43  {
44  return *p;
45  }
46 
47  error("Key <" + param + "> has not been found");
48 }
49 
50 template<typename T>
51 T
53 getConfigParameter(std::string const& param, T const& default_value) const
54 {
55  if (auto p = getConfigParameterOptional<T>(param))
56  {
57  return *p;
58  }
59 
60  return default_value;
61 }
62 
63 template <typename T>
65  std::string const& param) const
66 {
67  checkUnique(param);
68 
69  return getConfigParameterOptionalImpl(param, static_cast<T*>(nullptr));
70 }
71 
72 template <typename T>
74  std::string const& param, T*) const
75 {
76  if (auto p = getConfigSubtreeOptional(param))
77  {
78  return p->getValue<T>();
79  }
80 
81  return boost::none;
82 }
83 
84 template <typename T>
85 boost::optional<std::vector<T>> ConfigTree::getConfigParameterOptionalImpl(
86  std::string const& param, std::vector<T>*) const
87 {
88  if (auto p = getConfigSubtreeOptional(param))
89  {
90  std::istringstream sstr{p->getValue<std::string>()};
91  std::vector<T> result;
92  T value;
93  while (sstr >> value)
94  {
95  result.push_back(value);
96  }
97  if (!sstr.eof()) // The stream is not read until the end, must be an
98  // error. result contains number of read values.
99  {
100  error("Value for key <" + param + "> `" +
101  shortString(sstr.str()) +
102  "' not convertible to a vector of the desired type."
103  " Could not convert token no. " +
104  std::to_string(result.size() + 1) + ".");
105  return boost::none;
106  }
107 
108  return boost::make_optional(result);
109  }
110 
111  return boost::none;
112 }
113 
114 template<typename T>
117 getConfigParameterList(std::string const& param) const
118 {
119  checkUnique(param);
120  markVisited<T>(param, Attr::TAG, true);
121 
122  auto p = _tree->equal_range(param);
123  return Range<ValueIterator<T> >(
124  ValueIterator<T>(p.first, param, *this),
125  ValueIterator<T>(p.second, param, *this));
126 }
127 
128 template<typename T>
129 T
131 peekConfigParameter(std::string const& param) const
132 {
133  checkKeyname(param);
134 
135  if (auto p = _tree->get_child_optional(param))
136  {
137  try
138  {
139  return p->get_value<T>();
140  }
141  catch (boost::property_tree::ptree_bad_data const&)
142  {
143  error("Value for key <" + param + "> `" + shortString(p->data()) +
144  "' not convertible to the desired type.");
145  }
146  }
147  else
148  {
149  error("Key <" + param + "> has not been found");
150  }
151 }
152 
153 template<typename T>
154 void
156 checkConfigParameter(std::string const& param, T const& value) const
157 {
158  if (getConfigParameter<T>(param) != value) {
159  error("The value of key <" + param + "> is not the expected one.");
160  }
161 }
162 
163 template<typename Ch>
164 void
166 checkConfigParameter(std::string const& param, Ch const* value) const
167 {
168  if (getConfigParameter<std::string>(param) != value) {
169  error("The value of key <" + param + "> is not the expected one.");
170  }
171 }
172 
173 template<typename T>
174 T
176 getValue() const
177 {
178  if (_have_read_data) {
179  error("The data of this subtree has already been read.");
180  }
181 
182  _have_read_data = true;
183 
184  if (auto v = _tree->get_value_optional<T>()) {
185  return *v;
186  }
187  error("Value `" + shortString(_tree->data()) +
188  "' is not convertible to the desired type.");
189 }
190 
191 template<typename T>
192 T
194 getConfigAttribute(std::string const& attr) const
195 {
196  if (auto a = getConfigAttributeOptional<T>(attr))
197  {
198  return *a;
199  }
200 
201  error("Did not find XML attribute with name '" + attr + "'.");
202 }
203 
204 template <typename T>
205 T ConfigTree::getConfigAttribute(std::string const& attr,
206  T const& default_value) const
207 {
208  if (auto a = getConfigAttributeOptional<T>(attr))
209  {
210  return *a;
211  }
212 
213  return default_value;
214 }
215 
216 template<typename T>
217 boost::optional<T>
219 getConfigAttributeOptional(std::string const& attr) const
220 {
221  checkUniqueAttr(attr);
222  auto& ct = markVisited<T>(attr, Attr::ATTR, true);
223 
224  if (auto attrs = _tree->get_child_optional("<xmlattr>")) {
225  if (auto a = attrs->get_child_optional(attr)) {
226  ++ct.count; // count only if attribute has been found
227  if (auto v = a->get_value_optional<T>()) {
228  return v;
229  }
230  error("Value for XML attribute '" + attr + "' `" +
231  shortString(a->data()) +
232  "' not convertible to the desired type.");
233  }
234  }
235 
236  return boost::none;
237 }
238 
239 template<typename T>
242 markVisited(std::string const& key, Attr const is_attr,
243  bool const peek_only) const
244 {
245  auto const type = std::type_index(typeid(T));
246 
247  auto p = _visited_params.emplace(std::make_pair(is_attr, key),
248  CountType{peek_only ? 0 : 1, type});
249 
250  if (!p.second) { // no insertion happened
251  auto& v = p.first->second;
252  if (v.type == type) {
253  if (!peek_only)
254  {
255  ++v.count;
256  }
257  } else {
258  error("There already was an attempt to obtain key <" + key +
259  "> with type '" + v.type.name() + "' (now: '" + type.name() +
260  "').");
261  }
262  }
263 
264  return p.first->second;
265 }
266 
267 } // namespace BaseLib
CountType & markVisited(std::string const &key, Attr const is_attr, bool peek_only) const
Attr
Used to indicate if dealing with XML tags or XML attributes.
Definition: ConfigTree.h:535
boost::optional< T > getConfigParameterOptionalImpl(std::string const &param, T *) const
Default implementation of reading a value of type T.
std::size_t size() const
T getConfigParameter(std::string const &param) const
Range(Iterator begin, Iterator end)
void checkConfigParameter(std::string const &param, T const &value) const
T peekConfigParameter(std::string const &param) const
Wraps a pair of iterators for use as a range in range-based for-loops.
Iterator begin() const
Build information.
T getConfigAttribute(std::string const &attr) const
bool empty() const
Iterator end() const
boost::optional< T > getConfigAttributeOptional(std::string const &attr) const
boost::optional< T > getConfigParameterOptional(std::string const &param) const
Range< ValueIterator< T > > getConfigParameterList(std::string const &param) const