Skip to content

Commit

Permalink
Fix up spaceship operators on path_view to match P1030R7.
Browse files Browse the repository at this point in the history
  • Loading branch information
ned14 committed Aug 29, 2024
1 parent e7b0ca8 commit 95a1816
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 44 deletions.
6 changes: 3 additions & 3 deletions include/llfio/revision.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
#define LLFIO_PREVIOUS_COMMIT_REF dc08ec4b231900c4236a0a6a493b6a30d91ae81a
#define LLFIO_PREVIOUS_COMMIT_DATE "2024-08-22 13:23:33 +00:00"
#define LLFIO_PREVIOUS_COMMIT_UNIQUE dc08ec4b
#define LLFIO_PREVIOUS_COMMIT_REF e7b0ca825515759b49176417c4ae1aa0d5b8a890
#define LLFIO_PREVIOUS_COMMIT_DATE "2024-08-23 11:19:37 +00:00"
#define LLFIO_PREVIOUS_COMMIT_UNIQUE e7b0ca82
226 changes: 185 additions & 41 deletions include/llfio/v2.0/path_view.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* A view of a path to something
(C) 2017-2022 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
(C) 2017-2024 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
File Created: Jul 2017
Expand Down Expand Up @@ -219,15 +219,20 @@ namespace detail
class path_view;
class path_view_component;
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator==(path_view_component x, path_view_component y) noexcept;
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator==(path_view x, path_view y) noexcept;
#if __cplusplus >= 202000L || _HAS_CXX20
inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(path_view_component x, path_view_component y) noexcept;
inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(path_view x, path_view y) noexcept;
#else
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator!=(path_view_component x, path_view_component y) noexcept;
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator<(path_view_component x, path_view_component y) noexcept;
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator!=(path_view x, path_view y) noexcept;
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator<(path_view x, path_view y) noexcept;
#endif
inline LLFIO_PATH_VIEW_CONSTEXPR size_t hash_value(path_view_component x) noexcept;
template <class F> inline LLFIO_PATH_VIEW_CONSTEXPR auto visit(path_view_component view, F &&f);
template <class F> inline LLFIO_PATH_VIEW_CONSTEXPR auto visit(F &&f, path_view_component view);
inline std::ostream &operator<<(std::ostream &s, const path_view_component &v);
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator==(path_view x, path_view y) noexcept;
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator!=(path_view x, path_view y) noexcept;
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator<(path_view x, path_view y) noexcept;
inline LLFIO_PATH_VIEW_CONSTEXPR size_t hash_value(path_view x) noexcept;

/*! \class path_view_component
Expand All @@ -238,21 +243,11 @@ class LLFIO_DECL path_view_component
friend class path_view;
friend class detail::path_view_iterator;
friend inline LLFIO_PATH_VIEW_CONSTEXPR bool LLFIO_V2_NAMESPACE::operator==(path_view_component x, path_view_component y) noexcept;
#if __cplusplus >= 202000L || _HAS_CXX20
friend inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(path_view_component x, path_view_component y) noexcept;
#else
friend inline LLFIO_PATH_VIEW_CONSTEXPR bool LLFIO_V2_NAMESPACE::operator!=(path_view_component x, path_view_component y) noexcept;
friend inline LLFIO_PATH_VIEW_CONSTEXPR bool LLFIO_V2_NAMESPACE::operator<(path_view_component x, path_view_component y) noexcept;
#if __cplusplus >= 202000L || _HAS_CXX20
friend inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(path_view_component x, path_view_component y) noexcept
{
if(x == y)
{
return std::strong_ordering::equal;
}
if(x < y)
{
return std::strong_ordering::less;
}
return std::strong_ordering::greater;
}
#endif
friend inline LLFIO_PATH_VIEW_CONSTEXPR size_t hash_value(path_view_component x) noexcept;
template <class F> friend inline LLFIO_PATH_VIEW_CONSTEXPR auto LLFIO_V2_NAMESPACE::visit(path_view_component view, F &&f);
Expand Down Expand Up @@ -1598,6 +1593,7 @@ class LLFIO_DECL path_view_component
};
static_assert(std::is_trivially_copyable<path_view_component>::value, "path_view_component is not trivially copyable!");
static_assert(sizeof(path_view_component) == 3 * sizeof(void *), "path_view_component is not three pointers in size!");

//! \brief Compares **identity** equality not equivalence i.e. backing storage type must be identical, and backing bytes must be identical. Use `compare()` if
//! you want something stronger.
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator==(path_view_component x, path_view_component y) noexcept
Expand Down Expand Up @@ -1635,6 +1631,106 @@ inline LLFIO_PATH_VIEW_CONSTEXPR bool operator==(path_view_component x, path_vie
const auto bytes = (x._wchar || x._utf16) ? (x._length * 2) : x._length;
return 0 == memcmp(x._bytestr, y._bytestr, bytes);
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>))
inline constexpr bool operator==(path_view_component /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator== with path_view_component and a string literal, use .compare<>()");
return false;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>))
inline constexpr bool operator==(const CharT * /*unused*/, path_view_component /*unused*/) noexcept
{
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator== with path_view_component and a string literal, use .compare<>()");
return false;
}
#if __cplusplus >= 202000L || _HAS_CXX20
inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(path_view_component x, path_view_component y) noexcept
{
if(x.native_size() < y.native_size())
{
return std::strong_ordering::less;
}
if(x.native_size() > y.native_size())
{
return std::strong_ordering::greater;
}
if(x._passthrough < y._passthrough)
{
return std::strong_ordering::less;
}
if(x._passthrough > y._passthrough)
{
return std::strong_ordering::greater;
}
if(x._char < y._char)
{
return std::strong_ordering::less;
}
if(x._char > y._char)
{
return std::strong_ordering::greater;
}
if(x._wchar < y._wchar)
{
return std::strong_ordering::less;
}
if(x._wchar > y._wchar)
{
return std::strong_ordering::greater;
}
if(x._utf8 < y._utf8)
{
return std::strong_ordering::less;
}
if(x._utf8 > y._utf8)
{
return std::strong_ordering::greater;
}
if(x._utf16 < y._utf16)
{
return std::strong_ordering::less;
}
if(x._utf16 > y._utf16)
{
return std::strong_ordering::greater;
}
if(x.native_size() == 0)
{
return std::strong_ordering::equal;
}
assert(x._bytestr != nullptr);
assert(y._bytestr != nullptr);
const auto bytes = (x._wchar || x._utf16) ? (x._length * 2) : x._length;
int comp = memcmp(x._bytestr, y._bytestr, bytes);
if(comp == 0)
{
return std::strong_ordering::equal;
}
else if(comp < 0)
{
return std::strong_ordering::less;
}
return std::strong_ordering::greater;
}

LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>))
inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(path_view_component /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator<=> with path_view_component and a string literal, use .compare<>()");
return std::strong_ordering::equal;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>))
inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(const CharT * /*unused*/, path_view_component /*unused*/) noexcept
{
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator<=> with path_view_component and a string literal, use .compare<>()");
return std::strong_ordering::equal;
}

#else
//! \brief Compares **identity** inequality not disequivalence i.e. backing storage type must be different, or backing bytes must be different. Use `compare()`
//! if you want something stronger.
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator!=(path_view_component x, path_view_component y) noexcept
Expand Down Expand Up @@ -1736,32 +1832,34 @@ inline LLFIO_PATH_VIEW_CONSTEXPR bool operator<(path_view_component x, path_view

LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>))
inline constexpr bool operator==(path_view_component /*unused*/, const CharT * /*unused*/) noexcept
inline constexpr bool operator!=(path_view_component /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator== with path_view_component and a string literal, use .compare<>()");
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator!= with path_view_component and a string literal, use .compare<>()");
return false;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>))
inline constexpr bool operator==(const CharT * /*unused*/, path_view_component /*unused*/) noexcept
inline constexpr bool operator!=(const CharT * /*unused*/, path_view_component /*unused*/) noexcept
{
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator== with path_view_component and a string literal, use .compare<>()");
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator!= with path_view_component and a string literal, use .compare<>()");
return false;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>))
inline constexpr bool operator!=(path_view_component /*unused*/, const CharT * /*unused*/) noexcept
inline constexpr bool operator<(path_view_component /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator!= with path_view_component and a string literal, use .compare<>()");
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator< with path_view_component and a string literal, use .compare<>()");
return false;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>))
inline constexpr bool operator!=(const CharT * /*unused*/, path_view_component /*unused*/) noexcept
inline constexpr bool operator<(const CharT * /*unused*/, path_view_component /*unused*/) noexcept
{
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator!= with path_view_component and a string literal, use .compare<>()");
static_assert(!path_view_component::is_source_acceptable<CharT>, "Do not use operator< with path_view_component and a string literal, use .compare<>()");
return false;
}
#endif

//! \brief Hashes a `path_view_component`.
inline LLFIO_PATH_VIEW_CONSTEXPR size_t hash_value(path_view_component view) noexcept
{
Expand Down Expand Up @@ -1915,10 +2013,11 @@ class path_view : public path_view_component
{
friend class detail::path_view_iterator;
friend inline LLFIO_PATH_VIEW_CONSTEXPR bool LLFIO_V2_NAMESPACE::operator==(path_view x, path_view y) noexcept;
#if __cplusplus >= 202000L || _HAS_CXX20
friend inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(path_view x, path_view y) noexcept;
#else
friend inline LLFIO_PATH_VIEW_CONSTEXPR bool LLFIO_V2_NAMESPACE::operator!=(path_view x, path_view y) noexcept;
friend inline LLFIO_PATH_VIEW_CONSTEXPR bool LLFIO_V2_NAMESPACE::operator<(path_view x, path_view y) noexcept;
#if __cplusplus >= 202000L || _HAS_CXX20
friend inline LLFIO_PATH_VIEW_CONSTEXPR auto operator<=>(path_view x, path_view y) = default;
#endif
friend inline LLFIO_PATH_VIEW_CONSTEXPR size_t hash_value(path_view x) noexcept;

Expand Down Expand Up @@ -2861,6 +2960,60 @@ inline LLFIO_PATH_VIEW_CONSTEXPR bool operator==(path_view x, path_view y) noexc
}
return true;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<CharT>))
inline constexpr bool operator==(path_view /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view::is_source_acceptable<CharT>, "Do not use operator== with path_view and a string literal, use .compare<>()");
return false;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<CharT>))
inline constexpr bool operator==(const CharT * /*unused*/, path_view /*unused*/) noexcept
{
static_assert(!path_view::is_source_acceptable<CharT>, "Do not use operator== with path_view and a string literal, use .compare<>()");
return false;
}
#if __cplusplus >= 202000L || _HAS_CXX20
inline LLFIO_PATH_VIEW_CONSTEXPR std::strong_ordering operator<=>(path_view x, path_view y) noexcept
{
auto it1 = x.begin(), it2 = y.begin();
for(; it1 != x.end() && it2 != y.end(); ++it1, ++it2)
{
if(*it1 < *it2)
{
return std::strong_ordering::less;
}
if(*it1 > *it2)
{
return std::strong_ordering::greater;
}
}
if(it1 == x.end() && it2 != y.end())
{
return std::strong_ordering::less;
}
if(it2 == x.end() && it1 != y.end())
{
return std::strong_ordering::greater;
}
return std::strong_ordering::equal;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<CharT>))
inline constexpr std::strong_ordering operator<=>(path_view /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view::is_source_acceptable<CharT>, "Do not use operator<=> with path_view and a string literal, use .compare<>()");
return std::strong_ordering::equal;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<CharT>))
inline constexpr std::strong_ordering operator<=>(const CharT * /*unused*/, path_view /*unused*/) noexcept
{
static_assert(!path_view::is_source_acceptable<CharT>, "Do not use operator<=> with path_view and a string literal, use .compare<>()");
return std::strong_ordering::equal;
}
#else
//! \brief Compares individual path view components for non-**identity** not disequivalence. Use `compare()` if you want something stronger.
inline LLFIO_PATH_VIEW_CONSTEXPR bool operator!=(path_view x, path_view y) noexcept
{
Expand Down Expand Up @@ -2892,6 +3045,10 @@ inline LLFIO_PATH_VIEW_CONSTEXPR bool operator<(path_view x, path_view y) noexce
{
return true;
}
if(*it2 < *it1)
{
return false;
}
}
if(it1 == x.end() && it2 != y.end())
{
Expand All @@ -2901,20 +3058,6 @@ inline LLFIO_PATH_VIEW_CONSTEXPR bool operator<(path_view x, path_view y) noexce
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<CharT>))
inline constexpr bool operator==(path_view /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view::is_source_acceptable<CharT>, "Do not use operator== with path_view and a string literal, use .compare<>()");
return false;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<CharT>))
inline constexpr bool operator==(const CharT * /*unused*/, path_view /*unused*/) noexcept
{
static_assert(!path_view::is_source_acceptable<CharT>, "Do not use operator== with path_view and a string literal, use .compare<>()");
return false;
}
LLFIO_TEMPLATE(class CharT)
LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<CharT>))
inline constexpr bool operator!=(path_view /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view::is_source_acceptable<CharT>, "Do not use operator!= with path_view and a string literal, use .compare<>()");
Expand All @@ -2927,6 +3070,7 @@ inline constexpr bool operator!=(const CharT * /*unused*/, path_view /*unused*/)
static_assert(!path_view::is_source_acceptable<CharT>, "Do not use operator!= with path_view and a string literal, use .compare<>()");
return false;
}
#endif
//! \brief Return the combined hash of individual path components
inline LLFIO_PATH_VIEW_CONSTEXPR size_t hash_value(path_view x) noexcept
{
Expand Down

0 comments on commit 95a1816

Please sign in to comment.