summaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2020-03-21 22:11:44 +0000
committerJonathan Wakely <jwakely@redhat.com>2020-03-21 22:11:44 +0000
commita577c0c26931090e7c25e56ef5ffc807627961ec (patch)
treed5ba69e0d731c6255ab49ea2810edca0d0efe8f3 /libstdc++-v3
parent9fc985118d9f5014afc1caf32a411ee5803fba61 (diff)
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.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog5
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_path.h40
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc46
3 files changed, 73 insertions, 18 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 52944dd475c..7b9c30e3b64 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,10 @@
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
* include/bits/fs_path.h (path::_S_str_convert): Replace first
parameter with basic_string_view so that strings with different
diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h
index 7b3d9926e60..d7234c08a00 100644
--- a/libstdc++-v3/include/experimental/bits/fs_path.h
+++ b/libstdc++-v3/include/experimental/bits/fs_path.h
@@ -1086,34 +1086,56 @@ namespace __detail
inline std::u32string
path::u32string() const { return string<char32_t>(); }
-#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS
template<typename _CharT, typename _Traits, typename _Allocator>
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<char>(); }
#if _GLIBCXX_USE_WCHAR_T
inline std::wstring
- path::generic_wstring() const { return wstring(); }
+ path::generic_wstring() const { return generic_string<wchar_t>(); }
#endif
#ifdef _GLIBCXX_USE_CHAR8_T
inline std::u8string
- path::generic_u8string() const { return u8string(); }
+ path::generic_u8string() const { return generic_string<char8_t>(); }
#else
inline std::string
- path::generic_u8string() const { return u8string(); }
+ path::generic_u8string() const { return generic_string<char>(); }
#endif
inline std::u16string
- path::generic_u16string() const { return u16string(); }
+ path::generic_u16string() const { return generic_string<char16_t>(); }
inline std::u32string
- path::generic_u32string() const { return u32string(); }
-#endif
+ path::generic_u32string() const { return generic_string<char32_t>(); }
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 40b39d22023..aa977847436 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 <experimental/filesystem>
#include <testsuite_fs.h>
-#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
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<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;
- 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();
}