OGS 6.1.0-1721-g6382411ad
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  return *p;
44 
45  error("Key <" + param + "> has not been found");
46 }
47 
48 template<typename T>
49 T
51 getConfigParameter(std::string const& param, T const& default_value) const
52 {
53  if (auto p = getConfigParameterOptional<T>(param))
54  return *p;
55 
56  return default_value;
57 }
58 
59 template <typename T>
61  std::string const& param) const
62 {
63  checkUnique(param);
64 
65  return getConfigParameterOptionalImpl(param, static_cast<T*>(nullptr));
66 }
67 
68 template <typename T>
70  std::string const& param, T*) const
71 {
72  if (auto p = getConfigSubtreeOptional(param)) return p->getValue<T>();
73 
74  return boost::none;
75 }
76 
77 template <typename T>
78 boost::optional<std::vector<T>> ConfigTree::getConfigParameterOptionalImpl(
79  std::string const& param, std::vector<T>*) const
80 {
81  if (auto p = getConfigSubtreeOptional(param))
82  {
83  std::istringstream sstr{p->getValue<std::string>()};
84  std::vector<T> result;
85  T value;
86  while (sstr >> value)
87  result.push_back(value);
88  if (!sstr.eof()) // The stream is not read until the end, must be an
89  // error. result contains number of read values.
90  {
91  error("Value for key <" + param + "> `" +
92  shortString(sstr.str()) +
93  "' not convertible to a vector of the desired type."
94  " Could not convert token no. " +
95  std::to_string(result.size() + 1) + ".");
96  return boost::none;
97  }
98 
99  return boost::make_optional(result);
100  }
101 
102  return boost::none;
103 }
104 
105 template<typename T>
108 getConfigParameterList(std::string const& param) const
109 {
110  checkUnique(param);
111  markVisited<T>(param, Attr::TAG, true);
112 
113  auto p = _tree->equal_range(param);
114  return Range<ValueIterator<T> >(
115  ValueIterator<T>(p.first, param, *this),
116  ValueIterator<T>(p.second, param, *this));
117 }
118 
119 template<typename T>
120 T
122 peekConfigParameter(std::string const& param) const
123 {
124  checkKeyname(param);
125 
126  if (auto p = _tree->get_child_optional(param))
127  {
128  try
129  {
130  return p->get_value<T>();
131  }
132  catch (boost::property_tree::ptree_bad_data const&)
133  {
134  error("Value for key <" + param + "> `" + shortString(p->data()) +
135  "' not convertible to the desired type.");
136  }
137  }
138  else
139  {
140  error("Key <" + param + "> has not been found");
141  }
142 }
143 
144 template<typename T>
145 void
147 checkConfigParameter(std::string const& param, T const& value) const
148 {
149  if (getConfigParameter<T>(param) != value) {
150  error("The value of key <" + param + "> is not the expected one.");
151  }
152 }
153 
154 template<typename Ch>
155 void
157 checkConfigParameter(std::string const& param, Ch const* value) const
158 {
159  if (getConfigParameter<std::string>(param) != value) {
160  error("The value of key <" + param + "> is not the expected one.");
161  }
162 }
163 
164 template<typename T>
165 T
167 getValue() const
168 {
169  if (_have_read_data) {
170  error("The data of this subtree has already been read.");
171  }
172 
173  _have_read_data = true;
174 
175  if (auto v = _tree->get_value_optional<T>()) {
176  return *v;
177  }
178  error("Value `" + shortString(_tree->data()) +
179  "' is not convertible to the desired type.");
180 }
181 
182 template<typename T>
183 T
185 getConfigAttribute(std::string const& attr) const
186 {
187  if (auto a = getConfigAttributeOptional<T>(attr))
188  return *a;
189 
190  error("Did not find XML attribute with name '" + attr + "'.");
191 }
192 
193 template <typename T>
194 T ConfigTree::getConfigAttribute(std::string const& attr,
195  T const& default_value) const
196 {
197  if (auto a = getConfigAttributeOptional<T>(attr))
198  return *a;
199 
200  return default_value;
201 }
202 
203 template<typename T>
204 boost::optional<T>
206 getConfigAttributeOptional(std::string const& attr) const
207 {
208  checkUniqueAttr(attr);
209  auto& ct = markVisited<T>(attr, Attr::ATTR, true);
210 
211  if (auto attrs = _tree->get_child_optional("<xmlattr>")) {
212  if (auto a = attrs->get_child_optional(attr)) {
213  ++ct.count; // count only if attribute has been found
214  if (auto v = a->get_value_optional<T>()) {
215  return v;
216  }
217  error("Value for XML attribute '" + attr + "' `" +
218  shortString(a->data()) +
219  "' not convertible to the desired type.");
220  }
221  }
222 
223  return boost::none;
224 }
225 
226 template<typename T>
229 markVisited(std::string const& key, Attr const is_attr,
230  bool const peek_only) const
231 {
232  auto const type = std::type_index(typeid(T));
233 
234  auto p = _visited_params.emplace(std::make_pair(is_attr, key),
235  CountType{peek_only ? 0 : 1, type});
236 
237  if (!p.second) { // no insertion happened
238  auto& v = p.first->second;
239  if (v.type == type) {
240  if (!peek_only) ++v.count;
241  } else {
242  error("There already was an attempt to obtain key <" + key +
243  "> with type '" + v.type.name() + "' (now: '" + type.name() +
244  "').");
245  }
246  }
247 
248  return p.first->second;
249 }
250 
251 }
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:534
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