14#include <forward_list>
22template class boost::property_tree::basic_ptree<std::string, std::string,
39 : top_level_tree_(std::make_shared<
PTree>(std::move(top_level_tree))),
40 tree_(top_level_tree_.get()),
41 filename_(std::move(filename)),
42 onerror_(std::move(error_cb)),
43 onwarning_(std::move(warning_cb))
47 OGS_FATAL(
"ConfigTree: No valid error handler provided.");
51 OGS_FATAL(
"ConfigTree: No valid warning handler provided.");
56 std::string
const& root)
57 : top_level_tree_(parent.top_level_tree_),
60 filename_(parent.filename_),
61 onerror_(parent.onerror_),
62 onwarning_(parent.onwarning_)
68 : top_level_tree_(std::move(other.top_level_tree_)),
70 path_(std::move(other.path_)),
71 filename_(std::move(other.filename_)),
72 visited_params_(std::move(other.visited_params_)),
73 have_read_data_(other.have_read_data_),
74 onerror_(std::move(other.onerror_)),
75 onwarning_(std::move(other.onwarning_))
77 other.tree_ =
nullptr;
82 if (std::uncaught_exceptions() > 0)
94 catch (std::exception& e)
96 ERR(
"{:s}", e.what());
107 other.tree_ =
nullptr;
108 path_ = std::move(other.path_);
112 onerror_ = std::move(other.onerror_);
121 if (ct.hasChildren())
123 error(
"Requested parameter <" + param +
"> actually is a subtree.");
129 std::string
const& param)
const
132 if (ct && ct->hasChildren())
134 error(
"Requested parameter <" + param +
"> actually is a subtree.");
140 const std::string& param)
const
145 auto p =
tree_->equal_range(param);
152 std::string_view
const value)
const
155 if (parameter_value != value)
157 error(
"For the tag <" + param +
"> expected to read value '" +
158 value.data() +
"', but got '" + parameter_value +
"'.");
166 return std::move(*t);
168 error(
"Key <" + root +
"> has not been found.");
172 std::string
const& root)
const
176 if (
auto subtree =
tree_->get_child_optional(root))
186 std::string
const& root)
const
191 auto p =
tree_->equal_range(root);
201 bool peek_only =
tree_->find(param) ==
tree_->not_found();
211 bool peek_only = !
tree_->get_child_optional(
"<xmlattr>." + attr);
221 auto p =
tree_->equal_range(param);
222 for (
auto it = p.first; it != p.second; ++it)
232 "ConfigTree: The error handler does not break out of the normal "
242 const std::string& message)
244 OGS_FATAL(
"ConfigTree: In file `{:s}' at path <{:s}>: {:s}", filename, path,
249 const std::string& message)
251 WARN(
"ConfigTree: In file `{:s}' at path <{:s}>: {:s}", filename, path,
262 ERR(
"ConfigTree: There have been errors when parsing the configuration "
270 OGS_FATAL(
"There have been errors when parsing the configuration file(s).");
275 const std::size_t maxlen = 100;
277 if (s.size() < maxlen)
282 return s.substr(0, maxlen - 3) +
"...";
289 error(
"Search for empty key.");
293 error(
"Key <" + key +
"> starts with an illegal character.");
295 else if (key.find_first_not_of(
key_chars, 1) != std::string::npos)
297 error(
"Key <" + key +
"> contains illegal characters.");
299 else if (key.find(
"__") != std::string::npos)
305 error(
"Key <" + key +
"> contains double underscore.");
310 const std::string& p2)
const
314 error(
"Second path to be joined is empty.");
331 error(
"Key <" + key +
"> has already been processed.");
339 if (attr.find(
':') != std::string::npos)
341 auto pos =
decltype(std::string::npos){0};
349 pos = attr2.find_first_of(
":ABCDEFGHIJKLMNOPQRSTUVWXYZ", pos);
350 if (pos != std::string::npos)
354 }
while (pos != std::string::npos);
365 error(
"Attribute '" + attr +
"' has already been processed.");
371 bool const peek_only)
const
377 std::string
const& key)
const
379 auto const type = std::type_index(
typeid(
nullptr));
386 auto& v = p.first->second;
393 auto const& tree = *
tree_;
394 if (tree.begin() == tree.end())
398 if (tree.front().first ==
"<xmlattr>" && (++tree.begin()) == tree.end())
419 "' of this tag has not been read.");
423 for (
auto const& p : *
tree_)
425 if (p.first !=
"<xmlattr>")
432 if (
auto attrs =
tree_->get_child_optional(
"<xmlattr>"))
434 for (
auto const& p : *attrs)
442 auto const& tag = p.first.second;
443 auto const& count = p.second.count;
445 switch (p.first.first)
450 warning(
"XML attribute '" + tag +
"' has been read " +
451 std::to_string(count) +
452 " time(s) more than it was present in the "
453 "configuration tree.");
457 warning(
"XML attribute '" + tag +
"' has been read " +
458 std::to_string(-count) +
459 " time(s) less than it was present in the "
460 "configuration tree.");
466 warning(
"Key <" + tag +
"> has been read " +
467 std::to_string(count) +
468 " time(s) more than it was present in the "
469 "configuration tree.");
473 warning(
"Key <" + tag +
"> has been read " +
474 std::to_string(-count) +
475 " time(s) less than it was present in the "
476 "configuration tree.");
503 conf->checkAndInvalidate();
static std::forward_list< std::string > configtree_destructor_error_messages
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
void markVisitedDecrement(Attr const is_attr, std::string const &key) const
void ignoreConfigParameter(std::string const ¶m) const
static void onerror(std::string const &filename, std::string const &path, std::string const &message)
void checkAndInvalidate()
static void assertNoSwallowedErrors()
Asserts that there have not been any errors reported in the destructor.
Callback onwarning_
Custom warning callback.
static const char pathseparator
Character separating two path components.
void checkUniqueAttr(std::string const &attr) const
Asserts that the attribute attr has not been read yet.
std::map< KeyType, CountType > visited_params_
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_
void error(std::string const &message) const
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
std::optional< T > getConfigParameterOptional(std::string const ¶m) const
void ignoreConfigAttribute(std::string const &attr) const
void checkUnique(std::string const &key) const
Asserts that the key has not been read yet.
T getConfigParameter(std::string const ¶m) const
Attr
Used to indicate if dealing with XML tags or XML attributes.
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.
ConfigTree getConfigSubtree(std::string const &root) const
std::string path_
A path printed in error/warning messages.
CountType & markVisited(std::string const &key, Attr const is_attr, bool peek_only) const
void ignoreConfigParameterAll(std::string const ¶m) const
Callback onerror_
Custom error callback.
std::string joinPaths(std::string const &p1, std::string const &p2) const
Used to generate the path of a subtree.
Range< ValueIterator< T > > getConfigParameterList(std::string const ¶m) const
void warning(std::string const &message) const
bool hasChildren() const
Checks if this tree has any children.
PTree const * tree_
The wrapped tree.
ConfigTree(PTree &&top_level_tree, std::string filename, Callback error_cb, Callback warning_cb)
void checkConfigParameter(std::string const ¶m, std::string_view const value) const
boost::property_tree::ptree PTree
The tree being wrapped by this class.
ConfigTree & operator=(ConfigTree const &)=delete
copying is not compatible with the semantics of this class
std::string filename_
The path of the file from which this tree has been read.
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
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.
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...
std::string joinPaths(std::string const &pathA, std::string const &pathB)