mirror of
https://github.com/gulrak/filesystem.git
synced 2025-12-07 01:06:38 +08:00
Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fda7b0afb | ||
|
|
076592ce6e | ||
|
|
157feb3651 | ||
|
|
f08e8b0064 | ||
|
|
99c3500205 | ||
|
|
f43846877b | ||
|
|
b1982f06c8 | ||
|
|
fbc5d213fc | ||
|
|
72a03b3c6d | ||
|
|
9fe68b91c7 | ||
|
|
56776c92f7 | ||
|
|
42ea4fc615 | ||
|
|
eeed314237 | ||
|
|
768b5cb11b | ||
|
|
2fc4b46375 | ||
|
|
fc19b58459 | ||
|
|
f19cbbbd31 | ||
|
|
0ef214a7a0 | ||
|
|
fcea331ebb | ||
|
|
1ab54e53cc | ||
|
|
58e983167c | ||
|
|
c4683aa4a1 | ||
|
|
144954ff4e | ||
|
|
48d46cccef | ||
|
|
23710d3b56 | ||
|
|
64f9c5a61a | ||
|
|
a55c96a2ba | ||
|
|
aaaf381d9d | ||
|
|
72a76d774e | ||
|
|
e5ae1bd3e3 | ||
|
|
8a2edd6d92 | ||
|
|
e9e32f8830 | ||
|
|
9f61ee0eb5 | ||
|
|
d1f0d79054 | ||
|
|
61176cd82a | ||
|
|
78b746d901 | ||
|
|
9df22d5396 | ||
|
|
9ffca3839f | ||
|
|
2a81c2c355 | ||
|
|
e3341b2f64 | ||
|
|
6a94e84da4 | ||
|
|
a7a6d930fb | ||
|
|
7da9be91c9 | ||
|
|
e6b34e29bf | ||
|
|
b1ff2ce95e | ||
|
|
3afbd9c315 | ||
|
|
de64decd91 | ||
|
|
f3c1058928 | ||
|
|
f3033c29fb | ||
|
|
4041174f96 | ||
|
|
c8113e14b1 | ||
|
|
b6d302f5b9 | ||
|
|
efc077f553 | ||
|
|
bc05cc59f4 | ||
|
|
a9c18e0880 | ||
|
|
9afb43851d | ||
|
|
c57242b4bc | ||
|
|
3337cc252a | ||
|
|
655b0b354a | ||
|
|
f0caeb7d58 | ||
|
|
6c6f2c2ec0 | ||
|
|
3e5b930d96 | ||
|
|
d3d968e583 | ||
|
|
404c57f1b0 | ||
|
|
4c33b91fe9 | ||
|
|
089ef64aa3 | ||
|
|
4f0824fd76 | ||
|
|
28f7c929e0 | ||
|
|
ab8a78d806 | ||
|
|
f6d7d5b826 | ||
|
|
cd6805e94d | ||
|
|
6cc60fb687 | ||
|
|
fb4bb2b764 | ||
|
|
c4907cc681 | ||
|
|
5d1d579048 | ||
|
|
7fa1bde113 | ||
|
|
7a53650e73 | ||
|
|
1ae0195287 | ||
|
|
e5bbc754e7 | ||
|
|
977e5d6284 | ||
|
|
723c787b9e | ||
|
|
91e71f7f54 | ||
|
|
c4b507e9d8 | ||
|
|
e8a17c1319 | ||
|
|
d4e12344d6 | ||
|
|
f437344e79 | ||
|
|
f0467f4384 | ||
|
|
a07ddedeae |
27
.cirrus.yml
27
.cirrus.yml
@ -1,6 +1,6 @@
|
|||||||
freebsd_task:
|
freebsd_task:
|
||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: freebsd-12-1
|
image_family: freebsd-14-0
|
||||||
install_script: |
|
install_script: |
|
||||||
pkg install -y cmake
|
pkg install -y cmake
|
||||||
pw groupadd testgrp
|
pw groupadd testgrp
|
||||||
@ -11,25 +11,24 @@ freebsd_task:
|
|||||||
test_script: |
|
test_script: |
|
||||||
sudo -u testuser .ci/unix-test.sh
|
sudo -u testuser .ci/unix-test.sh
|
||||||
|
|
||||||
centos7_task:
|
rockylinux8_task:
|
||||||
container:
|
container:
|
||||||
image: centos:7
|
image: docker.io/rockylinux:8
|
||||||
install_script: |
|
install_script: |
|
||||||
yum install -y centos-release-scl
|
dnf group install -y "Development Tools"
|
||||||
yum install -y devtoolset-9
|
dnf install cmake -y
|
||||||
curl -L https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-Linux-x86_64.tar.gz | tar xzvf - -C /usr/local --strip-components 1
|
|
||||||
build_script: |
|
build_script: |
|
||||||
source /opt/rh/devtoolset-9/enable && PATH=$PATH:/usr/local/bin .ci/unix-build.sh
|
.ci/unix-build.sh
|
||||||
test_script: |
|
test_script: |
|
||||||
PATH=$PATH:/usr/local/bin .ci/unix-test.sh
|
.ci/unix-test.sh
|
||||||
|
|
||||||
centos8_task:
|
rockylinux9_task:
|
||||||
container:
|
container:
|
||||||
image: centos:8
|
image: docker.io/rockylinux:9
|
||||||
install_script: |
|
install_script: |
|
||||||
yum group install -y "Development Tools"
|
dnf group install -y "Development Tools"
|
||||||
curl -L https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-Linux-x86_64.tar.gz | tar xzvf - -C /usr/local --strip-components 1
|
dnf install cmake -y
|
||||||
build_script: |
|
build_script: |
|
||||||
PATH=$PATH:/usr/local/bin .ci/unix-build.sh
|
.ci/unix-build.sh
|
||||||
test_script: |
|
test_script: |
|
||||||
PATH=$PATH:/usr/local/bin .ci/unix-test.sh
|
.ci/unix-test.sh
|
||||||
|
|||||||
107
.github/workflows/build_cmake.yml
vendored
107
.github/workflows/build_cmake.yml
vendored
@ -10,6 +10,42 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
config:
|
config:
|
||||||
|
- name: "Ubuntu 22.04 GCC 11"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
build_type: Release
|
||||||
|
packages: ninja-build
|
||||||
|
generator: Ninja
|
||||||
|
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
|
||||||
|
cc: gcc
|
||||||
|
cxx: g++
|
||||||
|
|
||||||
|
- name: "Ubuntu 22.04 Clang 13.0"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
build_type: Release
|
||||||
|
packages: ninja-build libc++-13-dev libc++abi-13-dev
|
||||||
|
generator: Ninja
|
||||||
|
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
|
||||||
|
cc: clang-13
|
||||||
|
cxx: clang++-13
|
||||||
|
|
||||||
|
- name: "Ubuntu 22.04 Clang 15.0"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
build_type: Release
|
||||||
|
packages: ninja-build libc++-15-dev libc++abi-15-dev
|
||||||
|
generator: Ninja
|
||||||
|
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
|
||||||
|
cc: clang-15
|
||||||
|
cxx: clang++-15
|
||||||
|
|
||||||
|
- name: "Ubuntu 22.04 GCC 11 coverage"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
build_type: Debug
|
||||||
|
packages: ninja-build lcov
|
||||||
|
generator: Ninja
|
||||||
|
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
|
||||||
|
cc: gcc
|
||||||
|
cxx: g++
|
||||||
|
|
||||||
- name: "Ubuntu 20.04 GCC 9.3"
|
- name: "Ubuntu 20.04 GCC 9.3"
|
||||||
os: ubuntu-20.04
|
os: ubuntu-20.04
|
||||||
build_type: Release
|
build_type: Release
|
||||||
@ -46,71 +82,8 @@ jobs:
|
|||||||
cc: gcc
|
cc: gcc
|
||||||
cxx: g++
|
cxx: g++
|
||||||
|
|
||||||
- name: "Ubuntu 18.04 GCC 8.4"
|
|
||||||
os: ubuntu-18.04
|
|
||||||
build_type: Release
|
|
||||||
packages: ninja-build gcc-8 g++-8
|
|
||||||
generator: Ninja
|
|
||||||
compatibility: "cxx_std_11;cxx_std_17"
|
|
||||||
cc: gcc-8
|
|
||||||
cxx: g++-8
|
|
||||||
|
|
||||||
- name: "Ubuntu 18.04 GCC 7.5"
|
|
||||||
os: ubuntu-18.04
|
|
||||||
build_type: Release
|
|
||||||
packages: ninja-build
|
|
||||||
generator: Ninja
|
|
||||||
compatibility: "cxx_std_11;cxx_std_17"
|
|
||||||
cc: gcc-7
|
|
||||||
cxx: g++-7
|
|
||||||
|
|
||||||
- name: "Ubuntu 18.04 GCC 6.5"
|
|
||||||
os: ubuntu-18.04
|
|
||||||
build_type: Release
|
|
||||||
packages: ninja-build gcc-6 g++-6
|
|
||||||
generator: Ninja
|
|
||||||
compatibility: "cxx_std_11;cxx_std_17"
|
|
||||||
cc: gcc-6
|
|
||||||
cxx: g++-6
|
|
||||||
|
|
||||||
- name: "Ubuntu 18.04 GCC 5.5"
|
|
||||||
os: ubuntu-18.04
|
|
||||||
build_type: Release
|
|
||||||
packages: ninja-build gcc-5 g++-5
|
|
||||||
generator: Ninja
|
|
||||||
compatibility: "cxx_std_11;cxx_std_17"
|
|
||||||
cc: gcc-5
|
|
||||||
cxx: g++-5
|
|
||||||
|
|
||||||
- name: "Ubuntu 18.04 Clang 9.0"
|
|
||||||
os: ubuntu-18.04
|
|
||||||
build_type: Release
|
|
||||||
packages: ninja-build libc++-9-dev libc++abi-9-dev
|
|
||||||
generator: Ninja
|
|
||||||
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
|
|
||||||
cc: clang
|
|
||||||
cxx: clang++
|
|
||||||
|
|
||||||
- name: "Ubuntu 18.04 Clang 6.0"
|
|
||||||
os: ubuntu-18.04
|
|
||||||
build_type: Release
|
|
||||||
packages: ninja-build clang-6.0
|
|
||||||
generator: Ninja
|
|
||||||
compatibility: "cxx_std_11;cxx_std_17"
|
|
||||||
cc: clang-6.0
|
|
||||||
cxx: clang++-6.0
|
|
||||||
|
|
||||||
- name: "Ubuntu 18.04 Clang 5.0"
|
|
||||||
os: ubuntu-18.04
|
|
||||||
build_type: Release
|
|
||||||
packages: ninja-build clang-5.0
|
|
||||||
generator: Ninja
|
|
||||||
compatibility: "cxx_std_11;cxx_std_17"
|
|
||||||
cc: clang-5.0
|
|
||||||
cxx: clang++-5.0
|
|
||||||
|
|
||||||
- name: "Windows MSVC 2019"
|
- name: "Windows MSVC 2019"
|
||||||
os: windows-latest
|
os: windows-2019
|
||||||
build_type: Release
|
build_type: Release
|
||||||
packages: ninja
|
packages: ninja
|
||||||
generator: "Visual Studio 16 2019"
|
generator: "Visual Studio 16 2019"
|
||||||
@ -118,12 +91,12 @@ jobs:
|
|||||||
cc: cl
|
cc: cl
|
||||||
cxx: cl
|
cxx: cl
|
||||||
|
|
||||||
- name: "macOS 10.15 AppleClang"
|
- name: "macOS 13 AppleClang"
|
||||||
os: macos-10.15
|
os: macos-13
|
||||||
build_type: Release
|
build_type: Release
|
||||||
packages: ninja
|
packages: ninja
|
||||||
generator: Ninja
|
generator: Ninja
|
||||||
compatibility: "cxx_std_11;cxx_std_17"
|
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
|
||||||
cc: clang
|
cc: clang
|
||||||
cxx: clang++
|
cxx: clang++
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.7.2)
|
cmake_minimum_required(VERSION 3.7.2)
|
||||||
project(ghcfilesystem)
|
project(
|
||||||
|
ghcfilesystem,
|
||||||
|
VERSION 1.5.15
|
||||||
|
)
|
||||||
|
|
||||||
if (POLICY CMP0077)
|
if (POLICY CMP0077)
|
||||||
cmake_policy(SET CMP0077 NEW)
|
cmake_policy(SET CMP0077 NEW)
|
||||||
@ -15,7 +18,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
|||||||
else()
|
else()
|
||||||
option(GHC_FILESYSTEM_BUILD_EXAMPLES "Build examples" OFF)
|
option(GHC_FILESYSTEM_BUILD_EXAMPLES "Build examples" OFF)
|
||||||
option(GHC_FILESYSTEM_BUILD_TESTING "Enable tests" OFF)
|
option(GHC_FILESYSTEM_BUILD_TESTING "Enable tests" OFF)
|
||||||
option(GHC_FILESYSTEM_WITH_INSTALL "With install target" ON)
|
option(GHC_FILESYSTEM_WITH_INSTALL "With install target" OFF)
|
||||||
endif()
|
endif()
|
||||||
option(GHC_FILESYSTEM_BUILD_STD_TESTING "Enable STD tests" ${GHC_FILESYSTEM_BUILD_TESTING})
|
option(GHC_FILESYSTEM_BUILD_STD_TESTING "Enable STD tests" ${GHC_FILESYSTEM_BUILD_TESTING})
|
||||||
if(NOT DEFINED GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
|
if(NOT DEFINED GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
|
||||||
@ -32,9 +35,14 @@ endif()
|
|||||||
if(CMAKE_CXX_STANDARD LESS 11)
|
if(CMAKE_CXX_STANDARD LESS 11)
|
||||||
message(FATAL_ERROR "CMAKE_CXX_STANDARD is less than 11, ghc::filesystem only works with C++11 and above.")
|
message(FATAL_ERROR "CMAKE_CXX_STANDARD is less than 11, ghc::filesystem only works with C++11 and above.")
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "CMAKE_CXX_COMPILE_FEATURES: ${CMAKE_CXX_COMPILE_FEATURES}")
|
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
|
message(STATUS "System name: ${CMAKE_SYSTEM_NAME}")
|
||||||
|
message(STATUS "Compiler ID: ${CMAKE_CXX_COMPILER_ID}")
|
||||||
|
message(STATUS "CMAKE_CXX_COMPILE_FEATURES: ${CMAKE_CXX_COMPILE_FEATURES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(ghc_filesystem INTERFACE)
|
add_library(ghc_filesystem INTERFACE)
|
||||||
|
add_library(ghcFilesystem::ghc_filesystem ALIAS ghc_filesystem)
|
||||||
target_include_directories(ghc_filesystem INTERFACE
|
target_include_directories(ghc_filesystem INTERFACE
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
$<INSTALL_INTERFACE:include>)
|
$<INSTALL_INTERFACE:include>)
|
||||||
@ -68,7 +76,15 @@ if(GHC_FILESYSTEM_WITH_INSTALL)
|
|||||||
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
|
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
|
||||||
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem"
|
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem"
|
||||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR)
|
PATH_VARS CMAKE_INSTALL_INCLUDEDIR)
|
||||||
install(FILES "${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
|
write_basic_package_version_file(
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem")
|
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config-version.cmake"
|
||||||
add_library(ghcFilesystem::ghc_filesystem ALIAS ghc_filesystem)
|
VERSION ${PROJECT_VERSION}
|
||||||
|
COMPATIBILITY SameMinorVersion
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
|
||||||
|
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config-version.cmake"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
369
README.md
369
README.md
@ -3,48 +3,52 @@
|
|||||||
[](https://github.com/gulrak/filesystem/actions/workflows/build_cmake.yml)
|
[](https://github.com/gulrak/filesystem/actions/workflows/build_cmake.yml)
|
||||||
[](https://ci.appveyor.com/project/gulrak/filesystem)
|
[](https://ci.appveyor.com/project/gulrak/filesystem)
|
||||||
[](https://cirrus-ci.com/github/gulrak/filesystem)
|
[](https://cirrus-ci.com/github/gulrak/filesystem)
|
||||||
[](https://cloud.drone.io/gulrak/filesystem)
|
|
||||||
[](https://coveralls.io/github/gulrak/filesystem?branch=master)
|
[](https://coveralls.io/github/gulrak/filesystem?branch=master)
|
||||||
[](https://github.com/gulrak/filesystem/tree/v1.5.10)
|
[](https://github.com/gulrak/filesystem/tree/v1.5.14)
|
||||||
|
<!-- [](https://cloud.drone.io/gulrak/filesystem) -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- TOC -->
|
||||||
|
* [Filesystem](#filesystem)
|
||||||
|
* [Motivation](#motivation)
|
||||||
|
* [Why the namespace GHC?](#why-the-namespace-ghc)
|
||||||
|
* [Platforms](#platforms)
|
||||||
|
* [Tests](#tests)
|
||||||
|
* [Usage](#usage)
|
||||||
|
* [Downloads](#downloads)
|
||||||
|
* [Using it as Single-File-Header](#using-it-as-single-file-header)
|
||||||
|
* [Using it as Forwarding-/Implementation-Header](#using-it-as-forwarding-implementation-header)
|
||||||
|
* [Git Submodule and CMake](#git-submodule-and-cmake)
|
||||||
|
* [Versioning](#versioning)
|
||||||
|
* [Documentation](#documentation)
|
||||||
|
* [`ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream`](#ghcfilesystemifstream--ghcfilesystemofstream--ghcfilesystemfstream)
|
||||||
|
* [`ghc::filesystem::u8arguments`](#ghcfilesystemu8arguments)
|
||||||
|
* [Differences](#differences)
|
||||||
|
* [LWG Defects](#lwg-defects)
|
||||||
|
* [Not Implemented on C++ before C++17](#not-implemented-on-c-before-c17)
|
||||||
|
* [Differences in API](#differences-in-api)
|
||||||
|
* [Differences of Specific Interfaces](#differences-of-specific-interfaces)
|
||||||
|
* [Differences in Behavior](#differences-in-behavior)
|
||||||
|
* [fs.path (ref)](#fspath--ref-)
|
||||||
|
* [Open Issues](#open-issues)
|
||||||
|
* [Windows](#windows)
|
||||||
|
* [Symbolic Links on Windows](#symbolic-links-on-windows)
|
||||||
|
* [Permissions](#permissions)
|
||||||
|
* [Release Notes](#release-notes)
|
||||||
|
<!-- TOC -->
|
||||||
|
|
||||||
- [Filesystem](#filesystem)
|
|
||||||
- [Motivation](#motivation)
|
|
||||||
- [Why the namespace GHC?](#why-the-namespace-ghc)
|
|
||||||
- [Platforms](#platforms)
|
|
||||||
- [Tests](#tests)
|
|
||||||
- [Usage](#usage)
|
|
||||||
- [Downloads](#downloads)
|
|
||||||
- [Using it as Single-File-Header](#using-it-as-single-file-header)
|
|
||||||
- [Using it as Forwarding-/Implementation-Header](#using-it-as-forwarding-implementation-header)
|
|
||||||
- [Git Submodule and CMake](#git-submodule-and-cmake)
|
|
||||||
- [Versioning](#versioning)
|
|
||||||
- [Documentation](#documentation)
|
|
||||||
- [`ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream`](#ghcfilesystemifstream-ghcfilesystemofstream-ghcfilesystemfstream)
|
|
||||||
- [`ghc::filesystem::u8arguments`](#ghcfilesystemu8arguments)
|
|
||||||
- [Differences](#differences)
|
|
||||||
- [LWG Defects](#lwg-defects)
|
|
||||||
- [Not Implemented on C++ before C++17](#not-implemented-on-c-before-c17)
|
|
||||||
- [Differences in API](#differences-in-api)
|
|
||||||
- [Differences of Specific Interfaces](#differences-of-specific-interfaces)
|
|
||||||
- [Differences in Behavior](#differences-in-behavior)
|
|
||||||
- [fs.path](#fspath-refhttpsencppreferencecomwcppfilesystempath)
|
|
||||||
- [Open Issues](#open-issues)
|
|
||||||
- [Windows](#windows)
|
|
||||||
- [Symbolic Links on Windows](#symbolic-links-on-windows)
|
|
||||||
- [Permissions](#permissions)
|
|
||||||
- [Release Notes](#release-notes)
|
|
||||||
|
|
||||||
# Filesystem
|
# Filesystem
|
||||||
|
|
||||||
This is a header-only single-file `std::filesystem` compatible helper library,
|
This is a header-only single-file `std::filesystem` compatible helper library,
|
||||||
based on the C++17 and C++20 specs, but implemented for C++11, C++14, C++17 or C++20
|
based on the C++17 and C++20 specs, but implemented for C++11, C++14, C++17 or C++20
|
||||||
(tightly following the C++17 standard with very few documented exceptions). It is currently tested on
|
(tightly following the C++17 standard with very few documented exceptions). It is currently tested on
|
||||||
macOS 10.12/10.14/10.15, Windows 10, Ubuntu 18.04, Ubuntu 20.04, CentOS 7, CentOS 8, FreeBSD 12
|
macOS 10.12/10.14/10.15/11.6, Windows 10, Ubuntu 18.04, Ubuntu 20.04, CentOS 7, CentOS 8, FreeBSD 12,
|
||||||
and Alpine ARM/ARM64 Linux but should work on other systems too, as long as you have
|
Alpine ARM/ARM64 Linux and Solaris 10 but should work on other systems too, as long as you have
|
||||||
at least a C++11 compatible compiler. It should work with Android NDK, Emscripten and I even
|
at least a C++11 compatible compiler. It should work with Android NDK, Emscripten and I even
|
||||||
had reports of it being used on iOS (within sandboxing constraints) and with v1.5.6 there
|
had reports of it being used on iOS (within sandboxing constraints) and with v1.5.6 there
|
||||||
is experimental support for QNX. The support of Android NDK, Emscripten and QNX is not
|
is experimental support for QNX. The support of Android NDK, Emscripten, QNX, and since 1.5.14
|
||||||
backed up by automated testing but PRs and bug reports are welcome for those too.
|
GNU/Hurd and Haiku is not backed up by automated testing but PRs and bug reports are welcome
|
||||||
|
for those too and they are reported to work.
|
||||||
It is of course in its own namespace `ghc::filesystem` to not interfere with a regular `std::filesystem`
|
It is of course in its own namespace `ghc::filesystem` to not interfere with a regular `std::filesystem`
|
||||||
should you use it in a mixed C++17 environment (which is possible).
|
should you use it in a mixed C++17 environment (which is possible).
|
||||||
|
|
||||||
@ -87,15 +91,15 @@ to do with Haskell**, sorry for the name clash).
|
|||||||
## Platforms
|
## Platforms
|
||||||
|
|
||||||
`ghc::filesystem` is developed on macOS but CI tested on macOS, Windows,
|
`ghc::filesystem` is developed on macOS but CI tested on macOS, Windows,
|
||||||
various Linux Distributions and FreeBSD. It should work on any of these with a C++11-capable
|
various Linux Distributions, FreeBSD and starting with v1.5.12 on Solaris.
|
||||||
compiler. Also there are some checks to hopefully better work on Android, but
|
It should work on any of these with a C++11-capable compiler. Also there are some
|
||||||
as I currently don't test with the Android NDK, I wouldn't call it a
|
checks to hopefully better work on Android, but as I currently don't test with the
|
||||||
supported platform yet, same is valid for using it with Emscripten. It is now
|
Android NDK, I wouldn't call it a supported platform yet, same is valid for using
|
||||||
part of the detected platforms, I fixed the obvious issues and ran some tests with
|
it with Emscripten. It is now part of the detected platforms, I fixed the obvious
|
||||||
it, so it should be fine. All in all, I don't see it replacing `std::filesystem`
|
issues and ran some tests with it, so it should be fine. All in all, I don't see it
|
||||||
where full C++17 or C++20 is available, it doesn't try to be a "better"
|
replacing `std::filesystem` where full C++17 or C++20 is available, it doesn't try
|
||||||
`std::filesystem`, just an almost drop-in if you can't use it (with the exception
|
to be a "better" `std::filesystem`, just an almost drop-in if you can't use it
|
||||||
of the UTF-8 preference).
|
(with the exception of the UTF-8 preference).
|
||||||
|
|
||||||
:information_source: **Important:** _This implementation is following the ["UTF-8 Everywhere" philosophy](https://utf8everywhere.org/) in that all
|
:information_source: **Important:** _This implementation is following the ["UTF-8 Everywhere" philosophy](https://utf8everywhere.org/) in that all
|
||||||
`std::string` instances will be interpreted the same as `std::u8string` encoding
|
`std::string` instances will be interpreted the same as `std::u8string` encoding
|
||||||
@ -107,8 +111,10 @@ Unit tests are currently run with:
|
|||||||
* macOS 10.12: Xcode 9.2 (clang-900.0.39.2), GCC 9.2, Clang 9.0, macOS 10.13: Xcode 10.1, macOS 10.14: Xcode 11.2, macOS 10.15: Xcode 11.6, Xcode 12.4
|
* macOS 10.12: Xcode 9.2 (clang-900.0.39.2), GCC 9.2, Clang 9.0, macOS 10.13: Xcode 10.1, macOS 10.14: Xcode 11.2, macOS 10.15: Xcode 11.6, Xcode 12.4
|
||||||
* Windows: Visual Studio 2017, Visual Studio 2015, Visual Studio 2019, MinGW GCC 6.3 (Win32), GCC 7.2 (Win64), Cygwin GCC 10.2 (no CI yet)
|
* Windows: Visual Studio 2017, Visual Studio 2015, Visual Studio 2019, MinGW GCC 6.3 (Win32), GCC 7.2 (Win64), Cygwin GCC 10.2 (no CI yet)
|
||||||
* Linux (Ubuntu): GCC (5.5, 6.5, 7.4, 8.3, 9.2), Clang (5.0, 6.0, 7.1, 8.0, 9.0)
|
* Linux (Ubuntu): GCC (5.5, 6.5, 7.4, 8.3, 9.2), Clang (5.0, 6.0, 7.1, 8.0, 9.0)
|
||||||
* Linux (Alpine ARM/ARM64): GCC 9.2.0
|
* ~~Linux (Alpine ARM/ARM64): GCC 9.2.0~~ (The Drone build scripts stopped working,
|
||||||
|
as they where a contribution, I couldn't figure out what went wrong, any help appreciated.)
|
||||||
* FreeBSD: Clang 8.0
|
* FreeBSD: Clang 8.0
|
||||||
|
* Solaris: GCC 5.5
|
||||||
|
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@ -148,8 +154,8 @@ in the standard, and there might be issues in these implementations too.
|
|||||||
|
|
||||||
### Downloads
|
### Downloads
|
||||||
|
|
||||||
The latest release version is [v1.5.10](https://github.com/gulrak/filesystem/tree/v1.5.10) and
|
The latest release version is [v1.5.14](https://github.com/gulrak/filesystem/tree/v1.5.14) and
|
||||||
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.5.10).
|
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.5.14).
|
||||||
|
|
||||||
The latest pre-native-backend version is [v1.4.0](https://github.com/gulrak/filesystem/tree/v1.4.0) and
|
The latest pre-native-backend version is [v1.4.0](https://github.com/gulrak/filesystem/tree/v1.4.0) and
|
||||||
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.4.0).
|
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.4.0).
|
||||||
@ -170,60 +176,83 @@ Everything is in the namespace `ghc::filesystem`, so one way to use it only as
|
|||||||
a fallback could be:
|
a fallback could be:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#ifdef __APPLE__
|
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
|
||||||
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
|
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
|
||||||
|
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
|
||||||
|
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
|
||||||
|
#define GHC_USE_STD_FS
|
||||||
|
|
||||||
|
// Old Apple OSs don't support std::filesystem, though the header is available at compile
|
||||||
|
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
|
||||||
|
// and watchOS 6.0.
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <Availability.h>
|
||||||
|
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
|
||||||
|
// released after std::filesystem, where std::filesystem is always available.
|
||||||
|
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
|
||||||
|
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|
||||||
|
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
|
||||||
|
#undef GHC_USE_STD_FS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
|
||||||
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
#ifdef GHC_USE_STD_FS
|
||||||
#define GHC_USE_STD_FS
|
#include <filesystem>
|
||||||
#include <filesystem>
|
namespace fs = std::filesystem;
|
||||||
namespace fs = std::filesystem;
|
#else
|
||||||
#endif
|
#include "filesystem.hpp"
|
||||||
#endif
|
namespace fs = ghc::filesystem;
|
||||||
#ifndef GHC_USE_STD_FS
|
|
||||||
#include <ghc/filesystem.hpp>
|
|
||||||
namespace fs = ghc::filesystem;
|
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note that this code uses a two-stage preprocessor condition because Visual Studio 2015
|
|
||||||
doesn't like the `(<...>)` syntax, even if it could cut evaluation early before. This code also
|
|
||||||
used the minimum deployment target to detect if `std::filesystem` really is available on macOS
|
|
||||||
compilation.**
|
|
||||||
|
|
||||||
**Note also, this detection now works on MSVC versions prior to 15.7 on, or without setting
|
|
||||||
the `/Zc:__cplusplus` compile switch that would fix `__cplusplus` on MSVC. (Without the switch
|
|
||||||
the compiler always reports `199711L`
|
|
||||||
([see](https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/)),
|
|
||||||
but `_MSVC_LANG` works without it.**
|
|
||||||
|
|
||||||
If you want to also use the `fstream` wrapper with `path` support as fallback,
|
If you want to also use the `fstream` wrapper with `path` support as fallback,
|
||||||
you might use:
|
you might use:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#ifdef __APPLE__
|
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
|
||||||
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
|
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
|
||||||
|
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
|
||||||
|
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
|
||||||
|
#define GHC_USE_STD_FS
|
||||||
|
|
||||||
|
// Old Apple OSs don't support std::filesystem, though the header is available at compile
|
||||||
|
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
|
||||||
|
// and watchOS 6.0.
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <Availability.h>
|
||||||
|
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
|
||||||
|
// released after std::filesystem, where std::filesystem is always available.
|
||||||
|
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
|
||||||
|
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|
||||||
|
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
|
||||||
|
#undef GHC_USE_STD_FS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
|
||||||
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
#ifdef GHC_USE_STD_FS
|
||||||
#define GHC_USE_STD_FS
|
#include <filesystem>
|
||||||
#include <filesystem>
|
namespace fs {
|
||||||
namespace fs {
|
using namespace std::filesystem;
|
||||||
using namespace std::filesystem;
|
using ifstream = std::ifstream;
|
||||||
using ifstream = std::ifstream;
|
using ofstream = std::ofstream;
|
||||||
using ofstream = std::ofstream;
|
using fstream = std::fstream;
|
||||||
using fstream = std::fstream;
|
}
|
||||||
}
|
#else
|
||||||
#endif
|
#include "filesystem.hpp"
|
||||||
#endif
|
namespace fs {
|
||||||
#ifndef GHC_USE_STD_FS
|
using namespace ghc::filesystem;
|
||||||
#include <ghc/filesystem.hpp>
|
using ifstream = ghc::filesystem::ifstream;
|
||||||
namespace fs {
|
using ofstream = ghc::filesystem::ofstream;
|
||||||
using namespace ghc::filesystem;
|
using fstream = ghc::filesystem::fstream;
|
||||||
using ifstream = ghc::filesystem::ifstream;
|
}
|
||||||
using ofstream = ghc::filesystem::ofstream;
|
|
||||||
using fstream = ghc::filesystem::fstream;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -263,29 +292,46 @@ If you use the forwarding/implementation approach, you can still use the dynamic
|
|||||||
switching like this:
|
switching like this:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#ifdef __APPLE__
|
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
|
||||||
#include <Availability.h> // for deployment target to support pre-catalina targets without std::fs
|
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
|
||||||
|
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
|
||||||
|
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
|
||||||
|
#define GHC_USE_STD_FS
|
||||||
|
|
||||||
|
// Old Apple OSs don't support std::filesystem, though the header is available at compile
|
||||||
|
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
|
||||||
|
// and watchOS 6.0.
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <Availability.h>
|
||||||
|
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
|
||||||
|
// released after std::filesystem, where std::filesystem is always available.
|
||||||
|
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
|
||||||
|
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|
||||||
|
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
|
||||||
|
#undef GHC_USE_STD_FS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
|
||||||
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
#ifdef GHC_USE_STD_FS
|
||||||
#define GHC_USE_STD_FS
|
#include <filesystem>
|
||||||
#include <filesystem>
|
namespace fs {
|
||||||
namespace fs {
|
using namespace std::filesystem;
|
||||||
using namespace std::filesystem;
|
using ifstream = std::ifstream;
|
||||||
using ifstream = std::ifstream;
|
using ofstream = std::ofstream;
|
||||||
using ofstream = std::ofstream;
|
using fstream = std::fstream;
|
||||||
using fstream = std::fstream;
|
}
|
||||||
}
|
#else
|
||||||
#endif
|
#include "fs_fwd.hpp"
|
||||||
#endif
|
namespace fs {
|
||||||
#ifndef GHC_USE_STD_FS
|
using namespace ghc::filesystem;
|
||||||
#include <ghc/fs-fwd.hpp>
|
using ifstream = ghc::filesystem::ifstream;
|
||||||
namespace fs {
|
using ofstream = ghc::filesystem::ofstream;
|
||||||
using namespace ghc::filesystem;
|
using fstream = ghc::filesystem::fstream;
|
||||||
using ifstream = ghc::filesystem::ifstream;
|
}
|
||||||
using ofstream = ghc::filesystem::ofstream;
|
|
||||||
using fstream = ghc::filesystem::fstream;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -293,25 +339,38 @@ and in the implementation hiding cpp, you might use (before any include that inc
|
|||||||
to take precedence:
|
to take precedence:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#ifdef __APPLE__ // for deployment target to support pre-catalina targets without std::fs
|
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
|
||||||
#include <Availability.h>
|
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
|
||||||
#endif
|
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
|
||||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
|
||||||
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
#define GHC_USE_STD_FS
|
||||||
#define GHC_USE_STD_FS
|
|
||||||
#endif
|
// Old Apple OSs don't support std::filesystem, though the header is available at compile
|
||||||
|
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
|
||||||
|
// and watchOS 6.0.
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <Availability.h>
|
||||||
|
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
|
||||||
|
// released after std::filesystem, where std::filesystem is always available.
|
||||||
|
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
|
||||||
|
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|
||||||
|
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
|
||||||
|
#undef GHC_USE_STD_FS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GHC_USE_STD_FS
|
#ifndef GHC_USE_STD_FS
|
||||||
#define GHC_FILESYSTEM_IMPLEMENTATION
|
#include "fs_impl.hpp"
|
||||||
#include <ghc/filesystem.hpp>
|
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
:information_source: **Hint:** There are additional helper headers, named `ghc/fs_std_fwd.hpp` and
|
:information_source: **Hint:** There are additional helper headers, named `ghc/fs_std_fwd.hpp` and
|
||||||
`ghc/fs_std_impl.hpp` that use this technique, so you can simply include them
|
`ghc/fs_std_impl.hpp` that use this technique, so you can simply include them
|
||||||
if you want to dynamically select the filesystem implementation. they also
|
if you want to dynamically select the filesystem implementation.
|
||||||
enable the `wchar_t` support on `ghc::filesystem` on Windows, so the resulting
|
|
||||||
implementation in the `fs` namespace will be compatible.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -338,6 +397,10 @@ The `CMakeLists.txt` offers a few options to customize its behavior:
|
|||||||
`CMAKE_CXX_COMPILE_FEATURES` when the detection of C++17 or C++20 for additional tests
|
`CMAKE_CXX_COMPILE_FEATURES` when the detection of C++17 or C++20 for additional tests
|
||||||
is not working (e.g. `cxx_std_20` to enforce building a `filesystem_test_cpp20` with C++20).
|
is not working (e.g. `cxx_std_20` to enforce building a `filesystem_test_cpp20` with C++20).
|
||||||
|
|
||||||
|
### Bazel
|
||||||
|
|
||||||
|
Please use [hedronvision/bazel-cc-filesystem-backport](https://github.com/hedronvision/bazel-cc-filesystem-backport), which will automatically set everything up for you.
|
||||||
|
|
||||||
### Versioning
|
### Versioning
|
||||||
|
|
||||||
There is a version macro `GHC_FILESYSTEM_VERSION` defined in case future changes
|
There is a version macro `GHC_FILESYSTEM_VERSION` defined in case future changes
|
||||||
@ -403,7 +466,7 @@ int main(int argc, char* argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now use argc/argv as usual, they have utf-8 enconding on windows
|
// now use argc/argv as usual, they have utf-8 encoding on windows
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -583,6 +646,60 @@ to the expected behavior.
|
|||||||
|
|
||||||
## Release Notes
|
## Release Notes
|
||||||
|
|
||||||
|
### v1.5.15 (wip)
|
||||||
|
|
||||||
|
* Fix for [#166](https://github.com/gulrak/filesystem/issues/166),
|
||||||
|
`extension()` did return non empty result for the directory name
|
||||||
|
`".."`
|
||||||
|
|
||||||
|
### [v1.5.14](https://github.com/gulrak/filesystem/releases/tag/v1.5.14)
|
||||||
|
|
||||||
|
* Pull request [#163](https://github.com/gulrak/filesystem/pull/163), build
|
||||||
|
support for Haiku (also fixes [#159](https://github.com/gulrak/filesystem/issues/159))
|
||||||
|
* Pull request [#162](https://github.com/gulrak/filesystem/pull/162), fix for
|
||||||
|
directory iterator treating all files subsequent to a symlink as symlink
|
||||||
|
on Windows
|
||||||
|
* Pull request [#161](https://github.com/gulrak/filesystem/pull/161), the
|
||||||
|
CMake alias `ghcFilesystem::ghc_filesystem` is now set unconditionally
|
||||||
|
* Fix for [#160](https://github.com/gulrak/filesystem/issues/160), the cmake
|
||||||
|
config now only sets install targets by default if the project is no
|
||||||
|
subproject, as documented
|
||||||
|
* Fix for [#157](https://github.com/gulrak/filesystem/issues/157), suppress
|
||||||
|
C4191 warning on MSVC for GetProcAddress casts
|
||||||
|
* Fix for [#156](https://github.com/gulrak/filesystem/issues/156), on POSIX
|
||||||
|
`stem()`, `filename()` and `extension()` of `fs::path` would return wrong
|
||||||
|
result if a colon was in the filename
|
||||||
|
* Pull request [#154](https://github.com/gulrak/filesystem/pull/145), build
|
||||||
|
support for GNU/Hurd
|
||||||
|
* Pull request [#153](https://github.com/gulrak/filesystem/pull/153), fixed
|
||||||
|
`fs::last_write_time(path, time, ec)` setter on iOS, tvOS and watchOS
|
||||||
|
* Fix for [#151](https://github.com/gulrak/filesystem/issues/156),
|
||||||
|
`fs::directory_entry::refresh()` now, consistently with `status()` will not
|
||||||
|
throw on symlinks to non-existing targets, but make the entry have
|
||||||
|
`file_type::not_found` as the type
|
||||||
|
* Pull request [#149](https://github.com/gulrak/filesystem/pull/149), add
|
||||||
|
version to CMake project and export it
|
||||||
|
* Fix for [#146](https://github.com/gulrak/filesystem/issues/146), handle `EINTR`
|
||||||
|
on POSIX directory iteration and file copy to avoid errors on network
|
||||||
|
filesystems
|
||||||
|
* Pull request [#145](https://github.com/gulrak/filesystem/pull/145), fix for
|
||||||
|
Y2038 bug in timeToFILETIME on Windows
|
||||||
|
* Pull request [#144](https://github.com/gulrak/filesystem/pull/144), `fs::copy_file()`
|
||||||
|
now also copies the permissions
|
||||||
|
* Pull request [#143](https://github.com/gulrak/filesystem/pull/143), fix
|
||||||
|
for `fs::copy_file()` ignoring the `skip_existing` option.
|
||||||
|
|
||||||
|
### [v1.5.12](https://github.com/gulrak/filesystem/releases/tag/v1.5.12)
|
||||||
|
|
||||||
|
* Fix for [#142](https://github.com/gulrak/filesystem/issues/142), removed need
|
||||||
|
for `GHC_NO_DIRENT_D_TYPE` on systems that don't support `dirent::d_type` and
|
||||||
|
fixed build configuration and tests to support Solaris as new platform.
|
||||||
|
* Pull request [#138](https://github.com/gulrak/filesystem/pull/138), if the
|
||||||
|
platform uses the POSIX backend and has no `PATH_MAX`, one is defined.
|
||||||
|
* Pull request [#137](https://github.com/gulrak/filesystem/pull/137), update
|
||||||
|
of Catch2 to version v2.13.7
|
||||||
|
* Added macOS 11 to the automatically tested platforms.
|
||||||
|
|
||||||
### [v1.5.10](https://github.com/gulrak/filesystem/releases/tag/v1.5.10)
|
### [v1.5.10](https://github.com/gulrak/filesystem/releases/tag/v1.5.10)
|
||||||
|
|
||||||
* Pull request [#136](https://github.com/gulrak/filesystem/pull/136), the Windows
|
* Pull request [#136](https://github.com/gulrak/filesystem/pull/136), the Windows
|
||||||
@ -599,7 +716,7 @@ to the expected behavior.
|
|||||||
|
|
||||||
### [v1.5.8](https://github.com/gulrak/filesystem/releases/tag/v1.5.8)
|
### [v1.5.8](https://github.com/gulrak/filesystem/releases/tag/v1.5.8)
|
||||||
|
|
||||||
* Fix for [#125]((https://github.com/gulrak/filesystem/issues/124), where
|
* Fix for [#125](https://github.com/gulrak/filesystem/issues/124), where
|
||||||
`fs::create_directories` on Windows no longer breaks on long filenames.
|
`fs::create_directories` on Windows no longer breaks on long filenames.
|
||||||
|
|
||||||
### [v1.5.6](https://github.com/gulrak/filesystem/releases/tag/v1.5.6)
|
### [v1.5.6](https://github.com/gulrak/filesystem/releases/tag/v1.5.6)
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
macro(AddExecutableWithStdFS targetName)
|
macro(AddExecutableWithStdFS targetName)
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
include_directories(/usr/local/opt/llvm/include)
|
include_directories(/usr/local/opt/llvm/include)
|
||||||
link_directories(/usr/local/opt/llvm/lib)
|
link_directories(/usr/local/opt/llvm/lib)
|
||||||
@ -20,6 +19,12 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION
|
|||||||
target_link_libraries(${targetName} -stdlib=libc++)
|
target_link_libraries(${targetName} -stdlib=libc++)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||||
|
target_link_libraries(filesystem_test xnet)
|
||||||
|
endif()
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||||
|
target_link_libraries(filesystem_test network)
|
||||||
|
endif()
|
||||||
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -29,6 +34,12 @@ if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 O
|
|||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
|
||||||
target_link_libraries(${targetName} -lstdc++fs)
|
target_link_libraries(${targetName} -lstdc++fs)
|
||||||
endif()
|
endif()
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||||
|
target_link_libraries(${targetName} xnet)
|
||||||
|
endif()
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||||
|
target_link_libraries(${targetName} network)
|
||||||
|
endif()
|
||||||
target_compile_options(${targetName} PRIVATE $<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
|
target_compile_options(${targetName} PRIVATE $<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
|
||||||
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||||
endif()
|
endif()
|
||||||
@ -47,6 +58,12 @@ macro(AddTestExecutableWithStdCpp cppStd)
|
|||||||
add_executable(filesystem_test_cpp${cppStd} ${ARGN})
|
add_executable(filesystem_test_cpp${cppStd} ${ARGN})
|
||||||
set_property(TARGET filesystem_test_cpp${cppStd} PROPERTY CXX_STANDARD ${cppStd})
|
set_property(TARGET filesystem_test_cpp${cppStd} PROPERTY CXX_STANDARD ${cppStd})
|
||||||
target_link_libraries(filesystem_test_cpp${cppStd} ghc_filesystem)
|
target_link_libraries(filesystem_test_cpp${cppStd} ghc_filesystem)
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||||
|
target_link_libraries(filesystem_test_cpp${cppStd} xnet)
|
||||||
|
endif()
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||||
|
target_link_libraries(filesystem_test_cpp${cppStd} network)
|
||||||
|
endif()
|
||||||
target_compile_options(filesystem_test_cpp${cppStd} PRIVATE
|
target_compile_options(filesystem_test_cpp${cppStd} PRIVATE
|
||||||
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
|
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
|
||||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror -Wno-error=deprecated-declarations>
|
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror -Wno-error=deprecated-declarations>
|
||||||
|
|||||||
@ -25,23 +25,6 @@
|
|||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
//
|
|
||||||
// To dynamically select std::filesystem where available on most platforms,
|
|
||||||
// you could use:
|
|
||||||
//
|
|
||||||
// #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
|
||||||
// #if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
|
||||||
// #define GHC_USE_STD_FS
|
|
||||||
// #include <filesystem>
|
|
||||||
// namespace fs = std::filesystem;
|
|
||||||
// #endif
|
|
||||||
// #endif
|
|
||||||
// #ifndef GHC_USE_STD_FS
|
|
||||||
// #include <ghc/filesystem.hpp>
|
|
||||||
// namespace fs = ghc::filesystem;
|
|
||||||
// #endif
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------------------
|
|
||||||
#ifndef GHC_FILESYSTEM_H
|
#ifndef GHC_FILESYSTEM_H
|
||||||
#define GHC_FILESYSTEM_H
|
#define GHC_FILESYSTEM_H
|
||||||
|
|
||||||
@ -53,7 +36,7 @@
|
|||||||
|
|
||||||
#ifndef GHC_OS_DETECTED
|
#ifndef GHC_OS_DETECTED
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
#define GHC_OS_MACOS
|
#define GHC_OS_APPLE
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
#define GHC_OS_LINUX
|
#define GHC_OS_LINUX
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
@ -67,6 +50,8 @@
|
|||||||
#define GHC_OS_WIN32
|
#define GHC_OS_WIN32
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
#define GHC_OS_CYGWIN
|
#define GHC_OS_CYGWIN
|
||||||
|
#elif defined(__sun) && defined(__SVR4)
|
||||||
|
#define GHC_OS_SOLARIS
|
||||||
#elif defined(__svr4__)
|
#elif defined(__svr4__)
|
||||||
#define GHC_OS_SYS5R4
|
#define GHC_OS_SYS5R4
|
||||||
#elif defined(BSD)
|
#elif defined(BSD)
|
||||||
@ -76,7 +61,8 @@
|
|||||||
#include <wasi/api.h>
|
#include <wasi/api.h>
|
||||||
#elif defined(__QNX__)
|
#elif defined(__QNX__)
|
||||||
#define GHC_OS_QNX
|
#define GHC_OS_QNX
|
||||||
#define GHC_NO_DIRENT_D_TYPE
|
#elif defined(__HAIKU__)
|
||||||
|
#define GHC_OS_HAIKU
|
||||||
#else
|
#else
|
||||||
#error "Operating system currently not supported!"
|
#error "Operating system currently not supported!"
|
||||||
#endif
|
#endif
|
||||||
@ -178,7 +164,7 @@
|
|||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef GHC_OS_MACOS
|
#ifdef GHC_OS_APPLE
|
||||||
#include <Availability.h>
|
#include <Availability.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -254,6 +240,10 @@
|
|||||||
#include <experimental/string_view>
|
#include <experimental/string_view>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(GHC_OS_WINDOWS) && !defined(PATH_MAX)
|
||||||
|
#define PATH_MAX 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp):
|
// Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp):
|
||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
@ -274,19 +264,19 @@
|
|||||||
// * if this->has_root_directory() and !p.has_root_directory() return -1
|
// * if this->has_root_directory() and !p.has_root_directory() return -1
|
||||||
// * if !this->has_root_directory() and p.has_root_directory() return -1
|
// * if !this->has_root_directory() and p.has_root_directory() return -1
|
||||||
// * else result of element wise comparison of path iteration where first comparison is != 0 or 0
|
// * else result of element wise comparison of path iteration where first comparison is != 0 or 0
|
||||||
// if all comparisons are 0 (on Windows this implementation does case insensitive root_name()
|
// if all comparisons are 0 (on Windows this implementation does case-insensitive root_name()
|
||||||
// comparison)
|
// comparison)
|
||||||
#define LWG_2936_BEHAVIOUR
|
#define LWG_2936_BEHAVIOUR
|
||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2)
|
// LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2)
|
||||||
#define LWG_2937_BEHAVIOUR
|
#define LWG_2937_BEHAVIOUR
|
||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// UTF8-Everywhere is the original behaviour of ghc::filesystem. But since v1.5 the windows
|
// UTF8-Everywhere is the original behaviour of ghc::filesystem. But since v1.5 the Windows
|
||||||
// version defaults to std::wstring storage backend. Still all std::string will be interpreted
|
// version defaults to std::wstring storage backend. Still all std::string will be interpreted
|
||||||
// as UTF-8 encoded. With this define you can enfoce the old behavior on Windows, using
|
// as UTF-8 encoded. With this define you can enforce the old behavior on Windows, using
|
||||||
// std::string as backend and for fs::path::native() and char for fs::path::c_str(). This
|
// std::string as backend and for fs::path::native() and char for fs::path::c_str(). This
|
||||||
// needs more conversions so it is (an was before v1.5) slower, bot might help keeping source
|
// needs more conversions, so it is (and was before v1.5) slower, bot might help keeping source
|
||||||
// homogeneous in a multi platform project.
|
// homogeneous in a multi-platform project.
|
||||||
// #define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
|
// #define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
|
||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// Raise errors/exceptions when invalid unicode codepoints or UTF-8 sequences are found,
|
// Raise errors/exceptions when invalid unicode codepoints or UTF-8 sequences are found,
|
||||||
@ -301,7 +291,7 @@
|
|||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
|
// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
|
||||||
#define GHC_FILESYSTEM_VERSION 10510L
|
#define GHC_FILESYSTEM_VERSION 10515L
|
||||||
|
|
||||||
#if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND))
|
#if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND))
|
||||||
#define GHC_WITH_EXCEPTIONS
|
#define GHC_WITH_EXCEPTIONS
|
||||||
@ -1152,6 +1142,10 @@ 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)))
|
||||||
|
#define GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
|
||||||
|
#endif
|
||||||
|
|
||||||
// Non-C++17 add-on std::fstream wrappers with path
|
// Non-C++17 add-on std::fstream wrappers with path
|
||||||
template <class charT, class traits = std::char_traits<charT>>
|
template <class charT, class traits = std::char_traits<charT>>
|
||||||
class basic_filebuf : public std::basic_filebuf<charT, traits>
|
class basic_filebuf : public std::basic_filebuf<charT, traits>
|
||||||
@ -1163,7 +1157,7 @@ public:
|
|||||||
const basic_filebuf& operator=(const basic_filebuf&) = delete;
|
const basic_filebuf& operator=(const basic_filebuf&) = delete;
|
||||||
basic_filebuf<charT, traits>* open(const path& p, std::ios_base::openmode mode)
|
basic_filebuf<charT, traits>* open(const path& p, std::ios_base::openmode mode)
|
||||||
{
|
{
|
||||||
#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
|
#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;
|
||||||
#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;
|
||||||
@ -1176,7 +1170,7 @@ class basic_ifstream : public std::basic_ifstream<charT, traits>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
basic_ifstream() {}
|
basic_ifstream() {}
|
||||||
#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
|
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
|
||||||
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.wstring().c_str(), mode)
|
: std::basic_ifstream<charT, traits>(p.wstring().c_str(), mode)
|
||||||
{
|
{
|
||||||
@ -1199,7 +1193,7 @@ class basic_ofstream : public std::basic_ofstream<charT, traits>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
basic_ofstream() {}
|
basic_ofstream() {}
|
||||||
#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
|
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
|
||||||
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.wstring().c_str(), mode)
|
: std::basic_ofstream<charT, traits>(p.wstring().c_str(), mode)
|
||||||
{
|
{
|
||||||
@ -1222,7 +1216,7 @@ class basic_fstream : public std::basic_fstream<charT, traits>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
basic_fstream() {}
|
basic_fstream() {}
|
||||||
#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
|
#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR
|
||||||
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.wstring().c_str(), mode)
|
: std::basic_fstream<charT, traits>(p.wstring().c_str(), mode)
|
||||||
{
|
{
|
||||||
@ -1298,6 +1292,65 @@ GHC_FS_API std::error_code make_error_code(portable_error err);
|
|||||||
GHC_FS_API std::error_code make_system_error(uint32_t err = 0);
|
GHC_FS_API std::error_code make_system_error(uint32_t err = 0);
|
||||||
#else
|
#else
|
||||||
GHC_FS_API std::error_code make_system_error(int err = 0);
|
GHC_FS_API std::error_code make_system_error(int err = 0);
|
||||||
|
|
||||||
|
template <typename T, typename = int>
|
||||||
|
struct has_d_type : std::false_type{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_d_type<T, decltype((void)T::d_type, 0)> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
GHC_INLINE file_type file_type_from_dirent_impl(const T&, std::false_type)
|
||||||
|
{
|
||||||
|
return file_type::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
GHC_INLINE file_type file_type_from_dirent_impl(const T& t, std::true_type)
|
||||||
|
{
|
||||||
|
switch (t.d_type) {
|
||||||
|
#ifdef DT_BLK
|
||||||
|
case DT_BLK:
|
||||||
|
return file_type::block;
|
||||||
|
#endif
|
||||||
|
#ifdef DT_CHR
|
||||||
|
case DT_CHR:
|
||||||
|
return file_type::character;
|
||||||
|
#endif
|
||||||
|
#ifdef DT_DIR
|
||||||
|
case DT_DIR:
|
||||||
|
return file_type::directory;
|
||||||
|
#endif
|
||||||
|
#ifdef DT_FIFO
|
||||||
|
case DT_FIFO:
|
||||||
|
return file_type::fifo;
|
||||||
|
#endif
|
||||||
|
#ifdef DT_LNK
|
||||||
|
case DT_LNK:
|
||||||
|
return file_type::symlink;
|
||||||
|
#endif
|
||||||
|
#ifdef DT_REG
|
||||||
|
case DT_REG:
|
||||||
|
return file_type::regular;
|
||||||
|
#endif
|
||||||
|
#ifdef DT_SOCK
|
||||||
|
case DT_SOCK:
|
||||||
|
return file_type::socket;
|
||||||
|
#endif
|
||||||
|
#ifdef DT_UNKNOWN
|
||||||
|
case DT_UNKNOWN:
|
||||||
|
return file_type::none;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return file_type::unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
GHC_INLINE file_type file_type_from_dirent(const T& t)
|
||||||
|
{
|
||||||
|
return file_type_from_dirent_impl(t, has_d_type<T>{});
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
@ -1891,10 +1944,15 @@ GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink,
|
|||||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||||
|
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4191)
|
||||||
#endif
|
#endif
|
||||||
static CreateSymbolicLinkW_fp api_call = reinterpret_cast<CreateSymbolicLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW"));
|
static CreateSymbolicLinkW_fp api_call = reinterpret_cast<CreateSymbolicLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW"));
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||||
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
if (api_call) {
|
if (api_call) {
|
||||||
if (api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 1 : 0) == 0) {
|
if (api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 1 : 0) == 0) {
|
||||||
@ -1915,10 +1973,15 @@ GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlin
|
|||||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||||
|
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4191)
|
||||||
#endif
|
#endif
|
||||||
static CreateHardLinkW_fp api_call = reinterpret_cast<CreateHardLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
|
static CreateHardLinkW_fp api_call = reinterpret_cast<CreateHardLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 8
|
#if defined(__GNUC__) && __GNUC__ >= 8
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||||
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
if (api_call) {
|
if (api_call) {
|
||||||
if (api_call(GHC_NATIVEWP(new_hardlink), GHC_NATIVEWP(target_name), NULL) == 0) {
|
if (api_call(GHC_NATIVEWP(new_hardlink), GHC_NATIVEWP(target_name), NULL) == 0) {
|
||||||
@ -2177,10 +2240,10 @@ GHC_INLINE time_t timeFromFILETIME(const FILETIME& ft)
|
|||||||
|
|
||||||
GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft)
|
GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft)
|
||||||
{
|
{
|
||||||
LONGLONG ll;
|
ULARGE_INTEGER ull;
|
||||||
ll = Int32x32To64(t, 10000000) + 116444736000000000;
|
ull.QuadPart = static_cast<ULONGLONG>((t * 10000000LL) + 116444736000000000LL);
|
||||||
ft.dwLowDateTime = static_cast<DWORD>(ll);
|
ft.dwLowDateTime = ull.LowPart;
|
||||||
ft.dwHighDateTime = static_cast<DWORD>(ll >> 32);
|
ft.dwHighDateTime = ull.HighPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename INFO>
|
template <typename INFO>
|
||||||
@ -2196,41 +2259,43 @@ GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const BY_H
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename INFO>
|
template <typename INFO>
|
||||||
GHC_INLINE DWORD reparse_tag_from_INFO(const INFO*)
|
GHC_INLINE bool is_symlink_from_INFO(const path &p, const INFO* info, std::error_code& ec)
|
||||||
{
|
{
|
||||||
return 0;
|
if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||||
|
auto reparseData = detail::getReparseData(p, ec);
|
||||||
|
if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
GHC_INLINE DWORD reparse_tag_from_INFO(const WIN32_FIND_DATAW* info)
|
GHC_INLINE bool is_symlink_from_INFO(const path &, const WIN32_FIND_DATAW* info, std::error_code&)
|
||||||
{
|
{
|
||||||
return info->dwReserved0;
|
// dwReserved0 is undefined unless dwFileAttributes includes the
|
||||||
|
// FILE_ATTRIBUTE_REPARSE_POINT attribute according to microsoft
|
||||||
|
// documentation. In practice, dwReserved0 is not reset which
|
||||||
|
// causes it to report the incorrect symlink status.
|
||||||
|
// Note that microsoft documentation does not say whether there is
|
||||||
|
// a null value for dwReserved0, so we test for symlink directly
|
||||||
|
// instead of returning the tag which requires returning a null
|
||||||
|
// value for non-reparse-point files.
|
||||||
|
return (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && info->dwReserved0 == IO_REPARSE_TAG_SYMLINK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename INFO>
|
template <typename INFO>
|
||||||
GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code& ec, uintmax_t* sz = nullptr, time_t* lwt = nullptr)
|
GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code& ec, uintmax_t* sz = nullptr, time_t* lwt = nullptr)
|
||||||
{
|
{
|
||||||
file_type ft = file_type::unknown;
|
file_type ft = file_type::unknown;
|
||||||
if (sizeof(INFO) == sizeof(WIN32_FIND_DATAW)) {
|
if (is_symlink_from_INFO(p, info, ec)) {
|
||||||
if (detail::reparse_tag_from_INFO(info) == IO_REPARSE_TAG_SYMLINK) {
|
ft = file_type::symlink;
|
||||||
ft = file_type::symlink;
|
}
|
||||||
}
|
else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
|
ft = file_type::directory;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
ft = file_type::regular;
|
||||||
auto reparseData = detail::getReparseData(p, ec);
|
|
||||||
if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
|
|
||||||
ft = file_type::symlink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ft == file_type::unknown) {
|
|
||||||
if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
||||||
ft = file_type::directory;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ft = file_type::regular;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
perms prms = perms::owner_read | perms::group_read | perms::others_read;
|
perms prms = perms::owner_read | perms::group_read | perms::others_read;
|
||||||
if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
||||||
@ -3092,7 +3157,7 @@ GHC_INLINE path path::extension() const
|
|||||||
auto iter = end();
|
auto iter = end();
|
||||||
const auto& fn = *--iter;
|
const auto& fn = *--iter;
|
||||||
impl_string_type::size_type pos = fn._path.rfind('.');
|
impl_string_type::size_type pos = fn._path.rfind('.');
|
||||||
if (pos != std::string::npos && pos > 0) {
|
if (pos != std::string::npos && pos > 0 && fn._path != "..") {
|
||||||
return path(fn._path.substr(pos), native_format);
|
return path(fn._path.substr(pos), native_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3241,6 +3306,9 @@ GHC_INLINE path path::lexically_relative(const path& base) const
|
|||||||
--count;
|
--count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (count == 0 && (a == end() || a->empty())) {
|
||||||
|
return path(".");
|
||||||
|
}
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
return path();
|
return path();
|
||||||
}
|
}
|
||||||
@ -3301,10 +3369,14 @@ GHC_INLINE path::impl_string_type::const_iterator path::iterator::increment(cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#ifdef GHC_OS_WINDOWS
|
||||||
if (fromStart && i != _last && *i == ':') {
|
if (fromStart && i != _last && *i == ':') {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
i = std::find(i, _last, preferred_separator);
|
i = std::find(i, _last, preferred_separator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3848,11 +3920,14 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
|
|||||||
ec = tecf;
|
ec = tecf;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (exists(st) && (!is_regular_file(st) || equivalent(from, to, ec) || (options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none)) {
|
|
||||||
ec = tect ? tect : detail::make_error_code(detail::portable_error::exists);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (exists(st)) {
|
if (exists(st)) {
|
||||||
|
if ((options & copy_options::skip_existing) == copy_options::skip_existing) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_regular_file(st) || equivalent(from, to, ec) || (options & (copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none) {
|
||||||
|
ec = tect ? tect : detail::make_error_code(detail::portable_error::exists);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ((options & copy_options::update_existing) == copy_options::update_existing) {
|
if ((options & copy_options::update_existing) == copy_options::update_existing) {
|
||||||
auto from_time = last_write_time(from, ec);
|
auto from_time = last_write_time(from, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
@ -3892,15 +3967,33 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options
|
|||||||
::close(in);
|
::close(in);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (st.permissions() != sf.permissions()) {
|
||||||
|
if (::fchmod(out, static_cast<mode_t>(sf.permissions() & perms::all)) != 0) {
|
||||||
|
ec = detail::make_system_error();
|
||||||
|
::close(in);
|
||||||
|
::close(out);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
ssize_t br, bw;
|
ssize_t br, bw;
|
||||||
while ((br = ::read(in, buffer.data(), buffer.size())) > 0) {
|
while (true) {
|
||||||
|
do { br = ::read(in, buffer.data(), buffer.size()); } while(errno == EINTR && !br);
|
||||||
|
if(!br) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(br < 0) {
|
||||||
|
ec = detail::make_system_error();
|
||||||
|
::close(in);
|
||||||
|
::close(out);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ssize_t offset = 0;
|
ssize_t offset = 0;
|
||||||
do {
|
do {
|
||||||
if ((bw = ::write(out, buffer.data() + offset, static_cast<size_t>(br))) > 0) {
|
if ((bw = ::write(out, buffer.data() + offset, static_cast<size_t>(br))) > 0) {
|
||||||
br -= bw;
|
br -= bw;
|
||||||
offset += bw;
|
offset += bw;
|
||||||
}
|
}
|
||||||
else if (bw < 0) {
|
else if (bw < 0 && errno != EINTR) {
|
||||||
ec = detail::make_system_error();
|
ec = detail::make_system_error();
|
||||||
::close(in);
|
::close(in);
|
||||||
::close(out);
|
::close(out);
|
||||||
@ -4135,6 +4228,13 @@ GHC_INLINE path current_path(std::error_code& ec)
|
|||||||
return path();
|
return path();
|
||||||
}
|
}
|
||||||
return path(std::wstring(buffer.get()), path::native_format);
|
return path(std::wstring(buffer.get()), path::native_format);
|
||||||
|
#elif defined(__GLIBC__)
|
||||||
|
std::unique_ptr<char, decltype(&std::free)> buffer { ::get_current_dir_name(), std::free };
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
ec = detail::make_system_error();
|
||||||
|
return path();
|
||||||
|
}
|
||||||
|
return path(buffer.get());
|
||||||
#else
|
#else
|
||||||
size_t pathlen = static_cast<size_t>(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX)));
|
size_t pathlen = static_cast<size_t>(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX)));
|
||||||
std::unique_ptr<char[]> buffer(new char[pathlen + 1]);
|
std::unique_ptr<char[]> buffer(new char[pathlen + 1]);
|
||||||
@ -4540,9 +4640,11 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
|
|||||||
if (!::SetFileTime(file.get(), 0, 0, &ft)) {
|
if (!::SetFileTime(file.get(), 0, 0, &ft)) {
|
||||||
ec = detail::make_system_error();
|
ec = detail::make_system_error();
|
||||||
}
|
}
|
||||||
#elif defined(GHC_OS_MACOS)
|
#elif defined(GHC_OS_APPLE) && \
|
||||||
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
|
(__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101300 \
|
||||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
|
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 110000 \
|
||||||
|
|| __TV_OS_VERSION_MIN_REQUIRED && __TVOS_VERSION_MIN_REQUIRED < 110000 \
|
||||||
|
|| __WATCH_OS_VERSION_MIN_REQUIRED && __WATCHOS_VERSION_MIN_REQUIRED < 40000)
|
||||||
struct ::stat fs;
|
struct ::stat fs;
|
||||||
if (::stat(p.c_str(), &fs) == 0) {
|
if (::stat(p.c_str(), &fs) == 0) {
|
||||||
struct ::timeval tv[2];
|
struct ::timeval tv[2];
|
||||||
@ -4556,18 +4658,6 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
|
|||||||
}
|
}
|
||||||
ec = detail::make_system_error();
|
ec = detail::make_system_error();
|
||||||
return;
|
return;
|
||||||
#else
|
|
||||||
struct ::timespec times[2];
|
|
||||||
times[0].tv_sec = 0;
|
|
||||||
times[0].tv_nsec = UTIME_OMIT;
|
|
||||||
times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
|
|
||||||
times[1].tv_nsec = 0; // std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
|
|
||||||
if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
|
|
||||||
ec = detail::make_system_error();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#ifndef UTIME_OMIT
|
#ifndef UTIME_OMIT
|
||||||
#define UTIME_OMIT ((1l << 30) - 2l)
|
#define UTIME_OMIT ((1l << 30) - 2l)
|
||||||
@ -4580,7 +4670,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
|
|||||||
#if defined(__ANDROID_API__) && __ANDROID_API__ < 12
|
#if defined(__ANDROID_API__) && __ANDROID_API__ < 12
|
||||||
if (syscall(__NR_utimensat, AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
|
if (syscall(__NR_utimensat, AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
|
||||||
#else
|
#else
|
||||||
if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
|
if (::utimensat((int)AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
|
||||||
#endif
|
#endif
|
||||||
ec = detail::make_system_error();
|
ec = detail::make_system_error();
|
||||||
}
|
}
|
||||||
@ -5195,7 +5285,7 @@ GHC_INLINE void directory_entry::refresh()
|
|||||||
{
|
{
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
refresh(ec);
|
refresh(ec);
|
||||||
if (ec) {
|
if (ec && (_status.type() == file_type::none || _symlink_status.type() != file_type::symlink)) {
|
||||||
throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec);
|
throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5606,7 +5696,7 @@ public:
|
|||||||
, _entry(nullptr)
|
, _entry(nullptr)
|
||||||
{
|
{
|
||||||
if (!path.empty()) {
|
if (!path.empty()) {
|
||||||
_dir = ::opendir(path.native().c_str());
|
do { _dir = ::opendir(path.native().c_str()); } while(errno == EINTR && !_dir);
|
||||||
if (!_dir) {
|
if (!_dir) {
|
||||||
auto error = errno;
|
auto error = errno;
|
||||||
_base = filesystem::path();
|
_base = filesystem::path();
|
||||||
@ -5633,7 +5723,7 @@ public:
|
|||||||
do {
|
do {
|
||||||
skip = false;
|
skip = false;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
_entry = ::readdir(_dir);
|
do { _entry = ::readdir(_dir); } while(errno == EINTR && !_entry);
|
||||||
if (_entry) {
|
if (_entry) {
|
||||||
_dir_entry._path = _base;
|
_dir_entry._path = _base;
|
||||||
_dir_entry._path.append_name(_entry->d_name);
|
_dir_entry._path.append_name(_entry->d_name);
|
||||||
@ -5647,7 +5737,7 @@ public:
|
|||||||
::closedir(_dir);
|
::closedir(_dir);
|
||||||
_dir = nullptr;
|
_dir = nullptr;
|
||||||
_dir_entry._path.clear();
|
_dir_entry._path.clear();
|
||||||
if (errno) {
|
if (errno && errno != EINTR) {
|
||||||
ec = detail::make_system_error();
|
ec = detail::make_system_error();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -5658,48 +5748,16 @@ public:
|
|||||||
|
|
||||||
void copyToDirEntry()
|
void copyToDirEntry()
|
||||||
{
|
{
|
||||||
#ifdef GHC_NO_DIRENT_D_TYPE
|
|
||||||
_dir_entry._symlink_status = file_status();
|
|
||||||
_dir_entry._status = file_status();
|
|
||||||
#else
|
|
||||||
_dir_entry._symlink_status.permissions(perms::unknown);
|
_dir_entry._symlink_status.permissions(perms::unknown);
|
||||||
switch (_entry->d_type) {
|
auto ft = detail::file_type_from_dirent(*_entry);
|
||||||
case DT_BLK:
|
_dir_entry._symlink_status.type(ft);
|
||||||
_dir_entry._symlink_status.type(file_type::block);
|
if (ft != file_type::symlink) {
|
||||||
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;
|
_dir_entry._status = _dir_entry._symlink_status;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_dir_entry._status.type(file_type::none);
|
_dir_entry._status.type(file_type::none);
|
||||||
_dir_entry._status.permissions(perms::unknown);
|
_dir_entry._status.permissions(perms::unknown);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
_dir_entry._file_size = static_cast<uintmax_t>(-1);
|
_dir_entry._file_size = static_cast<uintmax_t>(-1);
|
||||||
_dir_entry._hard_link_count = static_cast<uintmax_t>(-1);
|
_dir_entry._hard_link_count = static_cast<uintmax_t>(-1);
|
||||||
_dir_entry._last_write_time = 0;
|
_dir_entry._last_write_time = 0;
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
// fs_fwd.hpp - The forwarding header for the header/implementation seperated usage of
|
// fs_fwd.hpp - The forwarding header for the header/implementation separated usage of
|
||||||
// ghc::filesystem.
|
// ghc::filesystem.
|
||||||
// This file can be include at any place, where ghc::filesystem api is needed while
|
// This file can be include at any place, where ghc::filesystem api is needed while
|
||||||
// not bleeding implementation details (e.g. system includes) into the global namespace,
|
// not bleeding implementation details (e.g. system includes) into the global namespace,
|
||||||
@ -34,5 +34,5 @@
|
|||||||
#ifndef GHC_FILESYSTEM_FWD_H
|
#ifndef GHC_FILESYSTEM_FWD_H
|
||||||
#define GHC_FILESYSTEM_FWD_H
|
#define GHC_FILESYSTEM_FWD_H
|
||||||
#define GHC_FILESYSTEM_FWD
|
#define GHC_FILESYSTEM_FWD
|
||||||
#include <ghc/filesystem.hpp>
|
#include "filesystem.hpp"
|
||||||
#endif // GHC_FILESYSTEM_FWD_H
|
#endif // GHC_FILESYSTEM_FWD_H
|
||||||
|
|||||||
@ -25,11 +25,11 @@
|
|||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
// fs_impl.hpp - The implementation header for the header/implementation seperated usage of
|
// fs_impl.hpp - The implementation header for the header/implementation separated usage of
|
||||||
// ghc::filesystem.
|
// ghc::filesystem.
|
||||||
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
|
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
|
||||||
// The cpp has to include this before including fs_fwd.hpp directly or via a different
|
// The cpp has to include this before including fs_fwd.hpp directly or via a different
|
||||||
// header to work.
|
// header to work.
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
#define GHC_FILESYSTEM_IMPLEMENTATION
|
#define GHC_FILESYSTEM_IMPLEMENTATION
|
||||||
#include <ghc/filesystem.hpp>
|
#include "filesystem.hpp"
|
||||||
|
|||||||
@ -31,30 +31,47 @@
|
|||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
#ifndef GHC_FILESYSTEM_STD_H
|
#ifndef GHC_FILESYSTEM_STD_H
|
||||||
#define GHC_FILESYSTEM_STD_H
|
#define GHC_FILESYSTEM_STD_H
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include <Availability.h>
|
|
||||||
#endif
|
|
||||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
|
||||||
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
|
||||||
#define GHC_USE_STD_FS
|
|
||||||
#include <filesystem>
|
|
||||||
namespace fs {
|
|
||||||
using namespace std::filesystem;
|
|
||||||
using ifstream = std::ifstream;
|
|
||||||
using ofstream = std::ofstream;
|
|
||||||
using fstream = std::fstream;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifndef GHC_USE_STD_FS
|
|
||||||
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
|
|
||||||
#include <ghc/filesystem.hpp>
|
|
||||||
namespace fs {
|
|
||||||
using namespace ghc::filesystem;
|
|
||||||
using ifstream = ghc::filesystem::ifstream;
|
|
||||||
using ofstream = ghc::filesystem::ofstream;
|
|
||||||
using fstream = ghc::filesystem::fstream;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif // GHC_FILESYSTEM_STD_H
|
|
||||||
|
|
||||||
|
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
|
||||||
|
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
|
||||||
|
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
|
||||||
|
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
|
||||||
|
#define GHC_USE_STD_FS
|
||||||
|
|
||||||
|
// Old Apple OSs don't support std::filesystem, though the header is available at compile
|
||||||
|
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
|
||||||
|
// and watchOS 6.0.
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <Availability.h>
|
||||||
|
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
|
||||||
|
// released after std::filesystem, where std::filesystem is always available.
|
||||||
|
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
|
||||||
|
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|
||||||
|
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
|
||||||
|
#undef GHC_USE_STD_FS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GHC_USE_STD_FS
|
||||||
|
#include <filesystem>
|
||||||
|
namespace fs {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
using ifstream = std::ifstream;
|
||||||
|
using ofstream = std::ofstream;
|
||||||
|
using fstream = std::fstream;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include "filesystem.hpp"
|
||||||
|
namespace fs {
|
||||||
|
using namespace ghc::filesystem;
|
||||||
|
using ifstream = ghc::filesystem::ifstream;
|
||||||
|
using ofstream = ghc::filesystem::ofstream;
|
||||||
|
using fstream = ghc::filesystem::fstream;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // GHC_FILESYSTEM_STD_H
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
// fs_std_fwd.hpp - The forwarding header for the header/implementation seperated usage of
|
// fs_std_fwd.hpp - The forwarding header for the header/implementation separated usage of
|
||||||
// ghc::filesystem that uses std::filesystem if it detects it.
|
// ghc::filesystem that uses std::filesystem if it detects it.
|
||||||
// This file can be include at any place, where fs::filesystem api is needed while
|
// This file can be include at any place, where fs::filesystem api is needed while
|
||||||
// not bleeding implementation details (e.g. system includes) into the global namespace,
|
// not bleeding implementation details (e.g. system includes) into the global namespace,
|
||||||
@ -33,31 +33,47 @@
|
|||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
#ifndef GHC_FILESYSTEM_STD_FWD_H
|
#ifndef GHC_FILESYSTEM_STD_FWD_H
|
||||||
#define GHC_FILESYSTEM_STD_FWD_H
|
#define GHC_FILESYSTEM_STD_FWD_H
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include <Availability.h>
|
|
||||||
#endif
|
|
||||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
|
||||||
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
|
||||||
#define GHC_USE_STD_FS
|
|
||||||
#include <filesystem>
|
|
||||||
namespace fs {
|
|
||||||
using namespace std::filesystem;
|
|
||||||
using ifstream = std::ifstream;
|
|
||||||
using ofstream = std::ofstream;
|
|
||||||
using fstream = std::fstream;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifndef GHC_USE_STD_FS
|
|
||||||
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
|
|
||||||
#define GHC_FILESYSTEM_FWD
|
|
||||||
#include <ghc/filesystem.hpp>
|
|
||||||
namespace fs {
|
|
||||||
using namespace ghc::filesystem;
|
|
||||||
using ifstream = ghc::filesystem::ifstream;
|
|
||||||
using ofstream = ghc::filesystem::ofstream;
|
|
||||||
using fstream = ghc::filesystem::fstream;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif // GHC_FILESYSTEM_STD_FWD_H
|
|
||||||
|
|
||||||
|
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
|
||||||
|
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
|
||||||
|
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
|
||||||
|
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
|
||||||
|
#define GHC_USE_STD_FS
|
||||||
|
|
||||||
|
// Old Apple OSs don't support std::filesystem, though the header is available at compile
|
||||||
|
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
|
||||||
|
// and watchOS 6.0.
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <Availability.h>
|
||||||
|
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
|
||||||
|
// released after std::filesystem, where std::filesystem is always available.
|
||||||
|
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
|
||||||
|
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|
||||||
|
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
|
||||||
|
#undef GHC_USE_STD_FS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GHC_USE_STD_FS
|
||||||
|
#include <filesystem>
|
||||||
|
namespace fs {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
using ifstream = std::ifstream;
|
||||||
|
using ofstream = std::ofstream;
|
||||||
|
using fstream = std::fstream;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include "fs_fwd.hpp"
|
||||||
|
namespace fs {
|
||||||
|
using namespace ghc::filesystem;
|
||||||
|
using ifstream = ghc::filesystem::ifstream;
|
||||||
|
using ofstream = ghc::filesystem::ofstream;
|
||||||
|
using fstream = ghc::filesystem::fstream;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // GHC_FILESYSTEM_STD_FWD_H
|
||||||
|
|||||||
@ -25,22 +25,36 @@
|
|||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
// fs_std_impl.hpp - The implementation header for the header/implementation seperated usage of
|
// fs_std_impl.hpp - The implementation header for the header/implementation separated usage of
|
||||||
// ghc::filesystem that does nothing if std::filesystem is detected.
|
// ghc::filesystem that does nothing if std::filesystem is detected.
|
||||||
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
|
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
|
||||||
// The cpp has to include this before including fs_std_fwd.hpp directly or via a different
|
// The cpp has to include this before including fs_std_fwd.hpp directly or via a different
|
||||||
// header to work.
|
// header to work.
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
#if defined(__APPLE__)
|
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
|
||||||
#include <Availability.h>
|
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
|
||||||
#endif
|
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
|
||||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
|
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
|
||||||
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
|
#define GHC_USE_STD_FS
|
||||||
#define GHC_USE_STD_FS
|
|
||||||
#endif
|
// Old Apple OSs don't support std::filesystem, though the header is available at compile
|
||||||
|
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
|
||||||
|
// and watchOS 6.0.
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <Availability.h>
|
||||||
|
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
|
||||||
|
// released after std::filesystem, where std::filesystem is always available.
|
||||||
|
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
|
||||||
|
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|
||||||
|
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|
||||||
|
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
|
||||||
|
#undef GHC_USE_STD_FS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GHC_USE_STD_FS
|
#ifndef GHC_USE_STD_FS
|
||||||
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
|
#include "fs_impl.hpp"
|
||||||
#define GHC_FILESYSTEM_IMPLEMENTATION
|
|
||||||
#include <ghc/filesystem.hpp>
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -3,6 +3,20 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
|||||||
set(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS ON)
|
set(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS ON)
|
||||||
include(ParseAndAddCatchTests)
|
include(ParseAndAddCatchTests)
|
||||||
|
|
||||||
|
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND UNIX AND NOT APPLE AND NOT BSD)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "-lc++abi")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
function(SetTestCompileOptions target_name)
|
||||||
|
target_compile_options(${target_name} PRIVATE
|
||||||
|
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
|
||||||
|
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror -Wno-deprecated-declarations>
|
||||||
|
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror -Wno-deprecated-declarations>
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/WX /wd4996>
|
||||||
|
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
if(GHC_COVERAGE)
|
if(GHC_COVERAGE)
|
||||||
message("Generating test runner for coverage run...")
|
message("Generating test runner for coverage run...")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMCMAKE_EXE_LINKER_FLAGS} --coverage")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMCMAKE_EXE_LINKER_FLAGS} --coverage")
|
||||||
@ -13,6 +27,12 @@ if(GHC_COVERAGE)
|
|||||||
target_compile_options(filesystem_test PUBLIC --coverage)
|
target_compile_options(filesystem_test PUBLIC --coverage)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(filesystem_test PUBLIC ghc_filesystem --coverage)
|
target_link_libraries(filesystem_test PUBLIC ghc_filesystem --coverage)
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||||
|
target_link_libraries(filesystem_test PUBLIC xnet)
|
||||||
|
endif()
|
||||||
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||||
|
target_link_libraries(filesystem_test PUBLIC network)
|
||||||
|
endif()
|
||||||
if("cxx_std_17" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
|
if("cxx_std_17" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
|
||||||
AddTestExecutableWithStdCpp(17 filesystem_test.cpp catch.hpp)
|
AddTestExecutableWithStdCpp(17 filesystem_test.cpp catch.hpp)
|
||||||
endif()
|
endif()
|
||||||
@ -23,12 +43,13 @@ 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)
|
||||||
target_compile_options(filesystem_test PRIVATE
|
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||||
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
|
target_link_libraries(filesystem_test xnet)
|
||||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
|
endif()
|
||||||
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror>
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:/WX>
|
target_link_libraries(filesystem_test network)
|
||||||
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
|
endif()
|
||||||
|
SetTestCompileOptions(filesystem_test)
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
|
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||||
endif()
|
endif()
|
||||||
@ -42,10 +63,7 @@ else()
|
|||||||
if(WIN32)
|
if(WIN32)
|
||||||
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)
|
||||||
target_compile_options(filesystem_test_char PRIVATE
|
SetTestCompileOptions(filesystem_test_char)
|
||||||
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Werror>
|
|
||||||
$<$<CXX_COMPILER_ID:GNU>:-Wall -Werror>
|
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:/WX>)
|
|
||||||
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()
|
||||||
@ -67,12 +85,13 @@ add_test(multifile_test multifile_test)
|
|||||||
|
|
||||||
add_executable(fwd_impl_test fwd_test.cpp impl_test.cpp)
|
add_executable(fwd_impl_test fwd_test.cpp impl_test.cpp)
|
||||||
target_link_libraries(fwd_impl_test ghc_filesystem)
|
target_link_libraries(fwd_impl_test ghc_filesystem)
|
||||||
target_compile_options(fwd_impl_test PRIVATE
|
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
|
||||||
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
|
target_link_libraries(fwd_impl_test xnet)
|
||||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
|
endif()
|
||||||
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror>
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:/WX>
|
target_link_libraries(fwd_impl_test network)
|
||||||
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
|
endif()
|
||||||
|
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()
|
||||||
@ -83,9 +102,4 @@ if(NOT MSVC)
|
|||||||
target_compile_options(exception PRIVATE -fno-exceptions)
|
target_compile_options(exception PRIVATE -fno-exceptions)
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(exception PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include)
|
target_include_directories(exception PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include)
|
||||||
target_compile_options(exception PRIVATE
|
SetTestCompileOptions(exception)
|
||||||
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
|
|
||||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
|
|
||||||
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror>
|
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:/WX>
|
|
||||||
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
|
|
||||||
|
|||||||
7827
test/catch.hpp
7827
test/catch.hpp
File diff suppressed because it is too large
Load Diff
@ -99,7 +99,7 @@ using fstream = ghc::filesystem::fstream;
|
|||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
template <typename TP>
|
template <typename TP>
|
||||||
std::time_t to_time_t(TP tp)
|
static std::time_t to_time_t(TP tp)
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now() + system_clock::now());
|
auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now() + system_clock::now());
|
||||||
@ -107,7 +107,7 @@ std::time_t to_time_t(TP tp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TP>
|
template <typename TP>
|
||||||
TP from_time_t(std::time_t t)
|
static TP from_time_t(std::time_t t)
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
auto sctp = system_clock::from_time_t(t);
|
auto sctp = system_clock::from_time_t(t);
|
||||||
@ -214,7 +214,8 @@ static void generateFile(const fs::path& pathname, int withSize = -1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GHC_OS_WINDOWS
|
#ifdef GHC_OS_WINDOWS
|
||||||
inline bool isWow64Proc()
|
#if !defined(_WIN64) && defined(KEY_WOW64_64KEY)
|
||||||
|
static bool isWow64Proc()
|
||||||
{
|
{
|
||||||
typedef BOOL(WINAPI * IsWow64Process_t)(HANDLE, PBOOL);
|
typedef BOOL(WINAPI * IsWow64Process_t)(HANDLE, PBOOL);
|
||||||
BOOL bIsWow64 = FALSE;
|
BOOL bIsWow64 = FALSE;
|
||||||
@ -226,6 +227,7 @@ inline bool isWow64Proc()
|
|||||||
}
|
}
|
||||||
return bIsWow64 == TRUE;
|
return bIsWow64 == TRUE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool is_symlink_creation_supported()
|
static bool is_symlink_creation_supported()
|
||||||
{
|
{
|
||||||
@ -303,13 +305,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
bool operator==(TestAllocator<T> const&, TestAllocator<U> const&) noexcept
|
static bool operator==(TestAllocator<T> const&, TestAllocator<U> const&) noexcept
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
bool operator!=(TestAllocator<T> const& x, TestAllocator<U> const& y) noexcept
|
static bool operator!=(TestAllocator<T> const& x, TestAllocator<U> const& y) noexcept
|
||||||
{
|
{
|
||||||
return !(x == y);
|
return !(x == y);
|
||||||
}
|
}
|
||||||
@ -790,6 +792,9 @@ TEST_CASE("fs.path.decompose - path decomposition", "[filesystem][path][fs.path.
|
|||||||
CHECK(fs::path("C:/foo").filename() == "foo");
|
CHECK(fs::path("C:/foo").filename() == "foo");
|
||||||
CHECK(fs::path("C:\\foo").filename() == "foo");
|
CHECK(fs::path("C:\\foo").filename() == "foo");
|
||||||
CHECK(fs::path("C:foo").filename() == "foo");
|
CHECK(fs::path("C:foo").filename() == "foo");
|
||||||
|
CHECK(fs::path("t:est.txt").filename() == "est.txt");
|
||||||
|
#else
|
||||||
|
CHECK(fs::path("t:est.txt").filename() == "t:est.txt");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// stem()
|
// stem()
|
||||||
@ -807,6 +812,13 @@ TEST_CASE("fs.path.decompose - path decomposition", "[filesystem][path][fs.path.
|
|||||||
CHECK(fs::path("/foo/.profile").stem() == ".profile");
|
CHECK(fs::path("/foo/.profile").stem() == ".profile");
|
||||||
CHECK(fs::path(".bar").stem() == ".bar");
|
CHECK(fs::path(".bar").stem() == ".bar");
|
||||||
CHECK(fs::path("..bar").stem() == ".");
|
CHECK(fs::path("..bar").stem() == ".");
|
||||||
|
#ifdef GHC_OS_WINDOWS
|
||||||
|
CHECK(fs::path("t:est.txt").stem() == "est");
|
||||||
|
#else
|
||||||
|
CHECK(fs::path("t:est.txt").stem() == "t:est");
|
||||||
|
#endif
|
||||||
|
CHECK(fs::path("/foo/.").stem() == ".");
|
||||||
|
CHECK(fs::path("/foo/..").stem() == "..");
|
||||||
|
|
||||||
// extension()
|
// extension()
|
||||||
CHECK(fs::path("/foo/bar.txt").extension() == ".txt");
|
CHECK(fs::path("/foo/bar.txt").extension() == ".txt");
|
||||||
@ -814,6 +826,9 @@ TEST_CASE("fs.path.decompose - path decomposition", "[filesystem][path][fs.path.
|
|||||||
CHECK(fs::path("/foo/.profile").extension() == "");
|
CHECK(fs::path("/foo/.profile").extension() == "");
|
||||||
CHECK(fs::path(".bar").extension() == "");
|
CHECK(fs::path(".bar").extension() == "");
|
||||||
CHECK(fs::path("..bar").extension() == ".bar");
|
CHECK(fs::path("..bar").extension() == ".bar");
|
||||||
|
CHECK(fs::path("t:est.txt").extension() == ".txt");
|
||||||
|
CHECK(fs::path("/foo/.").extension() == "");
|
||||||
|
CHECK(fs::path("/foo/..").extension() == "");
|
||||||
|
|
||||||
if (has_host_root_name_support()) {
|
if (has_host_root_name_support()) {
|
||||||
// //host-based root-names
|
// //host-based root-names
|
||||||
@ -950,6 +965,10 @@ TEST_CASE("fs.path.gen - path generation", "[filesystem][path][fs.path.gen]")
|
|||||||
// lexically_relative()
|
// lexically_relative()
|
||||||
CHECK(fs::path("/a/d").lexically_relative("/a/b/c") == "../../d");
|
CHECK(fs::path("/a/d").lexically_relative("/a/b/c") == "../../d");
|
||||||
CHECK(fs::path("/a/b/c").lexically_relative("/a/d") == "../b/c");
|
CHECK(fs::path("/a/b/c").lexically_relative("/a/d") == "../b/c");
|
||||||
|
CHECK(fs::path("/a/b/c").lexically_relative("/a/b/c/d/..") == ".");
|
||||||
|
CHECK(fs::path("/a/b/c/").lexically_relative("/a/b/c/d/..") == ".");
|
||||||
|
CHECK(fs::path("").lexically_relative("/a/..") == "");
|
||||||
|
CHECK(fs::path("").lexically_relative("a/..") == ".");
|
||||||
CHECK(fs::path("a/b/c").lexically_relative("a") == "b/c");
|
CHECK(fs::path("a/b/c").lexically_relative("a") == "b/c");
|
||||||
CHECK(fs::path("a/b/c").lexically_relative("a/b/c/x/y") == "../..");
|
CHECK(fs::path("a/b/c").lexically_relative("a/b/c/x/y") == "../..");
|
||||||
CHECK(fs::path("a/b/c").lexically_relative("a/b/c") == ".");
|
CHECK(fs::path("a/b/c").lexically_relative("a/b/c") == ".");
|
||||||
@ -1199,7 +1218,7 @@ TEST_CASE("fs.class.filesystem_error - class filesystem_error", "[filesystem][fi
|
|||||||
CHECK(fse.path2() == "some/other");
|
CHECK(fse.path2() == "some/other");
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr fs::perms constExprOwnerAll()
|
static constexpr fs::perms constExprOwnerAll()
|
||||||
{
|
{
|
||||||
return fs::perms::owner_read | fs::perms::owner_write | fs::perms::owner_exec;
|
return fs::perms::owner_read | fs::perms::owner_write | fs::perms::owner_exec;
|
||||||
}
|
}
|
||||||
@ -1377,6 +1396,16 @@ TEST_CASE("fs.dir.entry - class directory_entry", "[filesystem][directory_entry]
|
|||||||
CHECK(!(d2 != d2));
|
CHECK(!(d2 != d2));
|
||||||
CHECK(d1 == d1);
|
CHECK(d1 == d1);
|
||||||
CHECK(!(d1 == d2));
|
CHECK(!(d1 == d2));
|
||||||
|
if(is_symlink_creation_supported()) {
|
||||||
|
fs::create_symlink(t.path() / "nonexistent", t.path() / "broken");
|
||||||
|
for (auto d3 : fs::directory_iterator(t.path())) {
|
||||||
|
CHECK_NOTHROW(d3.symlink_status());
|
||||||
|
CHECK_NOTHROW(d3.status());
|
||||||
|
CHECK_NOTHROW(d3.refresh());
|
||||||
|
}
|
||||||
|
fs::directory_entry entry(t.path() / "broken");
|
||||||
|
CHECK_NOTHROW(entry.refresh());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("fs.class.directory_iterator - class directory_iterator", "[filesystem][directory_iterator][fs.class.directory_iterator]")
|
TEST_CASE("fs.class.directory_iterator - class directory_iterator", "[filesystem][directory_iterator][fs.class.directory_iterator]")
|
||||||
@ -1778,6 +1807,19 @@ TEST_CASE("fs.op.copy_file - copy_file", "[filesystem][operations][fs.op.copy_fi
|
|||||||
CHECK_NOTHROW(fs::copy_file("foobar", "foobar2", ec));
|
CHECK_NOTHROW(fs::copy_file("foobar", "foobar2", ec));
|
||||||
CHECK(ec);
|
CHECK(ec);
|
||||||
CHECK(!fs::exists("foobar"));
|
CHECK(!fs::exists("foobar"));
|
||||||
|
fs::path file1("temp1.txt");
|
||||||
|
fs::path file2("temp2.txt");
|
||||||
|
generateFile(file1, 200);
|
||||||
|
generateFile(file2, 200);
|
||||||
|
auto allWrite = fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write;
|
||||||
|
CHECK_NOTHROW(fs::permissions(file1, allWrite, fs::perm_options::remove));
|
||||||
|
CHECK((fs::status(file1).permissions() & fs::perms::owner_write) != fs::perms::owner_write);
|
||||||
|
CHECK_NOTHROW(fs::permissions(file2, allWrite, fs::perm_options::add));
|
||||||
|
CHECK((fs::status(file2).permissions() & fs::perms::owner_write) == fs::perms::owner_write);
|
||||||
|
fs::copy_file(file1, file2, fs::copy_options::overwrite_existing);
|
||||||
|
CHECK((fs::status(file2).permissions() & fs::perms::owner_write) != fs::perms::owner_write);
|
||||||
|
CHECK_NOTHROW(fs::permissions(file1, allWrite, fs::perm_options::add));
|
||||||
|
CHECK_NOTHROW(fs::permissions(file2, allWrite, fs::perm_options::add));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("fs.op.copy_symlink - copy_symlink", "[filesystem][operations][fs.op.copy_symlink]")
|
TEST_CASE("fs.op.copy_symlink - copy_symlink", "[filesystem][operations][fs.op.copy_symlink]")
|
||||||
@ -2163,6 +2205,7 @@ public:
|
|||||||
|
|
||||||
fs::path character_path() const
|
fs::path character_path() const
|
||||||
{
|
{
|
||||||
|
#ifndef GHC_OS_SOLARIS
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
if (fs::exists("/dev/null", ec)) {
|
if (fs::exists("/dev/null", ec)) {
|
||||||
return "/dev/null";
|
return "/dev/null";
|
||||||
@ -2170,6 +2213,7 @@ public:
|
|||||||
else if (fs::exists("NUL", ec)) {
|
else if (fs::exists("NUL", ec)) {
|
||||||
return "NUL";
|
return "NUL";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return fs::path();
|
return fs::path();
|
||||||
}
|
}
|
||||||
fs::path temp_path() const { return _t.path(); }
|
fs::path temp_path() const { return _t.path(); }
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
#include <ghc/filesystem.hpp>
|
#include <ghc/filesystem.hpp>
|
||||||
namespace fs = ghc::filesystem;
|
namespace fs = ghc::filesystem;
|
||||||
|
|
||||||
// This test and the one in multi2.cpp doesn't actualy test relevant functionality,
|
// This test and the one in multi2.cpp doesn't actually test relevant functionality,
|
||||||
// it is just used to check that it is possible to include filesystem.h in multiple
|
// it is just used to check that it is possible to include filesystem.h in multiple
|
||||||
// source files.
|
// source files.
|
||||||
TEST_CASE("Multifile-test 1", "[multi]")
|
TEST_CASE("Multifile-test 1", "[multi]")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user