Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved string_view support #102

Merged
merged 1 commit into from
Feb 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 69 additions & 13 deletions include/ghc/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <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):
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -354,9 +389,13 @@ class GHC_FS_API_CLASS path
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>
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
Expand Down Expand Up @@ -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<value_type> x);
#ifdef GHC_WITH_STRING_VIEW
path& operator+=(basic_string_view<value_type> x);
#endif
path& operator+=(const value_type* x);
path& operator+=(value_type x);
Expand Down Expand Up @@ -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<value_type> s) const;
#ifdef GHC_WITH_STRING_VIEW
int compare(basic_string_view<value_type> s) const;
#endif
int compare(const value_type* s) const;

Expand Down Expand Up @@ -1521,8 +1560,8 @@ inline StringType fromUtf8(const Utf8String& utf8String, const typename StringTy
template <class StringType, typename charT, std::size_t N>
inline StringType fromUtf8(const charT (&utf8String)[N])
{
#ifdef __cpp_lib_string_view
return fromUtf8<StringType>(std::basic_string_view<charT>(utf8String, N - 1));
#ifdef GHC_WITH_STRING_VIEW
return fromUtf8<StringType>(basic_string_view<charT>(utf8String, N - 1));
#else
return fromUtf8<StringType>(std::basic_string<charT>(utf8String, N - 1));
#endif
Expand Down Expand Up @@ -1576,7 +1615,11 @@ inline std::string toUtf8(const strT& unicodeString)
template <typename charT>
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));
#endif
}

#ifdef GHC_USE_WCHAR_T
Expand Down Expand Up @@ -1622,7 +1665,11 @@ inline std::wstring toWChar(const strT& unicodeString)
template <typename charT>
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));
#endif
}
#endif // GHC_USE_WCHAR_T

Expand Down Expand Up @@ -2464,16 +2511,21 @@ 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<value_type> x)
#ifdef GHC_WITH_STRING_VIEW
GHC_INLINE path& path::operator+=(basic_string_view<value_type> x)
{
return concat(x);
}
#endif

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)
Expand Down Expand Up @@ -2501,7 +2553,11 @@ inline path::path_from_string<Source>& path::operator+=(const Source& x)
template <class EcharT>
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);
#endif
concat(part);
return *this;
}
Expand Down Expand Up @@ -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<value_type> s) const
#ifdef GHC_WITH_STRING_VIEW
GHC_INLINE int path::compare(basic_string_view<value_type> s) const
{
return compare(path(s));
}
Expand Down
29 changes: 21 additions & 8 deletions test/filesystem_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down