From ef8d8c01a4d630b55ee4cf7a23688a5a5d685419 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 29 Sep 2021 11:16:22 +0200 Subject: Factor path::{sub,sup}() to path_traits::{sub,sup}() --- libbutl/path.hxx | 16 +++++++++++ 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 + inline bool path_traits:: + 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 + inline bool path_traits:: + 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:: @@ -230,52 +269,16 @@ namespace butl inline bool basic_path:: 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 inline bool basic_path:: 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 -- cgit v1.1