Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ned14/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiall Douglas <s_github@nedprod.com>2022-09-19 22:14:04 +0300
committerNiall Douglas <s_github@nedprod.com>2022-09-19 22:14:04 +0300
commitf8d2eebeb1742a5ebec4da856d47ba6fd1a48a8c (patch)
treed6c099781c48e27445645e4f2d17b4436e1a9f5b
parent85eb69464878d4b36bacb337ec665176aea8fe69 (diff)
path_view: Final set of changes to match reference implementation with upcoming P1030R5.all_tests_passed_f8d2eebeb1742a5ebec4da856d47ba6fd1a48a8cmaster
-rw-r--r--include/llfio/revision.hpp6
-rw-r--r--include/llfio/v2.0/path_view.hpp383
2 files changed, 323 insertions, 66 deletions
diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp
index 8643f53d..f7490426 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 05141b444da3ce26740fa0a22baac7f13704609e
-#define LLFIO_PREVIOUS_COMMIT_DATE "2022-09-13 17:12:48 +00:00"
-#define LLFIO_PREVIOUS_COMMIT_UNIQUE 05141b44
+#define LLFIO_PREVIOUS_COMMIT_REF 85eb69464878d4b36bacb337ec665176aea8fe69
+#define LLFIO_PREVIOUS_COMMIT_DATE "2022-09-15 14:04:57 +00:00"
+#define LLFIO_PREVIOUS_COMMIT_UNIQUE 85eb6946
diff --git a/include/llfio/v2.0/path_view.hpp b/include/llfio/v2.0/path_view.hpp
index e7cdb802..309d1962 100644
--- a/include/llfio/v2.0/path_view.hpp
+++ b/include/llfio/v2.0/path_view.hpp
@@ -30,6 +30,10 @@ Distributed under the Boost Software License, Version 1.0.
#include <iterator>
#include <memory> // for unique_ptr
+#if __cplusplus >= 202000L || _HAS_CXX20
+#include <compare>
+#endif
+
#include "quickcpplib/algorithm/hash.hpp"
//! \file path_view.hpp Provides view of a path
@@ -208,12 +212,14 @@ 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_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 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
@@ -225,6 +231,21 @@ class LLFIO_DECL path_view_component
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;
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);
template <class F> friend inline LLFIO_PATH_VIEW_CONSTEXPR auto LLFIO_V2_NAMESPACE::visit(F &&f, path_view_component view);
@@ -924,60 +945,60 @@ private:
~_rendered_path_base_() = default;
//! Begin iteration
- constexpr iterator begin() { return _ref.begin(); }
+ constexpr iterator begin() noexcept { return _ref.begin(); }
//! Begin iteration
- constexpr const_iterator begin() const { return _ref.begin(); }
+ constexpr const_iterator begin() const noexcept { return _ref.begin(); }
//! Begin iteration
- constexpr const_iterator cbegin() const { return _ref.cbegin(); }
+ constexpr const_iterator cbegin() const noexcept { return _ref.cbegin(); }
//! End iteration
- constexpr iterator end() { return _ref.end(); }
+ constexpr iterator end() noexcept { return _ref.end(); }
//! End iteration
- constexpr const_iterator end() const { return _ref.end(); }
+ constexpr const_iterator end() const noexcept { return _ref.end(); }
//! End iteration
- constexpr const_iterator cend() const { return _ref.cend(); }
+ constexpr const_iterator cend() const noexcept { return _ref.cend(); }
//! Begin reverse iteration
- constexpr reverse_iterator rbegin() { return _ref.rbegin(); }
+ constexpr reverse_iterator rbegin() noexcept { return _ref.rbegin(); }
//! Begin reverse iteration
- constexpr const_reverse_iterator rbegin() const { return _ref.rbegin(); }
+ constexpr const_reverse_iterator rbegin() const noexcept { return _ref.rbegin(); }
//! Begin reverse iteration
- constexpr const_reverse_iterator crbegin() const { return _ref.crbegin(); }
+ constexpr const_reverse_iterator crbegin() const noexcept { return _ref.crbegin(); }
//! End reverse iteration
- constexpr reverse_iterator rend() { return _ref.rend(); }
+ constexpr reverse_iterator rend() noexcept { return _ref.rend(); }
//! End reverse iteration
- constexpr const_reverse_iterator rend() const { return _ref.rend(); }
+ constexpr const_reverse_iterator rend() const noexcept { return _ref.rend(); }
//! End reverse iteration
- constexpr const_reverse_iterator crend() const { return _ref.crend(); }
+ constexpr const_reverse_iterator crend() const noexcept { return _ref.crend(); }
//! Access
- constexpr reference operator[](size_type idx) { return _ref[idx]; }
+ constexpr reference operator[](size_type idx) noexcept { return _ref[idx]; }
//! Access
- constexpr const_reference operator[](size_type idx) const { return _ref[idx]; }
+ constexpr const_reference operator[](size_type idx) const noexcept { return _ref[idx]; }
//! Access
constexpr reference at(size_type idx) { return _ref.at(idx); }
//! Access
constexpr const_reference at(size_type idx) const { return _ref.at(idx); }
//! Access
- constexpr reference front() { return _ref.front(); }
+ constexpr reference front() noexcept { return _ref.front(); }
//! Access
- constexpr const_reference front() const { return _ref.front(); }
+ constexpr const_reference front() const noexcept { return _ref.front(); }
//! Access
- constexpr reference back() { return _ref.back(); }
+ constexpr reference back() noexcept { return _ref.back(); }
//! Access
- constexpr const_reference back() const { return _ref.back(); }
+ constexpr const_reference back() const noexcept { return _ref.back(); }
//! Access
- constexpr pointer data() { return _ref.data(); }
+ constexpr pointer data() noexcept { return _ref.data(); }
//! Access
- constexpr const_pointer data() const { return _ref.data(); }
+ constexpr const_pointer data() const noexcept { return _ref.data(); }
//! Size
- constexpr size_type size() const { return _ref.size(); }
+ constexpr size_type size() const noexcept { return _ref.size(); }
//! Size
- constexpr size_type length() const { return _ref.length(); }
+ constexpr size_type length() const noexcept { return _ref.length(); }
//! Max size
- constexpr size_type max_size() const { return _ref.max_size(); }
+ constexpr size_type max_size() const noexcept { return _ref.max_size(); }
//! Empty
- QUICKCPPLIB_NODISCARD constexpr bool empty() const { return _ref.empty(); }
+ QUICKCPPLIB_NODISCARD constexpr bool empty() const noexcept { return _ref.empty(); }
//! As span
- constexpr _view_type as_span() const { return _ref; }
+ constexpr _view_type as_span() const noexcept { return _ref; }
};
template <enum path_view_component::zero_termination ZeroTermination, class T, bool = false> struct _rendered_path_base : public _rendered_path_base_<T>
{
@@ -1580,6 +1601,39 @@ public:
template <class T = typename filesystem::path::value_type, class AllocatorOrDeleter = default_rendered_path_deleter<T[]>,
size_t _internal_buffer_size = default_internal_buffer_size>
using not_zero_terminated_rendered_path = rendered_path<zero_termination::not_zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>;
+ //! Convenience function
+ LLFIO_TEMPLATE(enum path_view_component::zero_termination ZeroTermination, class T = typename filesystem::path::value_type,
+ class AllocatorOrDeleter = default_rendered_path_deleter<T[]>, size_t _internal_buffer_size = default_internal_buffer_size, class... Args)
+ LLFIO_TREQUIRES(
+ LLFIO_TPRED(is_source_acceptable<T>),
+ LLFIO_TEXPR(std::is_constructible<rendered_path<ZeroTermination, T, AllocatorOrDeleter, _internal_buffer_size>, path_view_component, Args...>::value))
+ rendered_path<ZeroTermination, T, AllocatorOrDeleter, _internal_buffer_size> render(path_view_component view, Args &&...args)
+ {
+ return rendered_path<ZeroTermination, T, AllocatorOrDeleter, _internal_buffer_size>(view, std::forward<Args>(args)...);
+ }
+ //! Convenience function
+ LLFIO_TEMPLATE(class T = typename filesystem::path::value_type, class AllocatorOrDeleter = default_rendered_path_deleter<T[]>,
+ size_t _internal_buffer_size = default_internal_buffer_size, class... Args)
+ LLFIO_TREQUIRES(LLFIO_TPRED(is_source_acceptable<T>),
+ LLFIO_TEXPR(std::is_constructible<rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>,
+ path_view_component, Args...>::value))
+ rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size> render_zero_terminated(path_view_component view,
+ Args &&...args)
+ {
+ return rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>(view, std::forward<Args>(args)...);
+ }
+ //! Convenience function
+ LLFIO_TEMPLATE(class T = typename filesystem::path::value_type, class AllocatorOrDeleter = default_rendered_path_deleter<T[]>,
+ size_t _internal_buffer_size = default_internal_buffer_size, class... Args)
+ LLFIO_TREQUIRES(LLFIO_TPRED(is_source_acceptable<T>),
+ LLFIO_TEXPR(std::is_constructible<rendered_path<zero_termination::zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>,
+ path_view_component, Args...>::value))
+ rendered_path<zero_termination::not_zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size> render_not_zero_terminated(path_view_component view,
+ Args &&...args)
+ {
+ return rendered_path<zero_termination::not_zero_terminated, T, AllocatorOrDeleter, _internal_buffer_size>(view, std::forward<Args>(args)...);
+ }
+
#ifdef __cpp_concepts
template <enum path_view_component::zero_termination ZeroTermination, class T, class Deleter, size_t _internal_buffer_size>
requires(is_source_acceptable<T>)
@@ -1621,7 +1675,7 @@ inline LLFIO_PATH_VIEW_CONSTEXPR bool operator==(path_view_component x, path_vie
{
return false;
}
- if(0 == x._length && 0 == y._length)
+ if(x.native_size() == 0)
{
return true;
}
@@ -1658,7 +1712,7 @@ inline LLFIO_PATH_VIEW_CONSTEXPR bool operator!=(path_view_component x, path_vie
{
return true;
}
- if(0 == x._length && 0 == y._length)
+ if(x.native_size() == 0)
{
return false;
}
@@ -1667,6 +1721,68 @@ 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);
}
+//! \brief Compares **identity** for ordering 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
+{
+ if(x.native_size() < y.native_size())
+ {
+ return true;
+ }
+ if(x.native_size() > y.native_size())
+ {
+ return false;
+ }
+ if(x._passthrough < y._passthrough)
+ {
+ return true;
+ }
+ if(x._passthrough > y._passthrough)
+ {
+ return false;
+ }
+ if(x._char < y._char)
+ {
+ return true;
+ }
+ if(x._char > y._char)
+ {
+ return false;
+ }
+ if(x._wchar < y._wchar)
+ {
+ return true;
+ }
+ if(x._wchar > y._wchar)
+ {
+ return false;
+ }
+ if(x._utf8 < y._utf8)
+ {
+ return true;
+ }
+ if(x._utf8 > y._utf8)
+ {
+ return false;
+ }
+ if(x._utf16 < y._utf16)
+ {
+ return true;
+ }
+ if(x._utf16 > y._utf16)
+ {
+ return false;
+ }
+ if(x.native_size() == 0)
+ {
+ return false;
+ }
+ assert(x._bytestr != nullptr);
+ assert(y._bytestr != nullptr);
+ const auto bytes = (x._wchar || x._utf16) ? (x._length * 2) : x._length;
+ return memcmp(x._bytestr, y._bytestr, bytes) < 0;
+}
+
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
@@ -1849,6 +1965,10 @@ 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;
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;
public:
@@ -2009,17 +2129,35 @@ public:
path_view &operator=(path_view &&p) noexcept = default;
//! True if has root path
- LLFIO_PATH_VIEW_CONSTEXPR bool has_root_path() const noexcept { return !root_path().empty(); }
+ LLFIO_PATH_VIEW_CONSTEXPR bool has_root_path() const noexcept
+ {
+ return !root_path().empty();
+ }
//! True if has root name
- LLFIO_PATH_VIEW_CONSTEXPR bool has_root_name() const noexcept { return !root_name().empty(); }
+ LLFIO_PATH_VIEW_CONSTEXPR bool has_root_name() const noexcept
+ {
+ return !root_name().empty();
+ }
//! True if has root directory
- LLFIO_PATH_VIEW_CONSTEXPR bool has_root_directory() const noexcept { return !root_directory().empty(); }
+ LLFIO_PATH_VIEW_CONSTEXPR bool has_root_directory() const noexcept
+ {
+ return !root_directory().empty();
+ }
//! True if has relative path
- LLFIO_PATH_VIEW_CONSTEXPR bool has_relative_path() const noexcept { return !relative_path().empty(); }
+ LLFIO_PATH_VIEW_CONSTEXPR bool has_relative_path() const noexcept
+ {
+ return !relative_path().empty();
+ }
//! True if has parent path
- LLFIO_PATH_VIEW_CONSTEXPR bool has_parent_path() const noexcept { return !parent_path().empty(); }
+ LLFIO_PATH_VIEW_CONSTEXPR bool has_parent_path() const noexcept
+ {
+ return !parent_path().empty();
+ }
//! True if has filename
- LLFIO_PATH_VIEW_CONSTEXPR bool has_filename() const noexcept { return !filename().empty(); }
+ LLFIO_PATH_VIEW_CONSTEXPR bool has_filename() const noexcept
+ {
+ return !filename().empty();
+ }
//! True if absolute
constexpr bool is_absolute() const noexcept
{
@@ -2414,16 +2552,23 @@ namespace detail
private:
const path_view *_parent{nullptr};
size_type _begin{0}, _end{0};
- int _special{0}; // -2 if at preceding /, -1 if at / after a //, +1 if at trailing /
+ enum class _at : uint8_t
+ {
+ unused=0,
+ leading_slash , // 1
+ slash_after_unc_prefix , // 2
+ none , // 3
+ trailing_slash // 4
+ } _inc_state{_at::unused}, _dec_state{_at::unused};
static constexpr auto _npos = string_view::npos;
- constexpr bool _is_end() const noexcept { return (nullptr == _parent) || (!_special && _parent->native_size() == _begin); }
+ constexpr bool _state_not_special() const noexcept
+ {
+ return (_inc_state == _at::none || _inc_state == _at::unused) && (_dec_state == _at::none || _dec_state == _at::unused);
+ }
+ constexpr bool _is_end() const noexcept { return (nullptr == _parent) || (_state_not_special() && _parent->native_size() == _begin); }
constexpr size_t _find_unc_prefix() const noexcept
{
-#if defined(_LIBCPP_VERSION)
- // libc++'s path doesn't implement UNC prefixing
- return _npos;
-#else
auto a = _parent->_find_first_sep(0);
if(a != 0)
{
@@ -2449,7 +2594,6 @@ namespace detail
}
return e;
}
-#endif
}
LLFIO_PATH_VIEW_CONSTEXPR value_type _get() const noexcept
{
@@ -2465,15 +2609,42 @@ namespace detail
}
LLFIO_PATH_VIEW_CONSTEXPR void _inc() noexcept
{
+ //std::cout << "ENTRY: _inc begin = " << _begin << " end = " << _end << " inc_state = " << (int) _inc_state << " dec_state = " << (int) _dec_state
+ // << " string = " << **this << std::endl;
+ //auto onexit = make_scope_exit(
+ //[&]() noexcept
+ //{
+ // std::cout << "EXIT: _inc begin = " << _begin << " end = " << _end << " inc_state = " << (int) _inc_state << " dec_state = " << (int) _dec_state
+ // << " string = " << **this << std::endl;
+ //});
+ if(_dec_state != _at::unused)
+ {
+ assert(_inc_state == _at::unused);
+ _inc_state = _at::none;
+ switch(_dec_state)
+ {
+ case _at::leading_slash:
+ _inc_state = _at::slash_after_unc_prefix;
+ // fallthrough
+ case _at::unused:
+ case _at::slash_after_unc_prefix:
+ case _at::none:
+ case _at::trailing_slash:
+ _dec_state = _at::unused;
+ break;
+ }
+ }
do
{
- _begin = (_end > 0 && !_special) ? (_end + 1) : _end;
+ //std::cout << "ITER: _inc begin = " << _begin << " end = " << _end << " inc_state = " << (int) _inc_state << " dec_state = " << (int) _dec_state
+ // << " string = " << **this << std::endl;
+ _begin = (_end > 0 && _state_not_special()) ? (_end + 1) : _end;
_end = _parent->_find_first_sep(_begin);
- } while(_special == 0 && _begin == _end && _end != 0);
+ } while(_state_not_special() && _begin == _end && _end != 0);
if(0 == _end)
{
// Path has a beginning /[/*] and all must be returned as a single component
- _special = -2;
+ _inc_state = _at::leading_slash;
_end = _find_unc_prefix();
if(_npos == _end)
{
@@ -2482,33 +2653,40 @@ namespace detail
}
else
{
- _special = -1;
+#if defined(_LIBCPP_VERSION)
+ // libc++'s path doesn't implement UNC prefixing yet, but it does treat many leading separators as one
+ _inc_state = _at::leading_slash;
+ _end = _parent->_find_last_sep(_end - 1) + 1;
+ _begin = _end - 1;
+#else
+ _inc_state = _at::slash_after_unc_prefix;
+#endif
}
return;
}
- if(-1 == _special)
+ if(_inc_state == _at::slash_after_unc_prefix) // is / after unc //?
{
if(_npos != _end)
{
// For a //server/path/ form, //server is returned first then /
_end = _begin + 1;
- _special = -2;
+ _inc_state = _at::leading_slash;
}
else
{
// This was just //server
_end = _begin;
- _special = 0;
+ _inc_state = _at::none;
}
return;
}
if(_npos == _end)
{
_end = _parent->native_size();
- if(_begin == _end && !_special)
+ if(_begin == _end && _state_not_special())
{
// Path has a trailing /
- _special = 1;
+ _inc_state = _at::trailing_slash;
return;
}
if(_begin > _end)
@@ -2516,21 +2694,46 @@ namespace detail
_begin = _end;
}
}
- _special = 0;
+ _inc_state = _at::none;
}
constexpr void _dec() noexcept
{
+ //std::cout << "ENTRY: _dec begin = " << _begin << " end = " << _end << " inc_state = " << (int) _inc_state << " dec_state = " << (int) _dec_state
+ // << " string = " << **this << std::endl;
+ //auto onexit = make_scope_exit(
+ //[&]() noexcept
+ //{
+ // std::cout << "EXIT: _dec begin = " << _begin << " end = " << _end << " inc_state = " << (int) _inc_state << " dec_state = " << (int) _dec_state
+ // << " string = " << **this << std::endl;
+ //});
+ if(_inc_state != _at::unused)
+ {
+ assert(_dec_state == _at::unused);
+ _dec_state = _at::none;
+ switch(_inc_state)
+ {
+ case _at::slash_after_unc_prefix:
+ _dec_state = _at::leading_slash;
+ // fallthrough
+ case _at::unused:
+ case _at::leading_slash:
+ case _at::none:
+ case _at::trailing_slash:
+ _inc_state = _at::unused;
+ break;
+ }
+ }
const auto unc_prefix_end = _find_unc_prefix();
- if(_special == -2 && unc_prefix_end != _npos)
+ if(_dec_state == _at::slash_after_unc_prefix && unc_prefix_end != _npos)
{
- _special = -1;
+ _dec_state = _at::leading_slash;
_begin = 0;
_end = unc_prefix_end;
return;
}
- if(-1 == _special)
+ if(_dec_state == _at::leading_slash)
{
- _special = 0;
+ _dec_state = _at::unused;
_begin = 0;
_end = 0;
return;
@@ -2538,18 +2741,43 @@ namespace detail
do
{
auto is_end = _is_end();
+ //std::cout << "ITER: _dec begin = " << _begin << " end = " << _end << " inc_state = " << (int) _inc_state << " dec_state = " << (int) _dec_state
+ // << " is_end = " << is_end << " unc_prefix_end = " << unc_prefix_end << " string = " << **this << std::endl;
_end = is_end ? _begin : (_begin - 1);
if(0 == _end)
{
+#if defined(_LIBCPP_VERSION)
+ // libc++'s path doesn't implement UNC prefixing yet, but it does treat many leading separators as one
+ _dec_state = _at::unused;
+ _inc_state = _at::leading_slash;
+ _end = _parent->_find_last_sep(_begin) + 1;
+ _begin = _end - 1;
+#else
// Path has a beginning /
- _special = -2;
+ _dec_state = _at::unused;
+ _inc_state = _at::leading_slash;
_begin = 0;
_end = 1;
+#endif
return;
}
- if(_end == unc_prefix_end)
+ if(_end == unc_prefix_end && unc_prefix_end != _npos)
{
- _special = -2;
+#if defined(_LIBCPP_VERSION)
+ // libc++'s path doesn't implement UNC prefixing yet, but it does treat many leading separators as one
+ _begin = _parent->_find_last_sep(unc_prefix_end - 1) + 1;
+ if(_begin == unc_prefix_end)
+ {
+ _begin = _end - 1;
+ }
+ else
+ {
+ _end = unc_prefix_end;
+ }
+ _dec_state = _at::unused;
+ _inc_state = _at::leading_slash;
+#else
+ _dec_state = _at::slash_after_unc_prefix;
_begin = _end;
if(_end < _parent->native_size())
{
@@ -2558,8 +2786,9 @@ namespace detail
else
{
_begin = 0;
- _special = -1;
+ _dec_state = _at::leading_slash;
}
+#endif
return;
}
_begin = _parent->_find_last_sep(_end - 1);
@@ -2568,17 +2797,28 @@ namespace detail
// Path has a trailing /
if(_begin == unc_prefix_end || _begin == 0)
{
- _special = -2;
+#if defined(_LIBCPP_VERSION)
+ if(_begin == 0)
+ {
+ _dec_state = _at::unused;
+ _inc_state = _at::leading_slash;
+ return;
+ }
+ _dec_state = _at::trailing_slash;
+ _begin = _end;
+#else
+ _dec_state = _at::slash_after_unc_prefix;
+#endif
}
else
{
- _special = 1;
+ _dec_state = _at::trailing_slash;
_begin = _end;
}
return;
}
_begin = (_npos == _begin) ? 0 : (_begin + 1);
- _special = 0;
+ _dec_state = _at::none;
} while(_begin == _end);
}
@@ -2624,7 +2864,7 @@ namespace detail
{
return false;
}
- return _parent != o._parent || _begin != o._begin || _end != o._end || _special != o._special;
+ return _parent != o._parent || _begin != o._begin || _end != o._end || _state_not_special() != o._state_not_special();
}
constexpr bool operator==(path_view_iterator o) const noexcept
{
@@ -2632,7 +2872,7 @@ namespace detail
{
return true;
}
- return _parent == o._parent && _begin == o._begin && _end == o._end && _special == o._special;
+ return _parent == o._parent && _begin == o._begin && _end == o._end && _state_not_special() == o._state_not_special();
}
constexpr path_view_iterator &operator--() noexcept
@@ -2727,6 +2967,23 @@ inline LLFIO_PATH_VIEW_CONSTEXPR bool operator!=(path_view x, path_view y) noexc
}
return false;
}
+//! \brief Compares individual path view components for ordering. Use `compare()` if you want something stronger.
+inline LLFIO_PATH_VIEW_CONSTEXPR bool 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 true;
+ }
+ }
+ if(it1 == x.end() && it2 != y.end())
+ {
+ return true;
+ }
+ 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