16template class boost::property_tree::basic_ptree<std::string, std::string,
40 OGS_FATAL(
"ConfigTree: No valid error handler provided.");
44 OGS_FATAL(
"ConfigTree: No valid warning handler provided.");
47 std::filesystem::path
const filepath{filename};
49 auto absolute_filepath = absolute(filepath, ec);
53 "ConfigTree: could not get the absolute path of '{}'. Using the "
54 "path unmodified. Error code = {}",
55 filepath.string(), ec.value());
56 absolute_filepath = filepath;
66 DBUG(
"ConfigTree: The project directory '{}' does not exist.",
72 std::string
const& root)
93 other.tree_ =
nullptr;
98 if (std::uncaught_exceptions() > 0)
110 catch (std::exception& e)
112 ERR(
"{:s}", e.what());
123 other.tree_ =
nullptr;
124 path_ = std::move(other.path_);
128 onerror_ = std::move(other.onerror_);
137 if (ct.hasChildren())
139 error(
"Requested parameter <" + param +
"> actually is a subtree.");
145 std::string
const& param)
const
148 if (ct && ct->hasChildren())
150 error(
"Requested parameter <" + param +
"> actually is a subtree.");
156 const std::string& param)
const
161 auto p =
tree_->equal_range(param);
168 std::string_view
const value)
const
171 if (parameter_value != value)
173 error(
"For the tag <" + param +
"> expected to read value '" +
174 value.data() +
"', but got '" + parameter_value +
"'.");
182 return std::move(*t);
184 error(
"Key <" + root +
"> has not been found.");
188 std::string
const& root)
const
192 if (
auto subtree =
tree_->get_child_optional(root))
202 std::string
const& root)
const
207 auto p =
tree_->equal_range(root);
225 for (
auto const& [tag, subtree] : *
tree_)
227 if (tag ==
"<xmlattr>")
242 bool peek_only =
tree_->find(param) ==
tree_->not_found();
252 bool peek_only = !
tree_->get_child_optional(
"<xmlattr>." + attr);
262 auto p =
tree_->equal_range(param);
263 for (
auto it = p.first; it != p.second; ++it)
278 "ConfigTree: The error handler does not break out of the normal "
288 const std::string& message)
290 OGS_FATAL(
"ConfigTree: In file `{:s}' at path <{:s}>: {:s}", filename, path,
295 const std::string& message)
297 WARN(
"ConfigTree: In file `{:s}' at path <{:s}>: {:s}", filename, path,
308 ERR(
"ConfigTree: There have been errors when parsing the configuration "
319 OGS_FATAL(
"There have been errors when parsing the configuration file(s).");
324 const std::size_t maxlen = 100;
326 if (s.size() < maxlen)
331 return s.substr(0, maxlen - 3) +
"...";
338 error(
"Search for empty key.");
342 error(
"Key <" + key +
"> starts with an illegal character.");
344 else if (key.find_first_not_of(
key_chars, 1) != std::string::npos)
346 error(
"Key <" + key +
"> contains illegal characters.");
348 else if (key.find(
"__") != std::string::npos)
354 error(
"Key <" + key +
"> contains double underscore.");
359 const std::string& p2)
const
363 error(
"Second path to be joined is empty.");
380 error(
"Key <" + key +
"> has already been processed.");
388 if (attr.find(
':') != std::string::npos)
390 auto pos =
decltype(std::string::npos){0};
398 pos = attr2.find_first_of(
":ABCDEFGHIJKLMNOPQRSTUVWXYZ", pos);
399 if (pos != std::string::npos)
403 }
while (pos != std::string::npos);
414 error(
"Attribute '" + attr +
"' has already been processed.");
420 bool const peek_only)
const
426 std::string
const& key)
const
428 auto const type = std::type_index(
typeid(
nullptr));
435 auto& v = p.first->second;
442 auto const& tree = *
tree_;
443 if (tree.begin() == tree.end())
447 if (tree.front().first ==
"<xmlattr>" && (++tree.begin()) == tree.end())
468 "' of this tag has not been read.");
472 for (
auto const& p : *
tree_)
474 if (p.first !=
"<xmlattr>")
481 if (
auto attrs =
tree_->get_child_optional(
"<xmlattr>"))
483 for (
auto const& p : *attrs)
491 auto const& tag = p.first.second;
492 auto const& count = p.second.count;
494 switch (p.first.first)
499 warning(
"XML attribute '" + tag +
"' has been read " +
500 std::to_string(count) +
501 " time(s) more than it was present in the "
502 "configuration tree.");
506 warning(
"XML attribute '" + tag +
"' has been read " +
507 std::to_string(-count) +
508 " time(s) less than it was present in the "
509 "configuration tree.");
515 warning(
"Key <" + tag +
"> has been read " +
516 std::to_string(count) +
517 " time(s) more than it was present in the "
518 "configuration tree.");
522 warning(
"Key <" + tag +
"> has been read " +
523 std::to_string(-count) +
524 " time(s) less than it was present in the "
525 "configuration tree.");
552 conf->checkAndInvalidate();
static std::forward_list< std::string > configtree_destructor_error_messages
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
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.
Children getAllChildren() const
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::filesystem::path projectDirectory() const
std::optional< T > getConfigParameterOptional(std::string const ¶m) const
void ignoreConfigAttribute(std::string const &attr) const
std::filesystem::path filepath_
The path of the file from which this tree has been read.
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.
std::vector< std::pair< std::string, Child > > Children
Return type of getAllChildren(): an owning vector of (tag, view) pairs.
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
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...