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

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2019-10-10 14:11:34 +0300
committerNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2019-10-10 14:11:34 +0300
commitd256ae1ed0c18280f656fd7e483d0d07ef74bde7 (patch)
treedd2b69eceb884601f8f81690352401639ee19af2
parentaad9e4b0a0aa3826c78400664c250e3aa3fab696 (diff)
Refactored path view now compiles on all platforms, doesn't link on POSIX, code is untested.
-rw-r--r--include/llfio/revision.hpp6
-rw-r--r--include/llfio/v2.0/detail/impl/path_view.ipp348
-rw-r--r--include/llfio/v2.0/detail/impl/windows/import.hpp32
-rw-r--r--include/llfio/v2.0/detail/impl/windows/path_view.ipp99
-rw-r--r--include/llfio/v2.0/path_view.hpp79
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
{