mirror of
https://git.mirrors.martin98.com/https://github.com/gulrak/filesystem
synced 2025-08-12 12:39:04 +08:00
Merge pull request #136 from phprus/win-smart-ptr
Performance optimization for Windows.
This commit is contained in:
commit
09908b7241
@ -424,7 +424,8 @@ public:
|
||||
template <typename T>
|
||||
using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char8_t>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value, path>::type;
|
||||
#else
|
||||
using path_from_string = typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value ||
|
||||
using path_from_string =
|
||||
typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value ||
|
||||
std::is_same<char16_t const*, typename std::decay<T>::type>::value || std::is_same<char16_t*, typename std::decay<T>::type>::value || std::is_same<char32_t const*, typename std::decay<T>::type>::value ||
|
||||
std::is_same<char32_t*, typename std::decay<T>::type>::value || std::is_same<wchar_t const*, typename std::decay<T>::type>::value || std::is_same<wchar_t*, typename std::decay<T>::type>::value,
|
||||
path>::type;
|
||||
@ -800,6 +801,7 @@ public:
|
||||
file_type type() const noexcept;
|
||||
perms permissions() const noexcept;
|
||||
friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); }
|
||||
|
||||
private:
|
||||
file_type _type;
|
||||
perms _perms;
|
||||
@ -2005,6 +2007,52 @@ GHC_INLINE file_status file_status_from_st_mode(T mode)
|
||||
}
|
||||
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
|
||||
class unique_handle
|
||||
{
|
||||
public:
|
||||
typedef HANDLE element_type;
|
||||
|
||||
unique_handle() noexcept
|
||||
: handle_(INVALID_HANDLE_VALUE)
|
||||
{
|
||||
}
|
||||
explicit unique_handle(element_type h) noexcept
|
||||
: handle_(h)
|
||||
{
|
||||
}
|
||||
unique_handle(unique_handle&& u) noexcept
|
||||
: handle_(u.release())
|
||||
{
|
||||
}
|
||||
~unique_handle() { reset(); }
|
||||
unique_handle& operator=(unique_handle&& u) noexcept
|
||||
{
|
||||
reset(u.release());
|
||||
return *this;
|
||||
}
|
||||
element_type get() const noexcept { return handle_; }
|
||||
explicit operator bool() const noexcept { return handle_ != INVALID_HANDLE_VALUE; }
|
||||
element_type release() noexcept
|
||||
{
|
||||
element_type tmp = handle_;
|
||||
handle_ = INVALID_HANDLE_VALUE;
|
||||
return tmp;
|
||||
}
|
||||
void reset(element_type h = INVALID_HANDLE_VALUE) noexcept
|
||||
{
|
||||
element_type tmp = handle_;
|
||||
handle_ = h;
|
||||
if (tmp != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(tmp);
|
||||
}
|
||||
}
|
||||
void swap(unique_handle& u) noexcept { std::swap(handle_, u.handle_); }
|
||||
|
||||
private:
|
||||
element_type handle_;
|
||||
};
|
||||
|
||||
#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
|
||||
typedef struct _REPARSE_DATA_BUFFER
|
||||
{
|
||||
@ -2041,15 +2089,21 @@ typedef struct _REPARSE_DATA_BUFFER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
GHC_INLINE std::shared_ptr<REPARSE_DATA_BUFFER> getReparseData(const path& p, std::error_code& ec)
|
||||
template <class T>
|
||||
struct free_deleter
|
||||
{
|
||||
std::shared_ptr<void> file(CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
|
||||
if (file.get() == INVALID_HANDLE_VALUE) {
|
||||
void operator()(T* p) const { std::free(p); }
|
||||
};
|
||||
|
||||
GHC_INLINE std::unique_ptr<REPARSE_DATA_BUFFER, free_deleter<REPARSE_DATA_BUFFER>> getReparseData(const path& p, std::error_code& ec)
|
||||
{
|
||||
unique_handle file(CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0));
|
||||
if (!file) {
|
||||
ec = detail::make_system_error();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<REPARSE_DATA_BUFFER> reparseData((REPARSE_DATA_BUFFER*)std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE), std::free);
|
||||
std::unique_ptr<REPARSE_DATA_BUFFER, free_deleter<REPARSE_DATA_BUFFER>> reparseData(reinterpret_cast<REPARSE_DATA_BUFFER*>(std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)));
|
||||
ULONG bufferUsed;
|
||||
if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) {
|
||||
return reparseData;
|
||||
@ -3057,7 +3111,8 @@ GHC_INLINE bool has_executable_extension(const path& p)
|
||||
return false;
|
||||
}
|
||||
const path::value_type* ext = fn._path.c_str() + pos + 1;
|
||||
if (detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("exe")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("cmd")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("bat")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("com"))) {
|
||||
if (detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("exe")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("cmd")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("bat")) ||
|
||||
detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("com"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -4153,10 +4208,10 @@ GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
std::shared_ptr<void> file1(::CreateFileW(GHC_NATIVEWP(p1), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
|
||||
detail::unique_handle file1(::CreateFileW(GHC_NATIVEWP(p1), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
|
||||
auto e1 = ::GetLastError();
|
||||
std::shared_ptr<void> file2(::CreateFileW(GHC_NATIVEWP(p2), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
|
||||
if (file1.get() == INVALID_HANDLE_VALUE || file2.get() == INVALID_HANDLE_VALUE) {
|
||||
detail::unique_handle file2(::CreateFileW(GHC_NATIVEWP(p2), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
|
||||
if (!file1 || !file2) {
|
||||
#ifdef LWG_2937_BEHAVIOUR
|
||||
ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
|
||||
#else
|
||||
@ -4246,9 +4301,9 @@ GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcep
|
||||
ec.clear();
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
uintmax_t result = static_cast<uintmax_t>(-1);
|
||||
std::shared_ptr<void> file(::CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
|
||||
detail::unique_handle file(::CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
|
||||
BY_HANDLE_FILE_INFORMATION inf;
|
||||
if (file.get() == INVALID_HANDLE_VALUE) {
|
||||
if (!file) {
|
||||
ec = detail::make_system_error();
|
||||
}
|
||||
else {
|
||||
@ -4477,7 +4532,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
|
||||
ec.clear();
|
||||
auto d = new_time.time_since_epoch();
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
std::shared_ptr<void> file(::CreateFileW(GHC_NATIVEWP(p), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL), ::CloseHandle);
|
||||
detail::unique_handle file(::CreateFileW(GHC_NATIVEWP(p), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL));
|
||||
FILETIME ft;
|
||||
auto tt = std::chrono::duration_cast<std::chrono::microseconds>(d).count() * 10 + 116444736000000000;
|
||||
ft.dwLowDateTime = static_cast<DWORD>(tt);
|
||||
@ -4831,8 +4886,8 @@ GHC_INLINE void resize_file(const path& p, uintmax_t size, std::error_code& ec)
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<void> file(CreateFileW(GHC_NATIVEWP(p), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle);
|
||||
if (file.get() == INVALID_HANDLE_VALUE) {
|
||||
detail::unique_handle file(CreateFileW(GHC_NATIVEWP(p), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL));
|
||||
if (!file) {
|
||||
ec = detail::make_system_error();
|
||||
}
|
||||
else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) {
|
||||
@ -5609,15 +5664,33 @@ public:
|
||||
#else
|
||||
_dir_entry._symlink_status.permissions(perms::unknown);
|
||||
switch (_entry->d_type) {
|
||||
case DT_BLK: _dir_entry._symlink_status.type(file_type::block); break;
|
||||
case DT_CHR: _dir_entry._symlink_status.type(file_type::character); break;
|
||||
case DT_DIR: _dir_entry._symlink_status.type(file_type::directory); break;
|
||||
case DT_FIFO: _dir_entry._symlink_status.type(file_type::fifo); break;
|
||||
case DT_LNK: _dir_entry._symlink_status.type(file_type::symlink); break;
|
||||
case DT_REG: _dir_entry._symlink_status.type(file_type::regular); break;
|
||||
case DT_SOCK: _dir_entry._symlink_status.type(file_type::socket); break;
|
||||
case DT_UNKNOWN: _dir_entry._symlink_status.type(file_type::none); break;
|
||||
default: _dir_entry._symlink_status.type(file_type::unknown); break;
|
||||
case DT_BLK:
|
||||
_dir_entry._symlink_status.type(file_type::block);
|
||||
break;
|
||||
case DT_CHR:
|
||||
_dir_entry._symlink_status.type(file_type::character);
|
||||
break;
|
||||
case DT_DIR:
|
||||
_dir_entry._symlink_status.type(file_type::directory);
|
||||
break;
|
||||
case DT_FIFO:
|
||||
_dir_entry._symlink_status.type(file_type::fifo);
|
||||
break;
|
||||
case DT_LNK:
|
||||
_dir_entry._symlink_status.type(file_type::symlink);
|
||||
break;
|
||||
case DT_REG:
|
||||
_dir_entry._symlink_status.type(file_type::regular);
|
||||
break;
|
||||
case DT_SOCK:
|
||||
_dir_entry._symlink_status.type(file_type::socket);
|
||||
break;
|
||||
case DT_UNKNOWN:
|
||||
_dir_entry._symlink_status.type(file_type::none);
|
||||
break;
|
||||
default:
|
||||
_dir_entry._symlink_status.type(file_type::unknown);
|
||||
break;
|
||||
}
|
||||
if (_entry->d_type != DT_LNK) {
|
||||
_dir_entry._status = _dir_entry._symlink_status;
|
||||
|
Loading…
x
Reference in New Issue
Block a user