mirror of
https://github.com/gulrak/filesystem.git
synced 2025-12-06 16:56:40 +08:00
Merge b99c2aebd5ddd6fb2f190731ba80b949fc3842b5 into 9fda7b0afbd0640f482f4aea8720a8c0afd18740
This commit is contained in:
commit
15c216a553
@ -74,6 +74,9 @@ macro(AddTestExecutableWithStdCpp cppStd)
|
|||||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
target_compile_definitions(filesystem_test_cpp${cppStd} PRIVATE _CRT_SECURE_NO_WARNINGS)
|
target_compile_definitions(filesystem_test_cpp${cppStd} PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
if(MINGW)
|
||||||
|
target_compile_options(filesystem_test_cpp${cppStd} PUBLIC "-Wa,-mbig-obj")
|
||||||
|
endif()
|
||||||
if(EMSCRIPTEN)
|
if(EMSCRIPTEN)
|
||||||
set_target_properties(filesystem_test_cpp${cppStd} PROPERTIES LINK_FLAGS "-g4 -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1")
|
set_target_properties(filesystem_test_cpp${cppStd} PROPERTIES LINK_FLAGS "-g4 -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -300,6 +300,21 @@
|
|||||||
#error "Can't raise unicode errors with exception support disabled"
|
#error "Can't raise unicode errors with exception support disabled"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(GHC_OS_WINDOWS)
|
||||||
|
#if !defined(__GLIBCXX__) || (defined(_GLIBCXX_HAVE__WFOPEN) && defined(_GLIBCXX_USE_WCHAR_T))
|
||||||
|
#define GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
|
||||||
|
#elif defined(__GLIBCXX__) && defined(_WIO_DEFINED)
|
||||||
|
#define GHC_HAS_WIO_DEFINED
|
||||||
|
#include <ext/stdio_filebuf.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <share.h>
|
||||||
|
#ifndef _S_IREAD
|
||||||
|
// Some tests disable the previous inclusion of sys/stat.h; however, we need it when using old versions of MinGW.
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ghc {
|
namespace ghc {
|
||||||
namespace filesystem {
|
namespace filesystem {
|
||||||
|
|
||||||
@ -1142,8 +1157,66 @@ GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std:
|
|||||||
GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
|
GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GHC_OS_WINDOWS) && (!defined(__GLIBCXX__) || (defined(_GLIBCXX_HAVE__WFOPEN) && defined(_GLIBCXX_USE_WCHAR_T)))
|
#ifdef GHC_HAS_WIO_DEFINED
|
||||||
#define GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
|
namespace detail {
|
||||||
|
inline int open_flags(std::ios::openmode mode)
|
||||||
|
{
|
||||||
|
const bool out = (mode & std::ios::out) != 0;
|
||||||
|
const bool in = (mode & std::ios::in) != 0;
|
||||||
|
int flags = 0;
|
||||||
|
if (in && out) {
|
||||||
|
flags |= _O_RDWR | _O_CREAT;
|
||||||
|
}
|
||||||
|
else if (out) {
|
||||||
|
flags |= _O_WRONLY | _O_CREAT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
flags |= _O_RDONLY;
|
||||||
|
}
|
||||||
|
if ((mode & std::ios::app) != 0) {
|
||||||
|
flags |= _O_APPEND;
|
||||||
|
}
|
||||||
|
if ((mode & std::ios::trunc) != 0) {
|
||||||
|
flags |= _O_TRUNC;
|
||||||
|
}
|
||||||
|
flags |= (mode & std::ios::binary) != 0 ? _O_BINARY : _O_TEXT;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int permission_flags(std::ios::openmode mode) {
|
||||||
|
int flags = 0;
|
||||||
|
if ((mode & std::ios::in) != 0) {
|
||||||
|
flags |= _S_IREAD;
|
||||||
|
}
|
||||||
|
if ((mode & std::ios::out) != 0) {
|
||||||
|
flags |= _S_IWRITE;
|
||||||
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class charT, class traits = std::char_traits< charT>>
|
||||||
|
__gnu_cxx::stdio_filebuf<charT, traits> open_filebuf_from_unicode_path(const path& file_path, std::ios::openmode mode) {
|
||||||
|
// Opening a file handle/descriptor from the native (wide) string path.
|
||||||
|
int file_handle = 0;
|
||||||
|
_wsopen_s(&file_handle, GHC_NATIVEWP(file_path), open_flags(mode), _SH_DENYNO, permission_flags(mode));
|
||||||
|
|
||||||
|
// Creating a GLIBCXX stdio_filebuf object from the file handle (it will check if the handle is actually opened).
|
||||||
|
__gnu_cxx::stdio_filebuf<charT, traits> result{file_handle, mode};
|
||||||
|
|
||||||
|
// If mode has the flag std::ios::ate, we need to seek at the end of the filebuf.
|
||||||
|
if (result.is_open() && (mode & std::ios::ate) != 0){
|
||||||
|
const auto seek_result = result.pubseekoff(0, std::ios::end, mode);
|
||||||
|
const auto end_pos = typename traits::pos_type(typename traits::off_type(-1));
|
||||||
|
if (seek_result == end_pos) {
|
||||||
|
// If the seeking fails, we need to close the filebuf (as per the standard).
|
||||||
|
result.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returning the filebuf in any case, whether we successfully opened it or not (the caller will check it).
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Non-C++17 add-on std::fstream wrappers with path
|
// Non-C++17 add-on std::fstream wrappers with path
|
||||||
@ -1159,6 +1232,16 @@ public:
|
|||||||
{
|
{
|
||||||
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
|
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
|
||||||
return std::basic_filebuf<charT, traits>::open(p.wstring().c_str(), mode) ? this : 0;
|
return std::basic_filebuf<charT, traits>::open(p.wstring().c_str(), mode) ? this : 0;
|
||||||
|
#elif defined(GHC_HAS_WIO_DEFINED)
|
||||||
|
if (this->is_open()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto filebuf = detail::open_filebuf_from_unicode_path<charT, traits>(p, mode);
|
||||||
|
if (!filebuf.is_open()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
this->swap(filebuf);
|
||||||
|
return this;
|
||||||
#else
|
#else
|
||||||
return std::basic_filebuf<charT, traits>::open(p.string().c_str(), mode) ? this : 0;
|
return std::basic_filebuf<charT, traits>::open(p.string().c_str(), mode) ? this : 0;
|
||||||
#endif
|
#endif
|
||||||
@ -1176,6 +1259,20 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream<charT, traits>::open(p.wstring().c_str(), mode); }
|
void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream<charT, traits>::open(p.wstring().c_str(), mode); }
|
||||||
|
#elif defined(GHC_HAS_WIO_DEFINED)
|
||||||
|
explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in)
|
||||||
|
{
|
||||||
|
open(p, mode);
|
||||||
|
}
|
||||||
|
void open(const path& p, std::ios_base::openmode mode = std::ios_base::in)
|
||||||
|
{
|
||||||
|
*this->rdbuf() = detail::open_filebuf_from_unicode_path<charT, traits>(p, mode | std::ios_base::in);
|
||||||
|
if (!this->is_open()) {
|
||||||
|
this->setstate(std::ios_base::failbit);
|
||||||
|
} else {
|
||||||
|
this->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in)
|
explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in)
|
||||||
: std::basic_ifstream<charT, traits>(p.string().c_str(), mode)
|
: std::basic_ifstream<charT, traits>(p.string().c_str(), mode)
|
||||||
@ -1199,6 +1296,20 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream<charT, traits>::open(p.wstring().c_str(), mode); }
|
void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream<charT, traits>::open(p.wstring().c_str(), mode); }
|
||||||
|
#elif defined(GHC_HAS_WIO_DEFINED)
|
||||||
|
explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out)
|
||||||
|
{
|
||||||
|
open(p, mode);
|
||||||
|
}
|
||||||
|
void open(const path& p, std::ios_base::openmode mode = std::ios_base::out)
|
||||||
|
{
|
||||||
|
*this->rdbuf() = detail::open_filebuf_from_unicode_path<charT, traits>(p, mode | std::ios_base::out);
|
||||||
|
if (!this->is_open()) {
|
||||||
|
this->setstate(std::ios_base::failbit);
|
||||||
|
} else {
|
||||||
|
this->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out)
|
explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out)
|
||||||
: std::basic_ofstream<charT, traits>(p.string().c_str(), mode)
|
: std::basic_ofstream<charT, traits>(p.string().c_str(), mode)
|
||||||
@ -1222,6 +1333,20 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream<charT, traits>::open(p.wstring().c_str(), mode); }
|
void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream<charT, traits>::open(p.wstring().c_str(), mode); }
|
||||||
|
#elif defined(GHC_HAS_WIO_DEFINED)
|
||||||
|
explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
||||||
|
{
|
||||||
|
open(p, mode);
|
||||||
|
}
|
||||||
|
void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
||||||
|
{
|
||||||
|
*this->rdbuf() = detail::open_filebuf_from_unicode_path<charT, traits>(p, mode | std::ios_base::in | std::ios_base::out);
|
||||||
|
if (!this->is_open()) {
|
||||||
|
this->setstate(std::ios_base::failbit);
|
||||||
|
} else {
|
||||||
|
this->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
||||||
: std::basic_fstream<charT, traits>(p.string().c_str(), mode)
|
: std::basic_fstream<charT, traits>(p.string().c_str(), mode)
|
||||||
|
|||||||
@ -43,6 +43,9 @@ else()
|
|||||||
message("Generating test runner for normal test...")
|
message("Generating test runner for normal test...")
|
||||||
add_executable(filesystem_test filesystem_test.cpp catch.hpp)
|
add_executable(filesystem_test filesystem_test.cpp catch.hpp)
|
||||||
target_link_libraries(filesystem_test ghc_filesystem)
|
target_link_libraries(filesystem_test ghc_filesystem)
|
||||||
|
if(MINGW)
|
||||||
|
target_compile_options(filesystem_test PUBLIC "-Wa,-mbig-obj")
|
||||||
|
endif()
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||||
target_link_libraries(filesystem_test xnet)
|
target_link_libraries(filesystem_test xnet)
|
||||||
endif()
|
endif()
|
||||||
@ -64,6 +67,9 @@ else()
|
|||||||
add_executable(filesystem_test_char filesystem_test.cpp catch.hpp)
|
add_executable(filesystem_test_char filesystem_test.cpp catch.hpp)
|
||||||
target_link_libraries(filesystem_test_char ghc_filesystem)
|
target_link_libraries(filesystem_test_char ghc_filesystem)
|
||||||
SetTestCompileOptions(filesystem_test_char)
|
SetTestCompileOptions(filesystem_test_char)
|
||||||
|
if(MINGW)
|
||||||
|
target_compile_options(filesystem_test_char PUBLIC "-Wa,-mbig-obj")
|
||||||
|
endif()
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
target_compile_definitions(filesystem_test_char PRIVATE _CRT_SECURE_NO_WARNINGS GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE)
|
target_compile_definitions(filesystem_test_char PRIVATE _CRT_SECURE_NO_WARNINGS GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE)
|
||||||
else()
|
else()
|
||||||
@ -95,6 +101,9 @@ SetTestCompileOptions(fwd_impl_test)
|
|||||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
target_compile_definitions(fwd_impl_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
|
target_compile_definitions(fwd_impl_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||||
endif()
|
endif()
|
||||||
|
if(MINGW)
|
||||||
|
target_compile_options(fwd_impl_test PUBLIC "-Wa,-mbig-obj")
|
||||||
|
endif()
|
||||||
add_test(fwd_impl_test fwd_impl_test)
|
add_test(fwd_impl_test fwd_impl_test)
|
||||||
|
|
||||||
add_executable(exception exception.cpp)
|
add_executable(exception exception.cpp)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user