From 259356f3b5dffadc1ecc6865844ec899ff394a0c Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 20 Jul 2020 16:09:49 +0200 Subject: STL Support: cm::filesystem::path: add support of Cygwin --- Utilities/std/cm/bits/fs_path.cxx | 60 ++++++++++++++++++++++++++++++++------- Utilities/std/cm/filesystem | 16 ++++++----- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/Utilities/std/cm/bits/fs_path.cxx b/Utilities/std/cm/bits/fs_path.cxx index 71386bb..b8c5631 100644 --- a/Utilities/std/cm/bits/fs_path.cxx +++ b/Utilities/std/cm/bits/fs_path.cxx @@ -13,8 +13,10 @@ # include # include # include -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) # include +# endif +# if defined(_WIN32) || defined(__CYGWIN__) # include # endif @@ -396,7 +398,7 @@ private: pointer consume_root_name(pointer ptr, pointer end, bool check_only = false) noexcept { -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) if (ptr < end) { if ((end - ptr) >= 2 && this->is_drive_name(ptr)) { // Drive letter (X:) is a root name @@ -409,7 +411,8 @@ private: (ptr[1] == '/' || ptr[1] == '\\') && (ptr[2] != '/' && ptr[2] != '\\')) { // server name (//server) is a root name - auto pos = std::find(ptr + 2, end, '/'); + auto pos = std::find_if(ptr + 2, end, + [](char c) { return c == '/' || c == '\\'; }); if (!check_only) { this->Entry = cm::string_view(ptr, pos - ptr); } @@ -438,6 +441,31 @@ private: } } } +# elif defined(__CYGWIN__) + if (ptr < end) { + if ((end - ptr) > 2 && ptr[0] == '/' && ptr[1] == '/' && ptr[2] != '/') { + // server name (//server) is a root name + auto pos = std::find(ptr + 2, end, '/'); + if (!check_only) { + this->Entry = cm::string_view(ptr, pos - ptr); + } + return pos; + } + } else { + if ((ptr - end) > 2 && ptr[0] != '/') { + std::reverse_iterator start(ptr); + std::reverse_iterator stop(end); + auto res = std::find(start, stop, '/'); + pointer pos = res.base() - 1; + if ((pos - 1) > end && pos[-1] == '/') { + // server name (//server) is a root name + if (!check_only) { + this->Entry = cm::string_view(pos - 1, ptr - pos + 2); + } + return pos - 2; + } + } + } # else (void)ptr; (void)end; @@ -514,13 +542,25 @@ path& path::operator/=(const path& p) this->path_ += static_cast(p.get_root_directory()); } else if (this->has_filename()) { this->path_ += this->preferred_separator; -# if defined(_WIN32) +# if defined(_WIN32) || defined(__CYGWIN__) // special case: "//host" / "b" => "//host/b" } else if (this->has_root_name() && !this->has_root_directory()) { if (this->path_.length() >= 3 && - (this->path_[0] == '/' || this->path_[0] == '\\') && - (this->path_[1] == '/' || this->path_[1] == '\\') && - (this->path_[2] != '/' || this->path_[2] != '\\')) { + (this->path_[0] == '/' +# if defined(_WIN32) && !defined(__CYGWIN__) + || this->path_[0] == '\\' +# endif + ) && + (this->path_[1] == '/' +# if defined(_WIN32) && !defined(__CYGWIN__) + || this->path_[1] == '\\' +# endif + ) && + (this->path_[2] != '/' +# if defined(_WIN32) && !defined(__CYGWIN__) + && this->path_[2] != '\\' +# endif + )) { this->path_ += this->preferred_separator; } # endif @@ -644,7 +684,7 @@ path path::lexically_relative(const path& base) const } auto is_path_absolute = [](cm::string_view rn, cm::string_view rd) -> bool { -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) return !rn.empty() && !rd.empty(); # else (void)rn; @@ -659,7 +699,7 @@ path path::lexically_relative(const path& base) const return path(); } -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) // LWG3070 handle special case: filename can also be a root-name auto is_drive_name = [](cm::string_view item) -> bool { return item.length() == 2 && item[1] == ':'; @@ -724,7 +764,7 @@ path::path_type path::get_generic() const { auto gen_path = this->path_; auto start = gen_path.begin(); -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) std::replace(gen_path.begin(), gen_path.end(), '\\', '/'); // preserve special syntax for root_name ('//server' or '//?') if (gen_path.length() > 2 && gen_path[2] != '/') { diff --git a/Utilities/std/cm/filesystem b/Utilities/std/cm/filesystem index d7ade34..6021712 100644 --- a/Utilities/std/cm/filesystem +++ b/Utilities/std/cm/filesystem @@ -27,7 +27,7 @@ # include # include -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) # include # endif @@ -616,7 +616,7 @@ class path }; public: -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) using value_type = wchar_t; # else using value_type = char; @@ -633,7 +633,7 @@ public: generic_format }; -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) static constexpr value_type preferred_separator = L'\\'; # else static constexpr value_type preferred_separator = '/'; @@ -800,7 +800,7 @@ public: path& make_preferred() { -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) std::replace( this->path_.begin(), this->path_.end(), '/', static_cast(this->preferred_separator)); @@ -845,7 +845,7 @@ public: // ================ const string_type& native() const noexcept { -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) this->native_path_ = internals::string_converter< path_type::value_type>::to(this->path_); return this->native_path_; @@ -990,9 +990,11 @@ public: bool is_absolute() const { -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) return this->has_root_name() && this->has_root_directory(); # else + // For CYGWIN, root_name (i.e. //host or /cygdrive/x) is not considered. + // Same as current GNU g++ implementation (9.3). return this->has_root_directory(); # endif } @@ -1085,7 +1087,7 @@ private: int compare_path(cm::string_view str) const; path_type path_; -# if defined(_WIN32) +# if defined(_WIN32) && !defined(__CYGWIN__) mutable string_type native_path_; # endif }; -- cgit v0.12