diff --git a/include/fast_io_device.h b/include/fast_io_device.h index 4e9d8d27..6239503f 100644 --- a/include/fast_io_device.h +++ b/include/fast_io_device.h @@ -21,7 +21,13 @@ Special file type region. They are usually not used for I/O but for other purpos However, they are still capable of doing I/O. */ -using dir_file = directory_file_wrapper>; +using dir_file = directory_file_wrapper< +#if ((defined(_WIN32) || defined(__CYGWIN__)) && defined(_WIN32_WINDOWS)) + win9x_dir +#else + basic_native_file +#endif + >; /* template region diff --git a/include/fast_io_hosted.h b/include/fast_io_hosted.h index f0d0111b..787bb725 100644 --- a/include/fast_io_hosted.h +++ b/include/fast_io_hosted.h @@ -60,9 +60,8 @@ freestanding ones. #endif #if !defined(__AVR__) -#if defined(__MSDOS__) +#include "fast_io_dsal/string_view.h" #include "fast_io_dsal/string.h" -#endif #include "fast_io_hosted/platforms/native.h" #include "fast_io_hosted/file_loaders/impl.h" #include "fast_io_hosted/wrapper.h" diff --git a/include/fast_io_hosted/file_loaders/win32_file_loader.h b/include/fast_io_hosted/file_loaders/win32_file_loader.h index 58e50400..c716c7c6 100644 --- a/include/fast_io_hosted/file_loaders/win32_file_loader.h +++ b/include/fast_io_hosted/file_loaders/win32_file_loader.h @@ -146,6 +146,13 @@ class win32_family_file_loader address_begin = ret.address_begin; address_end = ret.address_end; } + inline explicit win32_family_file_loader(win9x_fs_dirent fsdirent, open_mode om = open_mode::in, + perms pm = static_cast(436)) + { + auto ret{::fast_io::win32::details::win32_load_file_impl(fsdirent, om, pm)}; + address_begin = ret.address_begin; + address_end = ret.address_end; + } template <::fast_io::constructible_to_os_c_str T> inline explicit win32_family_file_loader(T const &filename, open_mode om = open_mode::in, perms pm = static_cast(436)) @@ -162,12 +169,26 @@ class win32_family_file_loader address_begin = ret.address_begin; address_end = ret.address_end; } + template <::fast_io::constructible_to_os_c_str T> + inline explicit win32_family_file_loader(win9x_at_entry ent, T const &filename, open_mode om = open_mode::in, + perms pm = static_cast(436)) + { + auto ret{::fast_io::win32::details::win32_load_file_impl(ent, filename, om, pm)}; + address_begin = ret.address_begin; + address_end = ret.address_end; + } inline explicit win32_family_file_loader(win32_mmap_options const &options, nt_at_entry ent) { auto ret{::fast_io::win32::details::win32_load_address_options_impl(options, ent.handle)}; address_begin = ret.address_begin; address_end = ret.address_end; } + inline explicit win32_family_file_loader(win32_mmap_options const &options, win9x_at_entry ent) + { + auto ret{::fast_io::win32::details::win32_load_address_options_impl(options, ent.handle.handle)}; + address_begin = ret.address_begin; + address_end = ret.address_end; + } inline explicit win32_family_file_loader(win32_mmap_options const &options, nt_fs_dirent fsdirent, open_mode om = open_mode::in, perms pm = static_cast(436)) { diff --git a/include/fast_io_hosted/filesystem/win9x.h b/include/fast_io_hosted/filesystem/win9x.h index 73b4b866..9f050511 100644 --- a/include/fast_io_hosted/filesystem/win9x.h +++ b/include/fast_io_hosted/filesystem/win9x.h @@ -1 +1,490 @@ #pragma once + +namespace fast_io +{ +struct win9x_dirent +{ + void *file_struct{}; + ::fast_io::u8string find_path{}; + + ::fast_io::win9x_dir_handle d_handle{}; + file_type d_type{}; + ::std::uint_least64_t d_ino{}; + ::fast_io::u8string filename{}; + + ~win9x_dirent() + { + if (file_struct) [[likely]] + { + ::fast_io::win32::FindClose(file_struct); + } + } +}; + +namespace win32::details +{ +inline bool set_win9x_dirent(win9x_dirent &entry, bool start) +{ + ::fast_io::win32::win32_find_dataa wfda{}; + if (start) + { + entry.find_path = ::fast_io::u8concat_fast_io(::fast_io::mnp::code_cvt(entry.d_handle.path), u8"\\*"); + entry.file_struct = ::fast_io::win32::FindFirstFileA(reinterpret_cast(entry.find_path.c_str()), __builtin_addressof(wfda)); + } + else + { + if (::fast_io::win32::FindNextFileA(entry.file_struct, __builtin_addressof(wfda)) == 0) [[unlikely]] + { + return false; + } + } + + entry.filename = ::fast_io::u8string{::fast_io::u8concat_fast_io(::fast_io::mnp::code_cvt_os_c_str(wfda.cFileName))}; + + if (wfda.dwFileAttributes & 0x400) + { + entry.d_type = file_type::symlink; + } + else if (wfda.dwFileAttributes & 0x40) + { + entry.d_type = file_type::character; + } + else if (wfda.dwFileAttributes & 0x10) + { + entry.d_type = file_type::directory; + } + else if (wfda.dwFileAttributes & 0x1000) + { + entry.d_type = file_type::remote; + } + else + { + entry.d_type = file_type::regular; + } + + return true; +} + +inline bool set_win9x_dirent_first(win9x_dirent &entry) +{ + return set_win9x_dirent(entry, true); +} + +inline bool win9x_dirent_next(win9x_dirent &entry) +{ + return set_win9x_dirent(entry, false); +} + +} // namespace win32::details + +struct win9x_directory_entry +{ + using native_char_type = char8_t; + using char_type = char8_t; + win9x_dirent *entry{}; + template + explicit constexpr operator basic_nt_family_io_observer() const noexcept + { + return {entry->d_handle.handle}; + } + template + explicit constexpr operator basic_win32_family_io_observer() const noexcept + { + return {entry->d_handle.handle}; + } + explicit constexpr operator win9x_dir_io_observer() const noexcept + { + return {entry->d_handle}; + } +}; + +inline constexpr win9x_at_entry at(win9x_directory_entry ndet) noexcept +{ + return win9x_at_entry{ndet.entry->d_handle}; +} + +inline constexpr ::fast_io::manipulators::basic_os_c_str_with_known_size +native_filename(win9x_directory_entry pioe) noexcept +{ + auto &ent{*pioe.entry}; + return {ent.filename.c_str(), ent.filename.size()}; +} + +inline constexpr win9x_fs_dirent drt(win9x_directory_entry pioe) noexcept +{ + auto &ent{*pioe.entry}; + return win9x_fs_dirent{ent.d_handle, {ent.filename.c_str(), ent.filename.size()}}; +} + +inline ::fast_io::manipulators::basic_os_c_str_with_known_size +u8filename(win9x_directory_entry pioe) noexcept +{ + using char8_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char8_t const *; + auto &ent{*pioe.entry}; + + return {reinterpret_cast(ent.filename.c_str()), ent.filename.size()}; +} + +inline constexpr ::std::uint_least64_t inode_ul64(win9x_directory_entry) noexcept +{ + return 0; +} + +inline constexpr file_type type(win9x_directory_entry pioe) noexcept +{ + return pioe.entry->d_type; +} + +inline bool is_dot(win9x_directory_entry ent) noexcept +{ + ::std::size_t const native_d_namlen{ent.entry->filename.size()}; + char8_t const *native_d_name_ptr{ent.entry->filename.c_str()}; + return ((native_d_namlen == 1 && *native_d_name_ptr == u8'.') || + (native_d_namlen == 2 && *native_d_name_ptr == u8'.' && native_d_name_ptr[1] == u8'.')); +} + +struct win9x_family_directory_iterator +{ + win9x_dirent *entry{}; + bool finish{}; +}; + +inline win9x_directory_entry operator*(win9x_family_directory_iterator pdit) noexcept +{ + return {pdit.entry}; +} + +inline win9x_family_directory_iterator &operator++(win9x_family_directory_iterator &pdit) +{ + if (!win32::details::win9x_dirent_next(*pdit.entry)) [[unlikely]] + { + pdit.finish = true; + } + + return pdit; +} + +inline constexpr bool operator==(::std::default_sentinel_t, win9x_family_directory_iterator b) noexcept +{ + return b.finish; +} + +inline constexpr bool operator==(win9x_family_directory_iterator b, ::std::default_sentinel_t other) noexcept +{ + return b.finish; +} + +inline constexpr bool operator!=(::std::default_sentinel_t other, win9x_family_directory_iterator b) noexcept +{ + return !b.finish; +} + +inline constexpr bool operator!=(win9x_family_directory_iterator b, ::std::default_sentinel_t other) noexcept +{ + return !b.finish; +} + +struct basic_win9x_directory_generator +{ + win9x_dirent entry{}; + constexpr basic_win9x_directory_generator() noexcept = default; + explicit constexpr basic_win9x_directory_generator(::fast_io::win9x_dir_handle directory_handle) noexcept + { + entry.d_handle = ::std::move(directory_handle); + } + + basic_win9x_directory_generator(basic_win9x_directory_generator const &) = default; + basic_win9x_directory_generator &operator=(basic_win9x_directory_generator const &) = default; + basic_win9x_directory_generator(basic_win9x_directory_generator &&__restrict other) noexcept + : entry(::std::move(other.entry)) + { + other.entry.d_handle.handle = nullptr; + } + basic_win9x_directory_generator & + operator=(basic_win9x_directory_generator &&__restrict other) noexcept + { + entry = ::std::move(other.entry); + other.entry.d_handle.handle = nullptr; + return *this; + } + ~basic_win9x_directory_generator() + { + entry.d_handle.handle = nullptr; + } +}; + +inline win9x_family_directory_iterator begin(basic_win9x_directory_generator &pdg) +{ + win32::details::set_win9x_dirent_first(pdg.entry); + return {__builtin_addressof(pdg.entry), false}; +} + +inline ::std::default_sentinel_t end(basic_win9x_directory_generator const &) noexcept +{ + return {}; +} + +inline basic_win9x_directory_generator current(win9x_at_entry nate) +{ + return basic_win9x_directory_generator(::std::move(nate.handle)); +} + +template +struct basic_win9x_recursive_directory_iterator +{ + using stack_type = StackType; + ::fast_io::win9x_dir_handle root_handle{}; + void *root_file_struct{}; + win9x_dirent *entry{}; + stack_type stack; + bool finish{}; + constexpr basic_win9x_recursive_directory_iterator() = default; + + explicit constexpr basic_win9x_recursive_directory_iterator(::fast_io::win9x_dir_handle rh, win9x_dirent *dp) + : root_handle(::std::move(rh)), entry(dp) + {} + + basic_win9x_recursive_directory_iterator(basic_win9x_recursive_directory_iterator const &) = delete; + basic_win9x_recursive_directory_iterator &operator=(basic_win9x_recursive_directory_iterator const &) = delete; + basic_win9x_recursive_directory_iterator(basic_win9x_recursive_directory_iterator &&) noexcept = default; + basic_win9x_recursive_directory_iterator &operator=(basic_win9x_recursive_directory_iterator &&) noexcept = default; +}; + +template +struct basic_win9x_recursive_directory_generator +{ + using stack_type = StackType; + ::fast_io::win9x_dir_handle root_handle{}; + win9x_dirent entry{}; + + constexpr basic_win9x_recursive_directory_generator() = default; + explicit constexpr basic_win9x_recursive_directory_generator(::fast_io::win9x_dir_handle rhd) + : root_handle(::std::move(rhd)) + { + } + basic_win9x_recursive_directory_generator(basic_win9x_recursive_directory_generator const &) = delete; + basic_win9x_recursive_directory_generator & + operator=(basic_win9x_recursive_directory_generator const &) = delete; + constexpr basic_win9x_recursive_directory_generator( + basic_win9x_recursive_directory_generator &&__restrict other) noexcept + : root_handle(::std::move(other.root_handle)), entry(::std::move(other.entry)) + { + other.root_handle.handle = nullptr; + entry.d_handle.handle = nullptr; + } + constexpr basic_win9x_recursive_directory_generator & + operator=(basic_win9x_recursive_directory_generator &&__restrict other) noexcept + { + root_handle = ::std::move(other.root_handle); + entry = ::std::move(other.entry); + return *this; + } + constexpr ~basic_win9x_recursive_directory_generator() + { + } +}; + +struct win9x_dir_file_stack_type +{ + win9x_dir fd{}; + void *file_struct{}; + + ~win9x_dir_file_stack_type() + { + if (file_struct) [[likely]] + { + ::fast_io::win32::FindClose(file_struct); + } + } +}; + +using win9x_recursive_directory_generator = + basic_win9x_recursive_directory_generator<::fast_io::containers::vector::allocator_type>>; + +template +inline ::std::size_t depth(basic_win9x_recursive_directory_iterator const &prdit) noexcept +{ + return prdit.stack.size(); +} + +template +inline basic_win9x_recursive_directory_iterator &operator++(basic_win9x_recursive_directory_iterator &prdit) +{ + for (;;) + { + prdit.finish = false; + if (prdit.stack.empty()) + { + prdit.entry->d_handle = prdit.root_handle; + prdit.entry->file_struct = prdit.root_file_struct; + if (!win32::details::win9x_dirent_next(*prdit.entry)) + { + prdit.finish = true; + return prdit; + } + } + else + { + auto &back{prdit.stack.back()}; + prdit.entry->d_handle = back.fd.handle; + prdit.entry->file_struct = back.file_struct; + if (back.file_struct == nullptr) + { + win32::details::set_win9x_dirent_first(*prdit.entry); + back.file_struct = prdit.entry->file_struct; + } + if (!win32::details::win9x_dirent_next(*prdit.entry)) + { + prdit.finish = true; + prdit.stack.pop_back(); + + continue; + } + } + if (prdit.entry->d_type == file_type::directory) + { + ::std::size_t const native_d_namlen{prdit.entry->filename.size()}; + char8_t const *native_d_name_ptr{prdit.entry->filename.c_str()}; + if ((native_d_namlen == 1 && *native_d_name_ptr == u8'.') || + (native_d_namlen == 2 && *native_d_name_ptr == u8'.' && native_d_name_ptr[1] == u8'.')) + { + continue; + } + prdit.stack.emplace_back( + win9x_dir{win9x_at_entry{prdit.stack.empty() ? prdit.root_handle : prdit.stack.back().fd.handle}, + ::fast_io::manipulators::basic_os_c_str_with_known_size{native_d_name_ptr, native_d_namlen}, + open_mode::directory}, + nullptr); + } + return prdit; + } + return prdit; +} + +template +inline void pop(basic_win9x_recursive_directory_iterator &prdit) +{ + if (prdit.stack.empty()) + { + prdit.entry = nullptr; + } + else + { + prdit.stack.pop_back(); + ++prdit; + } +} + +template +inline basic_win9x_recursive_directory_iterator +begin(basic_win9x_recursive_directory_generator &prg) noexcept +{ + basic_win9x_recursive_directory_iterator prdit{prg.root_handle, __builtin_addressof(prg.entry)}; + + prdit.entry->d_handle = prg.root_handle; + bool finish{win32::details::set_win9x_dirent_first(*prdit.entry)}; + prdit.root_file_struct = prdit.entry->file_struct; + + if (finish && prdit.entry->d_type == file_type::directory) + { + auto &ent{*prdit.entry}; + char8_t const *native_d_name_ptr{ent.filename.c_str()}; + ::std::size_t const native_d_namlen{ent.filename.size()}; + if ((native_d_namlen == 1 && *native_d_name_ptr == u8'.') || + (native_d_namlen == 2 && *native_d_name_ptr == u8'.' && native_d_name_ptr[1] == u8'.')) + { + ++prdit; + } + else + { + prdit.stack.emplace_back( + win9x_dir{win9x_at_entry{prdit.root_handle}, + ::fast_io::manipulators::basic_os_c_str_with_known_size{native_d_name_ptr, native_d_namlen}, + open_mode::directory}, + nullptr); + } + } + return prdit; +} + +template +inline ::std::default_sentinel_t +end(basic_win9x_recursive_directory_generator const &) noexcept +{ + return {}; +} + +template +inline win9x_directory_entry +operator*(basic_win9x_recursive_directory_iterator const &prdit) noexcept +{ + return {prdit.entry}; +} + +template +inline bool operator==(::std::default_sentinel_t, + basic_win9x_recursive_directory_iterator const &b) noexcept +{ + return b.stack.empty() && b.finish; +} + +template +inline bool operator==(basic_win9x_recursive_directory_iterator const &b, + ::std::default_sentinel_t sntnl) noexcept +{ + return b.stack.empty() && b.finish; +} + +template +inline bool operator!=(::std::default_sentinel_t sntnl, + basic_win9x_recursive_directory_iterator const &b) noexcept +{ + return !(b.stack.empty() && b.finish); +} + +template +inline bool operator!=(basic_win9x_recursive_directory_iterator const &b, + ::std::default_sentinel_t sntnl) noexcept +{ + return !(b.stack.empty() && b.finish); +} + +inline win9x_recursive_directory_generator recursive(win9x_at_entry nate) +{ + return win9x_recursive_directory_generator{nate.handle}; +} + +inline auto native_extension(win9x_directory_entry ent) noexcept +{ + auto &et{*ent.entry}; + return ::fast_io::details::find_dot_and_sep(et.filename.c_str(), et.filename.size()); +} + +inline auto native_stem(win9x_directory_entry ent) noexcept +{ + auto &et{*ent.entry}; + return ::fast_io::details::find_dot_and_sep(et.filename.c_str(), et.filename.size()); +} + +inline auto u8extension(win9x_directory_entry ent) noexcept +{ + auto &et{*ent.entry}; + return ::fast_io::details::find_dot_and_sep(et.filename.c_str(), et.filename.size()); +} + +inline auto u8stem(win9x_directory_entry ent) noexcept +{ + auto &et{*ent.entry}; + return ::fast_io::details::find_dot_and_sep(et.filename.c_str(), et.filename.size()); +} + +#ifndef __CYGWIN__ +using native_directory_entry = win9x_directory_entry; +#endif + + +} // namespace fast_io diff --git a/include/fast_io_hosted/platforms/native_base.h b/include/fast_io_hosted/platforms/native_base.h index 0b7a88a1..08b87fb6 100644 --- a/include/fast_io_hosted/platforms/native_base.h +++ b/include/fast_io_hosted/platforms/native_base.h @@ -17,6 +17,7 @@ inline constexpr ::std::uint_least32_t win32_stderr_number(static_cast<::std::ui #include "nt.h" // #include"win32_iocp_overlapped.h" + #include "win32.h" #include "win32_network/win32.h" #endif @@ -34,8 +35,13 @@ namespace fast_io { #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__) +#if defined(_WIN32_WINDOWS) +using native_at_entry = win9x_at_entry; +using native_fs_dirent = win9x_fs_dirent; +#else using native_at_entry = nt_at_entry; using native_fs_dirent = nt_fs_dirent; +#endif #if defined(_WIN32_WINDOWS) template <::std::integral ch_type> diff --git a/include/fast_io_hosted/platforms/nt.h b/include/fast_io_hosted/platforms/nt.h index bbb5d232..06ee044f 100644 --- a/include/fast_io_hosted/platforms/nt.h +++ b/include/fast_io_hosted/platforms/nt.h @@ -602,7 +602,7 @@ inline nt_at_entry nt_at_fdcwd() noexcept return nt_at_entry{bit_cast(value)}; } -#if !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__) +#if !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__) && !defined(_WIN32_WINDOWS) #if __has_cpp_attribute(__gnu__::__always_inline__) [[__gnu__::__always_inline__]] #elif __has_cpp_attribute(msvc::forceinline) @@ -1043,188 +1043,6 @@ inline void truncate(basic_nt_family_io_observer handle, ::std: { ::fast_io::win32::nt::details::nt_truncate_impl(handle.handle, newfilesize); } -#if 0 -template -inline posix_file_status status(basic_nt_family_io_observer handle) -{ - return ::fast_io::win32::nt::details::nt_status_impl(handle.handle); -} -#endif - -template -struct nt_family_file_lock -{ - void *handle{}; - template <::std::signed_integral int_type> - requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) - inline void lock(basic_flock_request &__restrict t) - { - ::fast_io::win32::nt::details::nt_family_file_lock_impl(this->handle, t); - } - template <::std::signed_integral int_type> - requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) - inline void unlock(basic_flock_request &__restrict t) noexcept - { - ::fast_io::win32::nt::details::nt_family_file_unlock_impl(this->handle, t); - } - template <::std::signed_integral int_type> - requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) - inline bool try_lock(basic_flock_request &__restrict t) noexcept - { - return ::fast_io::win32::nt::details::nt_family_file_try_lock_impl(this->handle, t); - } -}; - -using nt_file_lock = nt_family_file_lock; -using zw_file_lock = nt_family_file_lock; - -template -inline constexpr nt_family_file_lock file_lock(basic_nt_family_io_observer niob) noexcept -{ - return {niob}; -} - -template -struct -#if __has_cpp_attribute(clang::trivially_relocatable) - [[clang::trivially_relocatable]] -#endif - nt_family_file_factory -{ - using native_handle_type = void *; - void *handle{}; - explicit constexpr nt_family_file_factory(void *hd) noexcept - : handle(hd) {}; - nt_family_file_factory(nt_family_file_factory const &) = delete; - nt_family_file_factory &operator=(nt_family_file_factory const &) = delete; - ~nt_family_file_factory() - { - if (handle) [[likely]] - { - ::fast_io::win32::nt::nt_close(this->handle); - } - } -}; - -using nt_file_factory = nt_family_file_factory; -using zw_file_factory = nt_family_file_factory; - -template -class basic_nt_family_file : public basic_nt_family_io_observer -{ -public: - using typename basic_nt_family_io_observer::char_type; - using typename basic_nt_family_io_observer::input_char_type; - using typename basic_nt_family_io_observer::output_char_type; - using typename basic_nt_family_io_observer::native_handle_type; - using file_factory_type = nt_family_file_factory; - constexpr basic_nt_family_file() noexcept = default; - constexpr basic_nt_family_file(basic_nt_family_io_observer) noexcept = delete; - constexpr basic_nt_family_file &operator=(basic_nt_family_io_observer) noexcept = delete; - - template - requires ::std::same_as> - explicit constexpr basic_nt_family_file(native_hd hd) noexcept - : basic_nt_family_io_observer{hd} - { - } - constexpr basic_nt_family_file(decltype(nullptr)) noexcept = delete; - explicit constexpr basic_nt_family_file(nt_family_file_factory &&hd) noexcept - : basic_nt_family_io_observer{hd} - { - hd.handle = nullptr; - } - explicit basic_nt_family_file(io_dup_t, basic_nt_family_io_observer wiob) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_dup_impl(wiob.handle)} - { - } - explicit basic_nt_family_file(nt_fs_dirent fsdirent, open_mode om, perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_family_create_file_fs_dirent_impl(fsdirent.handle, fsdirent.filename.c_str(), fsdirent.filename.size(), {om, pm})} - { - } - template <::fast_io::constructible_to_os_c_str T> - explicit basic_nt_family_file(T const &t, open_mode om, perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_create_file_impl(t, {om, pm})} - { - } - template <::fast_io::constructible_to_os_c_str T> - explicit basic_nt_family_file(nt_at_entry ent, T const &t, open_mode om, perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle, t, {om, pm})} - { - } - - template <::fast_io::constructible_to_os_c_str T> - explicit basic_nt_family_file(io_kernel_t, T const &t, open_mode om, perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_create_file_kernel_impl(t, {om, pm})} - { - } - template <::fast_io::constructible_to_os_c_str T> - explicit basic_nt_family_file(io_kernel_t, nt_at_entry ent, T const &t, open_mode om, - perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle, t, - {om, pm})} - { - } - - void close() - { - if (this->handle) [[likely]] - { - auto status{::fast_io::win32::nt::nt_close(this->handle)}; - this->handle = nullptr; // POSIX standard says we should never call close(2) again even close syscall fails - if (status) [[unlikely]] - { - throw_nt_error(status); - } - } - } - void reset(native_handle_type newhandle = nullptr) noexcept - { - if (this->handle) [[likely]] - { - ::fast_io::win32::nt::nt_close(this->handle); - } - this->handle = newhandle; - } - basic_nt_family_file(basic_nt_family_file const &other) - : basic_nt_family_io_observer( - ::fast_io::win32::nt::details::nt_dup_impl(other.handle)) - { - } - basic_nt_family_file &operator=(basic_nt_family_file const &other) - { - this->handle = ::fast_io::win32::nt::details::nt_dup2_impl(other.handle, this->handle); - return *this; - } - constexpr basic_nt_family_file(basic_nt_family_file &&__restrict other) noexcept - : basic_nt_family_io_observer{other.handle} - { - other.handle = nullptr; - } - basic_nt_family_file &operator=(basic_nt_family_file &&__restrict other) noexcept - { - if (this->handle) [[likely]] - { - ::fast_io::win32::nt::nt_close(this->handle); - } - this->handle = other.handle; - other.handle = nullptr; - return *this; - } - ~basic_nt_family_file() - { - if (this->handle) [[likely]] - { - ::fast_io::win32::nt::nt_close(this->handle); - } - } -}; namespace win32::nt::details { @@ -1427,6 +1245,181 @@ inline posix_file_status status(basic_nt_family_io_observer wio return win32::nt::details::nt_status_impl(wiob.handle); } +template +struct nt_family_file_lock +{ + void *handle{}; + template <::std::signed_integral int_type> + requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) + inline void lock(basic_flock_request &__restrict t) + { + ::fast_io::win32::nt::details::nt_family_file_lock_impl(this->handle, t); + } + template <::std::signed_integral int_type> + requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) + inline void unlock(basic_flock_request &__restrict t) noexcept + { + ::fast_io::win32::nt::details::nt_family_file_unlock_impl(this->handle, t); + } + template <::std::signed_integral int_type> + requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) + inline bool try_lock(basic_flock_request &__restrict t) noexcept + { + return ::fast_io::win32::nt::details::nt_family_file_try_lock_impl(this->handle, t); + } +}; + +using nt_file_lock = nt_family_file_lock; +using zw_file_lock = nt_family_file_lock; + +template +inline constexpr nt_family_file_lock file_lock(basic_nt_family_io_observer niob) noexcept +{ + return {niob}; +} + +template +struct +#if __has_cpp_attribute(clang::trivially_relocatable) + [[clang::trivially_relocatable]] +#endif + nt_family_file_factory +{ + using native_handle_type = void *; + void *handle{}; + explicit constexpr nt_family_file_factory(void *hd) noexcept + : handle(hd) {}; + nt_family_file_factory(nt_family_file_factory const &) = delete; + nt_family_file_factory &operator=(nt_family_file_factory const &) = delete; + ~nt_family_file_factory() + { + if (handle) [[likely]] + { + ::fast_io::win32::nt::nt_close(this->handle); + } + } +}; + +using nt_file_factory = nt_family_file_factory; +using zw_file_factory = nt_family_file_factory; + +template +class basic_nt_family_file : public basic_nt_family_io_observer +{ +public: + using typename basic_nt_family_io_observer::char_type; + using typename basic_nt_family_io_observer::input_char_type; + using typename basic_nt_family_io_observer::output_char_type; + using typename basic_nt_family_io_observer::native_handle_type; + using file_factory_type = nt_family_file_factory; + constexpr basic_nt_family_file() noexcept = default; + constexpr basic_nt_family_file(basic_nt_family_io_observer) noexcept = delete; + constexpr basic_nt_family_file &operator=(basic_nt_family_io_observer) noexcept = delete; + + template + requires ::std::same_as> + explicit constexpr basic_nt_family_file(native_hd hd) noexcept + : basic_nt_family_io_observer{hd} + { + } + constexpr basic_nt_family_file(decltype(nullptr)) noexcept = delete; + explicit constexpr basic_nt_family_file(nt_family_file_factory &&hd) noexcept + : basic_nt_family_io_observer{hd} + { + hd.handle = nullptr; + } + explicit basic_nt_family_file(io_dup_t, basic_nt_family_io_observer wiob) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_dup_impl(wiob.handle)} + { + } + explicit basic_nt_family_file(nt_fs_dirent fsdirent, open_mode om, perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_family_create_file_fs_dirent_impl(fsdirent.handle, fsdirent.filename.c_str(), fsdirent.filename.size(), {om, pm})} + { + } + template <::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(T const &t, open_mode om, perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_create_file_impl(t, {om, pm})} + { + } + template <::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(nt_at_entry ent, T const &t, open_mode om, perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle, t, {om, pm})} + { + } + + template <::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(io_kernel_t, T const &t, open_mode om, perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_create_file_kernel_impl(t, {om, pm})} + { + } + template <::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(io_kernel_t, nt_at_entry ent, T const &t, open_mode om, + perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle, t, + {om, pm})} + { + } + + void close() + { + if (this->handle) [[likely]] + { + auto status{::fast_io::win32::nt::nt_close(this->handle)}; + this->handle = nullptr; // POSIX standard says we should never call close(2) again even close syscall fails + if (status) [[unlikely]] + { + throw_nt_error(status); + } + } + } + void reset(native_handle_type newhandle = nullptr) noexcept + { + if (this->handle) [[likely]] + { + ::fast_io::win32::nt::nt_close(this->handle); + } + this->handle = newhandle; + } + basic_nt_family_file(basic_nt_family_file const &other) + : basic_nt_family_io_observer( + ::fast_io::win32::nt::details::nt_dup_impl(other.handle)) + { + } + basic_nt_family_file &operator=(basic_nt_family_file const &other) + { + this->handle = ::fast_io::win32::nt::details::nt_dup2_impl(other.handle, this->handle); + return *this; + } + constexpr basic_nt_family_file(basic_nt_family_file &&__restrict other) noexcept + : basic_nt_family_io_observer{other.handle} + { + other.handle = nullptr; + } + basic_nt_family_file &operator=(basic_nt_family_file &&__restrict other) noexcept + { + if (this->handle) [[likely]] + { + ::fast_io::win32::nt::nt_close(this->handle); + } + this->handle = other.handle; + other.handle = nullptr; + return *this; + } + ~basic_nt_family_file() + { + if (this->handle) [[likely]] + { + ::fast_io::win32::nt::nt_close(this->handle); + } + } +}; + template <::std::integral char_type> using basic_nt_io_observer = basic_nt_family_io_observer; diff --git a/include/fast_io_hosted/platforms/posix.h b/include/fast_io_hosted/platforms/posix.h index 89b19520..505f8d94 100644 --- a/include/fast_io_hosted/platforms/posix.h +++ b/include/fast_io_hosted/platforms/posix.h @@ -1139,6 +1139,10 @@ class basic_posix_family_file : public basic_posix_family_io_observer(fsdirent, om, pm), om) { } + basic_posix_family_file(win9x_fs_dirent fsdirent, open_mode om, perms pm = static_cast(436)) + : basic_posix_family_file(basic_win32_file(fsdirent, om, pm), om) + { + } template <::fast_io::constructible_to_os_c_str T> basic_posix_family_file(T const &file, open_mode om, perms pm = static_cast(436)) : basic_posix_family_file(basic_win32_file(file, om, pm), om) @@ -1149,6 +1153,11 @@ class basic_posix_family_file : public basic_posix_family_io_observer(nate, file, om, pm), om) { } + template <::fast_io::constructible_to_os_c_str T> + basic_posix_family_file(win9x_at_entry nate, T const &file, open_mode om, perms pm = static_cast(436)) + : basic_posix_family_file(basic_win32_file(nate, file, om, pm), om) + { + } template explicit constexpr basic_posix_family_file(io_construct_t, basic_nt_family_io_observer hd, open_mode m) noexcept diff --git a/include/fast_io_hosted/platforms/win32.h b/include/fast_io_hosted/platforms/win32.h index a083062f..02073fd0 100644 --- a/include/fast_io_hosted/platforms/win32.h +++ b/include/fast_io_hosted/platforms/win32.h @@ -542,7 +542,6 @@ inline void *win32_create_file_at_fs_dirent_impl(void *directory_handle, char_ty return ::fast_io::win32::nt::details::nt_family_create_file_fs_dirent_impl(directory_handle, filename_c_str, filename_c_str_len, ompm); } - } // namespace details struct win32_io_redirection @@ -920,10 +919,641 @@ struct if (handle) [[likely]] { ::fast_io::win32::CloseHandle(handle); + handle = nullptr; + } + } +}; + +struct win9x_dir_handle +{ + void *handle; + ::fast_io::u8string path; +}; + +namespace win32::details +{ +inline void close_win9x_dir_handle(win9x_dir_handle &h) noexcept +{ + ::fast_io::win32::CloseHandle(h.handle); + h.path.clear(); +} + +inline win9x_dir_handle win9x_dir_dup_impl(win9x_dir_handle const &h) noexcept +{ + return {::fast_io::win32::details::win32_dup_impl(h.handle), h.path}; +} + +template <::std::integral char_type> +inline win9x_dir_handle win9x_create_dir_file_at_fs_dirent_impl(win9x_dir_handle directory_handle, char_type const *filename_c_str, + ::std::size_t filename_c_str_len, open_mode_perms ompm) +{ + auto c{filename_c_str}; + + if (auto const fc{*c}; fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + + ++c; + for (; c != filename_c_str + filename_c_str_len; ++c) + { + auto fc{*c}; + if (fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + } + + ::fast_io::u8string str{::fast_io::u8concat_fast_io(::fast_io::mnp::code_cvt(directory_handle.path), u8"\\", ::fast_io::mnp::code_cvt(::fast_io::mnp::os_c_str_with_known_size(filename_c_str, filename_c_str_len)))}; + auto handle{::fast_io::details::win32_create_file_impl(str, ompm)}; + return {handle, ::std::move(str)}; +} + +template + requires(::fast_io::constructible_to_os_c_str) +inline win9x_dir_handle win9x_create_dir_file_impl(T const &t, open_mode_perms ompm) +{ + ::fast_io::u8string path{::fast_io::u8concat_fast_io(::fast_io::mnp::code_cvt(t))}; + for (auto& c : path) + { + if (c == u8'/') + { + c = u8'\\'; + } + } + if (path.back() == u8'\\') + { + path.pop_back_unchecked(); + } + return {::fast_io::details::win32_create_file_impl(t, ompm), ::std::move(path)}; +} + +template + requires(::fast_io::constructible_to_os_c_str) +inline win9x_dir_handle win9x_create_dir_file_at_impl(win9x_dir_handle directory_handle, T const &t, open_mode_perms ompm) +{ + if constexpr (::std::is_array_v) + { + using cstr_char_type = ::std::remove_extent_t; + auto size{::fast_io::details::cal_array_size(t)}; + + auto c{t}; + + if (auto const fc{*c}; fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + + ++c; + for (; c != t + size; ++c) + { + auto fc{*c}; + if (fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + } + + } + else if constexpr (type_has_c_str_method) + { + using cstr_char_type = ::std::remove_pointer_t; + cstr_char_type const *b{}; + ::std::size_t size{}; + + if constexpr (::std::ranges::contiguous_range<::std::remove_cvref_t>) + { + b = ::std::ranges::data(t); + size = ::std::ranges::size(t); + } + else if constexpr (::fast_io::details::cxx_std_filesystem_pseudo_concept<::std::remove_cvref_t>) + { + auto const &native{t.native()}; + b = native.c_str(); + size = native.size(); + } + else + { + auto ptr{t.c_str()}; + b = ptr; + size = ::fast_io::cstr_len(ptr); + } + + auto c{b}; + + if (auto const fc{*c}; fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + + ++c; + for (; c != b + size; ++c) + { + auto fc{*c}; + if (fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + } + + } + else // types like ::std::basic_string_view, we must allocate new space to hold that type + { + using strvw_char_type = ::std::remove_pointer_t; + strvw_char_type const *b{t.data()}; + ::std::size_t size{t.length()}; + + auto c{b}; + + if (auto const fc{*c}; fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + + ++c; + for (; c != b + size; ++c) + { + auto fc{*c}; + if (fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + } + + } + + ::fast_io::u8string str{::fast_io::u8concat_fast_io(::fast_io::mnp::code_cvt(directory_handle.path), u8"\\", ::fast_io::mnp::code_cvt(t))}; + auto handle{::fast_io::details::win32_create_file_impl(str, ompm)}; + return {handle, ::std::move(str)}; +} + +} // namespace win32::details + +namespace details +{ +template <::std::integral char_type> +inline void *win9x_create_file_at_fs_dirent_impl(win9x_dir_handle directory_handle, char_type const *filename_c_str, + ::std::size_t filename_c_str_len, open_mode_perms ompm) +{ + auto c{filename_c_str}; + + if (auto const fc{*c}; fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + + ++c; + for (; c != filename_c_str + filename_c_str_len; ++c) + { + auto fc{*c}; + if (fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); } } + + ::fast_io::u8string str{::fast_io::u8concat_fast_io(::fast_io::mnp::code_cvt(directory_handle.path), u8"\\", ::fast_io::mnp::code_cvt(::fast_io::mnp::os_c_str_with_known_size(filename_c_str, filename_c_str_len)))}; + auto handle{::fast_io::details::win32_create_file_impl(str, ompm)}; + return handle; +} + + +template + requires(::fast_io::constructible_to_os_c_str) +inline void *win9x_create_file_at_impl(win9x_dir_handle directory_handle, T const &t, open_mode_perms ompm) +{ + if constexpr (::std::is_array_v) + { + using cstr_char_type = ::std::remove_extent_t; + auto size{::fast_io::details::cal_array_size(t)}; + + auto c{t}; + + if (auto const fc{*c}; fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + + ++c; + for (; c != t + size; ++c) + { + auto fc{*c}; + if (fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + } + } + else if constexpr (type_has_c_str_method) + { + using cstr_char_type = ::std::remove_pointer_t; + cstr_char_type const *b{}; + ::std::size_t size{}; + + if constexpr (::std::ranges::contiguous_range<::std::remove_cvref_t>) + { + b = ::std::ranges::data(t); + size = ::std::ranges::size(t); + } + else if constexpr (::fast_io::details::cxx_std_filesystem_pseudo_concept<::std::remove_cvref_t>) + { + auto const &native{t.native()}; + b = native.c_str(); + size = native.size(); + } + else + { + auto ptr{t.c_str()}; + b = ptr; + size = ::fast_io::cstr_len(ptr); + } + + auto c{b}; + + if (auto const fc{*c}; fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + + ++c; + for (; c != b + size; ++c) + { + auto fc{*c}; + if (fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + } + } + else // types like ::std::basic_string_view, we must allocate new space to hold that type + { + using strvw_char_type = ::std::remove_pointer_t; + strvw_char_type const *b{t.data()}; + ::std::size_t size{t.length()}; + + auto c{b}; + + if (auto const fc{*c}; fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + + ++c; + for (; c != b + size; ++c) + { + auto fc{*c}; + if (fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v || + fc == ::fast_io::char_literal_v) [[unlikely]] + { + throw_win32_error(3221225530); + } + } + } + + ::fast_io::u8string str{::fast_io::u8concat_fast_io(::fast_io::mnp::code_cvt(directory_handle.path), u8"\\", ::fast_io::mnp::code_cvt(t))}; + auto handle{::fast_io::details::win32_create_file_impl(str, ompm)}; + return handle; +} + +} // namespace details + +struct win9x_fs_dirent +{ + win9x_dir_handle handle{}; // path + ::fast_io::manipulators::basic_os_c_str_with_known_size filename{}; // file }; +struct win9x_at_entry +{ + using native_handle_type = win9x_dir_handle; + native_handle_type handle{}; + explicit constexpr win9x_at_entry() noexcept = default; + explicit constexpr win9x_at_entry(native_handle_type mhandle) noexcept + : handle(::std::move(mhandle)) + {} +}; + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline win9x_at_entry win9x_at_fdcwd() noexcept +{ + constexpr ::std::ptrdiff_t value{-3}; // use -3 as at_fdwcd handle + return win9x_at_entry{{::fast_io::bit_cast(value), ::fast_io::u8concat_fast_io(u8".")}}; +} + +#if !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__) && defined(_WIN32_WINDOWS) +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline win9x_at_entry at_fdcwd() noexcept +{ + return win9x_at_fdcwd(); +} +#endif + +struct +#if __has_cpp_attribute(clang::trivially_relocatable) + [[clang::trivially_relocatable]] +#endif + win9x_dir_file_factory +{ + using native_handle_type = win9x_dir_handle; + win9x_dir_handle handle{}; + explicit constexpr win9x_dir_file_factory(native_handle_type hd) noexcept + : handle(::std::move(hd)) {}; + win9x_dir_file_factory(win9x_dir_file_factory const &) = delete; + win9x_dir_file_factory &operator=(win9x_dir_file_factory const &) = delete; + ~win9x_dir_file_factory() + { + if (handle.handle) [[likely]] + { + ::fast_io::win32::details::close_win9x_dir_handle(handle); + handle.handle = nullptr; + } + } +}; + +class win9x_dir_io_observer +{ +public: + using native_handle_type = win9x_dir_handle; + using char_type = char8_t; + using input_char_type = char_type; + using output_char_type = char_type; + native_handle_type handle{}; + constexpr native_handle_type native_handle() const noexcept + { + return handle; + } + explicit operator bool() const noexcept + { + return handle.handle != nullptr && handle.handle != reinterpret_cast(static_cast<::std::ptrdiff_t>(-1)); + } + constexpr native_handle_type release() noexcept + { + auto temp{::std::move(handle)}; + handle.handle = nullptr; + return temp; + } +}; +inline constexpr bool operator==(win9x_dir_io_observer const &a, + win9x_dir_io_observer const &b) noexcept +{ + return a.handle.handle == b.handle.handle; +} + +#if __cpp_lib_three_way_comparison >= 201907L + +inline constexpr auto operator<=>(win9x_dir_io_observer const &a, + win9x_dir_io_observer const &b) noexcept +{ + return a.handle.handle <=> b.handle.handle; +} + +#endif + +class win9x_dir : public win9x_dir_io_observer +{ +public: + using typename win9x_dir_io_observer::char_type; + using typename win9x_dir_io_observer::input_char_type; + using typename win9x_dir_io_observer::output_char_type; + using typename win9x_dir_io_observer::native_handle_type; + using win9x_dir_io_observer::native_handle; + using file_factory_type = win9x_dir_file_factory; + explicit constexpr win9x_dir() noexcept = default; + + constexpr win9x_dir(win9x_dir_io_observer) noexcept = delete; + constexpr win9x_dir &operator=(win9x_dir_io_observer) noexcept = delete; + + win9x_dir(win9x_dir const &other) + : win9x_dir_io_observer{win32::details::win9x_dir_dup_impl(other.handle)} + { + } + win9x_dir &operator=(win9x_dir const &other) + { + this->handle = win32::details::win9x_dir_dup_impl(other.handle); + return *this; + } + win9x_dir(win9x_dir &&__restrict b) noexcept + : win9x_dir_io_observer{b.release()} + { + } + win9x_dir &operator=(win9x_dir &&__restrict b) noexcept + { + if (*this) [[likely]] + { + win32::details::close_win9x_dir_handle(this->handle); + } + this->handle = b.release(); + return *this; + } + void reset(native_handle_type newhandle = {}) noexcept + { + if (*this) [[likely]] + { + ::fast_io::win32::details::close_win9x_dir_handle(this->handle); + } + this->handle = ::std::move(newhandle); + } + void close() + { + if (*this) [[likely]] + { + ::fast_io::win32::details::close_win9x_dir_handle(this->handle); + this->handle.handle = nullptr; + } + } + + template + requires ::std::same_as> + explicit constexpr win9x_dir(native_hd handle1) noexcept + : win9x_dir_io_observer{::std::move(handle1)} + { + } + + win9x_dir(io_dup_t, win9x_dir_io_observer wiob) + : win9x_dir_io_observer{::fast_io::win32::details::win9x_dir_dup_impl(wiob.handle)} + { + } + + explicit constexpr win9x_dir(win9x_dir_file_factory &&fact) noexcept + : win9x_dir_io_observer{::std::move(fact.handle)} + { + fact.handle.handle = nullptr; + } + + explicit constexpr win9x_dir(decltype(nullptr)) noexcept = delete; + + explicit win9x_dir(win9x_fs_dirent fsdirent, open_mode om, perms pm = static_cast(436)) + : win9x_dir_io_observer{ + ::fast_io::win32::details::win9x_create_dir_file_at_fs_dirent_impl( + fsdirent.handle, fsdirent.filename.c_str(), fsdirent.filename.size(), {om, pm})} + { + } + + template <::fast_io::constructible_to_os_c_str T> + explicit win9x_dir(T const &filename, open_mode om, perms pm = static_cast(436)) + : win9x_dir_io_observer{ + ::fast_io::win32::details::win9x_create_dir_file_impl(filename, {om, pm})} + { + } + + template <::fast_io::constructible_to_os_c_str T> + explicit win9x_dir(win9x_at_entry nate, T const &filename, open_mode om, + perms pm = static_cast(436)) + : win9x_dir_io_observer{ + ::fast_io::win32::details::win9x_create_dir_file_at_impl(nate.handle, filename, {om, pm})} + { + } + + ~win9x_dir() + { + if (*this) [[likely]] + { + ::fast_io::win32::details::close_win9x_dir_handle(this->handle); + this->handle.handle = nullptr; + } + } +}; + +inline win9x_at_entry at(win9x_dir const &wiob) noexcept +{ + return win9x_at_entry{wiob.handle}; +} + template class basic_win32_family_file : public basic_win32_family_io_observer { @@ -1000,11 +1630,14 @@ class basic_win32_family_file : public basic_win32_family_io_observer{::fast_io::details::create_win32_temp_file_impl()} { } + explicit basic_win32_family_file(nt_fs_dirent fsdirent, open_mode om, perms pm = static_cast(436)) : basic_win32_family_io_observer{ ::fast_io::details::win32_create_file_at_fs_dirent_impl( @@ -1012,6 +1645,13 @@ class basic_win32_family_file : public basic_win32_family_io_observer(436)) + : basic_win32_family_io_observer{ + ::fast_io::details::win9x_create_file_at_fs_dirent_impl( + fsdirent.handle, fsdirent.filename.c_str(), fsdirent.filename.size(), {om, pm})} + { + } + template <::fast_io::constructible_to_os_c_str T> explicit basic_win32_family_file(T const &filename, open_mode om, perms pm = static_cast(436)) : basic_win32_family_io_observer{ @@ -1027,6 +1667,14 @@ class basic_win32_family_file : public basic_win32_family_io_observer + explicit basic_win32_family_file(win9x_at_entry nate, T const &filename, open_mode om, + perms pm = static_cast(436)) + : basic_win32_family_io_observer{ + ::fast_io::details::win9x_create_file_at_impl(nate.handle, filename, {om, pm})} + { + } + explicit basic_win32_family_file(io_async_t) requires(::std::same_as) : basic_win32_family_io_observer{details::create_io_completion_port_impl()} @@ -1037,21 +1685,70 @@ class basic_win32_family_file : public basic_win32_family_io_observerhandle); + this->handle = nullptr; } } }; -#if 0 -template -inline void truncate(basic_win32_family_io_observer handle,::fast_io::uintfpos_t size) +template +inline void truncate(basic_win32_family_io_observer handle, ::fast_io::uintfpos_t size) { - io_stream_seek_bytes_define(handle,size,seekdir::beg); - if(!::fast_io::win32::SetEndOfFile(handle.handle)) + win32::details::seek_impl(handle, size, seekdir::beg); + if (!::fast_io::win32::SetEndOfFile(handle.handle)) + { throw_win32_error(); + } } -#endif + namespace win32::details { +struct handle_guard +{ + void *h{}; + constexpr handle_guard() noexcept = default; + constexpr handle_guard(void *r) noexcept + : h{r} {}; + constexpr ~handle_guard() + { + if (h) [[likely]] + { + ::fast_io::win32::CloseHandle(h); + h = nullptr; + } + }; + constexpr void clear() noexcept + { + if (h) [[likely]] + { + ::fast_io::win32::CloseHandle(h); + h = nullptr; + } + } +}; + +struct map_guard +{ + void *map{}; + constexpr map_guard() noexcept = default; + constexpr map_guard(void *r) noexcept + : map{r} {}; + constexpr ~map_guard() + { + if (map) [[likely]] + { + ::fast_io::win32::UnmapViewOfFile(map); + map = nullptr; + } + }; + constexpr void clear() noexcept + { + if (map) [[likely]] + { + ::fast_io::win32::UnmapViewOfFile(map); + map = nullptr; + } + } +}; inline file_type file_type_impl(void *handle) { diff --git a/include/fast_io_hosted/platforms/win32/apis.h b/include/fast_io_hosted/platforms/win32/apis.h index acd37e52..472b12d0 100644 --- a/include/fast_io_hosted/platforms/win32/apis.h +++ b/include/fast_io_hosted/platforms/win32/apis.h @@ -3263,7 +3263,7 @@ extern int #if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) __stdcall #endif - GetExitCodeProcess(void *,::std::uint_least32_t*) noexcept + GetExitCodeProcess(void *, ::std::uint_least32_t *) noexcept #if defined(__clang__) || defined(__GNUC__) #if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) #if !defined(__clang__) @@ -3329,4 +3329,134 @@ extern ::std::uint_least32_t #endif ; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + FindFirstFileW(char16_t const *, win32_find_dataw *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("FindFirstFileW@8") +#else + __asm__("_FindFirstFileW@8") +#endif +#else + __asm__("FindFirstFileW") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void * +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + FindFirstFileA(char const *, win32_find_dataa *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("FindFirstFileA@8") +#else + __asm__("_FindFirstFileA@8") +#endif +#else + __asm__("FindFirstFileA") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + FindNextFileW(void *, win32_find_dataw *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("FindNextFileW@8") +#else + __asm__("_FindNextFileW@8") +#endif +#else + __asm__("FindNextFileW") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + FindNextFileA(void *, win32_find_dataa *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("FindNextFileA@8") +#else + __asm__("_FindNextFileA@8") +#endif +#else + __asm__("FindNextFileA") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + FindClose(void *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("FindClose@4") +#else + __asm__("_FindClose@4") +#endif +#else + __asm__("FindClose") +#endif +#endif + ; + } // namespace fast_io::win32 diff --git a/include/fast_io_hosted/platforms/win32/msvc_linker_32.h b/include/fast_io_hosted/platforms/win32/msvc_linker_32.h index efec9c8a..af676bda 100644 --- a/include/fast_io_hosted/platforms/win32/msvc_linker_32.h +++ b/include/fast_io_hosted/platforms/win32/msvc_linker_32.h @@ -129,6 +129,11 @@ #pragma comment(linker,"/alternatename:__imp_?GetExitCodeProcess@win32@fast_io@@YAHPAXPAI@Z=__imp_GetExitCodeProcess") #pragma comment(linker,"/alternatename:__imp_?QueryDosDeviceW@win32@fast_io@@YAIPB_SPA_SI@Z=__imp_QueryDosDeviceW") #pragma comment(linker,"/alternatename:__imp_?QueryDosDeviceA@win32@fast_io@@YAIPBDPADI@Z=__imp_QueryDosDeviceA") +#pragma comment(linker,"/alternatename:__imp_?FindFirstFileW@win32@fast_io@@YAPAXPB_SPAUwin32_find_dataw@12@@Z=__imp_FindFirstFileW") +#pragma comment(linker,"/alternatename:__imp_?FindFirstFileA@win32@fast_io@@YAPAXPBDPAUwin32_find_dataa@12@@Z=__imp_FindFirstFileA") +#pragma comment(linker,"/alternatename:__imp_?FindNextFileW@win32@fast_io@@YAHPAXPAUwin32_find_dataw@12@@Z=__imp_FindNextFileW") +#pragma comment(linker,"/alternatename:__imp_?FindNextFileA@win32@fast_io@@YAHPAXPAUwin32_find_dataa@12@@Z=__imp_FindNextFileA") +#pragma comment(linker,"/alternatename:__imp_?FindClose@win32@fast_io@@YAHPAX@Z=__imp_FindClose") // NT #pragma comment(linker,"/alternatename:__imp_?rtl_nt_status_to_dos_error@nt@win32@fast_io@@YAII@Z=__imp_RtlNtStatusToDosError") #pragma comment(linker,"/alternatename:__imp_?NtClose@nt@win32@fast_io@@YAIPAX@Z=__imp_NtClose") @@ -159,7 +164,7 @@ #pragma comment(linker,"/alternatename:__imp_?ZwSetSystemTime@nt@win32@fast_io@@YAIPA_K0@Z=__imp_ZwSetSystemTime") #pragma comment(linker,"/alternatename:__imp_?NtCreateProcess@nt@win32@fast_io@@YAIPAPAXIPAUobject_attributes@123@PAXI222@Z=__imp_NtCreateProcess") #pragma comment(linker,"/alternatename:__imp_?ZwCreateProcess@nt@win32@fast_io@@YAIPAPAXIPAUobject_attributes@123@PAXI222@Z=__imp_ZwCreateProcess") -#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YAEPB_WPAUunicode_string@123@PAPB_WPAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YAEPB_SPAUunicode_string@123@PAPB_SPAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U") #pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u_with_status@nt@win32@fast_io@@YAIPB_SPAUunicode_string@123@PAPB_SPAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U_WithStatus") #pragma comment(linker,"/alternatename:__imp_?rtl_free_unicode_string@nt@win32@fast_io@@YAXPAUunicode_string@123@@Z=__imp_RtlFreeUnicodeString") #pragma comment(linker,"/alternatename:__imp_?RtlInitializeCriticalSection@nt@win32@fast_io@@YAXPAX@Z=__imp_RtlInitializeCriticalSection") diff --git a/include/fast_io_hosted/platforms/win32/msvc_linker_32_i686.h b/include/fast_io_hosted/platforms/win32/msvc_linker_32_i686.h index 5b537131..a833b61d 100644 --- a/include/fast_io_hosted/platforms/win32/msvc_linker_32_i686.h +++ b/include/fast_io_hosted/platforms/win32/msvc_linker_32_i686.h @@ -129,6 +129,11 @@ #pragma comment(linker,"/alternatename:__imp_?GetExitCodeProcess@win32@fast_io@@YGHPAXPAI@Z=__imp__GetExitCodeProcess@8") #pragma comment(linker,"/alternatename:__imp_?QueryDosDeviceW@win32@fast_io@@YGIPB_SPA_SI@Z=__imp__QueryDosDeviceW@12") #pragma comment(linker,"/alternatename:__imp_?QueryDosDeviceA@win32@fast_io@@YGIPBDPADI@Z=__imp__QueryDosDeviceA@12") +#pragma comment(linker,"/alternatename:__imp_?FindFirstFileW@win32@fast_io@@YGPAXPB_SPAUwin32_find_dataw@12@@Z=__imp__FindFirstFileW@8") +#pragma comment(linker,"/alternatename:__imp_?FindFirstFileA@win32@fast_io@@YGPAXPBDPAUwin32_find_dataa@12@@Z=__imp__FindFirstFileA@8") +#pragma comment(linker,"/alternatename:__imp_?FindNextFileW@win32@fast_io@@YGHPAXPAUwin32_find_dataw@12@@Z=__imp__FindNextFileW@8") +#pragma comment(linker,"/alternatename:__imp_?FindNextFileA@win32@fast_io@@YGHPAXPAUwin32_find_dataa@12@@Z=__imp__FindNextFileA@8") +#pragma comment(linker,"/alternatename:__imp_?FindClose@win32@fast_io@@YGHPAX@Z=__imp__FindClose@4") // NT #pragma comment(linker,"/alternatename:__imp_?rtl_nt_status_to_dos_error@nt@win32@fast_io@@YGII@Z=__imp__RtlNtStatusToDosError@4") #pragma comment(linker,"/alternatename:__imp_?NtClose@nt@win32@fast_io@@YGIPAX@Z=__imp__NtClose@4") @@ -159,7 +164,7 @@ #pragma comment(linker,"/alternatename:__imp_?ZwSetSystemTime@nt@win32@fast_io@@YGIPA_K0@Z=__imp__ZwSetSystemTime@8") #pragma comment(linker,"/alternatename:__imp_?NtCreateProcess@nt@win32@fast_io@@YGIPAPAXIPAUobject_attributes@123@PAXI222@Z=__imp__NtCreateProcess@32") #pragma comment(linker,"/alternatename:__imp_?ZwCreateProcess@nt@win32@fast_io@@YGIPAPAXIPAUobject_attributes@123@PAXI222@Z=__imp__ZwCreateProcess@32") -#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YGEPB_WPAUunicode_string@123@PAPB_WPAUrtl_relative_name_u@123@@Z=__imp__RtlDosPathNameToNtPathName_U@16") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YGEPB_SPAUunicode_string@123@PAPB_SPAUrtl_relative_name_u@123@@Z=__imp__RtlDosPathNameToNtPathName_U@16") #pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u_with_status@nt@win32@fast_io@@YGIPB_SPAUunicode_string@123@PAPB_SPAUrtl_relative_name_u@123@@Z=__imp__RtlDosPathNameToNtPathName_U_WithStatus@16") #pragma comment(linker,"/alternatename:__imp_?rtl_free_unicode_string@nt@win32@fast_io@@YGXPAUunicode_string@123@@Z=__imp__RtlFreeUnicodeString@4") #pragma comment(linker,"/alternatename:__imp_?RtlInitializeCriticalSection@nt@win32@fast_io@@YGXPAX@Z=__imp__RtlInitializeCriticalSection@4") diff --git a/include/fast_io_hosted/platforms/win32/msvc_linker_64.h b/include/fast_io_hosted/platforms/win32/msvc_linker_64.h index 7a09800e..dfb02f87 100644 --- a/include/fast_io_hosted/platforms/win32/msvc_linker_64.h +++ b/include/fast_io_hosted/platforms/win32/msvc_linker_64.h @@ -129,6 +129,11 @@ #pragma comment(linker,"/alternatename:__imp_?GetExitCodeProcess@win32@fast_io@@YAHPEAXPEAI@Z=__imp_GetExitCodeProcess") #pragma comment(linker,"/alternatename:__imp_?QueryDosDeviceW@win32@fast_io@@YAIPEB_SPEA_SI@Z=__imp_QueryDosDeviceW") #pragma comment(linker,"/alternatename:__imp_?QueryDosDeviceA@win32@fast_io@@YAIPEBDPEADI@Z=__imp_QueryDosDeviceA") +#pragma comment(linker,"/alternatename:__imp_?FindFirstFileW@win32@fast_io@@YAPEAXPEB_SPEAUwin32_find_dataw@12@@Z=__imp_FindFirstFileW") +#pragma comment(linker,"/alternatename:__imp_?FindFirstFileA@win32@fast_io@@YAPEAXPEBDPEAUwin32_find_dataa@12@@Z=__imp_FindFirstFileA") +#pragma comment(linker,"/alternatename:__imp_?FindNextFileW@win32@fast_io@@YAHPEAXPEAUwin32_find_dataw@12@@Z=__imp_FindNextFileW") +#pragma comment(linker,"/alternatename:__imp_?FindNextFileA@win32@fast_io@@YAHPEAXPEAUwin32_find_dataa@12@@Z=__imp_FindNextFileA") +#pragma comment(linker,"/alternatename:__imp_?FindClose@win32@fast_io@@YAHPEAX@Z=__imp_FindClose") // NT #pragma comment(linker,"/alternatename:__imp_?rtl_nt_status_to_dos_error@nt@win32@fast_io@@YAII@Z=__imp_RtlNtStatusToDosError") #pragma comment(linker,"/alternatename:__imp_?NtClose@nt@win32@fast_io@@YAIPEAX@Z=__imp_NtClose") @@ -159,7 +164,7 @@ #pragma comment(linker,"/alternatename:__imp_?ZwSetSystemTime@nt@win32@fast_io@@YAIPEA_K0@Z=__imp_ZwSetSystemTime") #pragma comment(linker,"/alternatename:__imp_?NtCreateProcess@nt@win32@fast_io@@YAIPEAPEAXIPEAUobject_attributes@123@PEAXI222@Z=__imp_NtCreateProcess") #pragma comment(linker,"/alternatename:__imp_?ZwCreateProcess@nt@win32@fast_io@@YAIPEAPEAXIPEAUobject_attributes@123@PEAXI222@Z=__imp_ZwCreateProcess") -#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YAEPEB_WPEAUunicode_string@123@PEAPEB_WPEAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YAEPEB_SPEAUunicode_string@123@PEAPEB_SPEAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U") #pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u_with_status@nt@win32@fast_io@@YAIPEB_SPEAUunicode_string@123@PEAPEB_SPEAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U_WithStatus") #pragma comment(linker,"/alternatename:__imp_?rtl_free_unicode_string@nt@win32@fast_io@@YAXPEAUunicode_string@123@@Z=__imp_RtlFreeUnicodeString") #pragma comment(linker,"/alternatename:__imp_?RtlInitializeCriticalSection@nt@win32@fast_io@@YAXPEAX@Z=__imp_RtlInitializeCriticalSection") diff --git a/include/fast_io_hosted/platforms/win32/win32_definitions.h b/include/fast_io_hosted/platforms/win32/win32_definitions.h index b584145b..bcf68087 100644 --- a/include/fast_io_hosted/platforms/win32/win32_definitions.h +++ b/include/fast_io_hosted/platforms/win32/win32_definitions.h @@ -396,5 +396,43 @@ struct file_basic_info ::std::uint_least32_t FileAttributes; }; +struct win32_find_dataa +{ + ::std::uint_least32_t dwFileAttributes; + filetime ftCreationTime; + filetime ftLastAccessTime; + filetime ftLastWriteTime; + ::std::uint_least32_t nFileSizeHigh; + ::std::uint_least32_t nFileSizeLow; + ::std::uint_least32_t dwReserved0; + ::std::uint_least32_t dwReserved1; + char cFileName[260]; + char cAlternateFileName[14]; +#ifdef _MAC + ::std::uint_least32_t dwFileType; + ::std::uint_least32_t dwCreatorType; + ::std::uint_least16_t wFinderFlags; +#endif +}; + +struct win32_find_dataw +{ + ::std::uint_least32_t dwFileAttributes; + filetime ftCreationTime; + filetime ftLastAccessTime; + filetime ftLastWriteTime; + ::std::uint_least32_t nFileSizeHigh; + ::std::uint_least32_t nFileSizeLow; + ::std::uint_least32_t dwReserved0; + ::std::uint_least32_t dwReserved1; + char16_t cFileName[260]; + char16_t cAlternateFileName[14]; +#if defined(_68K_) || defined(_MPPC_) + ::std::uint_least32_t dwFileType; + ::std::uint_least32_t dwCreatorType; + ::std::uint_least16_t wFinderFlags; +#endif +} ; + } // namespace fast_io::win32 diff --git a/include/fast_io_hosted/process/win32.h b/include/fast_io_hosted/process/win32.h index d4ac6e45..d6690fca 100644 --- a/include/fast_io_hosted/process/win32.h +++ b/include/fast_io_hosted/process/win32.h @@ -105,54 +105,6 @@ inline void win32_duplicate_object_std(void *parent_process, void *&standard_io_ template using win32_process_char_type = ::std::conditional_t; -struct map_guard -{ - void *map{}; - constexpr map_guard() noexcept = default; - constexpr map_guard(void *r) noexcept - : map{r} {}; - constexpr ~map_guard() - { - if (map) [[likely]] - { - ::fast_io::win32::UnmapViewOfFile(map); - map = nullptr; - } - }; - constexpr void clear() noexcept - { - if (map) [[likely]] - { - ::fast_io::win32::UnmapViewOfFile(map); - map = nullptr; - } - } -}; - -struct handle_guard -{ - void *h{}; - constexpr handle_guard() noexcept = default; - constexpr handle_guard(void *r) noexcept - : h{r} {}; - constexpr ~handle_guard() - { - if (h) [[likely]] - { - ::fast_io::win32::CloseHandle(h); - h = nullptr; - } - }; - constexpr void clear() noexcept - { - if (h) [[likely]] - { - ::fast_io::win32::CloseHandle(h); - h = nullptr; - } - } -}; - template inline win32_user_process_information win32_process_create_impl(void *__restrict fhandle, win32_process_char_type const *args, win32_process_char_type const *envs, @@ -274,7 +226,46 @@ inline win32_user_process_information win32_process_create_impl(void *__restrict mg1.clear(); hg1.clear(); - // do not need to change nt path to dos path (9x) + // change nt path to dos path (9x) + auto address_begin{pszFilename}; + + // change nt path to dos path + auto k32_module{::fast_io::win32::GetModuleHandleA(reinterpret_cast(u8"Kernel32.dll"))}; + if (k32_module) + { + using QueryDosDeviceA_t = ::std::uint_least32_t (*)(char const *, char *, ::std::uint_least32_t) noexcept; + + // win95 may not have this function, need check (?) + auto QueryDosDeviceA_p{reinterpret_cast(::fast_io::win32::GetProcAddress(k32_module, reinterpret_cast(u8"QueryDosDeviceA")))}; + if (QueryDosDeviceA_p) + { + if (pszFilename[0] == '\\') + { + char DosDevice[4]{0, ':', 0, 0}; + char NtPath[64]; + char *RetStr{}; + ::std::size_t NtPathLen{}; + for (char i{65}; i < static_cast(26 + 65); i++) + { + DosDevice[0] = i; + if (QueryDosDeviceA_p(DosDevice, NtPath, 64)) + { + NtPathLen = ::fast_io::cstr_len(NtPath); + + if (::fast_io::freestanding::my_memcmp(pszFilename, NtPath, NtPathLen * sizeof(char)) == 0) [[unlikely]] + { + goto next2; + } + } + } + throw_win32_error(0x3); + next2: + address_begin += NtPathLen - 2; + address_begin[0] = DosDevice[0]; + address_begin[1] = ':'; + } + } + } // create process ::fast_io::win32::startupinfoa si{sizeof(si)}; si.hStdInput = processio.in.win32_handle ? processio.in.win32_handle : ::fast_io::win32_stdin().handle; @@ -283,7 +274,7 @@ inline win32_user_process_information win32_process_create_impl(void *__restrict si.dwFlags = 0x00000100; ::fast_io::win32::process_information pi{}; - if (!::fast_io::win32::CreateProcessA(pszFilename, const_cast(args), nullptr, nullptr, 1, 0, (void *)envs, nullptr, __builtin_addressof(si), __builtin_addressof(pi))) + if (!::fast_io::win32::CreateProcessA(address_begin, const_cast(args), nullptr, nullptr, 1, 0, (void *)envs, nullptr, __builtin_addressof(si), __builtin_addressof(pi))) { throw_win32_error(); }