diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp
index a102711b..a352921b 100644
--- a/include/llfio/revision.hpp
+++ b/include/llfio/revision.hpp
@@ -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
diff --git a/include/llfio/v2.0/path_view.hpp b/include/llfio/v2.0/path_view.hpp
index 7bdc5b04..ab899ed7 100644
--- a/include/llfio/v2.0/path_view.hpp
+++ b/include/llfio/v2.0/path_view.hpp
@@ -1,5 +1,5 @@
/* A view of a path to something
-(C) 2017-2022 Niall Douglas (20 commits)
+(C) 2017-2024 Niall Douglas (20 commits)
File Created: Jul 2017
@@ -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 inline LLFIO_PATH_VIEW_CONSTEXPR auto visit(path_view_component view, F &&f);
template 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
@@ -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 friend inline LLFIO_PATH_VIEW_CONSTEXPR auto LLFIO_V2_NAMESPACE::visit(path_view_component view, F &&f);
@@ -1598,6 +1593,7 @@ class LLFIO_DECL path_view_component
};
static_assert(std::is_trivially_copyable::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
@@ -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))
+inline constexpr bool operator==(path_view_component /*unused*/, const CharT * /*unused*/) noexcept
+{
+ static_assert(!path_view_component::is_source_acceptable, "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))
+inline constexpr bool operator==(const CharT * /*unused*/, path_view_component /*unused*/) noexcept
+{
+ static_assert(!path_view_component::is_source_acceptable, "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))
+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, "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))
+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, "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
@@ -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))
-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, "Do not use operator== with path_view_component and a string literal, use .compare<>()");
+ static_assert(!path_view_component::is_source_acceptable, "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))
-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, "Do not use operator== with path_view_component and a string literal, use .compare<>()");
+ static_assert(!path_view_component::is_source_acceptable, "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))
-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, "Do not use operator!= with path_view_component and a string literal, use .compare<>()");
+ static_assert(!path_view_component::is_source_acceptable, "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))
-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, "Do not use operator!= with path_view_component and a string literal, use .compare<>()");
+ static_assert(!path_view_component::is_source_acceptable, "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
{
@@ -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;
@@ -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))
+inline constexpr bool operator==(path_view /*unused*/, const CharT * /*unused*/) noexcept
+{
+ static_assert(!path_view::is_source_acceptable, "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))
+inline constexpr bool operator==(const CharT * /*unused*/, path_view /*unused*/) noexcept
+{
+ static_assert(!path_view::is_source_acceptable, "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))
+inline constexpr std::strong_ordering operator<=>(path_view /*unused*/, const CharT * /*unused*/) noexcept
+{
+ static_assert(!path_view::is_source_acceptable, "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))
+inline constexpr std::strong_ordering operator<=>(const CharT * /*unused*/, path_view /*unused*/) noexcept
+{
+ static_assert(!path_view::is_source_acceptable, "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
{
@@ -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())
{
@@ -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))
-inline constexpr bool operator==(path_view /*unused*/, const CharT * /*unused*/) noexcept
-{
- static_assert(!path_view::is_source_acceptable, "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))
-inline constexpr bool operator==(const CharT * /*unused*/, path_view /*unused*/) noexcept
-{
- static_assert(!path_view::is_source_acceptable, "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))
inline constexpr bool operator!=(path_view /*unused*/, const CharT * /*unused*/) noexcept
{
static_assert(!path_view::is_source_acceptable, "Do not use operator!= with path_view and a string literal, use .compare<>()");
@@ -2927,6 +3070,7 @@ inline constexpr bool operator!=(const CharT * /*unused*/, path_view /*unused*/)
static_assert(!path_view::is_source_acceptable, "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
{