aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbutl/path.hxx16
-rw-r--r--libbutl/path.ixx83
2 files changed, 59 insertions, 40 deletions
diff --git a/libbutl/path.hxx b/libbutl/path.hxx
index 8276130..fae145e 100644
--- a/libbutl/path.hxx
+++ b/libbutl/path.hxx
@@ -373,6 +373,22 @@ namespace butl
: (p = rfind_separator (s, n - 1)) == nullptr ? s : ++p;
}
+ // Return true if sb is a sub-path of sp (i.e., sp is a prefix). Expects
+ // both paths to be normalized. Note that this function returns true if
+ // the paths are equal. Empty path is considered a prefix of any path.
+ //
+ static bool
+ sub (const C* sb, size_type nb,
+ const C* sp, size_type np);
+
+ // Return true if sp is a super-path of sb (i.e., sb is a suffix). Expects
+ // both paths to be normalized. Note that this function returns true if
+ // the paths are equal. Empty path is considered a prefix of any path.
+ //
+ static bool
+ sup (const C* sp, size_type np,
+ const C* sb, size_type nb);
+
static int
compare (string_type const& l,
string_type const& r,
diff --git a/libbutl/path.ixx b/libbutl/path.ixx
index 2e4df2c..d2084f0 100644
--- a/libbutl/path.ixx
+++ b/libbutl/path.ixx
@@ -117,6 +117,45 @@ namespace butl
return r;
}
+ template <typename C>
+ inline bool path_traits<C>::
+ sub (const C* s, size_type n,
+ const C* ps, size_type pn)
+ {
+ // The thinking here is that we can use the full string representations
+ // (including the trailing slash in "/").
+ //
+ if (pn == 0)
+ return true;
+
+ // The second condition guards against the /foo-bar vs /foo case.
+ //
+ return n >= pn &&
+ compare (s, pn, ps, pn) == 0 &&
+ (is_separator (ps[pn - 1]) || // p ends with a separator
+ n == pn || // *this == p
+ is_separator (s[pn])); // next char is a separator
+ }
+
+ template <typename C>
+ inline bool path_traits<C>::
+ sup (const C* s, size_type n,
+ const C* ps, size_type pn)
+ {
+ // The thinking here is that we can use the full string representations
+ // (including the trailing slash in "/").
+ //
+ if (pn == 0)
+ return true;
+
+ // The second condition guards against the /foo-bar vs bar case.
+ //
+ return n >= pn &&
+ compare (s + n - pn, pn, ps, pn) == 0 &&
+ (n == pn || // *this == p
+ is_separator (s[n - pn - 1])); // Previous char is a separator.
+ }
+
#ifdef _WIN32
template <>
inline char path_traits<char>::
@@ -230,52 +269,16 @@ namespace butl
inline bool basic_path<C, K>::
sub (const basic_path& p) const
{
- // The thinking here is that we can use the full string representations
- // (including the trailing slash in "/").
- //
- const string_type& ps (p.path_);
- size_type pn (ps.size ());
-
- if (pn == 0)
- return true;
-
- const string_type& s (this->path_);
- size_type n (s.size ());
-
- // The second condition guards against the /foo-bar vs /foo case.
- //
- return n >= pn &&
- traits_type::compare (s.c_str (), pn, ps.c_str (), pn) == 0 &&
- (traits_type::is_separator (ps.back ()) || // p ends with a separator
- n == pn || // *this == p
- traits_type::is_separator (s[pn])); // next char is a separator
+ return traits_type::sub (this->path_.c_str (), this->path_.size (),
+ p.path_.c_str (), p.path_.size ());
}
template <typename C, typename K>
inline bool basic_path<C, K>::
sup (const basic_path& p) const
{
- // The thinking here is that we can use the full string representations
- // (including the trailing slash in "/").
- //
- const string_type& ps (p.path_);
- size_type pn (ps.size ());
-
- if (pn == 0)
- return true;
-
- const string_type& s (this->path_);
- size_type n (s.size ());
-
- // The second condition guards against the /foo-bar vs bar case.
- //
- return n >= pn &&
- traits_type::compare (s.c_str () + n - pn, pn, ps.c_str (), pn) == 0 &&
- (n == pn || // *this == p
- //
- // Previous char is a separator.
- //
- traits_type::is_separator (s[n - pn - 1]));
+ return traits_type::sup (this->path_.c_str (), this->path_.size (),
+ p.path_.c_str (), p.path_.size ());
}
template <typename C, typename K>