aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-08-05 18:19:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-08-05 18:19:28 +0200
commit07f657754b0af656ee48c38540805fcec7cee27d (patch)
tree46ee0de36bb9005a6bfc9a53624ad7444e1a0c62
parentc291ac321aa9863c515f84ba0b8b1599c5da2c9a (diff)
Implement path::normalized() predicate
-rw-r--r--libbutl/path.hxx48
-rw-r--r--libbutl/path.ixx8
2 files changed, 56 insertions, 0 deletions
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 <typename C, typename K>
inline bool basic_path<C, K>::
+ normalized (bool sep) const
+ {
+ return (!sep || this->tsep_ <= 1) &&
+ traits::normalized (this->path_, sep);
+ }
+
+ template <typename C, typename K>
+ inline bool basic_path<C, K>::
root () const
{
return traits::root (this->path_);