From b78b0239a3734c5b2b175dfde294e20f3d9385c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D1=81=D0=BB=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=A9=D0=B0=D0=BF=D0=BE=D0=B2?= Date: Tue, 16 Feb 2021 18:31:41 +0500 Subject: [PATCH] Improved string_view support --- include/ghc/filesystem.hpp | 82 ++++++++++++++++++++++++++++++++------ test/filesystem_test.cpp | 29 ++++++++++---- 2 files changed, 90 insertions(+), 21 deletions(-) diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index de445a5..472c608 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -218,6 +218,31 @@ #endif #endif // GHC_EXPAND_IMPL +// After standard library includes. +// Standard library support for std::string_view. +#if defined(__cpp_lib_string_view) +#define GHC_HAS_STD_STRING_VIEW +#elif defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 4000) && (__cplusplus >= 201402) +#define GHC_HAS_STD_STRING_VIEW +#elif defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE >= 7) && (__cplusplus >= 201703) +#define GHC_HAS_STD_STRING_VIEW +#elif defined(_MSC_VER) && (_MSC_VER >= 1910 && _MSVC_LANG >= 201703) +#define GHC_HAS_STD_STRING_VIEW +#endif + +// Standard library support for std::experimental::string_view. +#if defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 3700 && _LIBCPP_VERSION < 7000) && (__cplusplus >= 201402) +#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW +#elif defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)) && (__cplusplus >= 201402) +#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW +#endif + +#if defined(GHC_HAS_STD_STRING_VIEW) +#include +#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW) +#include +#endif + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp): //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -277,6 +302,16 @@ namespace ghc { namespace filesystem { +#if defined(GHC_HAS_CUSTOM_STRING_VIEW) +#define GHC_WITH_STRING_VIEW +#elif defined(GHC_HAS_STD_STRING_VIEW) +#define GHC_WITH_STRING_VIEW +using std::basic_string_view; +#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW) +#define GHC_WITH_STRING_VIEW +using std::experimental::basic_string_view; +#endif + // temporary existing exception type for yet unimplemented parts class GHC_FS_API_CLASS not_implemented_exception : public std::logic_error { @@ -354,9 +389,13 @@ class GHC_FS_API_CLASS path struct _is_basic_string, std::allocator>> : std::true_type { }; -#ifdef __cpp_lib_string_view +#ifdef GHC_WITH_STRING_VIEW + template + struct _is_basic_string> : std::true_type + { + }; template - struct _is_basic_string> : std::true_type + struct _is_basic_string>> : std::true_type { }; #endif @@ -417,8 +456,8 @@ class GHC_FS_API_CLASS path // 30.10.8.4.4 concatenation path& operator+=(const path& x); path& operator+=(const string_type& x); -#ifdef __cpp_lib_string_view - path& operator+=(std::basic_string_view x); +#ifdef GHC_WITH_STRING_VIEW + path& operator+=(basic_string_view x); #endif path& operator+=(const value_type* x); path& operator+=(value_type x); @@ -471,8 +510,8 @@ class GHC_FS_API_CLASS path // 30.10.8.4.8 compare int compare(const path& p) const noexcept; int compare(const string_type& s) const; -#ifdef __cpp_lib_string_view - int compare(std::basic_string_view s) const; +#ifdef GHC_WITH_STRING_VIEW + int compare(basic_string_view s) const; #endif int compare(const value_type* s) const; @@ -1521,8 +1560,8 @@ inline StringType fromUtf8(const Utf8String& utf8String, const typename StringTy template inline StringType fromUtf8(const charT (&utf8String)[N]) { -#ifdef __cpp_lib_string_view - return fromUtf8(std::basic_string_view(utf8String, N - 1)); +#ifdef GHC_WITH_STRING_VIEW + return fromUtf8(basic_string_view(utf8String, N - 1)); #else return fromUtf8(std::basic_string(utf8String, N - 1)); #endif @@ -1576,7 +1615,11 @@ inline std::string toUtf8(const strT& unicodeString) template inline std::string toUtf8(const charT* unicodeString) { +#ifdef GHC_WITH_STRING_VIEW + return toUtf8(basic_string_view>(unicodeString)); +#else return toUtf8(std::basic_string>(unicodeString)); +#endif } #ifdef GHC_USE_WCHAR_T @@ -1622,7 +1665,11 @@ inline std::wstring toWChar(const strT& unicodeString) template inline std::wstring toWChar(const charT* unicodeString) { +#ifdef GHC_WITH_STRING_VIEW + return toWChar(basic_string_view>(unicodeString)); +#else return toWChar(std::basic_string>(unicodeString)); +#endif } #endif // GHC_USE_WCHAR_T @@ -2464,8 +2511,8 @@ GHC_INLINE path& path::operator+=(const string_type& x) return concat(x); } -#ifdef __cpp_lib_string_view -GHC_INLINE path& path::operator+=(std::basic_string_view x) +#ifdef GHC_WITH_STRING_VIEW +GHC_INLINE path& path::operator+=(basic_string_view x) { return concat(x); } @@ -2473,7 +2520,12 @@ GHC_INLINE path& path::operator+=(std::basic_string_view x) GHC_INLINE path& path::operator+=(const value_type* x) { - return concat(string_type(x)); +#ifdef GHC_WITH_STRING_VIEW + basic_string_view part(x); +#else + string_type part(x); +#endif + return concat(part); } GHC_INLINE path& path::operator+=(value_type x) @@ -2501,7 +2553,11 @@ inline path::path_from_string& path::operator+=(const Source& x) template inline path::path_type_EcharT& path::operator+=(EcharT x) { +#ifdef GHC_WITH_STRING_VIEW + basic_string_view part(&x, 1); +#else std::basic_string part(1, x); +#endif concat(part); return *this; } @@ -2799,8 +2855,8 @@ GHC_INLINE int path::compare(const string_type& s) const return compare(path(s)); } -#ifdef __cpp_lib_string_view -GHC_INLINE int path::compare(std::basic_string_view s) const +#ifdef GHC_WITH_STRING_VIEW +GHC_INLINE int path::compare(basic_string_view s) const { return compare(path(s)); } diff --git a/test/filesystem_test.cpp b/test/filesystem_test.cpp index 81a4d23..2ad464a 100644 --- a/test/filesystem_test.cpp +++ b/test/filesystem_test.cpp @@ -2740,31 +2740,44 @@ TEST_CASE("30.10.15.39 weakly_canonical", "[filesystem][operations][fs.op.weakly TEST_CASE("std::string_view support", "[filesystem][fs.string_view]") { -#if __cpp_lib_string_view +#if defined(GHC_HAS_STD_STRING_VIEW) || defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW) + +#if defined(GHC_HAS_STD_STRING_VIEW) using namespace std::literals; + using string_view = std::string_view; +#if defined(IS_WCHAR_PATH) || defined(GHC_USE_WCHAR_T) + using wstring_view = std::wstring_view; +#endif +#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW) + using string_view = std::experimental::string_view; +#if defined(IS_WCHAR_PATH) || defined(GHC_USE_WCHAR_T) + using wstring_view = std::experimental::wstring_view; +#endif +#endif + { std::string p("foo/bar"); - std::string_view sv(p); + string_view sv(p); CHECK(fs::path(sv, fs::path::format::generic_format).generic_string() == "foo/bar"); fs::path p2("fo"); - p2 += std::string_view("o"); + p2 += string_view("o"); CHECK(p2 == "foo"); - CHECK(p2.compare(std::string_view("foo")) == 0); + CHECK(p2.compare(string_view("foo")) == 0); } { auto p = fs::path{"XYZ"}; - p /= std::string_view("Appendix"); + p /= string_view("Appendix"); CHECK(p == "XYZ/Appendix"); } #if defined(IS_WCHAR_PATH) || defined(GHC_USE_WCHAR_T) { std::wstring p(L"foo/bar"); - std::wstring_view sv(p); + wstring_view sv(p); CHECK(fs::path(sv, fs::path::format::generic_format).generic_string() == "foo/bar"); fs::path p2(L"fo"); - p2 += std::wstring_view(L"o"); + p2 += wstring_view(L"o"); CHECK(p2 == "foo"); - CHECK(p2.compare(std::wstring_view(L"foo")) == 0); + CHECK(p2.compare(wstring_view(L"foo")) == 0); } #endif