diff options
-rw-r--r-- | libbutl/path.hxx | 16 | ||||
-rw-r--r-- | libbutl/path.ixx | 83 |
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> |