13 #include <forward_list>
21 template class boost::property_tree::basic_ptree<std::string, std::string,
39 filename_(std::move(filename)),
40 onerror_(std::move(error_cb)),
41 onwarning_(std::move(warning_cb))
45 OGS_FATAL(
"ConfigTree: No valid error handler provided.");
49 OGS_FATAL(
"ConfigTree: No valid warning handler provided.");
54 std::string
const& root)
57 filename_(parent.filename_),
58 onerror_(parent.onerror_),
59 onwarning_(parent.onwarning_)
66 path_(std::move(other.path_)),
67 filename_(std::move(other.filename_)),
68 visited_params_(std::move(other.visited_params_)),
69 have_read_data_(other.have_read_data_),
70 onerror_(std::move(other.onerror_)),
71 onwarning_(std::move(other.onwarning_))
73 other.tree_ =
nullptr;
78 if (std::uncaught_exceptions() > 0)
90 catch (std::exception& e)
92 ERR(
"{:s}", e.what());
102 other.tree_ =
nullptr;
103 path_ = std::move(other.path_);
107 onerror_ = std::move(other.onerror_);
116 if (ct.hasChildren())
118 error(
"Requested parameter <" + root +
"> actually is a subtree.");
124 std::string
const& root)
const
127 if (ct && ct->hasChildren())
129 error(
"Requested parameter <" + root +
"> actually is a subtree.");
135 const std::string& param)
const
140 auto p =
tree_->equal_range(param);
150 return std::move(*t);
152 error(
"Key <" + root +
"> has not been found.");
156 std::string
const& root)
const
160 if (
auto subtree =
tree_->get_child_optional(root))
170 std::string
const& root)
const
175 auto p =
tree_->equal_range(root);
185 bool peek_only =
tree_->find(param) ==
tree_->not_found();
195 bool peek_only = !
tree_->get_child_optional(
"<xmlattr>." + attr);
205 auto p =
tree_->equal_range(param);
206 for (
auto it = p.first; it != p.second; ++it)
216 "ConfigTree: The error handler does not break out of the normal "
226 const std::string& message)
228 OGS_FATAL(
"ConfigTree: In file `{:s}' at path <{:s}>: {:s}", filename, path,
233 const std::string& message)
235 WARN(
"ConfigTree: In file `{:s}' at path <{:s}>: {:s}", filename, path,
246 ERR(
"ConfigTree: There have been errors when parsing the configuration "
254 OGS_FATAL(
"There have been errors when parsing the configuration file(s).");
259 const std::size_t maxlen = 100;
261 if (s.size() < maxlen)
266 return s.substr(0, maxlen - 3) +
"...";
273 error(
"Search for empty key.");
277 error(
"Key <" + key +
"> starts with an illegal character.");
279 else if (key.find_first_not_of(
key_chars, 1) != std::string::npos)
281 error(
"Key <" + key +
"> contains illegal characters.");
283 else if (key.find(
"__") != std::string::npos)
289 error(
"Key <" + key +
"> contains double underscore.");
294 const std::string& p2)
const
298 error(
"Second path to be joined is empty.");
315 error(
"Key <" + key +
"> has already been processed.");
323 if (attr.find(
':') != std::string::npos)
325 auto pos = decltype(std::string::npos){0};
333 pos = attr2.find_first_of(
":ABCDEFGHIJKLMNOPQRSTUVWXYZ", pos);
334 if (pos != std::string::npos)
338 }
while (pos != std::string::npos);
349 error(
"Attribute '" + attr +
"' has already been processed.");
355 bool const peek_only)
const
357 return markVisited<ConfigTree>(key, is_attr, peek_only);
361 std::string
const& key)
const
363 auto const type = std::type_index(
typeid(
nullptr));
370 auto& v = p.first->second;
377 auto const& tree = *
tree_;
378 if (tree.begin() == tree.end())
382 if (tree.front().first ==
"<xmlattr>" && (++tree.begin()) == tree.end())
403 "' of this tag has not been read.");
407 for (
auto const& p : *
tree_)
409 if (p.first !=
"<xmlattr>")
416 if (
auto attrs =
tree_->get_child_optional(
"<xmlattr>"))
418 for (
auto const& p : *attrs)
426 auto const& tag = p.first.second;
427 auto const& count = p.second.count;
429 switch (p.first.first)
434 warning(
"XML attribute '" + tag +
"' has been read " +
435 std::to_string(count) +
436 " time(s) more than it was present in the "
437 "configuration tree.");
441 warning(
"XML attribute '" + tag +
"' has been read " +
442 std::to_string(-count) +
443 " time(s) less than it was present in the "
444 "configuration tree.");
450 warning(
"Key <" + tag +
"> has been read " +
451 std::to_string(count) +
452 " time(s) more than it was present in the "
453 "configuration tree.");
457 warning(
"Key <" + tag +
"> has been read " +
458 std::to_string(-count) +
459 " time(s) less than it was present in the "
460 "configuration tree.");
487 conf->checkAndInvalidate();
static std::forward_list< std::string > configtree_destructor_error_messages
void ERR(char const *fmt, Args const &... args)
void WARN(char const *fmt, Args const &... 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
ConfigTree(PTree const &tree, std::string filename, Callback error_cb, Callback warning_cb)
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.
std::function< void(const std::string &filename, const std::string &path, const std::string &message)> Callback
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
boost::property_tree::ptree const * tree_
The wrapped tree.
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
ConfigTree & operator=(ConfigTree const &)=delete
copying is not compatible with the semantics of this class
void warning(std::string const &message) const
bool hasChildren() const
Checks if this tree has any children.
boost::property_tree::ptree PTree
The tree being wrapped by 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_].
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)