From d115cc49a5f91c9c547a7a4d27323f6ccc959da3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 6 Jun 2019 12:22:33 +0200 Subject: Add path::abnormalities(), note on normalization and symlinks --- libbutl/path.ixx | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) (limited to 'libbutl/path.ixx') diff --git a/libbutl/path.ixx b/libbutl/path.ixx index 9622a81..7786fbc 100644 --- a/libbutl/path.ixx +++ b/libbutl/path.ixx @@ -4,6 +4,120 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. { + // path_abnormality + // + + inline path_abnormality + operator& (path_abnormality x, path_abnormality y) + { + return x &= y; + } + + inline path_abnormality + operator| (path_abnormality x, path_abnormality y) + { + return x |= y; + } + + inline path_abnormality + operator&= (path_abnormality& x, path_abnormality y) + { + return x = static_cast ( + static_cast (x) & + static_cast (y)); + } + + inline path_abnormality + operator|= (path_abnormality& x, path_abnormality y) + { + return x = static_cast ( + static_cast (x) | + static_cast (y)); + } + + // path_traits + // + template + inline bool path_traits:: + normalized (const C* s, size_type n, bool sep) + { + // An early-return version of abnormalities(). + // + 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 (parent (p, m) || current (p, m)) + return false; + } + } + + // Last component. + // + const char* p (s + j); + size_t m (n - j); + + return !(parent (p, m) || current (p, m)); + } + + template + inline path_abnormality path_traits:: + abnormalities (const C* s, size_type n) + { + path_abnormality r (path_abnormality::none); + + 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 (c != directory_separator) + r |= path_abnormality::separator; + + const char* p (s + j); + size_t m (i - j); + j = i + 1; + + if (j != n && is_separator (s[j])) + r |= path_abnormality::separator; + + if (parent (p, m)) + r |= path_abnormality::parent; + else if (current (p, m)) + r |= path_abnormality::current; + } + } + + // Last component. + // + const char* p (s + j); + size_t m (n - j); + + if (parent (p, m)) + r |= path_abnormality::parent; + else if (current (p, m)) + r |= path_abnormality::current; + + return r; + } + #ifdef _WIN32 template <> inline char path_traits:: @@ -20,6 +134,9 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. } #endif + // path + // + template inline basic_path path_cast_impl (const basic_path& p, basic_path*) @@ -92,6 +209,18 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. } template + inline path_abnormality basic_path:: + abnormalities () const + { + path_abnormality r (traits_type::abnormalities (this->path_)); + + if (this->tsep_ > 1) + r |= path_abnormality::separator; + + return r; + } + + template inline bool basic_path:: root () const { -- cgit v1.1