diff options
author | Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com> | 2019-10-10 14:11:34 +0300 |
---|---|---|
committer | Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com> | 2019-10-10 14:11:34 +0300 |
commit | d256ae1ed0c18280f656fd7e483d0d07ef74bde7 (patch) | |
tree | dd2b69eceb884601f8f81690352401639ee19af2 | |
parent | aad9e4b0a0aa3826c78400664c250e3aa3fab696 (diff) |
Refactored path view now compiles on all platforms, doesn't link on POSIX, code is untested.
-rw-r--r-- | include/llfio/revision.hpp | 6 | ||||
-rw-r--r-- | include/llfio/v2.0/detail/impl/path_view.ipp | 348 | ||||
-rw-r--r-- | include/llfio/v2.0/detail/impl/windows/import.hpp | 32 | ||||
-rw-r--r-- | include/llfio/v2.0/detail/impl/windows/path_view.ipp | 99 | ||||
-rw-r--r-- | include/llfio/v2.0/path_view.hpp | 79 |
5 files changed, 431 insertions, 133 deletions
diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp index 625a88ac..4d43beeb 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 087e0c50299a222be979b59053b1b29d4beb7c63 -#define LLFIO_PREVIOUS_COMMIT_DATE "2019-10-09 10:54:14 +00:00" -#define LLFIO_PREVIOUS_COMMIT_UNIQUE 087e0c50 +#define LLFIO_PREVIOUS_COMMIT_REF aad9e4b0a0aa3826c78400664c250e3aa3fab696 +#define LLFIO_PREVIOUS_COMMIT_DATE "2019-10-10 09:38:46 +00:00" +#define LLFIO_PREVIOUS_COMMIT_UNIQUE aad9e4b0 diff --git a/include/llfio/v2.0/detail/impl/path_view.ipp b/include/llfio/v2.0/detail/impl/path_view.ipp new file mode 100644 index 00000000..cd4d614b --- /dev/null +++ b/include/llfio/v2.0/detail/impl/path_view.ipp @@ -0,0 +1,348 @@ +/* A view of a path to something +(C) 2017 Niall Douglas <http://www.nedproductions.biz/> (20 commits) +File Created: Jul 2017 + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License in the accompanying file +Licence.txt or at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +Distributed under the Boost Software License, Version 1.0. + (See accompanying file Licence.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +#include "../../path_view.hpp" + +#include <locale> + +#ifdef _WIN32 +#include "windows/import.hpp" +#endif + +LLFIO_V2_NAMESPACE_BEGIN + +namespace detail +{ + template <class T> inline T *cast_char8_t_ptr(T *v) { return v; } + template <class InternT, class ExternT> struct _codecvt : std::codecvt<InternT, ExternT, std::mbstate_t> + { + template <class... Args> + _codecvt(Args &&... args) + : std::codecvt<InternT, ExternT, std::mbstate_t>(std::forward<Args>(args)...) + { + } + ~_codecvt() {} + }; +#if !defined(__CHAR8_TYPE__) && __cplusplus < 20200000 + inline const char *cast_char8_t_ptr(const char8_t *v) { return (const char *) v; } + inline char *cast_char8_t_ptr(char8_t *v) { return (char *) v; } + template <> struct _codecvt<char8_t, char> : std::codecvt<char, char, std::mbstate_t> + { + template <class... Args> + _codecvt(Args &&... args) + : std::codecvt<char, char, std::mbstate_t>(std::forward<Args>(args)...) + { + } + ~_codecvt() {} + }; +#endif + template <class InT, class OutT> static _codecvt<InT, OutT> &_get_codecvt() noexcept + { + static _codecvt<InT, OutT> ret; + return ret; + } + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4127) // conditional expression is constant +#endif + /* Returns where the last character was written to. + toallocate may be written with how much must be written if there wasn't enough space. + */ + template <class DestT, class SrcT> inline DestT *_reencode_path_to(size_t &toallocate, DestT *dest_buffer, size_t dest_buffer_length, const SrcT *src_buffer, size_t src_buffer_length) + { + auto &convert = _get_codecvt<SrcT, DestT>(); + std::mbstate_t cstate{}; + auto *src_ptr = src_buffer; + auto *dest_ptr = dest_buffer; + + // Try the internal buffer first + if(dest_buffer_length != 0) + { + // First try the internal buffer, if we overflow, fall back to the allocator + auto result = convert.out(cstate, src_ptr, src_buffer + src_buffer_length, src_ptr, dest_ptr, dest_buffer + dest_buffer_length - 1, dest_ptr); + assert(std::codecvt_base::noconv != result); + if(std::codecvt_base::noconv == result) + { + LLFIO_LOG_FATAL(nullptr, "path_view_component::c_str should never do identity reencoding"); + abort(); + } + if(std::codecvt_base::error == result) + { + // If input is supposed to be valid UTF, barf + if(std::is_same<SrcT, char8_t>::value || std::is_same<SrcT, char16_t>::value) + { + throw std::system_error(make_error_code(std::errc::illegal_byte_sequence)); + } + // Otherwise proceed anyway :) + LLFIO_LOG_WARN(nullptr, "path_view_component::c_str saw failure to completely convert input encoding"); + result = std::codecvt_base::ok; + } + if(std::codecvt_base::ok == result) + { + *dest_ptr = 0; + toallocate = 0; + return dest_ptr; + } + } + + // This is a bit crap, but codecvt is hardly the epitome of good design :( + toallocate = convert.max_length() * (1 + src_buffer_length); +#ifdef _WIN32 + const size_t required_bytes = toallocate * sizeof(DestT); + if(required_bytes > 65535) + { + LLFIO_LOG_FATAL(nullptr, "Paths exceeding 64Kb are impossible on Microsoft Windows"); + abort(); + } +#endif + return dest_ptr; + } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + char *reencode_path_to(size_t & /*unused*/, char * /*unused*/, size_t /*unused*/, const LLFIO_V2_NAMESPACE::byte * /*unused*/, size_t /*unused*/) + { + LLFIO_LOG_FATAL(nullptr, "path_view_component::c_str reencoding function should never see passthrough."); + abort(); + } + char *reencode_path_to(size_t & /*unused*/, char * /*unused*/, size_t /*unused*/, const char * /*unused*/, size_t /*unused*/) + { + LLFIO_LOG_FATAL(nullptr, "path_view_component::c_str reencoding function should never see identity."); + abort(); + } + char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const wchar_t *src_buffer, size_t src_buffer_length) { return _reencode_path_to(toallocate, dest_buffer, dest_buffer_length, src_buffer, src_buffer_length); } + char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const char8_t *src_buffer, size_t src_buffer_length) + { +#ifdef _WIN32 + if(dest_buffer_length * sizeof(wchar_t) > 65535) + { + LLFIO_LOG_FATAL(nullptr, "Paths exceeding 64Kb are impossible on Microsoft Windows"); + abort(); + } + // Need to perform a UTF-8 to ANSI conversion using the Windows API + // *Probably* the safest way of doing this is from UTF-8 to wchar_t, + // then from wchar_t to ANSI. + windows_nt_kernel::init(); + using namespace windows_nt_kernel; + static thread_local struct state_t + { + const char8_t *src_buffer{nullptr}; // src + UNICODE_STRING buffer{}; // intermediate + ANSI_STRING str{}; // out + ~state_t() + { + if(buffer.Buffer != nullptr) + { + free(buffer.Buffer); + } + if(str.Buffer != nullptr) + { + RtlFreeAnsiString(&str); + } + } + } state; + if(state.src_buffer != nullptr) + { + if(state.src_buffer == src_buffer && state.str.Length == dest_buffer_length - 1) + { + successful: + // Use the precalculated reencoding + memcpy(dest_buffer, state.str.Buffer, state.str.Length); + dest_buffer[state.str.Length] = 0; + free(state.buffer.Buffer); + RtlFreeUnicodeString(&state.buffer); + state.buffer.Buffer = nullptr; + state.str.Buffer = nullptr; + state.src_buffer = nullptr; + // Successful + toallocate = 0; + return dest_buffer + dest_buffer_length - 1; + } + free(state.buffer.Buffer); + RtlFreeAnsiString(&state.str); + state.buffer.Buffer = nullptr; + state.str.Buffer = nullptr; + state.src_buffer = nullptr; + } + ULONG written = 0; + // Ask for the length needed + NTSTATUS ntstat = RtlUTF8ToUnicodeN(nullptr, 0, &written, (const char *) src_buffer, static_cast<ULONG>(src_buffer_length)); + if(ntstat < 0) + { + LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str()); + abort(); + } + state.buffer.Length = (USHORT) written; + state.buffer.MaximumLength = (USHORT)(written + sizeof(wchar_t)); + state.buffer.Buffer = (wchar_t *) malloc(state.buffer.MaximumLength); + if(nullptr == state.buffer.Buffer) + { + throw std::bad_alloc(); + } + // Do the conversion UTF-8 to UTF-16 + ntstat = RtlUTF8ToUnicodeN(state.buffer.Buffer, state.buffer.Length, &written, (const char *) src_buffer, static_cast<ULONG>(src_buffer_length)); + if(ntstat < 0) + { + LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str()); + abort(); + } + // Convert from UTF-16 to ANSI + ntstat = AreFileApisANSI() ? RtlUnicodeStringToAnsiString(&state.str, (PCUNICODE_STRING) &state.buffer, true) : RtlUnicodeStringToOemString(&state.str, (PCUNICODE_STRING) &state.buffer, true); + if(ntstat < 0) + { + LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str()); + abort(); + } + state.str.MaximumLength = state.str.Length + 1; + if(dest_buffer_length >= state.str.MaximumLength) + { + goto successful; + } + // Retry me with this dynamic allocation + state.src_buffer = src_buffer; + toallocate = state.str.MaximumLength; + return dest_buffer; +#else + (void) toallocate; + (void) dest_buffer; + (void) dest_buffer_length; + (void) src_buffer; + (void) src_buffer_length; + LLFIO_LOG_FATAL(nullptr, "path_view_component::c_str reencoding function should never see identity."); + abort(); +#endif + } + char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const char16_t *src_buffer, size_t src_buffer_length) { return _reencode_path_to(toallocate, dest_buffer, dest_buffer_length, src_buffer, src_buffer_length); } + + wchar_t *reencode_path_to(size_t & /*unused*/, wchar_t * /*unused*/, size_t /*unused*/, const LLFIO_V2_NAMESPACE::byte * /*unused*/, size_t /*unused*/) + { + LLFIO_LOG_FATAL(nullptr, "path_view_component::c_str reencoding function should never see passthrough."); + abort(); + } + wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char *src_buffer, size_t src_buffer_length) + { +#ifdef _WIN32 + if(dest_buffer_length * sizeof(wchar_t) > 65535) + { + LLFIO_LOG_FATAL(nullptr, "Paths exceeding 64Kb are impossible on Microsoft Windows"); + abort(); + } + // Need to perform an ANSI to Unicode conversion using the Windows API + windows_nt_kernel::init(); + using namespace windows_nt_kernel; + static thread_local struct state_t + { + UNICODE_STRING buffer{}; // out + ANSI_STRING str{}; // in + ~state_t() + { + if(buffer.Buffer != nullptr) + { + RtlFreeUnicodeString(&buffer); + } + } + } state; + if(state.buffer.Buffer != nullptr) + { + if(state.str.Buffer == src_buffer && state.buffer.MaximumLength == dest_buffer_length * sizeof(wchar_t)) + { + // Use the precalculated reencoding + memcpy(dest_buffer, state.buffer.Buffer, state.buffer.Length); + dest_buffer[state.buffer.Length] = 0; + RtlFreeUnicodeString(&state.buffer); + state.buffer.Buffer = nullptr; + // Successful + toallocate = 0; + return dest_buffer + state.buffer.Length; + } + RtlFreeUnicodeString(&state.buffer); + state.buffer.Buffer = nullptr; + } + state.buffer.Buffer = dest_buffer; + state.buffer.Length = state.buffer.MaximumLength = (USHORT)((dest_buffer_length - 1) * sizeof(wchar_t)); + state.str.Buffer = const_cast<char *>(src_buffer); + 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) + { + 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; + } + // Successful + toallocate = 0; + state.buffer.Buffer[(state.buffer.Length / sizeof(wchar_t))] = 0; + return state.buffer.Buffer + (state.buffer.Length / sizeof(wchar_t)) + 1; +#else + return _reencode_path_to(toallocate, dest_buffer, dest_buffer_length, src_buffer, src_buffer_length); +#endif + } + wchar_t *reencode_path_to(size_t & /*unused*/, wchar_t * /*unused*/, size_t /*unused*/, const wchar_t * /*unused*/, size_t /*unused*/) + { + LLFIO_LOG_FATAL(nullptr, "path_view_component::c_str reencoding function should never see identity."); + abort(); + } + wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char8_t *src_buffer, size_t src_buffer_length) + { +#if !defined(__CHAR8_TYPE__) && __cplusplus < 20200000 + return _reencode_path_to(toallocate, dest_buffer, dest_buffer_length, (const char *) src_buffer, src_buffer_length); +#else + return _reencode_path_to(toallocate, dest_buffer, dest_buffer_length, src_buffer, src_buffer_length); +#endif + } + wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char16_t *src_buffer, size_t src_buffer_length) + { +#ifdef _WIN32 + (void) toallocate; + (void) dest_buffer; + (void) dest_buffer_length; + (void) src_buffer; + (void) src_buffer_length; + LLFIO_LOG_FATAL(nullptr, "path_view_component::c_str reencoding function should never see identity."); + abort(); +#else + return _reencode_path_to(toallocate, dest_buffer, dest_buffer_length, src_buffer, src_buffer_length); +#endif + } + +} // namespace detail + +LLFIO_V2_NAMESPACE_END diff --git a/include/llfio/v2.0/detail/impl/windows/import.hpp b/include/llfio/v2.0/detail/impl/windows/import.hpp index ed8e8ec1..fa3a285f 100644 --- a/include/llfio/v2.0/detail/impl/windows/import.hpp +++ b/include/llfio/v2.0/detail/impl/windows/import.hpp @@ -355,8 +355,14 @@ namespace windows_nt_kernel using RtlAnsiStringToUnicodeString_t = NTSTATUS(NTAPI *)(PUNICODE_STRING DestinationString, PCANSI_STRING SourceString, BOOLEAN AllocateDestinationString); + using RtlUnicodeStringToAnsiString_t = NTSTATUS(NTAPI *)(PANSI_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString); + using RtlOemStringToUnicodeString_t = NTSTATUS(NTAPI *)(PUNICODE_STRING DestinationString, PCOEM_STRING SourceString, BOOLEAN AllocateDestinationString); + using RtlUnicodeStringToOemString_t = NTSTATUS(NTAPI *)(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString); + + using RtlFreeAnsiString_t = NTSTATUS(NTAPI *)(PANSI_STRING String); + using RtlFreeUnicodeString_t = NTSTATUS(NTAPI *)(PUNICODE_STRING String); typedef struct _FILE_BASIC_INFORMATION // NOLINT @@ -590,8 +596,11 @@ namespace windows_nt_kernel static RtlUTF8ToUnicodeN_t RtlUTF8ToUnicodeN; static RtlUnicodeToUTF8N_t RtlUnicodeToUTF8N; static RtlAnsiStringToUnicodeString_t RtlAnsiStringToUnicodeString; + static RtlUnicodeStringToAnsiString_t RtlUnicodeStringToAnsiString; static RtlOemStringToUnicodeString_t RtlOemStringToUnicodeString; + static RtlUnicodeStringToOemString_t RtlUnicodeStringToOemString; static RtlFreeUnicodeString_t RtlFreeUnicodeString; + static RtlFreeAnsiString_t RtlFreeAnsiString; #ifdef _MSC_VER @@ -601,7 +610,7 @@ namespace windows_nt_kernel #endif inline void doinit() { - if(RtlFreeUnicodeString != nullptr) + if(RtlFreeAnsiString != nullptr) { return; } @@ -864,6 +873,13 @@ namespace windows_nt_kernel abort(); } } + if(RtlUnicodeStringToAnsiString == nullptr) + { + if((RtlUnicodeStringToAnsiString = reinterpret_cast<RtlUnicodeStringToAnsiString_t>(GetProcAddress(ntdllh, "RtlUnicodeStringToAnsiString"))) == nullptr) + { + abort(); + } + } if(RtlOemStringToUnicodeString == nullptr) { if((RtlOemStringToUnicodeString = reinterpret_cast<RtlOemStringToUnicodeString_t>(GetProcAddress(ntdllh, "RtlOemStringToUnicodeString"))) == nullptr) @@ -871,6 +887,13 @@ namespace windows_nt_kernel abort(); } } + if(RtlUnicodeStringToOemString == nullptr) + { + if((RtlUnicodeStringToOemString = reinterpret_cast<RtlUnicodeStringToOemString_t>(GetProcAddress(ntdllh, "RtlUnicodeStringToOemString"))) == nullptr) + { + abort(); + } + } if(RtlFreeUnicodeString == nullptr) { if((RtlFreeUnicodeString = reinterpret_cast<RtlFreeUnicodeString_t>(GetProcAddress(ntdllh, "RtlFreeUnicodeString"))) == nullptr) @@ -878,6 +901,13 @@ namespace windows_nt_kernel abort(); } } + if(RtlFreeAnsiString == nullptr) + { + if((RtlFreeAnsiString = reinterpret_cast<RtlFreeAnsiString_t>(GetProcAddress(ntdllh, "RtlFreeAnsiString"))) == nullptr) + { + abort(); + } + } // MAKE SURE you update the early exit check at the top to whatever the last of these is! } diff --git a/include/llfio/v2.0/detail/impl/windows/path_view.ipp b/include/llfio/v2.0/detail/impl/windows/path_view.ipp deleted file mode 100644 index 97801a6a..00000000 --- a/include/llfio/v2.0/detail/impl/windows/path_view.ipp +++ /dev/null @@ -1,99 +0,0 @@ -/* A view of a path to something -(C) 2017 Niall Douglas <http://www.nedproductions.biz/> (20 commits) -File Created: Jul 2017 - - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License in the accompanying file -Licence.txt or at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -Distributed under the Boost Software License, Version 1.0. - (See accompanying file Licence.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -#include "../../../path_view.hpp" -#include "import.hpp" - -LLFIO_V2_NAMESPACE_BEGIN - -#if 0 -LLFIO_HEADERS_ONLY_MEMFUNC_SPEC std::unique_ptr<path_view_component::char8_t[]> path_view_component::_ansi_path_to_utf8(basic_string_view<char8_t> &out, basic_string_view<char> in) noexcept -{ - windows_nt_kernel::init(); - using namespace windows_nt_kernel; - ANSI_STRING astr; - astr.Buffer = const_cast<char *>(in.data()); - if(in.size() > 65535) - { - LLFIO_LOG_FATAL(nullptr, "path_view_component::_ansi_path_to_utf8() cannot convert path sources larger than 65535"); - abort(); - } - astr.Length = astr.MaximumLength = (USHORT) in.size(); - UNICODE_STRING ustr; - NTSTATUS ntstat = AreFileApisANSI() ? RtlAnsiStringToUnicodeString(&ustr, &astr, true) : RtlOemStringToUnicodeString(&ustr, &astr, true); - if(ntstat < 0) - { - return nullptr; - } - unsigned long maxbytecount = 0, actualbytecount = 0; - RtlUnicodeToUTF8N(nullptr, maxbytecount, &actualbytecount, ustr.Buffer, ustr.Length); - std::unique_ptr<char8_t[]> ret; - auto *p = new(std::nothrow) char8_t[actualbytecount + 1]; - if(nullptr != p) - { - ret = std::unique_ptr<char8_t[]>(p); - maxbytecount = actualbytecount; - ntstat = RtlUnicodeToUTF8N((char *) p, maxbytecount, &actualbytecount, ustr.Buffer, ustr.Length); - if(ntstat < 0) - { - ret.reset(); - } - else - { - p[actualbytecount] = 0; - p[maxbytecount] = 0; - out = {p, actualbytecount}; - } - } - RtlFreeUnicodeString(&ustr); - return ret; -} - -LLFIO_HEADERS_ONLY_MEMFUNC_SPEC void path_view::c_str::_from_utf8(const path_view &view) noexcept -{ - windows_nt_kernel::init(); - using namespace windows_nt_kernel; - ULONG written = 0; - NTSTATUS ntstat = RtlUTF8ToUnicodeN(_buffer, static_cast<ULONG>(sizeof(_buffer) - sizeof(wchar_t)), &written, view._state._utf8.data(), static_cast<ULONG>(view._state._utf8.size())); - if(ntstat < 0) - { - LLFIO_LOG_FATAL(ntstat, ntkernel_error(ntstat).message().c_str()); - abort(); - } - length = static_cast<uint16_t>(written / sizeof(wchar_t)); - _buffer[length] = 0; - wchar_t *p = _buffer; - do - { - p = wcschr(p, '/'); - if(p != nullptr) - { - *p = '\\'; - } - } while(p != nullptr); - buffer = _buffer; -} -#endif - -LLFIO_V2_NAMESPACE_END diff --git a/include/llfio/v2.0/path_view.hpp b/include/llfio/v2.0/path_view.hpp index a62a8e3c..e4a661e0 100644 --- a/include/llfio/v2.0/path_view.hpp +++ b/include/llfio/v2.0/path_view.hpp @@ -105,17 +105,17 @@ namespace detail { }; - LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const LLFIO_V2_NAMESPACE::byte *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const char *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const wchar_t *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const char8_t *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const char16_t *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - - LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const LLFIO_V2_NAMESPACE::byte *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const wchar_t *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char8_t *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); - LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char16_t *src_buffer, size_t src_buffer_length, bool src_is_zero_terminated); + LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const LLFIO_V2_NAMESPACE::byte *src_buffer, size_t src_buffer_length); + LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const char *src_buffer, size_t src_buffer_length); + LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const wchar_t *src_buffer, size_t src_buffer_length); + LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const char8_t *src_buffer, size_t src_buffer_length); + LLFIO_HEADERS_ONLY_FUNC_SPEC char *reencode_path_to(size_t &toallocate, char *dest_buffer, size_t dest_buffer_length, const char16_t *src_buffer, size_t src_buffer_length); + + LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const LLFIO_V2_NAMESPACE::byte *src_buffer, size_t src_buffer_length); + LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char *src_buffer, size_t src_buffer_length); + LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const wchar_t *src_buffer, size_t src_buffer_length); + LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char8_t *src_buffer, size_t src_buffer_length); + LLFIO_HEADERS_ONLY_FUNC_SPEC wchar_t *reencode_path_to(size_t &toallocate, wchar_t *dest_buffer, size_t dest_buffer_length, const char16_t *src_buffer, size_t src_buffer_length); class path_view_iterator; } // namespace detail @@ -364,14 +364,19 @@ private: template <class CharT> static filesystem::path _path_from_char_array(basic_string_view<CharT> v) { return {v.data(), v.data() + v.size()}; } static filesystem::path _path_from_char_array(basic_string_view<char8_t> v) { return filesystem::u8path((const char *) v.data(), (const char *) v.data() + v.size()); } - template <class CharT> int _do_compare(const CharT *a, const CharT *b, size_t length) noexcept { return memcmp(a, b, length * sizeof(CharT)); } - int _do_compare(const char8_t *_a, const char8_t *_b, size_t length) noexcept + template <class CharT> static int _do_compare(const CharT *a, const CharT *b, size_t length) noexcept { return memcmp(a, b, length * sizeof(CharT)); } + static int _do_compare(const char8_t *_a, const char8_t *_b, size_t length) noexcept { +#if !defined(__CHAR8_TYPE__) && __cplusplus < 20200000 basic_string_view<char> a((const char *) _a, length); basic_string_view<char> b((const char *) _b, length); +#else + basic_string_view<char8_t> a(_a, length); + basic_string_view<char8_t> b(_b, length); +#endif return a.compare(b); } - int _do_compare(const char16_t *_a, const char16_t *_b, size_t length) noexcept + static int _do_compare(const char16_t *_a, const char16_t *_b, size_t length) noexcept { basic_string_view<char16_t> a(_a, length); basic_string_view<char16_t> b(_b, length); @@ -580,23 +585,23 @@ public: value_type *end = nullptr; if(view._passthrough) { - end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._bytestr, view._length, view._zero_terminated); + end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._bytestr, view._length); } else if(view._char) { - end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._charstr, view._length, view._zero_terminated); + end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._charstr, view._length); } else if(view._wchar) { - end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._wcharstr, view._length, view._zero_terminated); + end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._wcharstr, view._length); } else if(view._utf8) { - end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._char8str, view._length, view._zero_terminated); + end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._char8str, view._length); } else if(view._utf16) { - end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._char16str, view._length, view._zero_terminated); + end = detail::reencode_path_to(required_length, _buffer, _internal_buffer_size, view._char16str, view._length); } else { @@ -623,23 +628,23 @@ public: end = allocated_buffer + (end - _buffer); if(view._passthrough) { - end = detail::reencode_path_to(length, end, required_length, view._bytestr, view._length, view._zero_terminated); + end = detail::reencode_path_to(length, end, required_length, view._bytestr, view._length); } else if(view._char) { - end = detail::reencode_path_to(length, end, required_length, view._charstr, view._length, view._zero_terminated); + end = detail::reencode_path_to(length, end, required_length, view._charstr, view._length); } else if(view._wchar) { - end = detail::reencode_path_to(length, end, required_length, view._wcharstr, view._length, view._zero_terminated); + end = detail::reencode_path_to(length, end, required_length, view._wcharstr, view._length); } else if(view._utf8) { - end = detail::reencode_path_to(length, end, required_length, view._char8str, view._length, view._zero_terminated); + end = detail::reencode_path_to(length, end, required_length, view._char8str, view._length); } else if(view._utf16) { - end = detail::reencode_path_to(length, end, required_length, view._char16str, view._length, view._zero_terminated); + end = detail::reencode_path_to(length, end, required_length, view._char16str, view._length); } else { @@ -670,8 +675,14 @@ public: // under optimisation if it can prove it is never used. value_type _buffer[internal_buffer_size]{}; }; - LLFIO_TEMPLATE(class T, class Deleter, size_t _internal_buffer_size) - LLFIO_TREQUIRES(LLFIO_TPRED(is_source_acceptable<T>)) +#ifdef __cpp_concepts + template <class T, class Deleter, size_t _internal_buffer_size> + requires is_source_acceptable<T> +#elif defined(_MSC_VER) + template <class T, class Deleter, size_t _internal_buffer_size, class> +#else + template <class T, class Deleter, size_t _internal_buffer_size, typename std::enable_if<(is_source_acceptable<T>), bool>::type> +#endif friend struct c_str; }; inline LLFIO_PATH_VIEW_GCC_CONSTEXPR bool operator==(path_view_component x, path_view_component y) noexcept @@ -1229,7 +1240,7 @@ public: compared directly. */ LLFIO_TEMPLATE(class T = typename filesystem::path::value_type, class Deleter = std::default_delete<T[]>, size_t _internal_buffer_size = default_internal_buffer_size) - LLFIO_TREQUIRES(LLFIO_TPRED(is_source_acceptable<T>)) + LLFIO_TREQUIRES(LLFIO_TPRED(path_view::is_source_acceptable<T>)) constexpr inline int compare(path_view p) const; //! \overload LLFIO_TEMPLATE(class T = typename filesystem::path::value_type, class Deleter = std::default_delete<T[]>, size_t _internal_buffer_size = default_internal_buffer_size, class Char) @@ -1261,8 +1272,14 @@ public: { } }; - LLFIO_TEMPLATE(class T, class Deleter, size_t _internal_buffer_size) - LLFIO_TREQUIRES(LLFIO_TPRED(is_source_acceptable<T>)) +#ifdef __cpp_concepts + template <class T, class Deleter, size_t _internal_buffer_size> + requires is_source_acceptable<T> +#elif defined(_MSC_VER) + template <class T, class Deleter, size_t _internal_buffer_size, class> +#else + template <class T, class Deleter, size_t _internal_buffer_size, typename std::enable_if<(is_source_acceptable<T>), bool>::type> +#endif friend struct c_str; }; inline LLFIO_PATH_VIEW_GCC_CONSTEXPR bool operator==(path_view x, path_view y) noexcept @@ -1438,8 +1455,10 @@ constexpr inline path_view::iterator path_view::end() noexcept #ifdef __cpp_concepts template <class T, class Deleter, size_t _internal_buffer_size> requires path_view::is_source_acceptable<T> -#else +#elif defined(_MSC_VER) template <class T, class Deleter, size_t _internal_buffer_size, class> +#else +template <class T, class Deleter, size_t _internal_buffer_size, typename std::enable_if<(path_view::is_source_acceptable<T>), bool>::type> #endif constexpr inline int path_view::compare(path_view o) const { |