diff options
author | Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com> | 2019-10-14 13:10:11 +0300 |
---|---|---|
committer | Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com> | 2019-10-14 13:10:11 +0300 |
commit | 34e40a322e66e754369f4fe84a976c7669d5bc9f (patch) | |
tree | 3805a4fb535466e9d8d5d4d2572b7803d31235de | |
parent | 2cca7cc4bc914d4cb92306faabb9d6db765b8464 (diff) |
Path view refactor passes all unit tests and asan.
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | include/llfio/revision.hpp | 6 | ||||
-rw-r--r-- | include/llfio/v2.0/detail/impl/path_view.ipp | 43 | ||||
-rw-r--r-- | include/llfio/v2.0/path_view.hpp | 120 | ||||
-rw-r--r-- | test/tests/directory_handle_enumerate/runner.cpp | 8 | ||||
-rw-r--r-- | test/tests/path_view.cpp | 6 |
6 files changed, 136 insertions, 52 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f09ae18..112bd8a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,10 +177,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") # Do make libc++ a requirement for the _dl edition target_compile_definitions(${PROJECT_NAME}_dl PUBLIC _LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_FILESYSTEM=1) target_compile_options(${PROJECT_NAME}_dl PUBLIC -stdlib=libc++) - target_link_libraries(${PROJECT_NAME}_dl PUBLIC -stdlib=libc++ -lc++abi -lc++experimental) + target_link_libraries(${PROJECT_NAME}_dl PUBLIC -stdlib=libc++ -lc++abi) foreach(special ${SPECIAL_BUILDS}) target_compile_options(${PROJECT_NAME}_dl-${special} PUBLIC -stdlib=libc++) - target_link_libraries(${PROJECT_NAME}_dl-${special} PUBLIC -stdlib=libc++ -lc++abi -lc++experimental) + target_link_libraries(${PROJECT_NAME}_dl-${special} PUBLIC -stdlib=libc++ -lc++abi) endforeach() endif() endif() @@ -242,7 +242,6 @@ if(NOT PROJECT_IS_DEPENDENCY) if(USING_LIBCXX_ON_LINUX) if(NOT test_target MATCHES _sl) apply_cxx_coroutines_to(PRIVATE ${test_target}) - target_link_libraries(${test_target} PRIVATE -lc++experimental) endif() else() apply_cxx_coroutines_to(PRIVATE ${test_target}) diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp index ae369fea..565f9c05 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 7a854e59e7bb402399a590be35c2292b6f081268 -#define LLFIO_PREVIOUS_COMMIT_DATE "2019-10-12 15:17:03 +00:00" -#define LLFIO_PREVIOUS_COMMIT_UNIQUE 7a854e59 +#define LLFIO_PREVIOUS_COMMIT_REF 2cca7cc4bc914d4cb92306faabb9d6db765b8464 +#define LLFIO_PREVIOUS_COMMIT_DATE "2019-10-14 08:51:16 +00:00" +#define LLFIO_PREVIOUS_COMMIT_UNIQUE 2cca7cc4 diff --git a/include/llfio/v2.0/detail/impl/path_view.ipp b/include/llfio/v2.0/detail/impl/path_view.ipp index 3e948a57..f2171651 100644 --- a/include/llfio/v2.0/detail/impl/path_view.ipp +++ b/include/llfio/v2.0/detail/impl/path_view.ipp @@ -287,30 +287,31 @@ namespace detail state.str.Length = state.str.MaximumLength = (USHORT) src_buffer_length; // Try using the internal buffer NTSTATUS ntstat = AreFileApisANSI() ? RtlAnsiStringToUnicodeString(&state.buffer, &state.str, false) : RtlOemStringToUnicodeString(&state.buffer, &state.str, false); + if(ntstat >= 0) + { + // Successful + toallocate = 0; + state.buffer.Buffer[(state.buffer.Length / sizeof(wchar_t))] = 0; + state.buffer.Buffer = nullptr; + return dest_buffer + (state.buffer.Length / sizeof(wchar_t)); + } + if(ntstat != STATUS_BUFFER_OVERFLOW) + { + LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str()); + abort(); + } + // Dynamically allocate + ntstat = AreFileApisANSI() ? RtlAnsiStringToUnicodeString(&state.buffer, &state.str, true) : RtlOemStringToUnicodeString(&state.buffer, &state.str, true); if(ntstat < 0) { - if(ntstat != STATUS_BUFFER_OVERFLOW) - { - LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str()); - abort(); - } - // Dynamically allocate - ntstat = AreFileApisANSI() ? RtlAnsiStringToUnicodeString(&state.buffer, &state.str, true) : RtlOemStringToUnicodeString(&state.buffer, &state.str, true); - if(ntstat < 0) - { - LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str()); - abort(); - } - // The thread local state will cache this for later - state.buffer.MaximumLength = state.buffer.Length + sizeof(wchar_t); - // Retry me with this dynamic allocation - toallocate = state.buffer.MaximumLength / sizeof(wchar_t); - return dest_buffer; + LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str()); + abort(); } - // Successful - toallocate = 0; - state.buffer.Buffer[(state.buffer.Length / sizeof(wchar_t))] = 0; - return state.buffer.Buffer + (state.buffer.Length / sizeof(wchar_t)); + // The thread local state will cache this for later + state.buffer.MaximumLength = state.buffer.Length + sizeof(wchar_t); + // Retry me with this dynamic allocation + toallocate = state.buffer.MaximumLength / sizeof(wchar_t); + return dest_buffer; #elif defined(_LIBCPP_VERSION) (void) toallocate; (void) dest_buffer; diff --git a/include/llfio/v2.0/path_view.hpp b/include/llfio/v2.0/path_view.hpp index f1b345e7..52791503 100644 --- a/include/llfio/v2.0/path_view.hpp +++ b/include/llfio/v2.0/path_view.hpp @@ -302,6 +302,15 @@ private: basic_string_view<char>((const char *) _bytestr, _length).rfind(preferred_separator, endidx))); #endif } + LLFIO_PATH_VIEW_GCC_CONSTEXPR path_view_component _filename() const noexcept + { + auto sep_idx = _find_last_sep(); + if(_npos == sep_idx) + { + return *this; + } + return _invoke([sep_idx, this](const auto &v) { return path_view_component(v.data() + sep_idx + 1, v.size() - sep_idx - 1, _zero_terminated); }); + } public: path_view_component(const path_view_component &) = default; @@ -344,23 +353,23 @@ public: //! Returns a view of the filename without any file extension constexpr path_view_component stem() const noexcept { - auto sep_idx = _find_last_sep(); - return _invoke([sep_idx, this](const auto &v) { + auto self = _filename(); + return self._invoke([self](const auto &v) { auto dot_idx = v.rfind('.'); - if(_npos == dot_idx || (_npos != sep_idx && dot_idx < sep_idx) || dot_idx == sep_idx + 1 || (dot_idx == sep_idx + 2 && v[dot_idx - 1] == '.')) + if(_npos == dot_idx || dot_idx == 0 || (dot_idx == 1 && v[dot_idx - 1] == '.')) { - return path_view_component(v.data() + sep_idx + 1, v.size() - sep_idx - 1, false); + return self; } - return path_view_component(v.data() + sep_idx + 1, dot_idx - sep_idx - 1, _zero_terminated); + return path_view_component(v.data(), dot_idx, false); }); } //! Returns a view of the file extension part of this view constexpr path_view_component extension() const noexcept { - auto sep_idx = _find_last_sep(); - return _invoke([sep_idx, this](const auto &v) { + auto self = _filename(); + return self._invoke([this](const auto &v) { auto dot_idx = v.rfind('.'); - if(_npos == dot_idx || (_npos != sep_idx && dot_idx < sep_idx) || dot_idx == sep_idx + 1 || (dot_idx == sep_idx + 2 && v[dot_idx - 1] == '.')) + if(_npos == dot_idx || dot_idx == 0 || (dot_idx == 1 && v[dot_idx - 1] == '.')) { return path_view_component(); } @@ -552,6 +561,13 @@ public: */ template <class U> c_str(path_view_component view, bool no_zero_terminate, U &&allocate) { + if(0 == view._length) + { + _buffer[0] = 0; + buffer = _buffer; + length = 0; + return; + } if(std::is_same<T, byte>::value || view._passthrough) { length = view._length; @@ -725,6 +741,12 @@ inline LLFIO_PATH_VIEW_GCC_CONSTEXPR bool operator==(path_view_component x, path { return false; } + if(0 == x._length && 0 == y._length) + { + return true; + } + assert(x._bytestr != nullptr); + assert(y._bytestr != nullptr); return 0 == memcmp(x._bytestr, y._bytestr, x._length); } inline LLFIO_PATH_VIEW_GCC_CONSTEXPR bool operator!=(path_view_component x, path_view_component y) noexcept @@ -753,8 +775,42 @@ inline LLFIO_PATH_VIEW_GCC_CONSTEXPR bool operator!=(path_view_component x, path { return true; } + if(0 == x._length && 0 == y._length) + { + return false; + } + assert(x._bytestr != nullptr); + assert(y._bytestr != nullptr); return 0 != memcmp(x._bytestr, y._bytestr, x._length); } +LLFIO_TEMPLATE(class CharT) +LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>)) +inline LLFIO_PATH_VIEW_GCC_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 LLFIO_PATH_VIEW_GCC_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; +} +LLFIO_TEMPLATE(class CharT) +LLFIO_TREQUIRES(LLFIO_TPRED(path_view_component::is_source_acceptable<CharT>)) +inline LLFIO_PATH_VIEW_GCC_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 LLFIO_PATH_VIEW_GCC_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; +} + namespace detail { struct string_view_printer @@ -1112,7 +1168,7 @@ public: auto sep_idx = _state._find_last_sep(); if(_npos == sep_idx) { - return *this; + return path_view(); } return _state._invoke([sep_idx](auto v) { return path_view(v.data(), sep_idx, false); }); } @@ -1226,15 +1282,7 @@ public: return _state._invoke([sep_idx](const auto &v) { return path_view(v.data(), sep_idx, false); }); } //! Returns a view of the filename part of this view. - LLFIO_PATH_VIEW_GCC_CONSTEXPR path_view filename() const noexcept - { - auto sep_idx = _state._find_last_sep(); - if(_npos == sep_idx) - { - return _state; - } - return _state._invoke([sep_idx, this](const auto &v) { return path_view_component(v.data() + sep_idx + 1, v.size() - sep_idx - 1, _state._zero_terminated); }); - } + LLFIO_PATH_VIEW_GCC_CONSTEXPR path_view filename() const noexcept { return _state._filename(); } //! Returns a view of the filename without any file extension constexpr path_view_component stem() const noexcept { return _state.stem(); } //! Returns a view of the file extension part of this view @@ -1310,6 +1358,34 @@ inline LLFIO_PATH_VIEW_GCC_CONSTEXPR bool operator!=(path_view x, path_view y) n { return x._state != y._state; } +LLFIO_TEMPLATE(class CharT) +LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<CharT>)) +inline LLFIO_PATH_VIEW_GCC_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 LLFIO_PATH_VIEW_GCC_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 LLFIO_PATH_VIEW_GCC_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 LLFIO_PATH_VIEW_GCC_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; +} inline std::ostream &operator<<(std::ostream &s, const path_view &v) { return s << v._state; @@ -1372,6 +1448,10 @@ namespace detail { _parent->_state._invoke([this](const auto &v) { _end = v.size(); }); } + if(_end > _begin) + { + ++_begin; + } } constexpr void _dec() noexcept { @@ -1381,6 +1461,10 @@ namespace detail { _begin = 0; } + if(_begin < _end) + { + --_end; + } } constexpr path_view_iterator(const path_view *p, bool end) diff --git a/test/tests/directory_handle_enumerate/runner.cpp b/test/tests/directory_handle_enumerate/runner.cpp index f762f6ed..ec1d25f9 100644 --- a/test/tests/directory_handle_enumerate/runner.cpp +++ b/test/tests/directory_handle_enumerate/runner.cpp @@ -100,19 +100,19 @@ template <class U> inline void directory_handle_enumerate_(U &&f) bool havedir = !glob.empty(); for (directory_entry &i : info) { - if (i.leafname == "012345678901234567890123456789012345678901234567890123456789012z.deleted") + if (0 == i.leafname.compare<>("012345678901234567890123456789012345678901234567890123456789012z.deleted")) { havedeleted1 = true; } - if (i.leafname == "0123456789012345678901234567890123456789012345678901234567890123.deleted") + if (0 == i.leafname.compare<>("0123456789012345678901234567890123456789012345678901234567890123.deleted")) { havedeleted2 = true; } - if (i.leafname == "foo.txt") + if (0 == i.leafname.compare<>("foo.txt")) { havefoo = true; } - if (i.leafname == "dir") + if (0 == i.leafname.compare<>("dir")) { havedir = true; } diff --git a/test/tests/path_view.cpp b/test/tests/path_view.cpp index b9b821b6..aa92b0c8 100644 --- a/test/tests/path_view.cpp +++ b/test/tests/path_view.cpp @@ -57,7 +57,7 @@ static inline void TestPathView() constexpr llfio::path_view a, b("hello"); BOOST_CHECK(a.empty()); BOOST_CHECK(!b.empty()); - BOOST_CHECK(b == "hello"); + BOOST_CHECK(0 == b.compare<>("hello")); // Globs BOOST_CHECK(llfio::path_view("niall*").contains_glob()); // Splitting @@ -65,8 +65,8 @@ static inline void TestPathView() llfio::path_view e(p); // NOLINT llfio::path_view f(e.filename()); e = e.remove_filename(); - BOOST_CHECK(e == "/mnt/c/Users/ned/Documents/boostish/afio/programs/build_posix/testdir"); - BOOST_CHECK(f == "0"); + BOOST_CHECK(0 == e.compare<>("/mnt/c/Users/ned/Documents/boostish/afio/programs/build_posix/testdir")); + BOOST_CHECK(0 == f.compare<>("0")); #ifndef _WIN32 // cstr llfio::path_view::c_str<> g(e); |