Commit a577c0c2 by Jonathan Wakely

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<C,T,A>()):
	* testsuite/experimental/filesystem/path/generic/generic_string.cc:
	Improve test coverage.
parent 9fc98511
2020-03-21 Jonathan Wakely <jwakely@redhat.com> 2020-03-21 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/93245
* include/experimental/bits/fs_path.h (path::generic_string<C,T,A>()):
* testsuite/experimental/filesystem/path/generic/generic_string.cc:
Improve test coverage.
PR libstdc++/94242 PR libstdc++/94242
* include/bits/fs_path.h (path::_S_str_convert): Replace first * include/bits/fs_path.h (path::_S_str_convert): Replace first
parameter with basic_string_view so that strings with different parameter with basic_string_view so that strings with different
......
...@@ -1086,34 +1086,56 @@ namespace __detail ...@@ -1086,34 +1086,56 @@ namespace __detail
inline std::u32string inline std::u32string
path::u32string() const { return string<char32_t>(); } path::u32string() const { return string<char32_t>(); }
#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS
template<typename _CharT, typename _Traits, typename _Allocator> template<typename _CharT, typename _Traits, typename _Allocator>
inline std::basic_string<_CharT, _Traits, _Allocator> inline std::basic_string<_CharT, _Traits, _Allocator>
path::generic_string(const _Allocator& __a) const 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 inline std::string
path::generic_string() const { return string(); } path::generic_string() const { return generic_string<char>(); }
#if _GLIBCXX_USE_WCHAR_T #if _GLIBCXX_USE_WCHAR_T
inline std::wstring inline std::wstring
path::generic_wstring() const { return wstring(); } path::generic_wstring() const { return generic_string<wchar_t>(); }
#endif #endif
#ifdef _GLIBCXX_USE_CHAR8_T #ifdef _GLIBCXX_USE_CHAR8_T
inline std::u8string inline std::u8string
path::generic_u8string() const { return u8string(); } path::generic_u8string() const { return generic_string<char8_t>(); }
#else #else
inline std::string inline std::string
path::generic_u8string() const { return u8string(); } path::generic_u8string() const { return generic_string<char>(); }
#endif #endif
inline std::u16string inline std::u16string
path::generic_u16string() const { return u16string(); } path::generic_u16string() const { return generic_string<char16_t>(); }
inline std::u32string inline std::u32string
path::generic_u32string() const { return u32string(); } path::generic_u32string() const { return generic_string<char32_t>(); }
#endif
inline int inline int
path::compare(const string_type& __s) const { return compare(path(__s)); } path::compare(const string_type& __s) const { return compare(path(__s)); }
......
...@@ -23,27 +23,55 @@ ...@@ -23,27 +23,55 @@
#include <experimental/filesystem> #include <experimental/filesystem>
#include <testsuite_fs.h> #include <testsuite_fs.h>
#include <testsuite_hooks.h> #include <testsuite_allocator.h>
using std::experimental::filesystem::path; using std::experimental::filesystem::path;
void void
test01() 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<C, std::char_traits<C>, SimpleAllocator<C>>();
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; // A path constructed from the generic format string should compare equal
p2.swap(p3); // to the original, because they represent the same path.
VERIFY( p2 == path() ); VERIFY( path(p.generic_string()) == p );
VERIFY( p3 == p ); VERIFY( path(p.generic_wstring()) == p );
p2.swap(p3); VERIFY( path(p.generic_u8string()) == p );
VERIFY( p2 == p ); VERIFY( path(p.generic_u16string()) == p );
VERIFY( p3 == path() ); 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 int
main() main()
{ {
test01(); test01();
test02();
test03();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment