Improved string_view support

This commit is contained in:
Владислав Щапов 2021-02-16 18:31:41 +05:00
parent daf0e7dfbf
commit b78b0239a3
2 changed files with 90 additions and 21 deletions

View File

@ -218,6 +218,31 @@
#endif #endif
#endif // GHC_EXPAND_IMPL #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 <string_view>
#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW)
#include <experimental/string_view>
#endif
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp): // Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp):
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -277,6 +302,16 @@
namespace ghc { namespace ghc {
namespace filesystem { 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 // temporary existing exception type for yet unimplemented parts
class GHC_FS_API_CLASS not_implemented_exception : public std::logic_error class GHC_FS_API_CLASS not_implemented_exception : public std::logic_error
{ {
@ -354,9 +389,13 @@ public:
struct _is_basic_string<std::basic_string<CharT, std::char_traits<CharT>, std::allocator<CharT>>> : std::true_type struct _is_basic_string<std::basic_string<CharT, std::char_traits<CharT>, std::allocator<CharT>>> : std::true_type
{ {
}; };
#ifdef __cpp_lib_string_view #ifdef GHC_WITH_STRING_VIEW
template <class CharT, class Traits>
struct _is_basic_string<basic_string_view<CharT, Traits>> : std::true_type
{
};
template <class CharT> template <class CharT>
struct _is_basic_string<std::basic_string_view<CharT>> : std::true_type struct _is_basic_string<basic_string_view<CharT, std::char_traits<CharT>>> : std::true_type
{ {
}; };
#endif #endif
@ -417,8 +456,8 @@ public:
// 30.10.8.4.4 concatenation // 30.10.8.4.4 concatenation
path& operator+=(const path& x); path& operator+=(const path& x);
path& operator+=(const string_type& x); path& operator+=(const string_type& x);
#ifdef __cpp_lib_string_view #ifdef GHC_WITH_STRING_VIEW
path& operator+=(std::basic_string_view<value_type> x); path& operator+=(basic_string_view<value_type> x);
#endif #endif
path& operator+=(const value_type* x); path& operator+=(const value_type* x);
path& operator+=(value_type x); path& operator+=(value_type x);
@ -471,8 +510,8 @@ public:
// 30.10.8.4.8 compare // 30.10.8.4.8 compare
int compare(const path& p) const noexcept; int compare(const path& p) const noexcept;
int compare(const string_type& s) const; int compare(const string_type& s) const;
#ifdef __cpp_lib_string_view #ifdef GHC_WITH_STRING_VIEW
int compare(std::basic_string_view<value_type> s) const; int compare(basic_string_view<value_type> s) const;
#endif #endif
int compare(const value_type* s) const; int compare(const value_type* s) const;
@ -1521,8 +1560,8 @@ inline StringType fromUtf8(const Utf8String& utf8String, const typename StringTy
template <class StringType, typename charT, std::size_t N> template <class StringType, typename charT, std::size_t N>
inline StringType fromUtf8(const charT (&utf8String)[N]) inline StringType fromUtf8(const charT (&utf8String)[N])
{ {
#ifdef __cpp_lib_string_view #ifdef GHC_WITH_STRING_VIEW
return fromUtf8<StringType>(std::basic_string_view<charT>(utf8String, N - 1)); return fromUtf8<StringType>(basic_string_view<charT>(utf8String, N - 1));
#else #else
return fromUtf8<StringType>(std::basic_string<charT>(utf8String, N - 1)); return fromUtf8<StringType>(std::basic_string<charT>(utf8String, N - 1));
#endif #endif
@ -1576,7 +1615,11 @@ inline std::string toUtf8(const strT& unicodeString)
template <typename charT> template <typename charT>
inline std::string toUtf8(const charT* unicodeString) inline std::string toUtf8(const charT* unicodeString)
{ {
#ifdef GHC_WITH_STRING_VIEW
return toUtf8(basic_string_view<charT, std::char_traits<charT>>(unicodeString));
#else
return toUtf8(std::basic_string<charT, std::char_traits<charT>>(unicodeString)); return toUtf8(std::basic_string<charT, std::char_traits<charT>>(unicodeString));
#endif
} }
#ifdef GHC_USE_WCHAR_T #ifdef GHC_USE_WCHAR_T
@ -1622,7 +1665,11 @@ inline std::wstring toWChar(const strT& unicodeString)
template <typename charT> template <typename charT>
inline std::wstring toWChar(const charT* unicodeString) inline std::wstring toWChar(const charT* unicodeString)
{ {
#ifdef GHC_WITH_STRING_VIEW
return toWChar(basic_string_view<charT, std::char_traits<charT>>(unicodeString));
#else
return toWChar(std::basic_string<charT, std::char_traits<charT>>(unicodeString)); return toWChar(std::basic_string<charT, std::char_traits<charT>>(unicodeString));
#endif
} }
#endif // GHC_USE_WCHAR_T #endif // GHC_USE_WCHAR_T
@ -2464,8 +2511,8 @@ GHC_INLINE path& path::operator+=(const string_type& x)
return concat(x); return concat(x);
} }
#ifdef __cpp_lib_string_view #ifdef GHC_WITH_STRING_VIEW
GHC_INLINE path& path::operator+=(std::basic_string_view<value_type> x) GHC_INLINE path& path::operator+=(basic_string_view<value_type> x)
{ {
return concat(x); return concat(x);
} }
@ -2473,7 +2520,12 @@ GHC_INLINE path& path::operator+=(std::basic_string_view<value_type> x)
GHC_INLINE path& path::operator+=(const value_type* x) GHC_INLINE path& path::operator+=(const value_type* x)
{ {
return concat(string_type(x)); #ifdef GHC_WITH_STRING_VIEW
basic_string_view<value_type> part(x);
#else
string_type part(x);
#endif
return concat(part);
} }
GHC_INLINE path& path::operator+=(value_type x) GHC_INLINE path& path::operator+=(value_type x)
@ -2501,7 +2553,11 @@ inline path::path_from_string<Source>& path::operator+=(const Source& x)
template <class EcharT> template <class EcharT>
inline path::path_type_EcharT<EcharT>& path::operator+=(EcharT x) inline path::path_type_EcharT<EcharT>& path::operator+=(EcharT x)
{ {
#ifdef GHC_WITH_STRING_VIEW
basic_string_view<EcharT> part(&x, 1);
#else
std::basic_string<EcharT> part(1, x); std::basic_string<EcharT> part(1, x);
#endif
concat(part); concat(part);
return *this; return *this;
} }
@ -2799,8 +2855,8 @@ GHC_INLINE int path::compare(const string_type& s) const
return compare(path(s)); return compare(path(s));
} }
#ifdef __cpp_lib_string_view #ifdef GHC_WITH_STRING_VIEW
GHC_INLINE int path::compare(std::basic_string_view<value_type> s) const GHC_INLINE int path::compare(basic_string_view<value_type> s) const
{ {
return compare(path(s)); return compare(path(s));
} }

View File

@ -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]") 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 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 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"); CHECK(fs::path(sv, fs::path::format::generic_format).generic_string() == "foo/bar");
fs::path p2("fo"); fs::path p2("fo");
p2 += std::string_view("o"); p2 += string_view("o");
CHECK(p2 == "foo"); CHECK(p2 == "foo");
CHECK(p2.compare(std::string_view("foo")) == 0); CHECK(p2.compare(string_view("foo")) == 0);
} }
{ {
auto p = fs::path{"XYZ"}; auto p = fs::path{"XYZ"};
p /= std::string_view("Appendix"); p /= string_view("Appendix");
CHECK(p == "XYZ/Appendix"); CHECK(p == "XYZ/Appendix");
} }
#if defined(IS_WCHAR_PATH) || defined(GHC_USE_WCHAR_T) #if defined(IS_WCHAR_PATH) || defined(GHC_USE_WCHAR_T)
{ {
std::wstring p(L"foo/bar"); 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"); CHECK(fs::path(sv, fs::path::format::generic_format).generic_string() == "foo/bar");
fs::path p2(L"fo"); fs::path p2(L"fo");
p2 += std::wstring_view(L"o"); p2 += wstring_view(L"o");
CHECK(p2 == "foo"); CHECK(p2 == "foo");
CHECK(p2.compare(std::wstring_view(L"foo")) == 0); CHECK(p2.compare(wstring_view(L"foo")) == 0);
} }
#endif #endif