OGS
ConfigTree.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#pragma once
5
6#include <boost/property_tree/ptree.hpp>
7#include <filesystem>
8#include <functional>
9#include <iosfwd>
10#include <iterator>
11#include <map>
12#include <memory>
13#include <optional>
14#include <string>
15#include <string_view>
16#include <typeindex>
17#include <utility>
18#include <vector>
19
20extern template class boost::property_tree::basic_ptree<
21 std::string, std::string, std::less<>>;
22
23namespace BaseLib
24{
25class ConfigTree;
26
33void checkAndInvalidate(ConfigTree* const conf);
34
36void checkAndInvalidate(std::unique_ptr<ConfigTree> const& conf);
37
40
41template <typename Iterator>
42class Range;
43
100class ConfigTree final
101{
102public:
109 {
110 public:
111 using iterator_category = std::input_iterator_tag;
113 using difference_type = std::ptrdiff_t;
116
117 using Iterator = boost::property_tree::ptree::const_assoc_iterator;
118
119 explicit SubtreeIterator(Iterator const& it, std::string const& root,
120 ConfigTree const& parent)
121 : it_(it), tagname_(root), parent_(parent)
122 {
123 }
124
126 {
127 ++it_;
128 has_incremented_ = true;
129 return *this;
130 }
131
133 {
134 // if this iterator has been incremented since the last dereference,
135 // tell the parent_ instance that a subtree now has been parsed.
137 {
138 has_incremented_ = false;
139 parent_.markVisited(tagname_, Attr::TAG, false);
140 }
141 return ConfigTree(it_->second, parent_, tagname_);
142 }
143
144 bool operator==(SubtreeIterator const& other) const
145 {
146 return it_ == other.it_;
147 }
148
149 bool operator!=(SubtreeIterator const& other) const
150 {
151 return it_ != other.it_;
152 }
153
154 private:
155 bool has_incremented_ = true;
157
158 protected:
159 std::string const tagname_;
161 };
162
170 {
171 public:
174
176 {
177 auto st = SubtreeIterator::operator*();
178 if (st.hasChildren())
179 {
180 parent_.error("The requested parameter <" + tagname_ +
181 "> has child elements.");
182 }
183 return st;
184 }
185 };
186
193 template <typename ValueType>
195 {
196 public:
197 using iterator_category = std::input_iterator_tag;
199 using difference_type = std::ptrdiff_t;
202
203 using Iterator = boost::property_tree::ptree::const_assoc_iterator;
204
205 explicit ValueIterator(Iterator const& it, std::string const& root,
206 ConfigTree const& parent)
207 : it_(it), tagname_(root), parent_(parent)
208 {
209 }
210
212 {
213 ++it_;
214 has_incremented_ = true;
215 return *this;
216 }
217
218 ValueType operator*()
219 {
220 // if this iterator has been incremented since the last dereference,
221 // tell the parent_ instance that a setting now has been parsed.
223 {
224 has_incremented_ = false;
225 parent_.markVisited<ValueType>(tagname_, Attr::TAG, false);
226 }
227 return ConfigTree(it_->second, parent_, tagname_)
228 .getValue<ValueType>();
229 }
230
231 bool operator==(ValueIterator<ValueType> const& other) const
232 {
233 return it_ == other.it_;
234 }
235
236 bool operator!=(ValueIterator<ValueType> const& other) const
237 {
238 return it_ != other.it_;
239 }
240
241 private:
242 bool has_incremented_ = true;
244 std::string const tagname_;
246 };
247
249 using PTree = boost::property_tree::ptree;
250
258 using Callback = std::function<void(const std::string& filename,
259 const std::string& path,
260 const std::string& message)>;
261
277 explicit ConfigTree(PTree&& top_level_tree,
278 std::string filename,
279 Callback error_cb,
280 Callback warning_cb);
281
283 ConfigTree(ConfigTree const&) = delete;
284
287 ConfigTree(ConfigTree&& other);
288
290 ConfigTree& operator=(ConfigTree const&) = delete;
291
295
297 std::filesystem::path const& projectFilePath() const { return filepath_; }
298
299 std::filesystem::path projectDirectory() const;
300
305
312 template <typename T>
313 T getConfigParameter(std::string const& param) const;
314
324 template <typename T>
325 T getConfigParameter(std::string const& param,
326 T const& default_value) const;
327
337 template <typename T>
338 std::optional<T> getConfigParameterOptional(std::string const& param) const;
339
347 template <typename T>
349 std::string const& param) const;
350
352
365
372 ConfigTree getConfigParameter(std::string const& root) const;
373
380 std::optional<ConfigTree> getConfigParameterOptional(
381 std::string const& param) const;
382
391 std::string const& param) const;
392
399 template <typename T>
400 T getValue() const;
401
408 template <typename T>
409 T getConfigAttribute(std::string const& attr) const;
410
422 template <typename T>
423 T getConfigAttribute(std::string const& attr, T const& default_value) const;
424
432 template <typename T>
433 std::optional<T> getConfigAttributeOptional(std::string const& attr) const;
434
436
444
457 template <typename T>
458 T peekConfigParameter(std::string const& param) const;
459
465 void checkConfigParameter(std::string const& param,
466 std::string_view const value) const;
467
469
473
480 ConfigTree getConfigSubtree(std::string const& root) const;
481
486 std::optional<ConfigTree> getConfigSubtreeOptional(
487 std::string const& root) const;
488
496 Range<SubtreeIterator> getConfigSubtreeList(std::string const& root) const;
497
499
503
510 void ignoreConfigParameter(std::string const& param) const;
511
519 void ignoreConfigParameterAll(std::string const& param) const;
520
527 void ignoreConfigAttribute(std::string const& attr) const;
528
530
534 ~ConfigTree();
535
538 static void onerror(std::string const& filename, std::string const& path,
539 std::string const& message);
540
543 static void onwarning(std::string const& filename, std::string const& path,
544 std::string const& message);
545
547 static void assertNoSwallowedErrors();
548
549private:
551 template <typename T>
552 std::optional<T> getConfigParameterOptionalImpl(std::string const& param,
553 T* /*unused*/) const;
554
556 template <typename T>
557 std::optional<std::vector<T>> getConfigParameterOptionalImpl(
558 std::string const& param, std::vector<T>* /*unused*/) const;
559
561 {
562 int count;
563 std::type_index type;
564 };
565
567 enum class Attr : bool
568 {
569 TAG = false,
570 ATTR = true
571 };
572
574 explicit ConfigTree(PTree const& tree, ConfigTree const& parent,
575 std::string const& root);
576
581 [[noreturn]] void error(std::string const& message) const;
582
585 void warning(std::string const& message) const;
586
588 void checkKeyname(std::string const& key) const;
589
591 std::string joinPaths(std::string const& p1, std::string const& p2) const;
592
594 void checkUnique(std::string const& key) const;
595
597 void checkUniqueAttr(std::string const& attr) const;
598
606 template <typename T>
607 CountType& markVisited(std::string const& key, Attr const is_attr,
608 bool peek_only) const;
609
617 CountType& markVisited(std::string const& key, Attr const is_attr,
618 bool const peek_only) const;
619
622 void markVisitedDecrement(Attr const is_attr, std::string const& key) const;
623
625 bool hasChildren() const;
626
633 void checkAndInvalidate();
634
636 static std::string shortString(std::string const& s);
637
641 std::shared_ptr<PTree const> top_level_tree_;
642
644 PTree const* tree_;
645
647 std::string path_;
648
650 std::filesystem::path filepath_;
651
653 using KeyType = std::pair<Attr, std::string>;
654
662 mutable std::map<KeyType, CountType> visited_params_;
663
666 mutable bool have_read_data_ = false;
667
670
672 static const char pathseparator;
673
675 static const std::string key_chars_start;
676
678 static const std::string key_chars;
679
680 friend void checkAndInvalidate(ConfigTree* const conf);
681 friend void checkAndInvalidate(ConfigTree& conf);
682 friend void checkAndInvalidate(std::unique_ptr<ConfigTree> const& conf);
683};
684
685} // namespace BaseLib
686
687#include "ConfigTree-impl.h" // IWYU pragma: keep
SubtreeIterator(Iterator const &it, std::string const &root, ConfigTree const &parent)
Inherit the constructor.
Definition ConfigTree.h:119
bool operator!=(SubtreeIterator const &other) const
Definition ConfigTree.h:149
std::input_iterator_tag iterator_category
Definition ConfigTree.h:111
boost::property_tree::ptree::const_assoc_iterator Iterator
Definition ConfigTree.h:117
SubtreeIterator(Iterator const &it, std::string const &root, ConfigTree const &parent)
Definition ConfigTree.h:119
bool operator==(SubtreeIterator const &other) const
Definition ConfigTree.h:144
boost::property_tree::ptree::const_assoc_iterator Iterator
Definition ConfigTree.h:203
std::input_iterator_tag iterator_category
Definition ConfigTree.h:197
ValueIterator< ValueType > & operator++()
Definition ConfigTree.h:211
bool operator==(ValueIterator< ValueType > const &other) const
Definition ConfigTree.h:231
ValueIterator(Iterator const &it, std::string const &root, ConfigTree const &parent)
Definition ConfigTree.h:205
bool operator!=(ValueIterator< ValueType > const &other) const
Definition ConfigTree.h:236
T peekConfigParameter(std::string const &param) const
void markVisitedDecrement(Attr const is_attr, std::string const &key) const
void ignoreConfigParameter(std::string const &param) const
static void onerror(std::string const &filename, std::string const &path, std::string const &message)
static void assertNoSwallowedErrors()
Asserts that there have not been any errors reported in the destructor.
Callback onwarning_
Custom warning callback.
Definition ConfigTree.h:669
static const char pathseparator
Character separating two path components.
Definition ConfigTree.h:672
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
std::shared_ptr< PTree const > top_level_tree_
Definition ConfigTree.h:641
void error(std::string const &message) const
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
std::filesystem::path projectDirectory() const
std::optional< T > getConfigParameterOptional(std::string const &param) const
void ignoreConfigAttribute(std::string const &attr) const
std::filesystem::path filepath_
The path of the file from which this tree has been read.
Definition ConfigTree.h:650
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
Range< SubtreeIterator > getConfigSubtreeList(std::string const &root) const
static const std::string key_chars_start
Set of allowed characters as the first letter of a key name.
Definition ConfigTree.h:675
ConfigTree getConfigSubtree(std::string const &root) const
std::pair< Attr, std::string > KeyType
A pair (is attribute, tag/attribute name).
Definition ConfigTree.h:653
std::string path_
A path printed in error/warning messages.
Definition ConfigTree.h:647
CountType & markVisited(std::string const &key, Attr const is_attr, bool peek_only) const
void ignoreConfigParameterAll(std::string const &param) const
Callback onerror_
Custom error callback.
Definition ConfigTree.h:668
std::string joinPaths(std::string const &p1, std::string const &p2) const
Used to generate the path of a subtree.
std::filesystem::path const & projectFilePath() const
Used to get the project file name.
Definition ConfigTree.h:297
std::optional< T > getConfigParameterOptionalImpl(std::string const &param, T *) const
Default implementation of reading a value of type T.
ConfigTree(ConfigTree const &)=delete
copying is not compatible with the semantics of this class
Range< ValueIterator< T > > getConfigParameterList(std::string const &param) const
std::optional< T > getConfigAttributeOptional(std::string const &attr) const
void warning(std::string const &message) const
bool hasChildren() const
Checks if this tree has any children.
PTree const * tree_
The wrapped tree.
Definition ConfigTree.h:644
ConfigTree(PTree &&top_level_tree, std::string filename, Callback error_cb, Callback warning_cb)
void checkConfigParameter(std::string const &param, std::string_view const value) const
boost::property_tree::ptree PTree
The tree being wrapped by this class.
Definition ConfigTree.h:249
ConfigTree & operator=(ConfigTree const &)=delete
copying is not compatible with the semantics of this class
void checkKeyname(std::string const &key) const
Checks if key complies with the rules [a-z0-9_].
std::function< void(const std::string &filename, const std::string &path, const std::string &message)> Callback
Definition ConfigTree.h:258
static void onwarning(std::string const &filename, std::string const &path, std::string const &message)
static const std::string key_chars
Set of allowed characters in a key name.
Definition ConfigTree.h:678
Wraps a pair of iterators for use as a range in range-based for-loops.
void checkAndInvalidate(ConfigTree &conf)
This is an overloaded member function, provided for convenience. It differs from the above function o...