From 584e8fce074286cbf1a5bf0c79265f789c050c59 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 27 Aug 2020 10:19:38 +0200 Subject: Add ability to pass alternative dir separator to path::canonicalize() This, for example, can be used to make paths with forward slashes on Windows. --- libbutl/path.ixx | 16 ++++++++++++---- libbutl/path.mxx | 29 ++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/libbutl/path.ixx b/libbutl/path.ixx index 8512286..9c96cfc 100644 --- a/libbutl/path.ixx +++ b/libbutl/path.ixx @@ -396,12 +396,20 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. template inline basic_path& basic_path:: - canonicalize () + canonicalize (char ds) { - traits_type::canonicalize (this->path_); + traits_type::canonicalize (this->path_, ds); - if (this->tsep_ > 1) // Non-canonical trailing separator. - this->tsep_ = 1; + // Canonicalize the trailing separator if any. + // + if (this->tsep_ > 0) + { + auto dss (traits_type::directory_separators); + difference_type i (ds == '\0' ? 1 : strchr (dss, ds) - dss + 1); + + if (this->tsep_ != i) + this->tsep_ = i; + } return *this; } diff --git a/libbutl/path.mxx b/libbutl/path.mxx index 1ee2a66..12479ce 100644 --- a/libbutl/path.mxx +++ b/libbutl/path.mxx @@ -12,6 +12,7 @@ #include #include // ptrdiff_t #include // uint16_t +#include // str*() #include // move(), swap() #include #include // invalid_argument @@ -427,21 +428,27 @@ LIBBUTL_MODEXPORT namespace butl } static void - canonicalize (string_type& s) + canonicalize (string_type& s, char ds = '\0') { //canonicalize (s.data (), s.size ()); // C++17 + if (ds == '\0') + ds = directory_separator; + for (size_t i (0), n (s.size ()); i != n; ++i) - if (is_separator (s[i]) && s[i] != directory_separator) - s[i] = directory_separator; + if (is_separator (s[i]) && s[i] != ds) + s[i] = ds; } static void - canonicalize (C* s, size_type n) + canonicalize (C* s, size_type n, char ds = '\0') { + if (ds == '\0') + ds = directory_separator; + for (const C* e (s + n); s != e; ++s) - if (is_separator (*s) && *s != directory_separator) - *s = directory_separator; + if (is_separator (*s) && *s != ds) + *s = ds; } // Get/set current working directory. Throw std::system_error to report @@ -1091,11 +1098,15 @@ LIBBUTL_MODEXPORT namespace butl public: // Canonicalize the path and return *this. Canonicalization involves - // converting all directory separators to the canonical form. Note that - // multiple directory separators are not collapsed. + // converting all directory separators to the canonical form (or to the + // alternative separator if specified). Note that multiple directory + // separators are not collapsed. + // + // Note that the alternative separator must be listed in path_trait:: + // directory_separators. // basic_path& - canonicalize (); + canonicalize (char dir_sep = '\0'); // Normalize the path and return *this. Normalization involves collapsing // the '.' and '..' directories if possible, collapsing multiple -- cgit v1.1