diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index f2af8e1..59610b8 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -292,12 +292,14 @@ bool has_executable_extension(const path& p); class GHC_FS_API_CLASS path #if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_WSTRING_STRING_TYPE) #define GHC_USE_WCHAR_T +#define GHC_NATIVEWP(p) p.c_str() #define GHC_PLATFORM_LITERAL(str) L##str : private path_helper_base { public: using path_helper_base::value_type; #else +#define GHC_NATIVEWP(p) p.wstring().c_str() #define GHC_PLATFORM_LITERAL(str) str : private path_helper_base { @@ -1821,7 +1823,7 @@ GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlin #pragma GCC diagnostic pop #endif if (api_call) { - if (api_call(detail::fromUtf8(new_hardlink.u8string()).c_str(), detail::fromUtf8(target_name.u8string()).c_str(), NULL) == 0) { + if (api_call(GHC_NATIVEWP(new_hardlink), GHC_NATIVEWP(target_name), NULL) == 0) { ec = detail::make_system_error(); } } @@ -1945,7 +1947,7 @@ GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec) #endif #endif - std::shared_ptr file(CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); + std::shared_ptr 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) { ec = detail::make_system_error(); return path(); @@ -2078,7 +2080,7 @@ GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uin #ifdef GHC_OS_WINDOWS file_status fs; WIN32_FILE_ATTRIBUTE_DATA attr; - if (!GetFileAttributesExW(detail::fromUtf8(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) { + if (!GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { ec = detail::make_system_error(); } else { @@ -2123,7 +2125,7 @@ GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status return file_status(file_type::unknown); } WIN32_FILE_ATTRIBUTE_DATA attr; - if (!::GetFileAttributesExW(p.wstring().c_str(), GetFileExInfoStandard, &attr)) { + if (!::GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { ec = detail::make_system_error(); } else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { @@ -3396,10 +3398,10 @@ GHC_INLINE path absolute(const path& p, std::error_code& ec) if (p.empty()) { return absolute(current_path(ec), ec) / ""; } - ULONG size = ::GetFullPathNameW(p.wstring().c_str(), 0, 0, 0); + ULONG size = ::GetFullPathNameW(GHC_NATIVEWP(p), 0, 0, 0); if (size) { std::vector buf(size, 0); - ULONG s2 = GetFullPathNameW(p.wstring().c_str(), size, buf.data(), nullptr); + ULONG s2 = GetFullPathNameW(GHC_NATIVEWP(p), size, buf.data(), nullptr); if (s2 && s2 < size) { path result = path(std::wstring(buf.data(), s2)); if (p.filename() == ".") { @@ -3668,7 +3670,7 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options overwrite = true; } #ifdef GHC_OS_WINDOWS - if (!::CopyFileW(detail::fromUtf8(from.u8string()).c_str(), detail::fromUtf8(to.u8string()).c_str(), !overwrite)) { + if (!::CopyFileW(GHC_NATIVEWP(from), GHC_NATIVEWP(to), !overwrite)) { ec = detail::make_system_error(); return false; } @@ -3831,12 +3833,12 @@ GHC_INLINE bool create_directory(const path& p, const path& attributes, std::err #endif #ifdef GHC_OS_WINDOWS if (!attributes.empty()) { - if (!::CreateDirectoryExW(detail::fromUtf8(attributes.u8string()).c_str(), detail::fromUtf8(p.u8string()).c_str(), NULL)) { + if (!::CreateDirectoryExW(GHC_NATIVEWP(attributes), GHC_NATIVEWP(p), NULL)) { ec = detail::make_system_error(); return false; } } - else if (!::CreateDirectoryW(detail::fromUtf8(p.u8string()).c_str(), NULL)) { + else if (!::CreateDirectoryW(GHC_NATIVEWP(p), NULL)) { ec = detail::make_system_error(); return false; } @@ -3957,7 +3959,7 @@ GHC_INLINE void current_path(const path& p, std::error_code& ec) noexcept { ec.clear(); #ifdef GHC_OS_WINDOWS - if (!::SetCurrentDirectoryW(detail::fromUtf8(p.u8string()).c_str())) { + if (!::SetCurrentDirectoryW(GHC_NATIVEWP(p))) { ec = detail::make_system_error(); } #else @@ -4004,9 +4006,9 @@ GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec) { ec.clear(); #ifdef GHC_OS_WINDOWS - std::shared_ptr file1(::CreateFileW(p1.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); + std::shared_ptr file1(::CreateFileW(GHC_NATIVEWP(p1), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); auto e1 = ::GetLastError(); - std::shared_ptr file2(::CreateFileW(p2.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); + std::shared_ptr 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) { #ifdef LWG_2937_BEHAVIOUR ec = detail::make_system_error(e1 ? e1 : ::GetLastError()); @@ -4064,7 +4066,7 @@ GHC_INLINE uintmax_t file_size(const path& p, std::error_code& ec) noexcept ec.clear(); #ifdef GHC_OS_WINDOWS WIN32_FILE_ATTRIBUTE_DATA attr; - if (!GetFileAttributesExW(detail::fromUtf8(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) { + if (!GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { ec = detail::make_system_error(); return static_cast(-1); } @@ -4097,7 +4099,7 @@ 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(-1); - std::shared_ptr file(::CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); + std::shared_ptr file(::CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); BY_HANDLE_FILE_INFORMATION inf; if (file.get() == INVALID_HANDLE_VALUE) { ec = detail::make_system_error(); @@ -4328,7 +4330,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 file(::CreateFileW(p.wstring().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL), ::CloseHandle); + std::shared_ptr 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); FILETIME ft; auto tt = std::chrono::duration_cast(d).count() * 10 + 116444736000000000; ft.dwLowDateTime = static_cast(tt); @@ -4417,10 +4419,10 @@ GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::e } #ifdef GHC_OS_WINDOWS #ifdef __GNUC__ - auto oldAttr = GetFileAttributesW(p.wstring().c_str()); + auto oldAttr = GetFileAttributesW(GHC_NATIVEWP(p)); if (oldAttr != INVALID_FILE_ATTRIBUTES) { DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~(static_cast(FILE_ATTRIBUTE_READONLY)) : oldAttr | FILE_ATTRIBUTE_READONLY; - if (oldAttr == newAttr || SetFileAttributesW(p.wstring().c_str(), newAttr)) { + if (oldAttr == newAttr || SetFileAttributesW(GHC_NATIVEWP(p), newAttr)) { return; } } @@ -4525,8 +4527,13 @@ GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept { ec.clear(); #ifdef GHC_OS_WINDOWS +#ifdef GHC_USE_WCHAR_T + auto cstr = p.c_str(); +#else std::wstring np = detail::fromUtf8(p.u8string()); - DWORD attr = GetFileAttributesW(np.c_str()); + auto cstr = np.c_str(); +#endif + DWORD attr = GetFileAttributesW(cstr); if (attr == INVALID_FILE_ATTRIBUTES) { auto error = ::GetLastError(); if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) { @@ -4536,12 +4543,12 @@ GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept } if (!ec) { if (attr & FILE_ATTRIBUTE_DIRECTORY) { - if (!RemoveDirectoryW(np.c_str())) { + if (!RemoveDirectoryW(cstr)) { ec = detail::make_system_error(); } } else { - if (!DeleteFileW(np.c_str())) { + if (!DeleteFileW(cstr)) { ec = detail::make_system_error(); } } @@ -4633,7 +4640,7 @@ GHC_INLINE void rename(const path& from, const path& to, std::error_code& ec) no ec.clear(); #ifdef GHC_OS_WINDOWS if (from != to) { - if (!MoveFileExW(detail::fromUtf8(from.u8string()).c_str(), detail::fromUtf8(to.u8string()).c_str(), (DWORD)MOVEFILE_REPLACE_EXISTING)) { + if (!MoveFileExW(GHC_NATIVEWP(from), GHC_NATIVEWP(to), (DWORD)MOVEFILE_REPLACE_EXISTING)) { ec = detail::make_system_error(); } } @@ -4671,7 +4678,7 @@ GHC_INLINE void resize_file(const path& p, uintmax_t size, std::error_code& ec) #endif return; } - std::shared_ptr file(CreateFileW(detail::fromUtf8(p.u8string()).c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle); + std::shared_ptr file(CreateFileW(GHC_NATIVEWP(p), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle); if (file.get() == INVALID_HANDLE_VALUE) { ec = detail::make_system_error(); } @@ -4704,7 +4711,7 @@ GHC_INLINE space_info space(const path& p, std::error_code& ec) noexcept ULARGE_INTEGER freeBytesAvailableToCaller = {{ 0, 0 }}; ULARGE_INTEGER totalNumberOfBytes = {{ 0, 0 }}; ULARGE_INTEGER totalNumberOfFreeBytes = {{ 0, 0 }}; - if (!GetDiskFreeSpaceExW(detail::fromUtf8(p.u8string()).c_str(), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) { + if (!GetDiskFreeSpaceExW(GHC_NATIVEWP(p), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) { ec = detail::make_system_error(); return {static_cast(-1), static_cast(-1), static_cast(-1)}; } @@ -5265,7 +5272,7 @@ public: { if (!_base.empty()) { ZeroMemory(&_findData, sizeof(WIN32_FIND_DATAW)); - if ((_dirHandle = FindFirstFileW(detail::fromUtf8((_base / "*").u8string()).c_str(), &_findData)) != INVALID_HANDLE_VALUE) { + if ((_dirHandle = FindFirstFileW(GHC_NATIVEWP((_base / "*")), &_findData)) != INVALID_HANDLE_VALUE) { if (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L"..") { increment(_ec); }