mirror of
https://git.mirrors.martin98.com/https://github.com/gulrak/filesystem
synced 2025-08-13 18:36:01 +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>
|
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;
|
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
|
#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<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,
|
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;
|
path>::type;
|
||||||
@ -800,6 +801,7 @@ public:
|
|||||||
file_type type() const noexcept;
|
file_type type() const noexcept;
|
||||||
perms permissions() 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(); }
|
friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
file_type _type;
|
file_type _type;
|
||||||
perms _perms;
|
perms _perms;
|
||||||
@ -2005,6 +2007,52 @@ GHC_INLINE file_status file_status_from_st_mode(T mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GHC_OS_WINDOWS
|
#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
|
#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
|
||||||
typedef struct _REPARSE_DATA_BUFFER
|
typedef struct _REPARSE_DATA_BUFFER
|
||||||
{
|
{
|
||||||
@ -2041,15 +2089,21 @@ typedef struct _REPARSE_DATA_BUFFER
|
|||||||
#endif
|
#endif
|
||||||
#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);
|
void operator()(T* p) const { std::free(p); }
|
||||||
if (file.get() == INVALID_HANDLE_VALUE) {
|
};
|
||||||
|
|
||||||
|
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();
|
ec = detail::make_system_error();
|
||||||
return nullptr;
|
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;
|
ULONG bufferUsed;
|
||||||
if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) {
|
if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) {
|
||||||
return reparseData;
|
return reparseData;
|
||||||
@ -3057,7 +3111,8 @@ GHC_INLINE bool has_executable_extension(const path& p)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const path::value_type* ext = fn._path.c_str() + pos + 1;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4153,10 +4208,10 @@ GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec)
|
|||||||
{
|
{
|
||||||
ec.clear();
|
ec.clear();
|
||||||
#ifdef GHC_OS_WINDOWS
|
#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();
|
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);
|
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.get() == INVALID_HANDLE_VALUE || file2.get() == INVALID_HANDLE_VALUE) {
|
if (!file1 || !file2) {
|
||||||
#ifdef LWG_2937_BEHAVIOUR
|
#ifdef LWG_2937_BEHAVIOUR
|
||||||
ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
|
ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
|
||||||
#else
|
#else
|
||||||
@ -4246,9 +4301,9 @@ GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcep
|
|||||||
ec.clear();
|
ec.clear();
|
||||||
#ifdef GHC_OS_WINDOWS
|
#ifdef GHC_OS_WINDOWS
|
||||||
uintmax_t result = static_cast<uintmax_t>(-1);
|
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;
|
BY_HANDLE_FILE_INFORMATION inf;
|
||||||
if (file.get() == INVALID_HANDLE_VALUE) {
|
if (!file) {
|
||||||
ec = detail::make_system_error();
|
ec = detail::make_system_error();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -4477,7 +4532,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
|
|||||||
ec.clear();
|
ec.clear();
|
||||||
auto d = new_time.time_since_epoch();
|
auto d = new_time.time_since_epoch();
|
||||||
#ifdef GHC_OS_WINDOWS
|
#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;
|
FILETIME ft;
|
||||||
auto tt = std::chrono::duration_cast<std::chrono::microseconds>(d).count() * 10 + 116444736000000000;
|
auto tt = std::chrono::duration_cast<std::chrono::microseconds>(d).count() * 10 + 116444736000000000;
|
||||||
ft.dwLowDateTime = static_cast<DWORD>(tt);
|
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
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::shared_ptr<void> file(CreateFileW(GHC_NATIVEWP(p), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle);
|
detail::unique_handle file(CreateFileW(GHC_NATIVEWP(p), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL));
|
||||||
if (file.get() == INVALID_HANDLE_VALUE) {
|
if (!file) {
|
||||||
ec = detail::make_system_error();
|
ec = detail::make_system_error();
|
||||||
}
|
}
|
||||||
else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) {
|
else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) {
|
||||||
@ -5609,15 +5664,33 @@ public:
|
|||||||
#else
|
#else
|
||||||
_dir_entry._symlink_status.permissions(perms::unknown);
|
_dir_entry._symlink_status.permissions(perms::unknown);
|
||||||
switch (_entry->d_type) {
|
switch (_entry->d_type) {
|
||||||
case DT_BLK: _dir_entry._symlink_status.type(file_type::block); break;
|
case DT_BLK:
|
||||||
case DT_CHR: _dir_entry._symlink_status.type(file_type::character); break;
|
_dir_entry._symlink_status.type(file_type::block);
|
||||||
case DT_DIR: _dir_entry._symlink_status.type(file_type::directory); break;
|
break;
|
||||||
case DT_FIFO: _dir_entry._symlink_status.type(file_type::fifo); break;
|
case DT_CHR:
|
||||||
case DT_LNK: _dir_entry._symlink_status.type(file_type::symlink); break;
|
_dir_entry._symlink_status.type(file_type::character);
|
||||||
case DT_REG: _dir_entry._symlink_status.type(file_type::regular); break;
|
break;
|
||||||
case DT_SOCK: _dir_entry._symlink_status.type(file_type::socket); break;
|
case DT_DIR:
|
||||||
case DT_UNKNOWN: _dir_entry._symlink_status.type(file_type::none); break;
|
_dir_entry._symlink_status.type(file_type::directory);
|
||||||
default: _dir_entry._symlink_status.type(file_type::unknown); break;
|
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) {
|
if (_entry->d_type != DT_LNK) {
|
||||||
_dir_entry._status = _dir_entry._symlink_status;
|
_dir_entry._status = _dir_entry._symlink_status;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user