From 07f657754b0af656ee48c38540805fcec7cee27d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 5 Aug 2017 18:19:28 +0200 Subject: Implement path::normalized() predicate --- libbutl/path.hxx | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ libbutl/path.ixx | 8 ++++++++ 2 files changed, 56 insertions(+) diff --git a/libbutl/path.hxx b/libbutl/path.hxx index 26b076f..342a188 100644 --- a/libbutl/path.hxx +++ b/libbutl/path.hxx @@ -146,6 +146,46 @@ namespace butl } static bool + normalized (const string_type& s, bool sep) + { + return normalized (s.c_str (), s.size (), sep); + } + + static bool + normalized (const C* s, size_type n, bool sep) + { + size_t j (0); // Beginning of path component. + + for (size_t i (0); i != n; ++i) + { + char c (s[i]); + + if (is_separator (c)) + { + if (sep && c != directory_separator) + return false; + + const char* p (s + j); + size_t m (i - j); + j = i + 1; + + if (j != n && is_separator (s[j])) + return false; + + if (current (p, m) || parent (p, m)) + return false; + } + } + + // Last component. + // + const char* p (s + j); + size_t m (n - j); + + return !(current (p, m) || parent (p, m)); + } + + static bool root (const string_type& s) { return root (s.c_str (), s.size ()); @@ -657,6 +697,14 @@ namespace butl bool parent () const; + // Return true if the path is normalized, that is, does not contain any + // current or parent directory components or multiple consecutive and, + // unless sep is false, non-canonical directory separators. Empty path + // is considered normalized. + // + bool + normalized (bool sep = true) const; + // Test, based on the presence/absence of the trailing separator, if the // path is to a directory. // diff --git a/libbutl/path.ixx b/libbutl/path.ixx index c140d1e..7227b72 100644 --- a/libbutl/path.ixx +++ b/libbutl/path.ixx @@ -102,6 +102,14 @@ namespace butl template inline bool basic_path:: + normalized (bool sep) const + { + return (!sep || this->tsep_ <= 1) && + traits::normalized (this->path_, sep); + } + + template + inline bool basic_path:: root () const { return traits::root (this->path_); -- cgit v1.1