mirror of
https://git.mirrors.martin98.com/https://github.com/gulrak/filesystem
synced 2025-07-21 17:04:24 +08:00
first successfull compile/test on macOS with g++-9 in c++20 mode
This commit is contained in:
parent
10937ca294
commit
115b7c5c64
@ -481,6 +481,11 @@ to the expected behavior.
|
||||
|
||||
## Release Notes
|
||||
|
||||
### v1.3.0 (wip)
|
||||
|
||||
* Initial support for C++20 - `ghc::filesystem` now supports interfacing with
|
||||
`char8_t` based `std::u8string`, when compiled in C++20 mode.
|
||||
|
||||
### [v1.2.10](https://github.com/gulrak/filesystem/releases/tag/v1.2.10)
|
||||
|
||||
* The Visual Studio 2019 compiler, GCC 9.2 and Clang 9.0 where added to the
|
||||
|
@ -31,6 +31,11 @@ if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 O
|
||||
endif()
|
||||
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||
endif()
|
||||
if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 9.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0))
|
||||
add_executable(${targetName}_20 ${ARGN})
|
||||
set_property(TARGET ${targetName}_20 PROPERTY CXX_STANDARD 20)
|
||||
target_compile_definitions(${targetName}_20 PRIVATE USE_STD_FS)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15))
|
||||
add_executable(${targetName} ${ARGN})
|
||||
@ -41,3 +46,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQ
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
macro(AddExecutableWithCppStd targetName cppStd)
|
||||
if ((CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 9.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0)) OR
|
||||
("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 9.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0)))
|
||||
add_executable(${targetName} ${ARGN})
|
||||
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD ${cppStd})
|
||||
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
target_link_libraries(${targetName} ghc_filesystem)
|
||||
target_compile_options(${targetName} PRIVATE -fchar8_t -Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror)
|
||||
endif()
|
||||
endmacro()
|
||||
|
@ -260,9 +260,15 @@ public:
|
||||
path>::type;
|
||||
template <typename T>
|
||||
using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value, path>::type;
|
||||
#else
|
||||
#ifdef __cpp_lib_char8_t
|
||||
template <typename T>
|
||||
using path_from_string = typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value
|
||||
|| std::is_same<char8_t const*, typename std::decay<T>::type>::value || std::is_same<char8_t*, typename std::decay<T>::type>::value, path>::type;
|
||||
#else
|
||||
template <typename T>
|
||||
using path_from_string = typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value, path>::type;
|
||||
#endif
|
||||
template <typename T>
|
||||
using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value, path>::type;
|
||||
#endif
|
||||
@ -335,7 +341,11 @@ public:
|
||||
std::basic_string<EcharT, traits, Allocator> string(const Allocator& a = Allocator()) const;
|
||||
std::string string() const;
|
||||
std::wstring wstring() const;
|
||||
#ifdef __cpp_lib_char8_t
|
||||
std::u8string u8string() const;
|
||||
#else
|
||||
std::string u8string() const;
|
||||
#endif
|
||||
std::u16string u16string() const;
|
||||
std::u32string u32string() const;
|
||||
|
||||
@ -344,7 +354,11 @@ public:
|
||||
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;
|
||||
#ifdef __cpp_lib_char8_t
|
||||
std::u8string generic_u8string() const;
|
||||
#else
|
||||
std::string generic_u8string() const;
|
||||
#endif
|
||||
std::u16string generic_u16string() const;
|
||||
std::u32string generic_u32string() const;
|
||||
|
||||
@ -1297,12 +1311,20 @@ GHC_INLINE bool validUtf8(const std::string& utf8String)
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class StringType, typename std::enable_if<(sizeof(typename StringType::value_type) == 1)>::type* = nullptr>
|
||||
template <class StringType, typename std::enable_if<std::is_same<typename StringType::value_type, char>::value>::type* = nullptr>
|
||||
inline StringType fromUtf8(const std::string& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
|
||||
{
|
||||
return StringType(utf8String.begin(), utf8String.end(), alloc);
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
template <class StringType, typename std::enable_if<std::is_same<typename StringType::value_type, char8_t>::value>::type* = nullptr>
|
||||
inline StringType fromUtf8(const std::string& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
|
||||
{
|
||||
return StringType(reinterpret_cast<const char8_t*>(utf8String.data()), utf8String.length(), alloc);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class StringType, typename std::enable_if<(sizeof(typename StringType::value_type) == 2)>::type* = nullptr>
|
||||
inline StringType fromUtf8(const std::string& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
|
||||
{
|
||||
@ -1376,12 +1398,20 @@ inline StringType fromUtf8(const std::string& utf8String, const typename StringT
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename charT, typename traits, typename Alloc, typename std::enable_if<(sizeof(charT) == 1), int>::type size = 1>
|
||||
template <typename charT, typename traits, typename Alloc, typename std::enable_if<std::is_same<charT,char>::value, int>::type size = 1>
|
||||
inline std::string toUtf8(const std::basic_string<charT, traits, Alloc>& unicodeString)
|
||||
{
|
||||
return std::string(unicodeString.begin(), unicodeString.end());
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
template <typename charT, typename traits, typename Alloc, typename std::enable_if<std::is_same<charT,char8_t>::value, int>::type size = 1>
|
||||
inline std::string toUtf8(const std::basic_string<charT, traits, Alloc>& unicodeString)
|
||||
{
|
||||
return std::string(reinterpret_cast<const char*>(unicodeString.data()), unicodeString.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename charT, typename traits, typename Alloc, typename std::enable_if<(sizeof(charT) == 2), int>::type size = 2>
|
||||
inline std::string toUtf8(const std::basic_string<charT, traits, Alloc>& unicodeString)
|
||||
{
|
||||
@ -2400,10 +2430,17 @@ GHC_INLINE std::wstring path::wstring() const
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
GHC_INLINE std::u8string path::u8string() const
|
||||
{
|
||||
return detail::fromUtf8<std::u8string>(native_impl());
|
||||
}
|
||||
#else
|
||||
GHC_INLINE std::string path::u8string() const
|
||||
{
|
||||
return native_impl();
|
||||
}
|
||||
#endif
|
||||
|
||||
GHC_INLINE std::u16string path::u16string() const
|
||||
{
|
||||
@ -2437,10 +2474,17 @@ GHC_INLINE std::wstring path::generic_wstring() const
|
||||
return detail::fromUtf8<std::wstring>(_path);
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
GHC_INLINE std::u8string path::generic_u8string() const
|
||||
{
|
||||
return detail::fromUtf8<std::u8string>(_path);
|
||||
}
|
||||
#else
|
||||
GHC_INLINE std::string path::generic_u8string() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
#endif
|
||||
|
||||
GHC_INLINE std::u16string path::generic_u16string() const
|
||||
{
|
||||
@ -2999,7 +3043,11 @@ GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const
|
||||
, _p1(p1)
|
||||
{
|
||||
if (!_p1.empty()) {
|
||||
#ifdef __cpp_lib_char8_t
|
||||
_what_arg += ": '" + detail::toUtf8(_p1.u8string()) + "'";
|
||||
#else
|
||||
_what_arg += ": '" + _p1.u8string() + "'";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -3011,10 +3059,18 @@ GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const
|
||||
, _p2(p2)
|
||||
{
|
||||
if (!_p1.empty()) {
|
||||
#ifdef __cpp_lib_char8_t
|
||||
_what_arg += ": '" + detail::toUtf8(_p1.u8string()) + "'";
|
||||
#else
|
||||
_what_arg += ": '" + _p1.u8string() + "'";
|
||||
#endif
|
||||
}
|
||||
if (!_p2.empty()) {
|
||||
#ifdef __cpp_lib_char8_t
|
||||
_what_arg += ", '" + detail::toUtf8(_p2.u8string()) + "'";
|
||||
#else
|
||||
_what_arg += ", '" + _p2.u8string() + "'";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ else()
|
||||
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
ParseAndAddCatchTests(filesystem_test)
|
||||
AddExecutableWithCppStd(filesystem_test_20 20 filesystem_test.cpp catch.hpp)
|
||||
AddExecutableWithStdFS(std_filesystem_test filesystem_test.cpp catch.hpp)
|
||||
if(WIN32)
|
||||
add_executable(filesystem_test_wchar filesystem_test.cpp catch.hpp)
|
||||
|
@ -29,8 +29,9 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
#include <algorithm>
|
||||
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
@ -48,6 +49,7 @@
|
||||
|
||||
#ifdef USE_STD_FS
|
||||
#include <filesystem>
|
||||
#include <codecvt>
|
||||
namespace fs {
|
||||
using namespace std::filesystem;
|
||||
using ifstream = std::ifstream;
|
||||
@ -89,6 +91,7 @@ using fstream = ghc::filesystem::fstream;
|
||||
#ifndef GHC_FILESYSTEM_FWD_TEST
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#endif
|
||||
#define CATCH_CONFIG_NO_WCHAR
|
||||
#include "catch.hpp"
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@ -135,6 +138,25 @@ struct StringMaker<fs::perms>
|
||||
static std::string convert(fs::perms const& value) { return std::to_string(static_cast<unsigned int>(value)); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringMaker<std::wstring>
|
||||
{
|
||||
static std::string convert(std::wstring const& value)
|
||||
{
|
||||
#ifdef USE_STD_FS
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wcu8;
|
||||
#else
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> wcu8;
|
||||
#endif
|
||||
return wcu8.to_bytes( value );
|
||||
#else
|
||||
return ghc::filesystem::detail::toUtf8(value);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct StringMaker<fs::file_time_type>
|
||||
{
|
||||
@ -269,6 +291,27 @@ static bool has_host_root_name_support()
|
||||
return fs::path("//host").has_root_name();
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
inline std::string U8S(const std::u8string& str)
|
||||
{
|
||||
std::string result(reinterpret_cast<const std::string::value_type*>(str.data()), str.length());
|
||||
return result;
|
||||
}
|
||||
inline const char* U8C(const char8_t* str)
|
||||
{
|
||||
return reinterpret_cast<const char*>(str);
|
||||
}
|
||||
#else
|
||||
inline std::string U8S(const std::string& str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
inline const char* U8C(const char* str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
class TestAllocator
|
||||
{
|
||||
@ -315,13 +358,13 @@ TEST_CASE("fs::detail::fromUtf8", "[filesystem][fs.detail.utf8]")
|
||||
{
|
||||
CHECK(fs::detail::fromUtf8<std::wstring>("foobar").length() == 6);
|
||||
CHECK(fs::detail::fromUtf8<std::wstring>("foobar") == L"foobar");
|
||||
CHECK(fs::detail::fromUtf8<std::wstring>(u8"föobar").length() == 6);
|
||||
CHECK(fs::detail::fromUtf8<std::wstring>(u8"föobar") == L"föobar");
|
||||
CHECK(fs::detail::fromUtf8<std::wstring>(U8S(u8"föobar")).length() == 6);
|
||||
CHECK(fs::detail::fromUtf8<std::wstring>(U8S(u8"föobar")) == L"föobar");
|
||||
|
||||
CHECK(fs::detail::toUtf8(std::wstring(L"foobar")).length() == 6);
|
||||
CHECK(fs::detail::toUtf8(std::wstring(L"foobar")) == "foobar");
|
||||
CHECK(fs::detail::toUtf8(std::wstring(L"föobar")).length() == 7);
|
||||
CHECK(fs::detail::toUtf8(std::wstring(L"föobar")) == u8"föobar");
|
||||
CHECK(fs::detail::toUtf8(std::wstring(L"föobar")) == U8C(u8"föobar"));
|
||||
|
||||
#ifdef GHC_RAISE_UNICODE_ERRORS
|
||||
CHECK_THROWS_AS(fs::detail::fromUtf8<std::u16string>(std::string("\xed\xa0\x80")), fs::filesystem_error);
|
||||
@ -563,16 +606,21 @@ TEST_CASE("30.10.8.4.6 path native format observers", "[filesystem][path][fs.pat
|
||||
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
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").native() == fs::path::string_type(u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
CHECK(!::strcmp(fs::u8path("\xc3\xa4/\xe2\x82\xac").c_str(), u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
CHECK((std::string)fs::u8path("\xc3\xa4/\xe2\x82\xac") == std::string(u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").string() == std::string(u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").native() == fs::path::string_type(U8S(u8"\xc3\xa4/\xe2\x82\xac")));
|
||||
CHECK(!::strcmp(fs::u8path("\xc3\xa4/\xe2\x82\xac").c_str(), U8C(u8"\xc3\xa4/\xe2\x82\xac")));
|
||||
CHECK((std::string)fs::u8path("\xc3\xa4/\xe2\x82\xac") == std::string(U8C(u8"\xc3\xa4/\xe2\x82\xac")));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").string() == std::string(U8C(u8"\xc3\xa4/\xe2\x82\xac")));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").wstring() == std::wstring(L"\u00E4/\u20AC"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").wstring() == std::wstring(L"ä/€"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").u8string() == std::string(u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").wstring().length() == std::wstring(L"\u00E4/\u20AC").length());
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").u8string() == (u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
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"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").u32string() == std::u32string(U"\U000000E4/\U000020AC"));
|
||||
#ifdef __cpp_char8_t
|
||||
CHECK(fs::path(u8"\xc3\xa4/\xe2\x82\xac").u8string() == u8"\xc3\xa4/\xe2\x82\xac");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -591,13 +639,13 @@ TEST_CASE("30.10.8.4.7 path generic format observers", "[filesystem][path][fs.pa
|
||||
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
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_string() == std::string(u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_string() == std::string(U8S(u8"\xc3\xa4/\xe2\x82\xac")));
|
||||
#ifndef USE_STD_FS
|
||||
auto t = fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_string<char, std::char_traits<char>, TestAllocator<char>>();
|
||||
CHECK(t.c_str() == std::string(u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
CHECK(t.c_str() == std::string(U8S(u8"\xc3\xa4/\xe2\x82\xac")));
|
||||
#endif
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_wstring() == std::wstring(L"ä/€"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_u8string() == std::string(u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
CHECK(fs::u8path("\xc3\xa4/\xe2\x82\xac").generic_u8string() == (u8"\xc3\xa4/\xe2\x82\xac"));
|
||||
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
|
||||
|
@ -4,6 +4,7 @@
|
||||
// fs_fwd.hpp (to test this with maximum functionality, the unit tests
|
||||
// are included here, signaling they should only include the fs_fwd.hpp)
|
||||
#define NOMINMAX
|
||||
#include <cstdio>
|
||||
#include <ghc/fs_impl.hpp>
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
Loading…
x
Reference in New Issue
Block a user