Skip to content

Commit

Permalink
refs #71, work on c++20 api changes
Browse files Browse the repository at this point in the history
  • Loading branch information
gulrak committed Dec 27, 2020
1 parent d2100b4 commit b345122
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 5 deletions.
66 changes: 61 additions & 5 deletions include/ghc/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@
#include <Availability.h>
#endif

#if defined(__cpp_impl_three_way_comparison) && defined(__has_include)
#if __has_include(<compare>)
#define GHC_HAS_THREEWAY_COMP
#include <compare>
#endif
#endif

#include <algorithm>
#include <cctype>
#include <chrono>
Expand All @@ -159,6 +166,13 @@
#include <vector>

#else // GHC_EXPAND_IMPL

#if defined(__cpp_impl_three_way_comparison) && defined(__has_include)
#if __has_include(<compare>)
#define GHC_HAS_THREEWAY_COMP
#include <compare>
#endif
#endif
#include <chrono>
#include <fstream>
#include <memory>
Expand Down Expand Up @@ -203,6 +217,10 @@
// instead of replacing them with the unicode replacement character (U+FFFD).
// #define GHC_RAISE_UNICODE_ERRORS
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Enforce C++17 API where possible when compiling for C++20, handles the following cases:
// * fs::path::u8string() returns std::string instead of std::u8string
// #define GHC_FILESYSTEM_ENFORCE_CPP17_API
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
#define GHC_FILESYSTEM_VERSION 10309L
Expand Down Expand Up @@ -381,7 +399,11 @@ class GHC_FS_API_CLASS path
std::basic_string<EcharT, traits, Allocator> string(const Allocator& a = Allocator()) const;
std::string string() const;
std::wstring wstring() const;
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
std::u8string u8string() const;
#else
std::string u8string() const;
#endif
std::u16string u16string() const;
std::u32string u32string() const;

Expand All @@ -390,7 +412,11 @@ class GHC_FS_API_CLASS path
std::basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const;
const std::string& generic_string() const; // this is different from the standard, that returns by value
std::wstring generic_wstring() const;
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
std::u8string generic_u8string() const;
#else
std::string generic_u8string() const;
#endif
std::u16string generic_u16string() const;
std::u32string generic_u32string() const;

Expand Down Expand Up @@ -480,13 +506,15 @@ class GHC_FS_API_CLASS path
// 30.10.8.6 path non-member functions
GHC_FS_API void swap(path& lhs, path& rhs) noexcept;
GHC_FS_API size_t hash_value(const path& p) noexcept;
#ifdef GHC_HAS_THREEWAY_COMP
GHC_FS_API std::strong_ordering operator<=>( const path& lhs, const path& rhs ) noexcept;
#endif
GHC_FS_API bool operator==(const path& lhs, const path& rhs) noexcept;
GHC_FS_API bool operator!=(const path& lhs, const path& rhs) noexcept;
GHC_FS_API bool operator<(const path& lhs, const path& rhs) noexcept;
GHC_FS_API bool operator<=(const path& lhs, const path& rhs) noexcept;
GHC_FS_API bool operator>(const path& lhs, const path& rhs) noexcept;
GHC_FS_API bool operator>=(const path& lhs, const path& rhs) noexcept;

GHC_FS_API path operator/(const path& lhs, const path& rhs);

// 30.10.8.6.1 path inserter and extractor
Expand All @@ -497,8 +525,14 @@ std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>&

// 30.10.8.6.2 path factory functions
template <class Source, typename = path::path_from_string<Source>>
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]]
#endif
path u8path(const Source& source);
template <class InputIterator>
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]]
#endif
path u8path(InputIterator first, InputIterator last);

// 30.10.9 class filesystem_error
Expand Down Expand Up @@ -2370,7 +2404,7 @@ GHC_INLINE path& path::operator/=(const path& p)
}
return *this;
}
if ((p.is_absolute() && (_path != root_name() || p._path != "/")) || (p.has_root_name() && p.root_name() != root_name())) {
if ((p.is_absolute() && (_path != root_name()._path || p._path != "/")) || (p.has_root_name() && p.root_name() != root_name())) {
assign(p);
return *this;
}
Expand Down Expand Up @@ -2640,10 +2674,17 @@ GHC_INLINE std::wstring path::wstring() const
#endif
}

#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
GHC_INLINE std::u8string path::u8string() const
{
return std::u8string(reinterpret_cast<const char8_t*>(native_impl().c_str()));
}
#else
GHC_INLINE std::string path::u8string() const
{
return native_impl();
}
#endif

GHC_INLINE std::u16string path::u16string() const
{
Expand Down Expand Up @@ -2677,10 +2718,17 @@ GHC_INLINE std::wstring path::generic_wstring() const
return detail::fromUtf8<std::wstring>(_path);
}

#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
GHC_INLINE std::u8string path::generic_u8string() const
{
return std::u8string(reinterpret_cast<const char8_t*>(_path.c_str()));
}
#else
GHC_INLINE std::string path::generic_u8string() const
{
return _path;
}
#endif

GHC_INLINE std::u16string path::generic_u16string() const
{
Expand Down Expand Up @@ -3212,6 +3260,13 @@ GHC_INLINE size_t hash_value(const path& p) noexcept
return std::hash<std::string>()(p.generic_string());
}

#ifdef GHC_HAS_THREEWAY_COMP
GHC_INLINE std::strong_ordering operator<=>( const path& lhs, const path& rhs ) noexcept
{
return lhs.compare(rhs) <=> 0;
}
#endif

GHC_INLINE bool operator==(const path& lhs, const path& rhs) noexcept
{
return lhs.compare(rhs) == 0;
Expand Down Expand Up @@ -3242,6 +3297,7 @@ GHC_INLINE bool operator>=(const path& lhs, const path& rhs) noexcept
return lhs.compare(rhs) >= 0;
}


GHC_INLINE path operator/(const path& lhs, const path& rhs)
{
path result(lhs);
Expand Down Expand Up @@ -3324,7 +3380,7 @@ GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const
, _p1(p1)
{
if (!_p1.empty()) {
_what_arg += ": '" + _p1.u8string() + "'";
_what_arg += ": '" + _p1.string() + "'";
}
}

Expand All @@ -3336,10 +3392,10 @@ GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const
, _p2(p2)
{
if (!_p1.empty()) {
_what_arg += ": '" + _p1.u8string() + "'";
_what_arg += ": '" + _p1.string() + "'";
}
if (!_p2.empty()) {
_what_arg += ", '" + _p2.u8string() + "'";
_what_arg += ", '" + _p2.string() + "'";
}
}

Expand Down
16 changes: 16 additions & 0 deletions test/filesystem_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,11 @@ TEST_CASE("30.10.8.4.6 path native format observers", "[filesystem][path][fs.pat
CHECK((std::string)fs::u8path("\xc3\xa4\\\xe2\x82\xac") == std::string("\xc3\xa4\\\xe2\x82\xac"));
#endif
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").wstring() == std::wstring(L"\u00E4\\\u20AC"));
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").u8string() == std::u8string(u8"\xc3\xa4\\\xe2\x82\xac"));
#else
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").u8string() == std::string("\xc3\xa4\\\xe2\x82\xac"));
#endif
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").u16string() == std::u16string(u"\u00E4\\\u20AC"));
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").u32string() == std::u32string(U"\U000000E4\\\U000020AC"));
#else
Expand All @@ -567,7 +571,11 @@ TEST_CASE("30.10.8.4.6 path native format observers", "[filesystem][path][fs.pat
CHECK((std::string)fs::u8path("\xc3\xa4/\xe2\x82\xac") == std::string("\xc3\xa4/\xe2\x82\xac"));
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").string() == std::string("\xc3\xa4/\xe2\x82\xac"));
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").wstring() == std::wstring(L"ä/€"));
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").u8string() == std::u8string(u8"\xc3\xa4/\xe2\x82\xac"));
#else
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").u8string() == std::string("\xc3\xa4/\xe2\x82\xac"));
#endif
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").u16string() == std::u16string(u"\u00E4/\u20AC"));
INFO("This check might fail on GCC8 (with \"Illegal byte sequence\") due to not detecting the valid unicode codepoint U+1D11E.");
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac\xf0\x9d\x84\x9e").u16string() == std::u16string(u"\u00E4/\u20AC\U0001D11E"));
Expand All @@ -586,7 +594,11 @@ TEST_CASE("30.10.8.4.7 path generic format observers", "[filesystem][path][fs.pa
CHECK(t.c_str() == std::string("\xc3\xa4/\xe2\x82\xac"));
#endif
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_wstring() == std::wstring(L"\U000000E4/\U000020AC"));
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_u8string() == std::u8string(u8"\xc3\xa4/\xe2\x82\xac"));
#else
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_u8string() == std::string("\xc3\xa4/\xe2\x82\xac"));
#endif
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_u16string() == std::u16string(u"\u00E4/\u20AC"));
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_u32string() == std::u32string(U"\U000000E4/\U000020AC"));
#else
Expand All @@ -596,7 +608,11 @@ TEST_CASE("30.10.8.4.7 path generic format observers", "[filesystem][path][fs.pa
CHECK(t.c_str() == std::string("\xc3\xa4/\xe2\x82\xac"));
#endif
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_wstring() == std::wstring(L"ä/€"));
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_u8string() == std::u8string(u8"\xc3\xa4/\xe2\x82\xac"));
#else
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_u8string() == std::string("\xc3\xa4/\xe2\x82\xac"));
#endif
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_u16string() == std::u16string(u"\u00E4/\u20AC"));
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_u32string() == std::u32string(U"\U000000E4/\U000020AC"));
#endif
Expand Down

0 comments on commit b345122

Please sign in to comment.