15template class boost::property_tree::basic_ptree<std::string, std::string,
39 OGS_FATAL(
"ConfigTree: No valid error handler provided.");
43 OGS_FATAL(
"ConfigTree: No valid warning handler provided.");
46 std::filesystem::path
const filepath{filename};
48 auto absolute_filepath = absolute(filepath, ec);
52 "ConfigTree: could not get the absolute path of '{}'. Using the "
53 "path unmodified. Error code = {}",
54 filepath.string(), ec.value());
55 absolute_filepath = filepath;
65 DBUG(
"ConfigTree: The project directory '{}' does not exist.",
71 std::string
const& root)
92 other.tree_ =
nullptr;
97 if (std::uncaught_exceptions() > 0)
109 catch (std::exception& e)
111 ERR(
"{:s}", e.what());
122 other.tree_ =
nullptr;
123 path_ = std::move(other.path_);
127 onerror_ = std::move(other.onerror_);
136 if (ct.hasChildren())
138 error(
"Requested parameter <" + param +
"> actually is a subtree.");
144 std::string
const& param)
const
147 if (ct && ct->hasChildren())
149 error(
"Requested parameter <" + param +
"> actually is a subtree.");
155 const std::string& param)
const
160 auto p =
tree_->equal_range(param);
167 std::string_view
const value)
const
170 if (parameter_value != value)
172 error(
"For the tag <" + param +
"> expected to read value '" +
173 value.data() +
"', but got '" + parameter_value +
"'.");
181 return std::move(*t);
183 error(
"Key <" + root +
"> has not been found.");
187 std::string
const& root)
const
191 if (
auto subtree =
tree_->get_child_optional(root))
201 std::string
const& root)
const
206 auto p =
tree_->equal_range(root);
216 bool peek_only =
tree_->find(param) ==
tree_->not_found();
226 bool peek_only = !
tree_->get_child_optional(
"<xmlattr>." + attr);
236 auto p =
tree_->equal_range(param);
237 for (
auto it = p.first; it != p.second; ++it)
252 "ConfigTree: The error handler does not break out of the normal "
262 const std::string& message)
264 OGS_FATAL(
"ConfigTree: In file `{:s}' at path <{:s}>: {:s}", filename, path,
269 const std::string& message)
271 WARN(
"ConfigTree: In file `{:s}' at path <{:s}>: {:s}", filename, path,
282 ERR(
"ConfigTree: There have been errors when parsing the configuration "
293 OGS_FATAL(
"There have been errors when parsing the configuration file(s).");
298 const std::size_t maxlen = 100;
300 if (s.size() < maxlen)
305 return s.substr(0, maxlen - 3) +
"...";
312 error(
"Search for empty key.");
316 error(
"Key <" + key +
"> starts with an illegal character.");
318 else if (key.find_first_not_of(
key_chars, 1) != std::string::npos)
320 error(
"Key <" + key +
"> contains illegal characters.");
322 else if (key.find(
"__") != std::string::npos)
328 error(
"Key <" + key +
"> contains double underscore.");
333 const std::string& p2)
const
337 error(
"Second path to be joined is empty.");
354 error(
"Key <" + key +
"> has already been processed.");
362 if (attr.find(
':') != std::string::npos)
364 auto pos =
decltype(std::string::npos){0};
372 pos = attr2.find_first_of(
":ABCDEFGHIJKLMNOPQRSTUVWXYZ", pos);
373 if (pos != std::string::npos)
377 }
while (pos != std::string::npos);
388 error(
"Attribute '" + attr +
"' has already been processed.");
394 bool const peek_only)
const
400 std::string
const& key)
const
402 auto const type = std::type_index(
typeid(
nullptr));
409 auto& v = p.first->second;
416 auto const& tree = *
tree_;
417 if (tree.begin() == tree.end())
421 if (tree.front().first ==
"<xmlattr>" && (++tree.begin()) == tree.end())
442 "' of this tag has not been read.");
446 for (
auto const& p : *
tree_)
448 if (p.first !=
"<xmlattr>")
455 if (
auto attrs =
tree_->get_child_optional(
"<xmlattr>"))
457 for (
auto const& p : *attrs)
465 auto const& tag = p.first.second;
466 auto const& count = p.second.count;
468 switch (p.first.first)
473 warning(
"XML attribute '" + tag +
"' has been read " +
474 std::to_string(count) +
475 " time(s) more than it was present in the "
476 "configuration tree.");
480 warning(
"XML attribute '" + tag +
"' has been read " +
481 std::to_string(-count) +
482 " time(s) less than it was present in the "
483 "configuration tree.");
489 warning(
"Key <" + tag +
"> has been read " +
490 std::to_string(count) +
491 " time(s) more than it was present in the "
492 "configuration tree.");
496 warning(
"Key <" + tag +
"> has been read " +
497 std::to_string(-count) +
498 " time(s) less than it was present in the "
499 "configuration tree.");
526 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.
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.
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...