Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions include/fast_io_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
#if !defined(__cpp_concepts)
#error "fast_io requires at least C++20 standard compiler."
#else

#include <version>
#include <cstdint>
#include <cstddef>
#include <climits>
#include <bit>
#include <limits>
#include <cstdint>
#include <version>

#if __cpp_lib_three_way_comparison >= 201907L
#include <compare>
Expand Down
8 changes: 4 additions & 4 deletions include/fast_io_core_impl/char_category/char_category.h
Original file line number Diff line number Diff line change
Expand Up @@ -1795,7 +1795,7 @@ inline constexpr bool is_html_whitespace_wide_impl(wchar_t ch) noexcept
};
}

inline constexpr bool is_dos_path_invalid_character_impl(char32_t ch) noexcept
inline constexpr bool is_dos_file_invalid_character_impl(char32_t ch) noexcept
{
if (ch < static_cast<char32_t>(32u))
{
Expand Down Expand Up @@ -1926,15 +1926,15 @@ To do: to_c_fullwidth
*/

template <::std::integral T>
inline constexpr bool is_dos_path_invalid_character(T ch) noexcept
inline constexpr bool is_dos_file_invalid_character(T ch) noexcept
{
if constexpr (::std::signed_integral<T>)
{
return ::fast_io::char_category::details::is_dos_path_invalid_character_impl(static_cast<char32_t>(static_cast<::std::make_unsigned_t<T>>(ch)));
return ::fast_io::char_category::details::is_dos_file_invalid_character_impl(static_cast<char32_t>(static_cast<::std::make_unsigned_t<T>>(ch)));
}
else
{
return ::fast_io::char_category::details::is_dos_path_invalid_character_impl(static_cast<char32_t>(ch));
return ::fast_io::char_category::details::is_dos_file_invalid_character_impl(static_cast<char32_t>(ch));
}
}

Expand Down
10 changes: 5 additions & 5 deletions include/fast_io_core_impl/char_category/char_category_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ enum class char_category_family : ::std::uint_least32_t
c_space, // Whitespace characters (space, tab, newline, etc.)
c_upper, // Uppercase alphabetic characters
c_xdigit, // Hexadecimal digits (0-9, A-F, a-f)
dos_path_invalid_character, // DOS Path invalid character
dos_file_invalid_character, // DOS Path invalid character
html_whitespace // HTML whitespace
};

Expand Down Expand Up @@ -96,9 +96,9 @@ class char_category_traits
{
ret = ::fast_io::char_category::is_c_fullwidth(ch);
}
else if constexpr (fam == ::fast_io::char_category::char_category_family::dos_path_invalid_character)
else if constexpr (fam == ::fast_io::char_category::char_category_family::dos_file_invalid_character)
{
ret = ::fast_io::char_category::is_dos_path_invalid_character(ch);
ret = ::fast_io::char_category::is_dos_file_invalid_character(ch);
}
if constexpr (negate)
{
Expand Down Expand Up @@ -192,7 +192,7 @@ using c_punct = ::fast_io::char_category::char_category_traits<::fast_io::char_c
using c_space = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::c_space, false>;
using c_upper = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::c_upper, false>;
using c_xdigit = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::c_xdigit, false>;
using dos_path_invalid_character = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::dos_path_invalid_character, false>;
using dos_file_invalid_character = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::dos_file_invalid_character, false>;
using html_whitespace = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::html_whitespace, false>;


Expand All @@ -210,7 +210,7 @@ using not_c_punct = ::fast_io::char_category::char_category_traits<::fast_io::ch
using not_c_space = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::c_space, true>;
using not_c_upper = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::c_upper, true>;
using not_c_xdigit = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::c_xdigit, true>;
using not_dos_path_invalid_character = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::dos_path_invalid_character, true>;
using not_dos_file_invalid_character = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::dos_file_invalid_character, true>;
using not_html_whitespace = ::fast_io::char_category::char_category_traits<::fast_io::char_category::char_category_family::html_whitespace, true>;

namespace details
Expand Down
14 changes: 14 additions & 0 deletions include/fast_io_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ using dir_file = directory_file_wrapper<
#endif
>;

// Note:
// The Win32 API layer is not well-suited for precise "dirfile" semantics,
// because it abstracts away the underlying NT object types. Unlike the NT I/O
// manager (where FILE_DIRECTORY_FILE and FILE_NON_DIRECTORY_FILE flags enforce
// strict open-type constraints), Win32’s CreateFileW does not distinguish
// between files and directories unless explicitly checked afterwards.
//
// FILE_FLAG_BACKUP_SEMANTICS merely *permits* opening a directory handle,
// but does not *require* the target to be a directory. Similarly, adding
// FILE_ATTRIBUTE_DIRECTORY has no enforcement effect — it's only a metadata hint.
// Therefore, to emulate dirfile-style correctness, one must explicitly query
// the object type (e.g., via GetFileInformationByHandle or GetFileAttributes)
// after opening the handle.

/*
template region
*/
Expand Down
6 changes: 3 additions & 3 deletions include/fast_io_driver/install_path/impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

#include"install_path.h"

#if defined(_WIN32)
#if defined(_WIN32) || defined(__CYGWIN__)
#include "argv0_null.h"
#else
#include "argv0.h"
#endif

#if (defined(__linux) || defined(__linux__) || defined(__gnu_linux__)) || defined(__CYGWIN__) || defined(__sun)
#if (defined(__linux) || defined(__linux__) || defined(__gnu_linux__)) || defined(__sun)
#include "linux.h"
#elif defined(_WIN32)
#elif defined(_WIN32) || defined(__CYGWIN__)
#if defined(_WIN32_WINDOWS)
#include "win32_9xa.h"
#else
Expand Down
7 changes: 7 additions & 0 deletions include/fast_io_dsal/impl/misc/push_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@
#undef move

#pragma push_macro("new")
#if __GNUC__ >= 16
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wkeyword-macro"
#undef new
#pragma GCC diagnostic pop
#else
#undef new
#endif

#pragma push_macro("refresh")
#undef refresh
Expand Down
2 changes: 1 addition & 1 deletion include/fast_io_hosted/dll/win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ inline void *create_win32_dll_9xa(char const *filename) // 9x kernel does not su
inline void *create_win32_dll_ntw(char16_t const *filename, [[maybe_unused]] dll_mode mode)
{
auto hmodule{
#if _WIN32_WINNT <= 0x0500
#if (defined(_WIN32_WINNT) && _WIN32_WINNT <= 0x0500)
// Windows 2000 does not support Ex apis
::fast_io::win32::LoadLibraryW(filename)
#else
Expand Down
22 changes: 17 additions & 5 deletions include/fast_io_hosted/filesystem/dos.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ namespace posix
// extern char const* my_dos_get_fd_name(int) noexcept __asm__("___get_fd_name");
extern DIR *my_dos_opendir(char const *) noexcept __asm__("_opendir");

extern int my_dos_closedir(DIR *) noexcept __asm__("_closedir");

inline DIR *my_dos_fdopendir(int fd) noexcept
{
return my_dos_opendir(::fast_io::noexcept_call(::__get_fd_name, fd));
Expand All @@ -69,6 +71,16 @@ inline DIR *my_dos_fdopendir(int fd) noexcept
namespace details
{

inline void check_dos_fd_is_dir(int fd)
{
auto const dir{::fast_io::posix::my_dos_fdopendir(fd)};
if (dir == nullptr) [[unlikely]]
{
throw_posix_error(ENOTDIR);
}
::fast_io::posix::my_dos_closedir(dir);
}

inline dos_DIR sys_dup_dir(dos_DIR dirp)
{
if (dirp.dirp == nullptr) [[unlikely]]
Expand Down Expand Up @@ -127,7 +139,7 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
auto newdir{details::sys_dup_dir(other.dirp)};
if (this->dirp.dirp) [[likely]]
{
noexcept_call(::closedir, this->dirp.dirp);
::fast_io::posix::my_dos_closedir(this->dirp.dirp);
}
if (this->dirp.fd != -1) [[likely]]
{
Expand All @@ -149,7 +161,7 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
}
if (this->dirp.dirp) [[likely]]
{
noexcept_call(::closedir, this->dirp.dirp);
::fast_io::posix::my_dos_closedir(this->dirp.dirp);
}
if (this->dirp.fd != -1) [[likely]]
{
Expand All @@ -163,7 +175,7 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
{
if (this->dirp.dirp) [[likely]]
{
noexcept_call(::closedir, this->dirp.dirp);
::fast_io::posix::my_dos_closedir(this->dirp.dirp);
}
if (this->dirp.fd != -1) [[likely]]
{
Expand All @@ -177,7 +189,7 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
if (*this) [[likely]]
{
int fd_to_close{this->dirp.fd};
int ret{noexcept_call(::closedir, this->dirp.dirp)};
int ret{::fast_io::posix::my_dos_closedir(this->dirp.dirp)};
this->dirp.dirp = nullptr;
this->dirp.fd = -1;
if (fd_to_close != -1)
Expand All @@ -195,7 +207,7 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
{
if (this->dirp.dirp) [[likely]]
{
noexcept_call(::closedir, this->dirp.dirp);
::fast_io::posix::my_dos_closedir(this->dirp.dirp);
}
if (this->dirp.fd != -1) [[likely]]
{
Expand Down
16 changes: 11 additions & 5 deletions include/fast_io_hosted/filesystem/nt_at.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,21 @@ inline void nt_unlinkat_impl(void *dirhd, char16_t const *path_c_str, ::std::siz
template <bool zw>
inline void nt_mkdirat_impl(void *dirhd, char16_t const *path_c_str, ::std::size_t path_size, perms pm, bool kernel)
{
constexpr fast_io::win32::nt::details::nt_open_mode create_dir_mode{
fast_io::win32::nt::details::calculate_nt_open_mode(
{fast_io::open_mode::creat | fast_io::open_mode::directory})};
auto m_dir_mode{create_dir_mode};
nt_open_mode m_dir_mode{
.DesiredAccess = 0x00100000 | 0x0001, // SYNCHRONIZE | FILE_LIST_DIRECTORY
.FileAttributes = 0x80, // FILE_ATTRIBUTE_NORMAL
.ShareAccess = 0x00000003, // FILE_SHARE_READ | FILE_SHARE_WRITE
.CreateDisposition = 0x00000002, // CREATE_NEW => FILE_CREATE (0x00000002)
.CreateOptions = 0x00004021 // FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
};

if ((pm & perms::owner_write) == perms::none)
{
m_dir_mode.FileAttributes |= 0x00000001; // FILE_ATTRIBUTE_READONLY
}

auto status{nt_close<zw>(nt_call_determine_kernel_callback(dirhd, path_c_str, path_size, kernel, nt_create_callback<zw>{m_dir_mode}))};

if (status)
{
throw_nt_error(status);
Expand Down Expand Up @@ -775,7 +781,7 @@ inline ::fast_io::details::basic_ct_string<char_type> nt_readlinkat_impl(void *d
.FileAttributes = 0x80, // FILE_ATTRIBUTE_NORMAL
.ShareAccess = 0x00000007, // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
.CreateDisposition = 0x00000001, // OPEN_EXISTING => FILE_OPEN
.CreateOptions = 0x00200000 // FILE_FLAG_OPEN_REPARSE_POINT => FILE_OPEN_REPARSE_POINT (0x00200000)
.CreateOptions = 0x00200000 | 0x00000020 // FILE_FLAG_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT
};

::fast_io::basic_nt_family_file<(zw ? nt_family::zw : nt_family::nt), char> file{
Expand Down
26 changes: 24 additions & 2 deletions include/fast_io_hosted/filesystem/posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,36 @@ namespace fast_io

namespace details
{
#if defined(__CYGWIN__)
struct my_cygwin_DIR
{
/* This is first to set alignment in non _LIBC case. */
unsigned long __d_cookie;
struct dirent *__d_dirent;
char *__d_dirname; /* use for internal caching */
::std::int32_t __d_position; /* used by telldir/seekdir */
int __d_fd;
::std::uintptr_t __d_internal;
void *__handle;
void *__fh;
unsigned __flags;
};

using my_cygwin_DIR_may_alias_ptr =
#if __has_cpp_attribute(__gnu__::__may_alias__)
[[__gnu__::__may_alias__]]
#endif
my_cygwin_DIR *;
#endif

inline int dirp_to_fd(DIR *dirp) noexcept
{
if (dirp == nullptr)
{
return -1;
}
#if defined(__CYGWIN__)
return dirp->__d_fd;
return reinterpret_cast<my_cygwin_DIR_may_alias_ptr>(dirp)->__d_fd;
#else
return dirfd(dirp);
#endif
Expand Down Expand Up @@ -58,7 +80,7 @@ inline DIR *sys_dup_dir(DIR *dirp)
}
auto fd{
#if defined(__CYGWIN__)
dirp->__d_fd
reinterpret_cast<my_cygwin_DIR_may_alias_ptr>(dirp)->__d_fd
#else
dirfd(dirp)
#endif
Expand Down
2 changes: 1 addition & 1 deletion include/fast_io_hosted/filesystem/posix_at.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ inline void posix_utimensat_impl(int dirfd, char const *path, unix_timestamp_opt
}

template<::std::integral char_type>
inline ::fast_io::details::basic_ct_string<char_type> posix_readlinkat_impl(int dirfd, char const *pathname)
inline ::fast_io::details::basic_ct_string<char_type> posix_readlinkat_impl([[maybe_unused]] int dirfd, [[maybe_unused]] char const *pathname)
{
#if defined(AT_SYMLINK_NOFOLLOW)
using posix_ssize_t = ::std::make_signed_t<::std::size_t>;
Expand Down
2 changes: 1 addition & 1 deletion include/fast_io_hosted/platforms/dos_filename.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ inline constexpr bool is_invalid_dos_filename_with_size(char_type const *filenam

for (; curr != end; ++curr)
{
if (auto fc{*curr}; ::fast_io::char_category::is_dos_path_invalid_character(fc)) [[unlikely]]
if (auto fc{*curr}; ::fast_io::char_category::is_dos_file_invalid_character(fc)) [[unlikely]]
{
return true;
}
Expand Down
Loading