From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1464) id 053013987838; Fri, 4 Sep 2020 19:27:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 053013987838 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1599247668; bh=qMaZNXCOd47rAVaERxQG1Neju5JtxeFA2INctYZ7Y/M=; h=From:To:Subject:Date:From; b=Kcy0jRCcAVOWVnT9u4cZt6+m4FtClTqYAsB+2DdGRs4mAUqUwS644wbZgKBOElw2d nYrr07O+wBx1e0YFHMrII7wy7m4PWrZcEE/wOXfKdhK12AzJEcxj2MS26oJoi1dVhd t9thNWRbm9xb/t8owwgXwyBckNUSMirNbpAa3b9U= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Peter Bergner To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/ibm/heads/gcc-9-branch)] libstdc++: Fix experimental::path::generic_string (PR 93245) X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/vendors/ibm/heads/gcc-9-branch X-Git-Oldrev: e7406c364496dae51ef294b5720923fe4a1dfccb X-Git-Newrev: 88f2b72e77fea11803b761f4fb569d83266e1d9e Message-Id: <20200904192748.053013987838@sourceware.org> Date: Fri, 4 Sep 2020 19:27:48 +0000 (GMT) X-BeenThere: libstdc++-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Sep 2020 19:27:48 -0000 https://gcc.gnu.org/g:88f2b72e77fea11803b761f4fb569d83266e1d9e commit 88f2b72e77fea11803b761f4fb569d83266e1d9e Author: Jonathan Wakely Date: Sat Mar 21 22:11:44 2020 +0000 libstdc++: Fix experimental::path::generic_string (PR 93245) This function was unimplemented, simply returning the native format string instead. PR libstdc++/93245 * include/experimental/bits/fs_path.h (path::generic_string()): Return the generic format path, not the native one. * testsuite/experimental/filesystem/path/generic/generic_string.cc: Improve test coverage. (cherry picked from commit a577c0c26931090e7c25e56ef5ffc807627961ec) Diff: --- libstdc++-v3/include/experimental/bits/fs_path.h | 40 ++++++++++++++----- .../filesystem/path/generic/generic_string.cc | 46 +++++++++++++++++----- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h index 64089b432eb..64329e36b54 100644 --- a/libstdc++-v3/include/experimental/bits/fs_path.h +++ b/libstdc++-v3/include/experimental/bits/fs_path.h @@ -996,34 +996,56 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 inline std::u32string path::u32string() const { return string(); } -#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS template inline std::basic_string<_CharT, _Traits, _Allocator> path::generic_string(const _Allocator& __a) const - { return string<_CharT, _Traits, _Allocator>(__a); } + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + const _CharT __slash = is_same<_CharT, wchar_t>::value + ? _CharT(L'/') + : _CharT('/'); // Assume value is correct for the encoding. +#else + const _CharT __slash = _CharT('/'); +#endif + basic_string<_CharT, _Traits, _Allocator> __str(__a); + __str.reserve(_M_pathname.size()); + bool __add_slash = false; + for (auto& __elem : *this) + { + if (__elem._M_type == _Type::_Root_dir) + { + __str += __slash; + continue; + } + if (__add_slash) + __str += __slash; + __str += __elem.string<_CharT, _Traits, _Allocator>(__a); + __add_slash = __elem._M_type == _Type::_Filename; + } + return __str; + } inline std::string - path::generic_string() const { return string(); } + path::generic_string() const { return generic_string(); } #if _GLIBCXX_USE_WCHAR_T inline std::wstring - path::generic_wstring() const { return wstring(); } + path::generic_wstring() const { return generic_string(); } #endif #ifdef _GLIBCXX_USE_CHAR8_T inline std::u8string - path::generic_u8string() const { return u8string(); } + path::generic_u8string() const { return generic_string(); } #else inline std::string - path::generic_u8string() const { return u8string(); } + path::generic_u8string() const { return generic_string(); } #endif inline std::u16string - path::generic_u16string() const { return u16string(); } + path::generic_u16string() const { return generic_string(); } inline std::u32string - path::generic_u32string() const { return u32string(); } -#endif + path::generic_u32string() const { return generic_string(); } inline int path::compare(const string_type& __s) const { return compare(path(__s)); } diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc index 2788ebd3082..efaa452a586 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc @@ -23,27 +23,55 @@ #include #include -#include +#include using std::experimental::filesystem::path; void test01() { - for (const path& p : __gnu_test::test_paths) + __gnu_test::compare_paths( path("///a//b///").generic_string(), "/a/b/." ); + __gnu_test::compare_paths( path("///a//b").generic_u16string(), "/a/b" ); + __gnu_test::compare_paths( path("//a//b").generic_u16string(), "//a/b" ); +} + +using __gnu_test::SimpleAllocator; + +void +test02() +{ + path p = "//foo//bar//."; + using C = char16_t; + auto g = p.generic_string, SimpleAllocator>(); + VERIFY( g == u"//foo/bar/." ); +} + + +void +test03() +{ + for (path p : { "/a///b//c", "///a//b//c", "a:b//c", "a://b///c" }) { - path p2(p), p3; - p2.swap(p3); - VERIFY( p2 == path() ); - VERIFY( p3 == p ); - p2.swap(p3); - VERIFY( p2 == p ); - VERIFY( p3 == path() ); + // A path constructed from the generic format string should compare equal + // to the original, because they represent the same path. + VERIFY( path(p.generic_string()) == p ); + VERIFY( path(p.generic_wstring()) == p ); + VERIFY( path(p.generic_u8string()) == p ); + VERIFY( path(p.generic_u16string()) == p ); + VERIFY( path(p.generic_u32string()) == p ); } + + // Except when the original consists entirely of a root-directory with + // multiple slashes, because path("///").native() is "///" but the + // generic format string is "/". In the Filesystem TS path::compare just + // compares native strings, so path("///") != path("/"). + VERIFY( path("///").generic_string() == "/" ); } int main() { test01(); + test02(); + test03(); }