WPILibC++ 2023.4.3
filesystem.hpp
Go to the documentation of this file.
1//---------------------------------------------------------------------------------------
2//
3// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14/C++17/C++20
4//
5//---------------------------------------------------------------------------------------
6//
7// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
8//
9// Permission is hereby granted, free of charge, to any person obtaining a copy
10// of this software and associated documentation files (the "Software"), to deal
11// in the Software without restriction, including without limitation the rights
12// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the Software is
14// furnished to do so, subject to the following conditions:
15//
16// The above copyright notice and this permission notice shall be included in all
17// copies or substantial portions of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25// SOFTWARE.
26//
27//---------------------------------------------------------------------------------------
28//
29// To dynamically select std::filesystem where available on most platforms,
30// you could use:
31//
32// #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
33// #if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
34// #define GHC_USE_STD_FS
35// #include <filesystem>
36// namespace fs = std::filesystem;
37// #endif
38// #endif
39// #ifndef GHC_USE_STD_FS
40// #include <ghc/filesystem.hpp>
41// namespace fs = ghc::filesystem;
42// #endif
43//
44//---------------------------------------------------------------------------------------
45#ifndef GHC_FILESYSTEM_H
46#define GHC_FILESYSTEM_H
47
48// #define BSD manifest constant only in
49// sys/param.h
50#ifndef _WIN32
51#include <sys/param.h>
52#endif
53
54#ifndef GHC_OS_DETECTED
55#if defined(__APPLE__) && defined(__MACH__)
56#define GHC_OS_MACOS
57#elif defined(__linux__)
58#define GHC_OS_LINUX
59#if defined(__ANDROID__)
60#define GHC_OS_ANDROID
61#endif
62#elif defined(_WIN64)
63#define GHC_OS_WINDOWS
64#define GHC_OS_WIN64
65#elif defined(_WIN32)
66#define GHC_OS_WINDOWS
67#define GHC_OS_WIN32
68#elif defined(__CYGWIN__)
69#define GHC_OS_CYGWIN
70#elif defined(__svr4__)
71#define GHC_OS_SYS5R4
72#elif defined(BSD)
73#define GHC_OS_BSD
74#elif defined(__EMSCRIPTEN__)
75#define GHC_OS_WEB
76#include <wasi/api.h>
77#elif defined(__QNX__)
78#define GHC_OS_QNX
79#define GHC_NO_DIRENT_D_TYPE
80#else
81#error "Operating system currently not supported!"
82#endif
83#define GHC_OS_DETECTED
84#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
85#if _MSVC_LANG == 201703L
86#define GHC_FILESYSTEM_RUNNING_CPP17
87#else
88#define GHC_FILESYSTEM_RUNNING_CPP20
89#endif
90#elif (defined(__cplusplus) && __cplusplus >= 201703L)
91#if __cplusplus == 201703L
92#define GHC_FILESYSTEM_RUNNING_CPP17
93#else
94#define GHC_FILESYSTEM_RUNNING_CPP20
95#endif
96#endif
97#endif
98
99#if defined(GHC_FILESYSTEM_IMPLEMENTATION)
100#define GHC_EXPAND_IMPL
101#define GHC_INLINE
102#ifdef GHC_OS_WINDOWS
103#ifndef GHC_FS_API
104#define GHC_FS_API
105#endif
106#ifndef GHC_FS_API_CLASS
107#define GHC_FS_API_CLASS
108#endif
109#else
110#ifndef GHC_FS_API
111#define GHC_FS_API __attribute__((visibility("default")))
112#endif
113#ifndef GHC_FS_API_CLASS
114#define GHC_FS_API_CLASS __attribute__((visibility("default")))
115#endif
116#endif
117#elif defined(GHC_FILESYSTEM_FWD)
118#define GHC_INLINE
119#ifdef GHC_OS_WINDOWS
120#ifndef GHC_FS_API
121#define GHC_FS_API extern
122#endif
123#ifndef GHC_FS_API_CLASS
124#define GHC_FS_API_CLASS
125#endif
126#else
127#ifndef GHC_FS_API
128#define GHC_FS_API extern
129#endif
130#ifndef GHC_FS_API_CLASS
131#define GHC_FS_API_CLASS
132#endif
133#endif
134#else
135#define GHC_EXPAND_IMPL
136#define GHC_INLINE inline
137#ifndef GHC_FS_API
138#define GHC_FS_API
139#endif
140#ifndef GHC_FS_API_CLASS
141#define GHC_FS_API_CLASS
142#endif
143#endif
144
145#ifdef GHC_EXPAND_IMPL
146
147#ifdef GHC_OS_WINDOWS
148#include <windows.h>
149// additional includes
150#include <shellapi.h>
151#include <sys/stat.h>
152#include <sys/types.h>
153#include <wchar.h>
154#include <winioctl.h>
155#else
156#include <dirent.h>
157#include <fcntl.h>
158#include <limits.h>
159#include <sys/param.h>
160#include <sys/stat.h>
161#include <sys/time.h>
162#include <sys/types.h>
163#include <unistd.h>
164#ifdef GHC_OS_ANDROID
165#include <android/api-level.h>
166#if __ANDROID_API__ < 12
167#include <sys/syscall.h>
168#endif
169#include <sys/vfs.h>
170#define statvfs statfs
171#else
172#include <sys/statvfs.h>
173#endif
174#ifdef GHC_OS_CYGWIN
175#include <strings.h>
176#endif
177#if !defined(__ANDROID__) || __ANDROID_API__ >= 26
178#include <langinfo.h>
179#endif
180#endif
181#ifdef GHC_OS_MACOS
182#include <Availability.h>
183#endif
184
185#if defined(__cpp_impl_three_way_comparison) && defined(__has_include)
186#if __has_include(<compare>)
187#define GHC_HAS_THREEWAY_COMP
188#include <compare>
189#endif
190#endif
191
192#include <algorithm>
193#include <cctype>
194#include <chrono>
195#include <clocale>
196#include <cstdlib>
197#include <cstring>
198#include <fstream>
199#include <functional>
200#include <memory>
201#include <stack>
202#include <stdexcept>
203#include <string>
204#include <system_error>
205#include <type_traits>
206#include <utility>
207#include <vector>
208
209#else // GHC_EXPAND_IMPL
210
211#if defined(__cpp_impl_three_way_comparison) && defined(__has_include)
212#if __has_include(<compare>)
213#define GHC_HAS_THREEWAY_COMP
214#include <compare>
215#endif
216#endif
217#include <chrono>
218#include <fstream>
219#include <memory>
220#include <stack>
221#include <stdexcept>
222#include <string>
223#include <system_error>
224#ifdef GHC_OS_WINDOWS
225#include <vector>
226#endif
227#endif // GHC_EXPAND_IMPL
228
229// After standard library includes.
230// Standard library support for std::string_view.
231#if defined(__cpp_lib_string_view)
232#define GHC_HAS_STD_STRING_VIEW
233#elif defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 4000) && (__cplusplus >= 201402)
234#define GHC_HAS_STD_STRING_VIEW
235#elif defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE >= 7) && (__cplusplus >= 201703)
236#define GHC_HAS_STD_STRING_VIEW
237#elif defined(_MSC_VER) && (_MSC_VER >= 1910 && _MSVC_LANG >= 201703)
238#define GHC_HAS_STD_STRING_VIEW
239#endif
240
241// Standard library support for std::experimental::string_view.
242#if defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 3700 && _LIBCPP_VERSION < 7000) && (__cplusplus >= 201402)
243#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW
244#elif defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)) && (__cplusplus >= 201402)
245#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW
246#elif defined(__GLIBCXX__) && defined(_GLIBCXX_USE_DUAL_ABI) && (__cplusplus >= 201402)
247// macro _GLIBCXX_USE_DUAL_ABI is always defined in libstdc++ from gcc-5 and newer
248#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW
249#endif
250
251#if defined(GHC_HAS_STD_STRING_VIEW)
252#include <string_view>
253#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW)
254#include <experimental/string_view>
255#endif
256
257//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
258// Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp):
259//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
260// Enforce C++17 API where possible when compiling for C++20, handles the following cases:
261// * fs::path::u8string() returns std::string instead of std::u8string
262// #define GHC_FILESYSTEM_ENFORCE_CPP17_API
263//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
264// LWG #2682 disables the since then invalid use of the copy option create_symlinks on directories
265// configure LWG conformance ()
266#define LWG_2682_BEHAVIOUR
267//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
268// LWG #2395 makes crate_directory/create_directories not emit an error if there is a regular
269// file with that name, it is superseded by P1164R1, so only activate if really needed
270// #define LWG_2935_BEHAVIOUR
271//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
272// LWG #2936 enables new element wise (more expensive) path comparison
273// * if this->root_name().native().compare(p.root_name().native()) != 0 return result
274// * if this->has_root_directory() and !p.has_root_directory() return -1
275// * if !this->has_root_directory() and p.has_root_directory() return -1
276// * else result of element wise comparison of path iteration where first comparison is != 0 or 0
277// if all comparisons are 0 (on Windows this implementation does case insensitive root_name()
278// comparison)
279#define LWG_2936_BEHAVIOUR
280//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
281// LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2)
282#define LWG_2937_BEHAVIOUR
283//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
284// UTF8-Everywhere is the original behaviour of ghc::filesystem. But since v1.5 the windows
285// version defaults to std::wstring storage backend. Still all std::string will be interpreted
286// as UTF-8 encoded. With this define you can enfoce the old behavior on Windows, using
287// std::string as backend and for fs::path::native() and char for fs::path::c_str(). This
288// needs more conversions so it is (an was before v1.5) slower, bot might help keeping source
289// homogeneous in a multi platform project.
290// #define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
291//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
292// Raise errors/exceptions when invalid unicode codepoints or UTF-8 sequences are found,
293// instead of replacing them with the unicode replacement character (U+FFFD).
294// #define GHC_RAISE_UNICODE_ERRORS
295//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
296// Automatic prefix windows path with "\\?\" if they would break the MAX_PATH length.
297// instead of replacing them with the unicode replacement character (U+FFFD).
298#ifndef GHC_WIN_DISABLE_AUTO_PREFIXES
299#define GHC_WIN_AUTO_PREFIX_LONG_PATH
300#endif // GHC_WIN_DISABLE_AUTO_PREFIXES
301//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
302
303// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
304#define GHC_FILESYSTEM_VERSION 10506L
305
306#if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND))
307#define GHC_WITH_EXCEPTIONS
308#endif
309#if !defined(GHC_WITH_EXCEPTIONS) && defined(GHC_RAISE_UNICODE_ERRORS)
310#error "Can't raise unicode errors with exception support disabled"
311#endif
312
313namespace ghc {
314namespace filesystem {
315
316#if defined(GHC_HAS_CUSTOM_STRING_VIEW)
317#define GHC_WITH_STRING_VIEW
318#elif defined(GHC_HAS_STD_STRING_VIEW)
319#define GHC_WITH_STRING_VIEW
320using std::basic_string_view;
321#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW)
322#define GHC_WITH_STRING_VIEW
323using std::experimental::basic_string_view;
324#endif
325
326// temporary existing exception type for yet unimplemented parts
327class GHC_FS_API_CLASS not_implemented_exception : public std::logic_error
328{
329public:
331 : std::logic_error("function not implemented yet.")
332 {
333 }
334};
335
336template <typename char_type>
338{
339public:
341#ifdef GHC_OS_WINDOWS
342 static constexpr value_type preferred_separator = '\\';
343#else
344 static constexpr value_type preferred_separator = '/';
345#endif
346};
347
348#if __cplusplus < 201703L
349template <typename char_type>
351#endif
352
353#ifdef GHC_OS_WINDOWS
354class path;
355namespace detail {
356bool has_executable_extension(const path& p);
357}
358#endif
359
360// [fs.class.path] class path
362#if defined(GHC_OS_WINDOWS) && !defined(GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE)
363#define GHC_USE_WCHAR_T
364#define GHC_NATIVEWP(p) p.c_str()
365#define GHC_PLATFORM_LITERAL(str) L##str
367{
368public:
369 using path_helper_base<std::wstring::value_type>::value_type;
370#else
371#define GHC_NATIVEWP(p) p.wstring().c_str()
372#define GHC_PLATFORM_LITERAL(str) str
374{
375public:
376 using path_helper_base<std::string::value_type>::value_type;
377#endif
378 using string_type = std::basic_string<value_type>;
379 using path_helper_base<value_type>::preferred_separator;
380
381 // [fs.enum.path.format] enumeration format
382 /// The path format in which the constructor argument is given.
383 enum format {
384 generic_format, ///< The generic format, internally used by
385 ///< ghc::filesystem::path with slashes
386 native_format, ///< The format native to the current platform this code
387 ///< is build for
388 auto_format, ///< Try to auto-detect the format, fallback to native
389 };
390
391 template <class T>
392 struct _is_basic_string : std::false_type
393 {
394 };
395 template <class CharT, class Traits, class Alloc>
396 struct _is_basic_string<std::basic_string<CharT, Traits, Alloc>> : std::true_type
397 {
398 };
399 template <class CharT>
400 struct _is_basic_string<std::basic_string<CharT, std::char_traits<CharT>, std::allocator<CharT>>> : std::true_type
401 {
402 };
403#ifdef GHC_WITH_STRING_VIEW
404 template <class CharT, class Traits>
405 struct _is_basic_string<basic_string_view<CharT, Traits>> : std::true_type
406 {
407 };
408 template <class CharT>
409 struct _is_basic_string<basic_string_view<CharT, std::char_traits<CharT>>> : std::true_type
410 {
411 };
412#endif
413
414 template <typename T1, typename T2 = void>
415 using path_type = typename std::enable_if<!std::is_same<path, T1>::value, path>::type;
416 template <typename T>
417#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
418 using path_from_string =
423 path>::type;
424 template <typename T>
425 using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char8_t>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value, path>::type;
426#else
430 path>::type;
431 template <typename T>
432 using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value, path>::type;
433#endif
434 // [fs.path.construct] constructors and destructor
435 path() noexcept;
436 path(const path& p);
437 path(path&& p) noexcept;
438 path(string_type&& source, format fmt = auto_format);
439 template <class Source, typename = path_from_string<Source>>
440 path(const Source& source, format fmt = auto_format);
441 template <class InputIterator>
442 path(InputIterator first, InputIterator last, format fmt = auto_format);
443#ifdef GHC_WITH_EXCEPTIONS
444 template <class Source, typename = path_from_string<Source>>
445 path(const Source& source, const std::locale& loc, format fmt = auto_format);
446 template <class InputIterator>
447 path(InputIterator first, InputIterator last, const std::locale& loc, format fmt = auto_format);
448#endif
449 ~path();
450
451 // [fs.path.assign] assignments
452 path& operator=(const path& p);
453 path& operator=(path&& p) noexcept;
454 path& operator=(string_type&& source);
455 path& assign(string_type&& source);
456 template <class Source>
457 path& operator=(const Source& source);
458 template <class Source>
459 path& assign(const Source& source);
460 template <class InputIterator>
461 path& assign(InputIterator first, InputIterator last);
462
463 // [fs.path.append] appends
464 path& operator/=(const path& p);
465 template <class Source>
466 path& operator/=(const Source& source);
467 template <class Source>
468 path& append(const Source& source);
469 template <class InputIterator>
470 path& append(InputIterator first, InputIterator last);
471
472 // [fs.path.concat] concatenation
473 path& operator+=(const path& x);
474 path& operator+=(const string_type& x);
475#ifdef GHC_WITH_STRING_VIEW
477#endif
478 path& operator+=(const value_type* x);
480 template <class Source>
481 path_from_string<Source>& operator+=(const Source& x);
482 template <class EcharT>
484 template <class Source>
485 path& concat(const Source& x);
486 template <class InputIterator>
487 path& concat(InputIterator first, InputIterator last);
488
489 // [fs.path.modifiers] modifiers
490 void clear() noexcept;
491 path& make_preferred();
492 path& remove_filename();
493 path& replace_filename(const path& replacement);
494 path& replace_extension(const path& replacement = path());
495 void swap(path& rhs) noexcept;
496
497 // [fs.path.native.obs] native format observers
498 const string_type& native() const noexcept;
499 const value_type* c_str() const noexcept;
500 operator string_type() const;
501 template <class EcharT, class traits = std::char_traits<EcharT>, class Allocator = std::allocator<EcharT>>
502 std::basic_string<EcharT, traits, Allocator> string(const Allocator& a = Allocator()) const;
503 std::string string() const;
504 std::wstring wstring() const;
505#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
506 std::u8string u8string() const;
507#else
508 std::string u8string() const;
509#endif
510 std::u16string u16string() const;
511 std::u32string u32string() const;
512
513 // [fs.path.generic.obs] generic format observers
514 template <class EcharT, class traits = std::char_traits<EcharT>, class Allocator = std::allocator<EcharT>>
515 std::basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const;
516 std::string generic_string() const;
517 std::wstring generic_wstring() const;
518#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
519 std::u8string generic_u8string() const;
520#else
521 std::string generic_u8string() const;
522#endif
523 std::u16string generic_u16string() const;
524 std::u32string generic_u32string() const;
525
526 // [fs.path.compare] compare
527 int compare(const path& p) const noexcept;
528 int compare(const string_type& s) const;
529#ifdef GHC_WITH_STRING_VIEW
530 int compare(basic_string_view<value_type> s) const;
531#endif
532 int compare(const value_type* s) const;
533
534 // [fs.path.decompose] decomposition
535 path root_name() const;
536 path root_directory() const;
537 path root_path() const;
538 path relative_path() const;
539 path parent_path() const;
540 path filename() const;
541 path stem() const;
542 path extension() const;
543
544 // [fs.path.query] query
545 bool empty() const noexcept;
546 bool has_root_name() const;
547 bool has_root_directory() const;
548 bool has_root_path() const;
549 bool has_relative_path() const;
550 bool has_parent_path() const;
551 bool has_filename() const;
552 bool has_stem() const;
553 bool has_extension() const;
554 bool is_absolute() const;
555 bool is_relative() const;
556
557 // [fs.path.gen] generation
558 path lexically_normal() const;
559 path lexically_relative(const path& base) const;
560 path lexically_proximate(const path& base) const;
561
562 // [fs.path.itr] iterators
563 class iterator;
564 using const_iterator = iterator;
565 iterator begin() const;
566 iterator end() const;
567
568private:
570 using impl_string_type = std::basic_string<impl_value_type>;
571 friend class directory_iterator;
572 void append_name(const value_type* name);
573 static constexpr impl_value_type generic_separator = '/';
574 template <typename InputIterator>
575 class input_iterator_range
576 {
577 public:
578 typedef InputIterator iterator;
579 typedef InputIterator const_iterator;
580 typedef typename InputIterator::difference_type difference_type;
581
582 input_iterator_range(const InputIterator& first, const InputIterator& last)
583 : _first(first)
584 , _last(last)
585 {
586 }
587
588 InputIterator begin() const { return _first; }
589 InputIterator end() const { return _last; }
590
591 private:
592 InputIterator _first;
593 InputIterator _last;
594 };
595 friend void swap(path& lhs, path& rhs) noexcept;
596 friend size_t hash_value(const path& p) noexcept;
597 friend path canonical(const path& p, std::error_code& ec);
598 string_type::size_type root_name_length() const noexcept;
599 void postprocess_path_with_format(format fmt);
600 void check_long_path();
601 impl_string_type _path;
602#ifdef GHC_OS_WINDOWS
603 void handle_prefixes();
604 friend bool detail::has_executable_extension(const path& p);
605#ifdef GHC_WIN_AUTO_PREFIX_LONG_PATH
606 string_type::size_type _prefixLength{0};
607#else // GHC_WIN_AUTO_PREFIX_LONG_PATH
608 static const string_type::size_type _prefixLength{0};
609#endif // GHC_WIN_AUTO_PREFIX_LONG_PATH
610#else
611 static const string_type::size_type _prefixLength{0};
612#endif
613};
614
615// [fs.path.nonmember] path non-member functions
616GHC_FS_API void swap(path& lhs, path& rhs) noexcept;
617GHC_FS_API size_t hash_value(const path& p) noexcept;
618#ifdef GHC_HAS_THREEWAY_COMP
619GHC_FS_API std::strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept;
620#endif
621GHC_FS_API bool operator==(const path& lhs, const path& rhs) noexcept;
622GHC_FS_API bool operator!=(const path& lhs, const path& rhs) noexcept;
623GHC_FS_API bool operator<(const path& lhs, const path& rhs) noexcept;
624GHC_FS_API bool operator<=(const path& lhs, const path& rhs) noexcept;
625GHC_FS_API bool operator>(const path& lhs, const path& rhs) noexcept;
626GHC_FS_API bool operator>=(const path& lhs, const path& rhs) noexcept;
627GHC_FS_API path operator/(const path& lhs, const path& rhs);
628
629// [fs.path.io] path inserter and extractor
630template <class charT, class traits>
631std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const path& p);
632template <class charT, class traits>
633std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, path& p);
634
635// [pfs.path.factory] path factory functions
636template <class Source, typename = path::path_from_string<Source>>
637#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
638[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]]
639#endif
640path u8path(const Source& source);
641template <class InputIterator>
642#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
643[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]]
644#endif
645path u8path(InputIterator first, InputIterator last);
646
647// [fs.class.filesystem_error] class filesystem_error
649{
650public:
651 filesystem_error(const std::string& what_arg, std::error_code ec);
652 filesystem_error(const std::string& what_arg, const path& p1, std::error_code ec);
653 filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec);
654 const path& path1() const noexcept;
655 const path& path2() const noexcept;
656 const char* what() const noexcept override;
657
658private:
659 std::string _what_arg;
660 std::error_code _ec;
661 path _p1, _p2;
662};
663
664class GHC_FS_API_CLASS path::iterator
665{
666public:
667 using value_type = const path;
668 using difference_type = std::ptrdiff_t;
669 using pointer = const path*;
670 using reference = const path&;
671 using iterator_category = std::bidirectional_iterator_tag;
672
674 iterator(const path& p, const impl_string_type::const_iterator& pos);
675 iterator& operator++();
676 iterator operator++(int);
677 iterator& operator--();
678 iterator operator--(int);
679 bool operator==(const iterator& other) const;
680 bool operator!=(const iterator& other) const;
683
684private:
685 friend class path;
686 impl_string_type::const_iterator increment(const impl_string_type::const_iterator& pos) const;
687 impl_string_type::const_iterator decrement(const impl_string_type::const_iterator& pos) const;
688 void updateCurrent();
689 impl_string_type::const_iterator _first;
690 impl_string_type::const_iterator _last;
691 impl_string_type::const_iterator _prefix;
692 impl_string_type::const_iterator _root;
693 impl_string_type::const_iterator _iter;
694 path _current;
695};
696
698{
699 uintmax_t capacity;
700 uintmax_t free;
701 uintmax_t available;
702};
703
704// [fs.enum] enumerations
705// [fs.enum.file_type]
706enum class file_type {
707 none,
708 not_found,
709 regular,
710 directory,
711 symlink,
712 block,
713 character,
714 fifo,
715 socket,
716 unknown,
717};
718
719// [fs.enum.perms]
720enum class perms : uint16_t {
721 none = 0,
722
723 owner_read = 0400,
724 owner_write = 0200,
725 owner_exec = 0100,
726 owner_all = 0700,
727
728 group_read = 040,
729 group_write = 020,
730 group_exec = 010,
731 group_all = 070,
732
733 others_read = 04,
734 others_write = 02,
735 others_exec = 01,
736 others_all = 07,
737
738 all = 0777,
739 set_uid = 04000,
740 set_gid = 02000,
741 sticky_bit = 01000,
742
743 mask = 07777,
744 unknown = 0xffff
745};
746
747// [fs.enum.perm.opts]
748enum class perm_options : uint16_t {
749 replace = 3,
750 add = 1,
751 remove = 2,
752 nofollow = 4,
753};
754
755// [fs.enum.copy.opts]
756enum class copy_options : uint16_t {
757 none = 0,
758
759 skip_existing = 1,
761 update_existing = 4,
762
763 recursive = 8,
764
765 copy_symlinks = 0x10,
766 skip_symlinks = 0x20,
767
768 directories_only = 0x40,
769 create_symlinks = 0x80,
770#ifndef GHC_OS_WEB
771 create_hard_links = 0x100
772#endif
773};
774
775// [fs.enum.dir.opts]
777 none = 0,
780};
781
782// [fs.class.file_status] class file_status
784{
785public:
786 // [fs.file_status.cons] constructors and destructor
787 file_status() noexcept;
788 explicit file_status(file_type ft, perms prms = perms::unknown) noexcept;
789 file_status(const file_status&) noexcept;
790 file_status(file_status&&) noexcept;
791 ~file_status();
792 // assignments:
793 file_status& operator=(const file_status&) noexcept;
794 file_status& operator=(file_status&&) noexcept;
795 // [fs.file_status.mods] modifiers
796 void type(file_type ft) noexcept;
797 void permissions(perms prms) noexcept;
798 // [fs.file_status.obs] observers
799 file_type type() const noexcept;
800 perms permissions() const noexcept;
801 friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); }
802private:
803 file_type _type;
804 perms _perms;
805};
806
807using file_time_type = std::chrono::time_point<std::chrono::system_clock>;
808
809// [fs.class.directory_entry] Class directory_entry
811{
812public:
813 // [fs.dir.entry.cons] constructors and destructor
814 directory_entry() noexcept = default;
816 directory_entry(directory_entry&&) noexcept = default;
817#ifdef GHC_WITH_EXCEPTIONS
818 explicit directory_entry(const path& p);
819#endif
820 directory_entry(const path& p, std::error_code& ec);
822
823 // assignments:
826
827 // [fs.dir.entry.mods] modifiers
828#ifdef GHC_WITH_EXCEPTIONS
829 void assign(const path& p);
830 void replace_filename(const path& p);
831 void refresh();
832#endif
833 void assign(const path& p, std::error_code& ec);
834 void replace_filename(const path& p, std::error_code& ec);
835 void refresh(std::error_code& ec) noexcept;
836
837 // [fs.dir.entry.obs] observers
838 const filesystem::path& path() const noexcept;
839 operator const filesystem::path&() const noexcept;
840#ifdef GHC_WITH_EXCEPTIONS
841 bool exists() const;
842 bool is_block_file() const;
843 bool is_character_file() const;
844 bool is_directory() const;
845 bool is_fifo() const;
846 bool is_other() const;
847 bool is_regular_file() const;
848 bool is_socket() const;
849 bool is_symlink() const;
850 uintmax_t file_size() const;
852 file_status status() const;
854#endif
855 bool exists(std::error_code& ec) const noexcept;
856 bool is_block_file(std::error_code& ec) const noexcept;
857 bool is_character_file(std::error_code& ec) const noexcept;
858 bool is_directory(std::error_code& ec) const noexcept;
859 bool is_fifo(std::error_code& ec) const noexcept;
860 bool is_other(std::error_code& ec) const noexcept;
861 bool is_regular_file(std::error_code& ec) const noexcept;
862 bool is_socket(std::error_code& ec) const noexcept;
863 bool is_symlink(std::error_code& ec) const noexcept;
864 uintmax_t file_size(std::error_code& ec) const noexcept;
865 file_time_type last_write_time(std::error_code& ec) const noexcept;
866 file_status status(std::error_code& ec) const noexcept;
867 file_status symlink_status(std::error_code& ec) const noexcept;
868
869#ifndef GHC_OS_WEB
870#ifdef GHC_WITH_EXCEPTIONS
871 uintmax_t hard_link_count() const;
872#endif
873 uintmax_t hard_link_count(std::error_code& ec) const noexcept;
874#endif
875
876#ifdef GHC_HAS_THREEWAY_COMP
877 std::strong_ordering operator<=>(const directory_entry& rhs) const noexcept;
878#endif
879 bool operator<(const directory_entry& rhs) const noexcept;
880 bool operator==(const directory_entry& rhs) const noexcept;
881 bool operator!=(const directory_entry& rhs) const noexcept;
882 bool operator<=(const directory_entry& rhs) const noexcept;
883 bool operator>(const directory_entry& rhs) const noexcept;
884 bool operator>=(const directory_entry& rhs) const noexcept;
885
886private:
887 friend class directory_iterator;
888#ifdef GHC_WITH_EXCEPTIONS
889 file_type status_file_type() const;
890#endif
891 file_type status_file_type(std::error_code& ec) const noexcept;
892 filesystem::path _path;
893 file_status _status;
894 file_status _symlink_status;
895 uintmax_t _file_size = static_cast<uintmax_t>(-1);
896#ifndef GHC_OS_WINDOWS
897 uintmax_t _hard_link_count = static_cast<uintmax_t>(-1);
898#endif
899 time_t _last_write_time = 0;
900};
901
902// [fs.class.directory.iterator] Class directory_iterator
904{
905public:
907 {
908 public:
909 const directory_entry& operator*() const& noexcept { return _dir_entry; }
910 directory_entry operator*() && noexcept { return std::move(_dir_entry); }
911
912 private:
913 explicit proxy(const directory_entry& dir_entry)
914 : _dir_entry(dir_entry)
915 {
916 }
917 friend class directory_iterator;
919 directory_entry _dir_entry;
920 };
921 using iterator_category = std::input_iterator_tag;
923 using difference_type = std::ptrdiff_t;
924 using pointer = const directory_entry*;
926
927 // [fs.dir.itr.members] member functions
928 directory_iterator() noexcept;
929#ifdef GHC_WITH_EXCEPTIONS
930 explicit directory_iterator(const path& p);
931 directory_iterator(const path& p, directory_options options);
932#endif
933 directory_iterator(const path& p, std::error_code& ec) noexcept;
934 directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept;
938 directory_iterator& operator=(const directory_iterator& rhs);
939 directory_iterator& operator=(directory_iterator&& rhs) noexcept;
940 const directory_entry& operator*() const;
941 const directory_entry* operator->() const;
942#ifdef GHC_WITH_EXCEPTIONS
944#endif
945 directory_iterator& increment(std::error_code& ec) noexcept;
946
947 // other members as required by [input.iterators]
948#ifdef GHC_WITH_EXCEPTIONS
949 proxy operator++(int)
950 {
951 proxy p{**this};
952 ++*this;
953 return p;
954 }
955#endif
956 bool operator==(const directory_iterator& rhs) const;
957 bool operator!=(const directory_iterator& rhs) const;
958
959private:
961 class impl;
962 std::shared_ptr<impl> _impl;
963};
964
965// [fs.dir.itr.nonmembers] directory_iterator non-member functions
968
969// [fs.class.re.dir.itr] class recursive_directory_iterator
971{
972public:
973 using iterator_category = std::input_iterator_tag;
975 using difference_type = std::ptrdiff_t;
976 using pointer = const directory_entry*;
978
979 // [fs.rec.dir.itr.members] constructors and destructor
981#ifdef GHC_WITH_EXCEPTIONS
982 explicit recursive_directory_iterator(const path& p);
984#endif
985 recursive_directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept;
986 recursive_directory_iterator(const path& p, std::error_code& ec) noexcept;
990
991 // [fs.rec.dir.itr.members] observers
992 directory_options options() const;
993 int depth() const;
994 bool recursion_pending() const;
995
996 const directory_entry& operator*() const;
997 const directory_entry* operator->() const;
998
999 // [fs.rec.dir.itr.members] modifiers recursive_directory_iterator&
1002#ifdef GHC_WITH_EXCEPTIONS
1004#endif
1005 recursive_directory_iterator& increment(std::error_code& ec) noexcept;
1006
1007#ifdef GHC_WITH_EXCEPTIONS
1008 void pop();
1009#endif
1010 void pop(std::error_code& ec);
1011 void disable_recursion_pending();
1012
1013 // other members as required by [input.iterators]
1014#ifdef GHC_WITH_EXCEPTIONS
1016 {
1017 directory_iterator::proxy proxy{**this};
1018 ++*this;
1019 return proxy;
1020 }
1021#endif
1022 bool operator==(const recursive_directory_iterator& rhs) const;
1023 bool operator!=(const recursive_directory_iterator& rhs) const;
1024
1025private:
1026 struct recursive_directory_iterator_impl
1027 {
1028 directory_options _options;
1029 bool _recursion_pending;
1030 std::stack<directory_iterator> _dir_iter_stack;
1031 recursive_directory_iterator_impl(directory_options options, bool recursion_pending)
1032 : _options(options)
1033 , _recursion_pending(recursion_pending)
1034 {
1035 }
1036 };
1037 std::shared_ptr<recursive_directory_iterator_impl> _impl;
1038};
1039
1040// [fs.rec.dir.itr.nonmembers] directory_iterator non-member functions
1041GHC_FS_API recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
1042GHC_FS_API recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
1043
1044// [fs.op.funcs] filesystem operations
1045#ifdef GHC_WITH_EXCEPTIONS
1046GHC_FS_API path absolute(const path& p);
1047GHC_FS_API path canonical(const path& p);
1048GHC_FS_API void copy(const path& from, const path& to);
1049GHC_FS_API void copy(const path& from, const path& to, copy_options options);
1050GHC_FS_API bool copy_file(const path& from, const path& to);
1051GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option);
1052GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink);
1053GHC_FS_API bool create_directories(const path& p);
1054GHC_FS_API bool create_directory(const path& p);
1055GHC_FS_API bool create_directory(const path& p, const path& attributes);
1056GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink);
1057GHC_FS_API void create_symlink(const path& to, const path& new_symlink);
1059GHC_FS_API void current_path(const path& p);
1060GHC_FS_API bool exists(const path& p);
1061GHC_FS_API bool equivalent(const path& p1, const path& p2);
1062GHC_FS_API uintmax_t file_size(const path& p);
1063GHC_FS_API bool is_block_file(const path& p);
1064GHC_FS_API bool is_character_file(const path& p);
1065GHC_FS_API bool is_directory(const path& p);
1066GHC_FS_API bool is_empty(const path& p);
1067GHC_FS_API bool is_fifo(const path& p);
1068GHC_FS_API bool is_other(const path& p);
1069GHC_FS_API bool is_regular_file(const path& p);
1070GHC_FS_API bool is_socket(const path& p);
1071GHC_FS_API bool is_symlink(const path& p);
1073GHC_FS_API void last_write_time(const path& p, file_time_type new_time);
1074GHC_FS_API void permissions(const path& p, perms prms, perm_options opts = perm_options::replace);
1075GHC_FS_API path proximate(const path& p, const path& base = current_path());
1076GHC_FS_API path read_symlink(const path& p);
1077GHC_FS_API path relative(const path& p, const path& base = current_path());
1078GHC_FS_API bool remove(const path& p);
1079GHC_FS_API uintmax_t remove_all(const path& p);
1080GHC_FS_API void rename(const path& from, const path& to);
1081GHC_FS_API void resize_file(const path& p, uintmax_t size);
1082GHC_FS_API space_info space(const path& p);
1083GHC_FS_API file_status status(const path& p);
1084GHC_FS_API file_status symlink_status(const path& p);
1086GHC_FS_API path weakly_canonical(const path& p);
1087#endif
1088GHC_FS_API path absolute(const path& p, std::error_code& ec);
1089GHC_FS_API path canonical(const path& p, std::error_code& ec);
1090GHC_FS_API void copy(const path& from, const path& to, std::error_code& ec) noexcept;
1091GHC_FS_API void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept;
1092GHC_FS_API bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept;
1093GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option, std::error_code& ec) noexcept;
1094GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept;
1095GHC_FS_API bool create_directories(const path& p, std::error_code& ec) noexcept;
1096GHC_FS_API bool create_directory(const path& p, std::error_code& ec) noexcept;
1097GHC_FS_API bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept;
1098GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept;
1099GHC_FS_API void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept;
1100GHC_FS_API path current_path(std::error_code& ec);
1101GHC_FS_API void current_path(const path& p, std::error_code& ec) noexcept;
1102GHC_FS_API bool exists(file_status s) noexcept;
1103GHC_FS_API bool exists(const path& p, std::error_code& ec) noexcept;
1104GHC_FS_API bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept;
1105GHC_FS_API uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
1106GHC_FS_API bool is_block_file(file_status s) noexcept;
1107GHC_FS_API bool is_block_file(const path& p, std::error_code& ec) noexcept;
1108GHC_FS_API bool is_character_file(file_status s) noexcept;
1109GHC_FS_API bool is_character_file(const path& p, std::error_code& ec) noexcept;
1110GHC_FS_API bool is_directory(file_status s) noexcept;
1111GHC_FS_API bool is_directory(const path& p, std::error_code& ec) noexcept;
1112GHC_FS_API bool is_empty(const path& p, std::error_code& ec) noexcept;
1113GHC_FS_API bool is_fifo(file_status s) noexcept;
1114GHC_FS_API bool is_fifo(const path& p, std::error_code& ec) noexcept;
1115GHC_FS_API bool is_other(file_status s) noexcept;
1116GHC_FS_API bool is_other(const path& p, std::error_code& ec) noexcept;
1117GHC_FS_API bool is_regular_file(file_status s) noexcept;
1118GHC_FS_API bool is_regular_file(const path& p, std::error_code& ec) noexcept;
1119GHC_FS_API bool is_socket(file_status s) noexcept;
1120GHC_FS_API bool is_socket(const path& p, std::error_code& ec) noexcept;
1121GHC_FS_API bool is_symlink(file_status s) noexcept;
1122GHC_FS_API bool is_symlink(const path& p, std::error_code& ec) noexcept;
1123GHC_FS_API file_time_type last_write_time(const path& p, std::error_code& ec) noexcept;
1124GHC_FS_API void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept;
1125GHC_FS_API void permissions(const path& p, perms prms, std::error_code& ec) noexcept;
1126GHC_FS_API void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) noexcept;
1127GHC_FS_API path proximate(const path& p, std::error_code& ec);
1128GHC_FS_API path proximate(const path& p, const path& base, std::error_code& ec);
1129GHC_FS_API path read_symlink(const path& p, std::error_code& ec);
1130GHC_FS_API path relative(const path& p, std::error_code& ec);
1131GHC_FS_API path relative(const path& p, const path& base, std::error_code& ec);
1132GHC_FS_API bool remove(const path& p, std::error_code& ec) noexcept;
1133GHC_FS_API uintmax_t remove_all(const path& p, std::error_code& ec) noexcept;
1134GHC_FS_API void rename(const path& from, const path& to, std::error_code& ec) noexcept;
1135GHC_FS_API void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept;
1136GHC_FS_API space_info space(const path& p, std::error_code& ec) noexcept;
1137GHC_FS_API file_status status(const path& p, std::error_code& ec) noexcept;
1138GHC_FS_API bool status_known(file_status s) noexcept;
1139GHC_FS_API file_status symlink_status(const path& p, std::error_code& ec) noexcept;
1140GHC_FS_API path temp_directory_path(std::error_code& ec) noexcept;
1141GHC_FS_API path weakly_canonical(const path& p, std::error_code& ec) noexcept;
1142
1143#ifndef GHC_OS_WEB
1144#ifdef GHC_WITH_EXCEPTIONS
1145GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link);
1146GHC_FS_API uintmax_t hard_link_count(const path& p);
1147#endif
1148GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept;
1149GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
1150#endif
1151
1152// Non-C++17 add-on std::fstream wrappers with path
1153template <class charT, class traits = std::char_traits<charT>>
1154class basic_filebuf : public std::basic_filebuf<charT, traits>
1155{
1156public:
1158 ~basic_filebuf() override {}
1160 const basic_filebuf& operator=(const basic_filebuf&) = delete;
1161 basic_filebuf<charT, traits>* open(const path& p, std::ios_base::openmode mode)
1162 {
1163#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
1164 return std::basic_filebuf<charT, traits>::open(p.wstring().c_str(), mode) ? this : 0;
1165#else
1166 return std::basic_filebuf<charT, traits>::open(p.string().c_str(), mode) ? this : 0;
1167#endif
1168 }
1169};
1170
1171template <class charT, class traits = std::char_traits<charT>>
1172class basic_ifstream : public std::basic_ifstream<charT, traits>
1173{
1174public:
1176#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
1177 explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in)
1178 : std::basic_ifstream<charT, traits>(p.wstring().c_str(), mode)
1179 {
1180 }
1181 void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream<charT, traits>::open(p.wstring().c_str(), mode); }
1182#else
1183 explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in)
1184 : std::basic_ifstream<charT, traits>(p.string().c_str(), mode)
1185 {
1186 }
1187 void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream<charT, traits>::open(p.string().c_str(), mode); }
1188#endif
1190 const basic_ifstream& operator=(const basic_ifstream&) = delete;
1191 ~basic_ifstream() override {}
1192};
1193
1194template <class charT, class traits = std::char_traits<charT>>
1195class basic_ofstream : public std::basic_ofstream<charT, traits>
1196{
1197public:
1199#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
1200 explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out)
1201 : std::basic_ofstream<charT, traits>(p.wstring().c_str(), mode)
1202 {
1203 }
1204 void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream<charT, traits>::open(p.wstring().c_str(), mode); }
1205#else
1206 explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out)
1207 : std::basic_ofstream<charT, traits>(p.string().c_str(), mode)
1208 {
1209 }
1210 void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream<charT, traits>::open(p.string().c_str(), mode); }
1211#endif
1213 const basic_ofstream& operator=(const basic_ofstream&) = delete;
1214 ~basic_ofstream() override {}
1215};
1216
1217template <class charT, class traits = std::char_traits<charT>>
1218class basic_fstream : public std::basic_fstream<charT, traits>
1219{
1220public:
1222#if defined(GHC_OS_WINDOWS) && !defined(__GLIBCXX__)
1223 explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
1224 : std::basic_fstream<charT, traits>(p.wstring().c_str(), mode)
1225 {
1226 }
1227 void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream<charT, traits>::open(p.wstring().c_str(), mode); }
1228#else
1229 explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
1230 : std::basic_fstream<charT, traits>(p.string().c_str(), mode)
1231 {
1232 }
1233 void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream<charT, traits>::open(p.string().c_str(), mode); }
1234#endif
1236 const basic_fstream& operator=(const basic_fstream&) = delete;
1237 ~basic_fstream() override {}
1238};
1239
1248
1250{
1251public:
1252 u8arguments(int& argc, char**& argv);
1254 {
1255 _refargc = _argc;
1256 _refargv = _argv;
1257 }
1258
1259 bool valid() const { return _isvalid; }
1260
1261private:
1262 int _argc;
1263 char** _argv;
1264 int& _refargc;
1265 char**& _refargv;
1266 bool _isvalid;
1267#ifdef GHC_OS_WINDOWS
1268 std::vector<std::string> _args;
1269 std::vector<char*> _argp;
1270#endif
1271};
1272
1273//-------------------------------------------------------------------------------------------------
1274// Implementation
1275//-------------------------------------------------------------------------------------------------
1276
1277namespace detail {
1278enum utf8_states_t { S_STRT = 0, S_RJCT = 8 };
1279GHC_FS_API void appendUTF8(std::string& str, uint32_t unicode);
1283GHC_FS_API unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t& codepoint);
1284enum class portable_error {
1285 none = 0,
1286 exists,
1287 not_found,
1292};
1293GHC_FS_API std::error_code make_error_code(portable_error err);
1294#ifdef GHC_OS_WINDOWS
1295GHC_FS_API std::error_code make_system_error(uint32_t err = 0);
1296#else
1297GHC_FS_API std::error_code make_system_error(int err = 0);
1298#endif
1299} // namespace detail
1300
1301namespace detail {
1302
1303#ifdef GHC_EXPAND_IMPL
1304
1306{
1307#ifdef GHC_OS_WINDOWS
1308 switch (err) {
1310 return std::error_code();
1312 return std::error_code(ERROR_ALREADY_EXISTS, std::system_category());
1314 return std::error_code(ERROR_PATH_NOT_FOUND, std::system_category());
1316 return std::error_code(ERROR_NOT_SUPPORTED, std::system_category());
1318 return std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category());
1320 return std::error_code(ERROR_INVALID_PARAMETER, std::system_category());
1322#ifdef ERROR_DIRECTORY_NOT_SUPPORTED
1323 return std::error_code(ERROR_DIRECTORY_NOT_SUPPORTED, std::system_category());
1324#else
1325 return std::error_code(ERROR_NOT_SUPPORTED, std::system_category());
1326#endif
1327 }
1328#else
1329 switch (err) {
1331 return std::error_code();
1333 return std::error_code(EEXIST, std::system_category());
1335 return std::error_code(ENOENT, std::system_category());
1337 return std::error_code(ENOTSUP, std::system_category());
1339 return std::error_code(ENOSYS, std::system_category());
1341 return std::error_code(EINVAL, std::system_category());
1343 return std::error_code(EISDIR, std::system_category());
1344 }
1345#endif
1346 return std::error_code();
1347}
1348
1349#ifdef GHC_OS_WINDOWS
1350GHC_INLINE std::error_code make_system_error(uint32_t err)
1351{
1352 return std::error_code(err ? static_cast<int>(err) : static_cast<int>(::GetLastError()), std::system_category());
1353}
1354#else
1355GHC_INLINE std::error_code make_system_error(int err)
1356{
1357 return std::error_code(err ? err : errno, std::system_category());
1358}
1359#endif
1360
1361#endif // GHC_EXPAND_IMPL
1362
1363template <typename Enum>
1364using EnableBitmask = typename std::enable_if<std::is_same<Enum, perms>::value || std::is_same<Enum, perm_options>::value || std::is_same<Enum, copy_options>::value || std::is_same<Enum, directory_options>::value, Enum>::type;
1365} // namespace detail
1366
1367template <typename Enum>
1369{
1371 return static_cast<Enum>(static_cast<underlying>(X) & static_cast<underlying>(Y));
1372}
1373
1374template <typename Enum>
1376{
1378 return static_cast<Enum>(static_cast<underlying>(X) | static_cast<underlying>(Y));
1379}
1380
1381template <typename Enum>
1383{
1385 return static_cast<Enum>(static_cast<underlying>(X) ^ static_cast<underlying>(Y));
1386}
1387
1388template <typename Enum>
1390{
1392 return static_cast<Enum>(~static_cast<underlying>(X));
1393}
1394
1395template <typename Enum>
1397{
1398 X = X & Y;
1399 return X;
1400}
1401
1402template <typename Enum>
1404{
1405 X = X | Y;
1406 return X;
1407}
1408
1409template <typename Enum>
1411{
1412 X = X ^ Y;
1413 return X;
1414}
1415
1416#ifdef GHC_EXPAND_IMPL
1417
1418namespace detail {
1419
1421{
1422 return (static_cast<uint32_t>(c - lo) < (hi - lo + 1));
1423}
1424
1426{
1427 return in_range(c, 0xd800, 0xdfff);
1428}
1429
1431{
1432 return (c & 0xfffffc00) == 0xd800;
1433}
1434
1436{
1437 return (c & 0xfffffc00) == 0xdc00;
1438}
1439
1440GHC_INLINE void appendUTF8(std::string& str, uint32_t unicode)
1441{
1442 if (unicode <= 0x7f) {
1443 str.push_back(static_cast<char>(unicode));
1444 }
1445 else if (unicode >= 0x80 && unicode <= 0x7ff) {
1446 str.push_back(static_cast<char>((unicode >> 6) + 192));
1447 str.push_back(static_cast<char>((unicode & 0x3f) + 128));
1448 }
1449 else if ((unicode >= 0x800 && unicode <= 0xd7ff) || (unicode >= 0xe000 && unicode <= 0xffff)) {
1450 str.push_back(static_cast<char>((unicode >> 12) + 224));
1451 str.push_back(static_cast<char>(((unicode & 0xfff) >> 6) + 128));
1452 str.push_back(static_cast<char>((unicode & 0x3f) + 128));
1453 }
1454 else if (unicode >= 0x10000 && unicode <= 0x10ffff) {
1455 str.push_back(static_cast<char>((unicode >> 18) + 240));
1456 str.push_back(static_cast<char>(((unicode & 0x3ffff) >> 12) + 128));
1457 str.push_back(static_cast<char>(((unicode & 0xfff) >> 6) + 128));
1458 str.push_back(static_cast<char>((unicode & 0x3f) + 128));
1459 }
1460 else {
1461#ifdef GHC_RAISE_UNICODE_ERRORS
1462 throw filesystem_error("Illegal code point for unicode character.", str, std::make_error_code(std::errc::illegal_byte_sequence));
1463#else
1464 appendUTF8(str, 0xfffd);
1465#endif
1466 }
1467}
1468
1469// Thanks to Bjoern Hoehrmann (https://bjoern.hoehrmann.de/utf-8/decoder/dfa/)
1470// and Taylor R Campbell for the ideas to this DFA approach of UTF-8 decoding;
1471// Generating debugging and shrinking my own DFA from scratch was a day of fun!
1472GHC_INLINE unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t& codepoint)
1473{
1474 static const uint32_t utf8_state_info[] = {
1475 // encoded states
1476 0x11111111u, 0x11111111u, 0x77777777u, 0x77777777u, 0x88888888u, 0x88888888u, 0x88888888u, 0x88888888u, 0x22222299u, 0x22222222u, 0x22222222u, 0x22222222u, 0x3333333au, 0x33433333u, 0x9995666bu, 0x99999999u,
1477 0x88888880u, 0x22818108u, 0x88888881u, 0x88888882u, 0x88888884u, 0x88888887u, 0x88888886u, 0x82218108u, 0x82281108u, 0x88888888u, 0x88888883u, 0x88888885u, 0u, 0u, 0u, 0u,
1478 };
1479 uint8_t category = fragment < 128 ? 0 : (utf8_state_info[(fragment >> 3) & 0xf] >> ((fragment & 7) << 2)) & 0xf;
1480 codepoint = (state ? (codepoint << 6) | (fragment & 0x3fu) : (0xffu >> category) & fragment);
1481 return state == S_RJCT ? static_cast<unsigned>(S_RJCT) : static_cast<unsigned>((utf8_state_info[category + 16] >> (state << 2)) & 0xf);
1482}
1483
1484GHC_INLINE bool validUtf8(const std::string& utf8String)
1485{
1486 std::string::const_iterator iter = utf8String.begin();
1487 unsigned utf8_state = S_STRT;
1488 std::uint32_t codepoint = 0;
1489 while (iter < utf8String.end()) {
1490 if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast<uint8_t>(*iter++), codepoint)) == S_RJCT) {
1491 return false;
1492 }
1493 }
1494 if (utf8_state) {
1495 return false;
1496 }
1497 return true;
1498}
1499
1500} // namespace detail
1501
1502#endif
1503
1504namespace detail {
1505
1506template <class StringType, class Utf8String, typename std::enable_if<path::_is_basic_string<Utf8String>::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 1)>::type* = nullptr>
1507inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1508{
1509 return StringType(utf8String.begin(), utf8String.end(), alloc);
1510}
1511
1512template <class StringType, class Utf8String, typename std::enable_if<path::_is_basic_string<Utf8String>::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 2)>::type* = nullptr>
1513inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1514{
1515 StringType result(alloc);
1516 result.reserve(utf8String.length());
1517 auto iter = utf8String.cbegin();
1518 unsigned utf8_state = S_STRT;
1519 std::uint32_t codepoint = 0;
1520 while (iter < utf8String.cend()) {
1521 if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast<uint8_t>(*iter++), codepoint)) == S_STRT) {
1522 if (codepoint <= 0xffff) {
1523 result += static_cast<typename StringType::value_type>(codepoint);
1524 }
1525 else {
1526 codepoint -= 0x10000;
1527 result += static_cast<typename StringType::value_type>((codepoint >> 10) + 0xd800);
1528 result += static_cast<typename StringType::value_type>((codepoint & 0x3ff) + 0xdc00);
1529 }
1530 codepoint = 0;
1531 }
1532 else if (utf8_state == S_RJCT) {
1533#ifdef GHC_RAISE_UNICODE_ERRORS
1534 throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1535#else
1536 result += static_cast<typename StringType::value_type>(0xfffd);
1537 utf8_state = S_STRT;
1538 codepoint = 0;
1539#endif
1540 }
1541 }
1542 if (utf8_state) {
1543#ifdef GHC_RAISE_UNICODE_ERRORS
1544 throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1545#else
1546 result += static_cast<typename StringType::value_type>(0xfffd);
1547#endif
1548 }
1549 return result;
1550}
1551
1552template <class StringType, class Utf8String, typename std::enable_if<path::_is_basic_string<Utf8String>::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 4)>::type* = nullptr>
1553inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1554{
1555 StringType result(alloc);
1556 result.reserve(utf8String.length());
1557 auto iter = utf8String.cbegin();
1558 unsigned utf8_state = S_STRT;
1559 std::uint32_t codepoint = 0;
1560 while (iter < utf8String.cend()) {
1561 if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast<uint8_t>(*iter++), codepoint)) == S_STRT) {
1562 result += static_cast<typename StringType::value_type>(codepoint);
1563 codepoint = 0;
1564 }
1565 else if (utf8_state == S_RJCT) {
1566#ifdef GHC_RAISE_UNICODE_ERRORS
1567 throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1568#else
1569 result += static_cast<typename StringType::value_type>(0xfffd);
1570 utf8_state = S_STRT;
1571 codepoint = 0;
1572#endif
1573 }
1574 }
1575 if (utf8_state) {
1576#ifdef GHC_RAISE_UNICODE_ERRORS
1577 throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1578#else
1579 result += static_cast<typename StringType::value_type>(0xfffd);
1580#endif
1581 }
1582 return result;
1583}
1584
1585template <class StringType, typename charT, std::size_t N>
1586inline StringType fromUtf8(const charT (&utf8String)[N])
1587{
1588#ifdef GHC_WITH_STRING_VIEW
1589 return fromUtf8<StringType>(basic_string_view<charT>(utf8String, N - 1));
1590#else
1591 return fromUtf8<StringType>(std::basic_string<charT>(utf8String, N - 1));
1592#endif
1593}
1594
1595template <typename strT, typename std::enable_if<path::_is_basic_string<strT>::value && (sizeof(typename strT::value_type) == 1), int>::type size = 1>
1596inline std::string toUtf8(const strT& unicodeString)
1597{
1598 return std::string(unicodeString.begin(), unicodeString.end());
1599}
1600
1601template <typename strT, typename std::enable_if<path::_is_basic_string<strT>::value && (sizeof(typename strT::value_type) == 2), int>::type size = 2>
1602inline std::string toUtf8(const strT& unicodeString)
1603{
1604 std::string result;
1605 for (auto iter = unicodeString.begin(); iter != unicodeString.end(); ++iter) {
1606 char32_t c = *iter;
1607 if (is_surrogate(c)) {
1608 ++iter;
1609 if (iter != unicodeString.end() && is_high_surrogate(c) && is_low_surrogate(*iter)) {
1610 appendUTF8(result, (char32_t(c) << 10) + *iter - 0x35fdc00);
1611 }
1612 else {
1613#ifdef GHC_RAISE_UNICODE_ERRORS
1614 throw filesystem_error("Illegal code point for unicode character.", result, std::make_error_code(std::errc::illegal_byte_sequence));
1615#else
1616 appendUTF8(result, 0xfffd);
1617 if (iter == unicodeString.end()) {
1618 break;
1619 }
1620#endif
1621 }
1622 }
1623 else {
1625 }
1626 }
1627 return result;
1628}
1629
1630template <typename strT, typename std::enable_if<path::_is_basic_string<strT>::value && (sizeof(typename strT::value_type) == 4), int>::type size = 4>
1631inline std::string toUtf8(const strT& unicodeString)
1632{
1633 std::string result;
1634 for (auto c : unicodeString) {
1635 appendUTF8(result, static_cast<uint32_t>(c));
1636 }
1637 return result;
1638}
1639
1640template <typename charT>
1641inline std::string toUtf8(const charT* unicodeString)
1642{
1643#ifdef GHC_WITH_STRING_VIEW
1644 return toUtf8(basic_string_view<charT, std::char_traits<charT>>(unicodeString));
1645#else
1646 return toUtf8(std::basic_string<charT, std::char_traits<charT>>(unicodeString));
1647#endif
1648}
1649
1650#ifdef GHC_USE_WCHAR_T
1651template <class StringType, class WString, typename std::enable_if<path::_is_basic_string<WString>::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 1), bool>::type = false>
1652inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1653{
1654 auto temp = toUtf8(wString);
1655 return StringType(temp.begin(), temp.end(), alloc);
1656}
1657
1658template <class StringType, class WString, typename std::enable_if<path::_is_basic_string<WString>::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 2), bool>::type = false>
1659inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1660{
1661 return StringType(wString.begin(), wString.end(), alloc);
1662}
1663
1664template <class StringType, class WString, typename std::enable_if<path::_is_basic_string<WString>::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 4), bool>::type = false>
1665inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type())
1666{
1667 auto temp = toUtf8(wString);
1668 return fromUtf8<StringType>(temp, alloc);
1669}
1670
1671template <typename strT, typename std::enable_if<path::_is_basic_string<strT>::value && (sizeof(typename strT::value_type) == 1), bool>::type = false>
1672inline std::wstring toWChar(const strT& unicodeString)
1673{
1674 return fromUtf8<std::wstring>(unicodeString);
1675}
1676
1677template <typename strT, typename std::enable_if<path::_is_basic_string<strT>::value && (sizeof(typename strT::value_type) == 2), bool>::type = false>
1678inline std::wstring toWChar(const strT& unicodeString)
1679{
1680 return std::wstring(unicodeString.begin(), unicodeString.end());
1681}
1682
1683template <typename strT, typename std::enable_if<path::_is_basic_string<strT>::value && (sizeof(typename strT::value_type) == 4), bool>::type = false>
1684inline std::wstring toWChar(const strT& unicodeString)
1685{
1686 auto temp = toUtf8(unicodeString);
1687 return fromUtf8<std::wstring>(temp);
1688}
1689
1690template <typename charT>
1691inline std::wstring toWChar(const charT* unicodeString)
1692{
1693#ifdef GHC_WITH_STRING_VIEW
1694 return toWChar(basic_string_view<charT, std::char_traits<charT>>(unicodeString));
1695#else
1696 return toWChar(std::basic_string<charT, std::char_traits<charT>>(unicodeString));
1697#endif
1698}
1699#endif // GHC_USE_WCHAR_T
1700
1701} // namespace detail
1702
1703#ifdef GHC_EXPAND_IMPL
1704
1705namespace detail {
1706
1707template <typename strT, typename std::enable_if<path::_is_basic_string<strT>::value, bool>::type = true>
1708GHC_INLINE bool startsWith(const strT& what, const strT& with)
1709{
1710 return with.length() <= what.length() && equal(with.begin(), with.end(), what.begin());
1711}
1712
1713template <typename strT, typename std::enable_if<path::_is_basic_string<strT>::value, bool>::type = true>
1714GHC_INLINE bool endsWith(const strT& what, const strT& with)
1715{
1716 return with.length() <= what.length() && what.compare(what.length() - with.length(), with.size(), with) == 0;
1717}
1718
1719} // namespace detail
1720
1721GHC_INLINE void path::check_long_path()
1722{
1723#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
1724 if (is_absolute() && _path.length() >= MAX_PATH - 12 && !detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\")))) {
1725 postprocess_path_with_format(native_format);
1726 }
1727#endif
1728}
1729
1730GHC_INLINE void path::postprocess_path_with_format(path::format fmt)
1731{
1732#ifdef GHC_RAISE_UNICODE_ERRORS
1733 if (!detail::validUtf8(_path)) {
1734 path t;
1735 t._path = _path;
1736 throw filesystem_error("Illegal byte sequence for unicode character.", t, std::make_error_code(std::errc::illegal_byte_sequence));
1737 }
1738#endif
1739 switch (fmt) {
1740#ifdef GHC_OS_WINDOWS
1742 case path::auto_format:
1744 for (auto& c : _path) {
1745 if (c == generic_separator) {
1747 }
1748 }
1749#ifdef GHC_WIN_AUTO_PREFIX_LONG_PATH
1750 if (is_absolute() && _path.length() >= MAX_PATH - 12 && !detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\")))) {
1751 _path = GHC_PLATFORM_LITERAL("\\\\?\\") + _path;
1752 }
1753#endif
1754 handle_prefixes();
1755 break;
1756#else
1757 case path::auto_format:
1760 // nothing to do
1761 break;
1762#endif
1763 }
1764 if (_path.length() > _prefixLength + 2 && _path[_prefixLength] == preferred_separator && _path[_prefixLength + 1] == preferred_separator && _path[_prefixLength + 2] != preferred_separator) {
1765 impl_string_type::iterator new_end = std::unique(_path.begin() + static_cast<string_type::difference_type>(_prefixLength) + 2, _path.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs == preferred_separator; });
1766 _path.erase(new_end, _path.end());
1767 }
1768 else {
1769 impl_string_type::iterator new_end = std::unique(_path.begin() + static_cast<string_type::difference_type>(_prefixLength), _path.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs == preferred_separator; });
1770 _path.erase(new_end, _path.end());
1771 }
1772}
1773
1774#endif // GHC_EXPAND_IMPL
1775
1776template <class Source, typename>
1777inline path::path(const Source& source, format fmt)
1778#ifdef GHC_USE_WCHAR_T
1779 : _path(detail::toWChar(source))
1780#else
1781 : _path(detail::toUtf8(source))
1782#endif
1783{
1784 postprocess_path_with_format(fmt);
1785}
1786
1787template <class Source, typename>
1788inline path u8path(const Source& source)
1789{
1790 return path(source);
1791}
1792template <class InputIterator>
1793inline path u8path(InputIterator first, InputIterator last)
1794{
1795 return path(first, last);
1796}
1797
1798template <class InputIterator>
1799inline path::path(InputIterator first, InputIterator last, format fmt)
1800 : path(std::basic_string<typename std::iterator_traits<InputIterator>::value_type>(first, last), fmt)
1801{
1802 // delegated
1803}
1804
1805#ifdef GHC_EXPAND_IMPL
1806
1807namespace detail {
1808
1810{
1811#ifdef GHC_OS_WINDOWS
1812#ifdef __GNUC__
1813 while (::tolower((unsigned char)*str1) == ::tolower((unsigned char)*str2++)) {
1814 if (*str1++ == 0)
1815 return true;
1816 }
1817 return false;
1818#else // __GNUC__
1819#ifdef GHC_USE_WCHAR_T
1820 return 0 == ::_wcsicmp(str1, str2);
1821#else // GHC_USE_WCHAR_T
1822 return 0 == ::_stricmp(str1, str2);
1823#endif // GHC_USE_WCHAR_T
1824#endif // __GNUC__
1825#else // GHC_OS_WINDOWS
1826 return 0 == ::strcasecmp(str1, str2);
1827#endif // GHC_OS_WINDOWS
1828}
1829
1830GHC_INLINE int compare_simple_insensitive(const path::value_type* str1, size_t len1, const path::value_type* str2, size_t len2)
1831{
1832 while (len1 > 0 && len2 > 0 && ::tolower(static_cast<unsigned char>(*str1)) == ::tolower(static_cast<unsigned char>(*str2))) {
1833 --len1;
1834 --len2;
1835 ++str1;
1836 ++str2;
1837 }
1838 if (len1 && len2) {
1839 return *str1 < *str2 ? -1 : 1;
1840 }
1841 if (len1 == 0 && len2 == 0) {
1842 return 0;
1843 }
1844 return len1 == 0 ? -1 : 1;
1845}
1846
1847GHC_INLINE const char* strerror_adapter(char* gnu, char*)
1848{
1849 return gnu;
1850}
1851
1852GHC_INLINE const char* strerror_adapter(int posix, char* buffer)
1853{
1854 if (posix) {
1855 return "Error in strerror_r!";
1856 }
1857 return buffer;
1858}
1859
1860template <typename ErrorNumber>
1861GHC_INLINE std::string systemErrorText(ErrorNumber code = 0)
1862{
1863#if defined(GHC_OS_WINDOWS)
1864 LPVOID msgBuf;
1865 DWORD dw = code ? static_cast<DWORD>(code) : ::GetLastError();
1866 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&msgBuf, 0, NULL);
1867 std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf));
1868 LocalFree(msgBuf);
1869 return msg;
1870#else
1871 char buffer[512];
1872 return strerror_adapter(strerror_r(code ? code : errno, buffer, sizeof(buffer)), buffer);
1873#endif
1874}
1875
1876#ifdef GHC_OS_WINDOWS
1877using CreateSymbolicLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, DWORD);
1878using CreateHardLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
1879
1880GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool to_directory, std::error_code& ec)
1881{
1882 std::error_code tec;
1883 auto fs = status(target_name, tec);
1884 if ((fs.type() == file_type::directory && !to_directory) || (fs.type() == file_type::regular && to_directory)) {
1886 return;
1887 }
1888#if defined(__GNUC__) && __GNUC__ >= 8
1889#pragma GCC diagnostic push
1890#pragma GCC diagnostic ignored "-Wcast-function-type"
1891#endif
1892 static CreateSymbolicLinkW_fp api_call = reinterpret_cast<CreateSymbolicLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW"));
1893#if defined(__GNUC__) && __GNUC__ >= 8
1894#pragma GCC diagnostic pop
1895#endif
1896 if (api_call) {
1897 if (api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), to_directory ? 1 : 0) == 0) {
1898 auto result = ::GetLastError();
1899 if (result == ERROR_PRIVILEGE_NOT_HELD && api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), to_directory ? 3 : 2) != 0) {
1900 return;
1901 }
1903 }
1904 }
1905 else {
1906 ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
1907 }
1908}
1909
1910GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec)
1911{
1912#if defined(__GNUC__) && __GNUC__ >= 8
1913#pragma GCC diagnostic push
1914#pragma GCC diagnostic ignored "-Wcast-function-type"
1915#endif
1916 static CreateHardLinkW_fp api_call = reinterpret_cast<CreateHardLinkW_fp>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"));
1917#if defined(__GNUC__) && __GNUC__ >= 8
1918#pragma GCC diagnostic pop
1919#endif
1920 if (api_call) {
1921 if (api_call(GHC_NATIVEWP(new_hardlink), GHC_NATIVEWP(target_name), NULL) == 0) {
1923 }
1924 }
1925 else {
1926 ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
1927 }
1928}
1929
1930GHC_INLINE path getFullPathName(const wchar_t* p, std::error_code& ec)
1931{
1932 ULONG size = ::GetFullPathNameW(p, 0, 0, 0);
1933 if (size) {
1934 std::vector<wchar_t> buf(size, 0);
1935 ULONG s2 = GetFullPathNameW(p, size, buf.data(), nullptr);
1936 if (s2 && s2 < size) {
1937 return path(std::wstring(buf.data(), s2));
1938 }
1939 }
1941 return path();
1942}
1943
1944#else
1945GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool, std::error_code& ec)
1946{
1947 if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0) {
1949 }
1950}
1951
1952#ifndef GHC_OS_WEB
1953GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec)
1954{
1955 if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) {
1957 }
1958}
1959#endif
1960#endif
1961
1962template <typename T>
1964{
1965#ifdef GHC_OS_WINDOWS
1967 if ((mode & _S_IFDIR) == _S_IFDIR) {
1969 }
1970 else if ((mode & _S_IFREG) == _S_IFREG) {
1971 ft = file_type::regular;
1972 }
1973 else if ((mode & _S_IFCHR) == _S_IFCHR) {
1975 }
1976 perms prms = static_cast<perms>(mode & 0xfff);
1977 return file_status(ft, prms);
1978#else
1980 if (S_ISDIR(mode)) {
1982 }
1983 else if (S_ISREG(mode)) {
1984 ft = file_type::regular;
1985 }
1986 else if (S_ISCHR(mode)) {
1988 }
1989 else if (S_ISBLK(mode)) {
1990 ft = file_type::block;
1991 }
1992 else if (S_ISFIFO(mode)) {
1993 ft = file_type::fifo;
1994 }
1995 else if (S_ISLNK(mode)) {
1996 ft = file_type::symlink;
1997 }
1998 else if (S_ISSOCK(mode)) {
1999 ft = file_type::socket;
2000 }
2001 perms prms = static_cast<perms>(mode & 0xfff);
2002 return file_status(ft, prms);
2003#endif
2004}
2005
2006#ifdef GHC_OS_WINDOWS
2007#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
2008typedef struct _REPARSE_DATA_BUFFER
2009{
2010 ULONG ReparseTag;
2011 USHORT ReparseDataLength;
2012 USHORT Reserved;
2013 union
2014 {
2015 struct
2016 {
2017 USHORT SubstituteNameOffset;
2018 USHORT SubstituteNameLength;
2019 USHORT PrintNameOffset;
2020 USHORT PrintNameLength;
2021 ULONG Flags;
2022 WCHAR PathBuffer[1];
2023 } SymbolicLinkReparseBuffer;
2024 struct
2025 {
2026 USHORT SubstituteNameOffset;
2027 USHORT SubstituteNameLength;
2028 USHORT PrintNameOffset;
2029 USHORT PrintNameLength;
2030 WCHAR PathBuffer[1];
2031 } MountPointReparseBuffer;
2032 struct
2033 {
2034 UCHAR DataBuffer[1];
2035 } GenericReparseBuffer;
2036 } DUMMYUNIONNAME;
2037} REPARSE_DATA_BUFFER;
2038#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
2039#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
2040#endif
2041#endif
2042
2043GHC_INLINE std::shared_ptr<REPARSE_DATA_BUFFER> getReparseData(const path& p, std::error_code& ec)
2044{
2045 std::shared_ptr<void> file(CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
2046 if (file.get() == INVALID_HANDLE_VALUE) {
2048 return nullptr;
2049 }
2050
2051 std::shared_ptr<REPARSE_DATA_BUFFER> reparseData((REPARSE_DATA_BUFFER*)std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE), std::free);
2052 ULONG bufferUsed;
2053 if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) {
2054 return reparseData;
2055 }
2056 else {
2058 }
2059 return nullptr;
2060}
2061#endif
2062
2063GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
2064{
2065#ifdef GHC_OS_WINDOWS
2066 path result;
2067 auto reparseData = detail::getReparseData(p, ec);
2068 if (!ec) {
2069 if (reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag)) {
2070 switch (reparseData->ReparseTag) {
2071 case IO_REPARSE_TAG_SYMLINK: {
2072 auto printName = std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR));
2073 auto substituteName =
2074 std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR));
2075 if (detail::endsWith(substituteName, printName) && detail::startsWith(substituteName, std::wstring(L"\\??\\"))) {
2076 result = printName;
2077 }
2078 else {
2079 result = substituteName;
2080 }
2081 if (reparseData->SymbolicLinkReparseBuffer.Flags & 0x1 /*SYMLINK_FLAG_RELATIVE*/) {
2082 result = p.parent_path() / result;
2083 }
2084 break;
2085 }
2086 case IO_REPARSE_TAG_MOUNT_POINT:
2087 result = detail::getFullPathName(GHC_NATIVEWP(p), ec);
2088 //result = std::wstring(&reparseData->MountPointReparseBuffer.PathBuffer[reparseData->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], reparseData->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR));
2089 break;
2090 default:
2091 break;
2092 }
2093 }
2094 }
2095 return result;
2096#else
2097 size_t bufferSize = 256;
2098 while (true) {
2099 std::vector<char> buffer(bufferSize, static_cast<char>(0));
2100 auto rc = ::readlink(p.c_str(), buffer.data(), buffer.size());
2101 if (rc < 0) {
2103 return path();
2104 }
2105 else if (rc < static_cast<int>(bufferSize)) {
2106 return path(std::string(buffer.data(), static_cast<std::string::size_type>(rc)));
2107 }
2108 bufferSize *= 2;
2109 }
2110 return path();
2111#endif
2112}
2113
2114#ifdef GHC_OS_WINDOWS
2115GHC_INLINE time_t timeFromFILETIME(const FILETIME& ft)
2116{
2117 ULARGE_INTEGER ull;
2118 ull.LowPart = ft.dwLowDateTime;
2119 ull.HighPart = ft.dwHighDateTime;
2120 return static_cast<time_t>(ull.QuadPart / 10000000ULL - 11644473600ULL);
2121}
2122
2123GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft)
2124{
2125 LONGLONG ll;
2126 ll = Int32x32To64(t, 10000000) + 116444736000000000;
2127 ft.dwLowDateTime = static_cast<DWORD>(ll);
2128 ft.dwHighDateTime = static_cast<DWORD>(ll >> 32);
2129}
2130
2131template <typename INFO>
2132GHC_INLINE uintmax_t hard_links_from_INFO(const INFO* info)
2133{
2134 return static_cast<uintmax_t>(-1);
2135}
2136
2137template <>
2138GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const BY_HANDLE_FILE_INFORMATION* info)
2139{
2140 return info->nNumberOfLinks;
2141}
2142
2143template <typename INFO>
2144GHC_INLINE DWORD reparse_tag_from_INFO(const INFO*)
2145{
2146 return 0;
2147}
2148
2149template <>
2150GHC_INLINE DWORD reparse_tag_from_INFO(const WIN32_FIND_DATAW* info)
2151{
2152 return info->dwReserved0;
2153}
2154
2155template <typename INFO>
2156GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code& ec, uintmax_t* sz = nullptr, time_t* lwt = nullptr)
2157{
2159 if (sizeof(INFO) == sizeof(WIN32_FIND_DATAW)) {
2160 if (detail::reparse_tag_from_INFO(info) == IO_REPARSE_TAG_SYMLINK) {
2161 ft = file_type::symlink;
2162 }
2163 }
2164 else {
2165 if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
2166 auto reparseData = detail::getReparseData(p, ec);
2167 if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
2168 ft = file_type::symlink;
2169 }
2170 }
2171 }
2172 if (ft == file_type::unknown) {
2173 if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2175 }
2176 else {
2177 ft = file_type::regular;
2178 }
2179 }
2181 if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
2183 }
2184 if (has_executable_extension(p)) {
2186 }
2187 if (sz) {
2188 *sz = static_cast<uintmax_t>(info->nFileSizeHigh) << (sizeof(info->nFileSizeHigh) * 8) | info->nFileSizeLow;
2189 }
2190 if (lwt) {
2191 *lwt = detail::timeFromFILETIME(info->ftLastWriteTime);
2192 }
2193 return file_status(ft, prms);
2194}
2195
2196#endif
2197
2198GHC_INLINE bool is_not_found_error(std::error_code& ec)
2199{
2200#ifdef GHC_OS_WINDOWS
2201 return ec.value() == ERROR_FILE_NOT_FOUND || ec.value() == ERROR_PATH_NOT_FOUND || ec.value() == ERROR_INVALID_NAME;
2202#else
2203 return ec.value() == ENOENT || ec.value() == ENOTDIR;
2204#endif
2205}
2206
2207GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uintmax_t* sz = nullptr, uintmax_t* nhl = nullptr, time_t* lwt = nullptr) noexcept
2208{
2209#ifdef GHC_OS_WINDOWS
2211 WIN32_FILE_ATTRIBUTE_DATA attr;
2212 if (!GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) {
2214 }
2215 else {
2216 ec.clear();
2217 fs = detail::status_from_INFO(p, &attr, ec, sz, lwt);
2218 if (nhl) {
2219 *nhl = 0;
2220 }
2221 }
2224 }
2225 return ec ? file_status(file_type::none) : fs;
2226#else
2227 (void)sz;
2228 (void)nhl;
2229 (void)lwt;
2230 struct ::stat fs;
2231 auto result = ::lstat(p.c_str(), &fs);
2232 if (result == 0) {
2233 ec.clear();
2235 return f_s;
2236 }
2240 }
2242#endif
2243}
2244
2245GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status* sls = nullptr, uintmax_t* sz = nullptr, uintmax_t* nhl = nullptr, time_t* lwt = nullptr, int recurse_count = 0) noexcept
2246{
2247 ec.clear();
2248#ifdef GHC_OS_WINDOWS
2249 if (recurse_count > 16) {
2250 ec = detail::make_system_error(0x2A9 /*ERROR_STOPPED_ON_SYMLINK*/);
2252 }
2253 WIN32_FILE_ATTRIBUTE_DATA attr;
2254 if (!::GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) {
2256 }
2257 else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
2258 auto reparseData = detail::getReparseData(p, ec);
2259 if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
2260 path target = resolveSymlink(p, ec);
2262 if (!ec && !target.empty()) {
2263 if (sls) {
2264 *sls = status_from_INFO(p, &attr, ec);
2265 }
2266 return detail::status_ex(target, ec, nullptr, sz, nhl, lwt, recurse_count + 1);
2267 }
2269 }
2270 }
2271 if (ec) {
2274 }
2276 }
2277 if (nhl) {
2278 *nhl = 0;
2279 }
2280 return detail::status_from_INFO(p, &attr, ec, sz, lwt);
2281#else
2282 (void)recurse_count;
2283 struct ::stat st;
2284 auto result = ::lstat(p.c_str(), &st);
2285 if (result == 0) {
2286 ec.clear();
2288 if (sls) {
2289 *sls = fs;
2290 }
2291 if (fs.type() == file_type::symlink) {
2292 result = ::stat(p.c_str(), &st);
2293 if (result == 0) {
2295 }
2296 else {
2300 }
2302 }
2303 }
2304 if (sz) {
2305 *sz = static_cast<uintmax_t>(st.st_size);
2306 }
2307 if (nhl) {
2308 *nhl = st.st_nlink;
2309 }
2310 if (lwt) {
2311 *lwt = st.st_mtime;
2312 }
2313 return fs;
2314 }
2315 else {
2319 }
2321 }
2322#endif
2323}
2324
2325} // namespace detail
2326
2327GHC_INLINE u8arguments::u8arguments(int& argc, char**& argv)
2328 : _argc(argc)
2329 , _argv(argv)
2330 , _refargc(argc)
2331 , _refargv(argv)
2332 , _isvalid(false)
2333{
2334#ifdef GHC_OS_WINDOWS
2335 LPWSTR* p;
2336 p = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
2337 _args.reserve(static_cast<size_t>(argc));
2338 _argp.reserve(static_cast<size_t>(argc));
2339 for (size_t i = 0; i < static_cast<size_t>(argc); ++i) {
2340 _args.push_back(detail::toUtf8(std::wstring(p[i])));
2341 _argp.push_back((char*)_args[i].data());
2342 }
2343 argv = _argp.data();
2344 ::LocalFree(p);
2345 _isvalid = true;
2346#else
2347 std::setlocale(LC_ALL, "");
2348#if defined(__ANDROID__) && __ANDROID_API__ < 26
2349 _isvalid = true;
2350#else
2351 if (detail::equals_simple_insensitive(::nl_langinfo(CODESET), "UTF-8")) {
2352 _isvalid = true;
2353 }
2354#endif
2355#endif
2356}
2357
2358//-----------------------------------------------------------------------------
2359// [fs.path.construct] constructors and destructor
2360
2361GHC_INLINE path::path() noexcept {}
2362
2364 : _path(p._path)
2365#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
2366 , _prefixLength(p._prefixLength)
2367#endif
2368{
2369}
2370
2372 : _path(std::move(p._path))
2373#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
2374 , _prefixLength(p._prefixLength)
2375#endif
2376{
2377}
2378
2380 : _path(std::move(source))
2381{
2382 postprocess_path_with_format(fmt);
2383}
2384
2385#endif // GHC_EXPAND_IMPL
2386
2387#ifdef GHC_WITH_EXCEPTIONS
2388template <class Source, typename>
2389inline path::path(const Source& source, const std::locale& loc, format fmt)
2390 : path(source, fmt)
2391{
2392 std::string locName = loc.name();
2393 if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) == "UTF-8" || locName.substr(locName.length() - 5) == "utf-8"))) {
2394 throw filesystem_error("This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported));
2395 }
2396}
2397
2398template <class InputIterator>
2399inline path::path(InputIterator first, InputIterator last, const std::locale& loc, format fmt)
2400 : path(std::basic_string<typename std::iterator_traits<InputIterator>::value_type>(first, last), fmt)
2401{
2402 std::string locName = loc.name();
2403 if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) == "UTF-8" || locName.substr(locName.length() - 5) == "utf-8"))) {
2404 throw filesystem_error("This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported));
2405 }
2406}
2407#endif
2408
2409#ifdef GHC_EXPAND_IMPL
2410
2412
2413//-----------------------------------------------------------------------------
2414// [fs.path.assign] assignments
2415
2417{
2418 _path = p._path;
2419#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
2420 _prefixLength = p._prefixLength;
2421#endif
2422 return *this;
2423}
2424
2426{
2427 _path = std::move(p._path);
2428#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
2429 _prefixLength = p._prefixLength;
2430#endif
2431 return *this;
2432}
2433
2435{
2436 return assign(source);
2437}
2438
2440{
2441 _path = std::move(source);
2442 postprocess_path_with_format(native_format);
2443 return *this;
2444}
2445
2446#endif // GHC_EXPAND_IMPL
2447
2448template <class Source>
2449inline path& path::operator=(const Source& source)
2450{
2451 return assign(source);
2452}
2453
2454template <class Source>
2455inline path& path::assign(const Source& source)
2456{
2457#ifdef GHC_USE_WCHAR_T
2458 _path.assign(detail::toWChar(source));
2459#else
2461#endif
2462 postprocess_path_with_format(native_format);
2463 return *this;
2464}
2465
2466template <>
2467inline path& path::assign<path>(const path& source)
2468{
2469 _path = source._path;
2470#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
2471 _prefixLength = source._prefixLength;
2472#endif
2473 return *this;
2474}
2475
2476template <class InputIterator>
2477inline path& path::assign(InputIterator first, InputIterator last)
2478{
2479 _path.assign(first, last);
2480 postprocess_path_with_format(native_format);
2481 return *this;
2482}
2483
2484#ifdef GHC_EXPAND_IMPL
2485
2486//-----------------------------------------------------------------------------
2487// [fs.path.append] appends
2488
2490{
2491 if (p.empty()) {
2492 // was: if ((!has_root_directory() && is_absolute()) || has_filename())
2493 if (!_path.empty() && _path[_path.length() - 1] != preferred_separator && _path[_path.length() - 1] != ':') {
2494 _path += preferred_separator;
2495 }
2496 return *this;
2497 }
2498 if ((p.is_absolute() && (_path != root_name()._path || p._path != "/")) || (p.has_root_name() && p.root_name() != root_name())) {
2499 assign(p);
2500 return *this;
2501 }
2502 if (p.has_root_directory()) {
2503 assign(root_name());
2504 }
2505 else if ((!has_root_directory() && is_absolute()) || has_filename()) {
2506 _path += preferred_separator;
2507 }
2508 auto iter = p.begin();
2509 bool first = true;
2510 if (p.has_root_name()) {
2511 ++iter;
2512 }
2513 while (iter != p.end()) {
2514 if (!first && !(!_path.empty() && _path[_path.length() - 1] == preferred_separator)) {
2515 _path += preferred_separator;
2516 }
2517 first = false;
2518 _path += (*iter++).native();
2519 }
2520 check_long_path();
2521 return *this;
2522}
2523
2524GHC_INLINE void path::append_name(const value_type* name)
2525{
2526 if (_path.empty()) {
2527 this->operator/=(path(name));
2528 }
2529 else {
2530 if (_path.back() != path::preferred_separator) {
2531 _path.push_back(path::preferred_separator);
2532 }
2533 _path += name;
2534 check_long_path();
2535 }
2536}
2537
2538#endif // GHC_EXPAND_IMPL
2539
2540template <class Source>
2541inline path& path::operator/=(const Source& source)
2542{
2543 return append(source);
2544}
2545
2546template <class Source>
2547inline path& path::append(const Source& source)
2548{
2549 return this->operator/=(path(source));
2550}
2551
2552template <>
2553inline path& path::append<path>(const path& p)
2554{
2555 return this->operator/=(p);
2556}
2557
2558template <class InputIterator>
2559inline path& path::append(InputIterator first, InputIterator last)
2560{
2561 std::basic_string<typename std::iterator_traits<InputIterator>::value_type> part(first, last);
2562 return append(part);
2563}
2564
2565#ifdef GHC_EXPAND_IMPL
2566
2567//-----------------------------------------------------------------------------
2568// [fs.path.concat] concatenation
2569
2571{
2572 return concat(x._path);
2573}
2574
2576{
2577 return concat(x);
2578}
2579
2580#ifdef GHC_WITH_STRING_VIEW
2582{
2583 return concat(x);
2584}
2585#endif
2586
2588{
2589#ifdef GHC_WITH_STRING_VIEW
2591#else
2592 string_type part(x);
2593#endif
2594 return concat(part);
2595}
2596
2598{
2599#ifdef GHC_OS_WINDOWS
2600 if (x == generic_separator) {
2602 }
2603#endif
2604 if (_path.empty() || _path.back() != preferred_separator) {
2605 _path += x;
2606 }
2607 check_long_path();
2608 return *this;
2609}
2610
2611#endif // GHC_EXPAND_IMPL
2612
2613template <class Source>
2615{
2616 return concat(x);
2617}
2618
2619template <class EcharT>
2621{
2622#ifdef GHC_WITH_STRING_VIEW
2623 basic_string_view<EcharT> part(&x, 1);
2624#else
2625 std::basic_string<EcharT> part(1, x);
2626#endif
2627 concat(part);
2628 return *this;
2629}
2630
2631template <class Source>
2632inline path& path::concat(const Source& x)
2633{
2634 path p(x);
2635 _path += p._path;
2636 postprocess_path_with_format(native_format);
2637 return *this;
2638}
2639template <class InputIterator>
2640inline path& path::concat(InputIterator first, InputIterator last)
2641{
2642 _path.append(first, last);
2643 postprocess_path_with_format(native_format);
2644 return *this;
2645}
2646
2647#ifdef GHC_EXPAND_IMPL
2648
2649//-----------------------------------------------------------------------------
2650// [fs.path.modifiers] modifiers
2652{
2653 _path.clear();
2654#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
2655 _prefixLength = 0;
2656#endif
2657}
2658
2660{
2661 // as this filesystem implementation only uses generic_format
2662 // internally, this must be a no-op
2663 return *this;
2664}
2665
2667{
2668 if (has_filename()) {
2669 _path.erase(_path.size() - filename()._path.size());
2670 }
2671 return *this;
2672}
2673
2675{
2677 return append(replacement);
2678}
2679
2681{
2682 if (has_extension()) {
2683 _path.erase(_path.size() - extension()._path.size());
2684 }
2685 if (!replacement.empty() && replacement._path[0] != '.') {
2686 _path += '.';
2687 }
2688 return concat(replacement);
2689}
2690
2691GHC_INLINE void path::swap(path& rhs) noexcept
2692{
2693 _path.swap(rhs._path);
2694#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
2695 std::swap(_prefixLength, rhs._prefixLength);
2696#endif
2697}
2698
2699//-----------------------------------------------------------------------------
2700// [fs.path.native.obs] native format observers
2702{
2703 return _path;
2704}
2705
2707{
2708 return native().c_str();
2709}
2710
2711GHC_INLINE path::operator path::string_type() const
2712{
2713 return native();
2714}
2715
2716#endif // GHC_EXPAND_IMPL
2717
2718template <class EcharT, class traits, class Allocator>
2719inline std::basic_string<EcharT, traits, Allocator> path::string(const Allocator& a) const
2720{
2721#ifdef GHC_USE_WCHAR_T
2722 return detail::fromWChar<std::basic_string<EcharT, traits, Allocator>>(_path, a);
2723#else
2724 return detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(_path, a);
2725#endif
2726}
2727
2728#ifdef GHC_EXPAND_IMPL
2729
2730GHC_INLINE std::string path::string() const
2731{
2732#ifdef GHC_USE_WCHAR_T
2733 return detail::toUtf8(native());
2734#else
2735 return native();
2736#endif
2737}
2738
2739GHC_INLINE std::wstring path::wstring() const
2740{
2741#ifdef GHC_USE_WCHAR_T
2742 return native();
2743#else
2744 return detail::fromUtf8<std::wstring>(native());
2745#endif
2746}
2747
2748#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
2749GHC_INLINE std::u8string path::u8string() const
2750{
2751#ifdef GHC_USE_WCHAR_T
2752 return std::u8string(reinterpret_cast<const char8_t*>(detail::toUtf8(native()).c_str()));
2753#else
2754 return std::u8string(reinterpret_cast<const char8_t*>(c_str()));
2755#endif
2756}
2757#else
2758GHC_INLINE std::string path::u8string() const
2759{
2760#ifdef GHC_USE_WCHAR_T
2761 return detail::toUtf8(native());
2762#else
2763 return native();
2764#endif
2765}
2766#endif
2767
2768GHC_INLINE std::u16string path::u16string() const
2769{
2770 // TODO: optimize
2771 return detail::fromUtf8<std::u16string>(string());
2772}
2773
2774GHC_INLINE std::u32string path::u32string() const
2775{
2776 // TODO: optimize
2777 return detail::fromUtf8<std::u32string>(string());
2778}
2779
2780#endif // GHC_EXPAND_IMPL
2781
2782//-----------------------------------------------------------------------------
2783// [fs.path.generic.obs] generic format observers
2784template <class EcharT, class traits, class Allocator>
2785inline std::basic_string<EcharT, traits, Allocator> path::generic_string(const Allocator& a) const
2786{
2787#ifdef GHC_OS_WINDOWS
2788#ifdef GHC_USE_WCHAR_T
2789 auto result = detail::fromWChar<std::basic_string<EcharT, traits, Allocator>, path::string_type>(_path, a);
2790#else
2791 auto result = detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(_path, a);
2792#endif
2793 for (auto& c : result) {
2794 if (c == preferred_separator) {
2795 c = generic_separator;
2796 }
2797 }
2798 return result;
2799#else
2800 return detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(_path, a);
2801#endif
2802}
2803
2804#ifdef GHC_EXPAND_IMPL
2805
2807{
2808#ifdef GHC_OS_WINDOWS
2809 return generic_string<std::string::value_type, std::string::traits_type, std::string::allocator_type>();
2810#else
2811 return _path;
2812#endif
2813}
2814
2816{
2817#ifdef GHC_OS_WINDOWS
2818 return generic_string<std::wstring::value_type, std::wstring::traits_type, std::wstring::allocator_type>();
2819#else
2820 return detail::fromUtf8<std::wstring>(_path);
2821#endif
2822} // namespace filesystem
2823
2824#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
2825GHC_INLINE std::u8string path::generic_u8string() const
2826{
2827#ifdef GHC_OS_WINDOWS
2828 return generic_string<std::u8string::value_type, std::u8string::traits_type, std::u8string::allocator_type>();
2829#else
2830 return std::u8string(reinterpret_cast<const char8_t*>(_path.c_str()));
2831#endif
2832}
2833#else
2835{
2836#ifdef GHC_OS_WINDOWS
2837 return generic_string<std::string::value_type, std::string::traits_type, std::string::allocator_type>();
2838#else
2839 return _path;
2840#endif
2841}
2842#endif
2843
2845{
2846#ifdef GHC_OS_WINDOWS
2847 return generic_string<std::u16string::value_type, std::u16string::traits_type, std::u16string::allocator_type>();
2848#else
2849 return detail::fromUtf8<std::u16string>(_path);
2850#endif
2851}
2852
2854{
2855#ifdef GHC_OS_WINDOWS
2856 return generic_string<std::u32string::value_type, std::u32string::traits_type, std::u32string::allocator_type>();
2857#else
2858 return detail::fromUtf8<std::u32string>(_path);
2859#endif
2860}
2861
2862//-----------------------------------------------------------------------------
2863// [fs.path.compare] compare
2864GHC_INLINE int path::compare(const path& p) const noexcept
2865{
2866#ifdef LWG_2936_BEHAVIOUR
2867 auto rnl1 = root_name_length();
2868 auto rnl2 = p.root_name_length();
2869#ifdef GHC_OS_WINDOWS
2870 auto rnc = detail::compare_simple_insensitive(_path.c_str(), rnl1, p._path.c_str(), rnl2);
2871#else
2872 auto rnc = _path.compare(0, rnl1, p._path, 0, (std::min(rnl1, rnl2)));
2873#endif
2874 if (rnc) {
2875 return rnc;
2876 }
2877 bool hrd1 = has_root_directory(), hrd2 = p.has_root_directory();
2878 if (hrd1 != hrd2) {
2879 return hrd1 ? 1 : -1;
2880 }
2881 if (hrd1) {
2882 ++rnl1;
2883 ++rnl2;
2884 }
2885 auto iter1 = _path.begin() + static_cast<int>(rnl1);
2886 auto iter2 = p._path.begin() + static_cast<int>(rnl2);
2887 while (iter1 != _path.end() && iter2 != p._path.end() && *iter1 == *iter2) {
2888 ++iter1;
2889 ++iter2;
2890 }
2891 if (iter1 == _path.end()) {
2892 return iter2 == p._path.end() ? 0 : -1;
2893 }
2894 if (iter2 == p._path.end()) {
2895 return 1;
2896 }
2897 if (*iter1 == preferred_separator) {
2898 return -1;
2899 }
2900 if (*iter2 == preferred_separator) {
2901 return 1;
2902 }
2903 return *iter1 < *iter2 ? -1 : 1;
2904#else // LWG_2936_BEHAVIOUR
2905#ifdef GHC_OS_WINDOWS
2906 auto rnl1 = root_name_length();
2907 auto rnl2 = p.root_name_length();
2908 auto rnc = detail::compare_simple_insensitive(_path.c_str(), rnl1, p._path.c_str(), rnl2);
2909 if (rnc) {
2910 return rnc;
2911 }
2912 return _path.compare(rnl1, std::string::npos, p._path, rnl2, std::string::npos);
2913#else
2914 return _path.compare(p._path);
2915#endif
2916#endif
2917}
2918
2920{
2921 return compare(path(s));
2922}
2923
2924#ifdef GHC_WITH_STRING_VIEW
2926{
2927 return compare(path(s));
2928}
2929#endif
2930
2932{
2933 return compare(path(s));
2934}
2935
2936//-----------------------------------------------------------------------------
2937// [fs.path.decompose] decomposition
2938#ifdef GHC_OS_WINDOWS
2939GHC_INLINE void path::handle_prefixes()
2940{
2941#if defined(GHC_WIN_AUTO_PREFIX_LONG_PATH)
2942 _prefixLength = 0;
2943 if (_path.length() >= 6 && _path[2] == '?' && std::toupper(static_cast<unsigned char>(_path[4])) >= 'A' && std::toupper(static_cast<unsigned char>(_path[4])) <= 'Z' && _path[5] == ':') {
2944 if (detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\"))) || detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\??\\")))) {
2945 _prefixLength = 4;
2946 }
2947 }
2948#endif // GHC_WIN_AUTO_PREFIX_LONG_PATH
2949}
2950#endif
2951
2952GHC_INLINE path::string_type::size_type path::root_name_length() const noexcept
2953{
2954#ifdef GHC_OS_WINDOWS
2955 if (_path.length() >= _prefixLength + 2 && std::toupper(static_cast<unsigned char>(_path[_prefixLength])) >= 'A' && std::toupper(static_cast<unsigned char>(_path[_prefixLength])) <= 'Z' && _path[_prefixLength + 1] == ':') {
2956 return 2;
2957 }
2958#endif
2959 if (_path.length() > _prefixLength + 2 && _path[_prefixLength] == preferred_separator && _path[_prefixLength + 1] == preferred_separator && _path[_prefixLength + 2] != preferred_separator && std::isprint(_path[_prefixLength + 2])) {
2960 impl_string_type::size_type pos = _path.find(preferred_separator, _prefixLength + 3);
2961 if (pos == impl_string_type::npos) {
2962 return _path.length();
2963 }
2964 else {
2965 return pos;
2966 }
2967 }
2968 return 0;
2969}
2970
2972{
2973 return path(_path.substr(_prefixLength, root_name_length()), native_format);
2974}
2975
2977{
2978 if (has_root_directory()) {
2979 static const path _root_dir(std::string(1, preferred_separator), native_format);
2980 return _root_dir;
2981 }
2982 return path();
2983}
2984
2986{
2987 return path(root_name().string() + root_directory().string(), native_format);
2988}
2989
2991{
2992 auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0);
2993 return path(_path.substr((std::min)(rootPathLen, _path.length())), generic_format);
2994}
2995
2997{
2998 auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0);
2999 if (rootPathLen < _path.length()) {
3000 if (empty()) {
3001 return path();
3002 }
3003 else {
3004 auto piter = end();
3005 auto iter = piter.decrement(_path.end());
3006 if (iter > _path.begin() + static_cast<long>(rootPathLen) && *iter != preferred_separator) {
3007 --iter;
3008 }
3009 return path(_path.begin(), iter, native_format);
3010 }
3011 }
3012 else {
3013 return *this;
3014 }
3015}
3016
3018{
3019 return !has_relative_path() ? path() : path(*--end());
3020}
3021
3023{
3024 impl_string_type fn = filename().native();
3025 if (fn != "." && fn != "..") {
3026 impl_string_type::size_type pos = fn.rfind('.');
3027 if (pos != impl_string_type::npos && pos > 0) {
3028 return path{fn.substr(0, pos), native_format};
3029 }
3030 }
3031 return path{fn, native_format};
3032}
3033
3035{
3036 if (has_relative_path()) {
3037 auto iter = end();
3038 const auto& fn = *--iter;
3039 impl_string_type::size_type pos = fn._path.rfind('.');
3040 if (pos != std::string::npos && pos > 0) {
3041 return path(fn._path.substr(pos), native_format);
3042 }
3043 }
3044 return path();
3045}
3046
3047#ifdef GHC_OS_WINDOWS
3048namespace detail {
3049GHC_INLINE bool has_executable_extension(const path& p)
3050{
3051 if (p.has_relative_path()) {
3052 auto iter = p.end();
3053 const auto& fn = *--iter;
3054 auto pos = fn._path.find_last_of('.');
3055 if (pos == std::string::npos || pos == 0 || fn._path.length() - pos != 3) {
3056 return false;
3057 }
3058 const path::value_type* ext = fn._path.c_str() + pos + 1;
3060 return true;
3061 }
3062 }
3063 return false;
3064}
3065} // namespace detail
3066#endif
3067
3068//-----------------------------------------------------------------------------
3069// [fs.path.query] query
3070GHC_INLINE bool path::empty() const noexcept
3071{
3072 return _path.empty();
3073}
3074
3076{
3077 return root_name_length() > 0;
3078}
3079
3081{
3082 auto rootLen = _prefixLength + root_name_length();
3083 return (_path.length() > rootLen && _path[rootLen] == preferred_separator);
3084}
3085
3087{
3088 return has_root_name() || has_root_directory();
3089}
3090
3092{
3093 auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0);
3094 return rootPathLen < _path.length();
3095}
3096
3098{
3099 return !parent_path().empty();
3100}
3101
3103{
3104 return has_relative_path() && !filename().empty();
3105}
3106
3108{
3109 return !stem().empty();
3110}
3111
3113{
3114 return !extension().empty();
3115}
3116
3118{
3119#ifdef GHC_OS_WINDOWS
3120 return has_root_name() && has_root_directory();
3121#else
3122 return has_root_directory();
3123#endif
3124}
3125
3127{
3128 return !is_absolute();
3129}
3130
3131//-----------------------------------------------------------------------------
3132// [fs.path.gen] generation
3134{
3135 path dest;
3136 bool lastDotDot = false;
3137 for (string_type s : *this) {
3138 if (s == ".") {
3139 dest /= "";
3140 continue;
3141 }
3142 else if (s == ".." && !dest.empty()) {
3143 auto root = root_path();
3144 if (dest == root) {
3145 continue;
3146 }
3147 else if (*(--dest.end()) != "..") {
3148 if (dest._path.back() == preferred_separator) {
3149 dest._path.pop_back();
3150 }
3151 dest.remove_filename();
3152 continue;
3153 }
3154 }
3155 if (!(s.empty() && lastDotDot)) {
3156 dest /= s;
3157 }
3158 lastDotDot = s == "..";
3159 }
3160 if (dest.empty()) {
3161 dest = ".";
3162 }
3163 return dest;
3164}
3165
3167{
3168 if (root_name() != base.root_name() || is_absolute() != base.is_absolute() || (!has_root_directory() && base.has_root_directory())) {
3169 return path();
3170 }
3171 const_iterator a = begin(), b = base.begin();
3172 while (a != end() && b != base.end() && *a == *b) {
3173 ++a;
3174 ++b;
3175 }
3176 if (a == end() && b == base.end()) {
3177 return path(".");
3178 }
3179 int count = 0;
3180 for (const auto& element : input_iterator_range<const_iterator>(b, base.end())) {
3181 if (element != "." && element != "" && element != "..") {
3182 ++count;
3183 }
3184 else if (element == "..") {
3185 --count;
3186 }
3187 }
3188 if (count < 0) {
3189 return path();
3190 }
3191 path result;
3192 for (int i = 0; i < count; ++i) {
3193 result /= "..";
3194 }
3195 for (const auto& element : input_iterator_range<const_iterator>(a, end())) {
3196 result /= element;
3197 }
3198 return result;
3199}
3200
3202{
3204 return result.empty() ? *this : result;
3205}
3206
3207//-----------------------------------------------------------------------------
3208// [fs.path.itr] iterators
3209GHC_INLINE path::iterator::iterator() {}
3210
3211GHC_INLINE path::iterator::iterator(const path& p, const impl_string_type::const_iterator& pos)
3212 : _first(p._path.begin())
3213 , _last(p._path.end())
3214 , _prefix(_first + static_cast<string_type::difference_type>(p._prefixLength))
3215 , _root(p.has_root_directory() ? _first + static_cast<string_type::difference_type>(p._prefixLength + p.root_name_length()) : _last)
3216 , _iter(pos)
3217{
3218 if(pos != _last) {
3219 updateCurrent();
3220 }
3221}
3222
3223GHC_INLINE path::impl_string_type::const_iterator path::iterator::increment(const path::impl_string_type::const_iterator& pos) const
3224{
3225 path::impl_string_type::const_iterator i = pos;
3226 bool fromStart = i == _first || i == _prefix;
3227 if (i != _last) {
3228 if (fromStart && i == _first && _prefix > _first) {
3229 i = _prefix;
3230 }
3231 else if (*i++ == preferred_separator) {
3232 // we can only sit on a slash if it is a network name or a root
3233 if (i != _last && *i == preferred_separator) {
3234 if (fromStart && !(i + 1 != _last && *(i + 1) == preferred_separator)) {
3235 // leadind double slashes detected, treat this and the
3236 // following until a slash as one unit
3237 i = std::find(++i, _last, preferred_separator);
3238 }
3239 else {
3240 // skip redundant slashes
3241 while (i != _last && *i == preferred_separator) {
3242 ++i;
3243 }
3244 }
3245 }
3246 }
3247 else {
3248 if (fromStart && i != _last && *i == ':') {
3249 ++i;
3250 }
3251 else {
3252 i = std::find(i, _last, preferred_separator);
3253 }
3254 }
3255 }
3256 return i;
3257}
3258
3259GHC_INLINE path::impl_string_type::const_iterator path::iterator::decrement(const path::impl_string_type::const_iterator& pos) const
3260{
3261 path::impl_string_type::const_iterator i = pos;
3262 if (i != _first) {
3263 --i;
3264 // if this is now the root slash or the trailing slash, we are done,
3265 // else check for network name
3266 if (i != _root && (pos != _last || *i != preferred_separator)) {
3267#ifdef GHC_OS_WINDOWS
3268 static const impl_string_type seps = GHC_PLATFORM_LITERAL("\\:");
3269 i = std::find_first_of(std::reverse_iterator<path::impl_string_type::const_iterator>(i), std::reverse_iterator<path::impl_string_type::const_iterator>(_first), seps.begin(), seps.end()).base();
3270 if (i > _first && *i == ':') {
3271 i++;
3272 }
3273#else
3274 i = std::find(std::reverse_iterator<path::impl_string_type::const_iterator>(i), std::reverse_iterator<path::impl_string_type::const_iterator>(_first), preferred_separator).base();
3275#endif
3276 // Now we have to check if this is a network name
3277 if (i - _first == 2 && *_first == preferred_separator && *(_first + 1) == preferred_separator) {
3278 i -= 2;
3279 }
3280 }
3281 }
3282 return i;
3283}
3284
3285GHC_INLINE void path::iterator::updateCurrent()
3286{
3287 if ((_iter == _last) || (_iter != _first && _iter != _last && (*_iter == preferred_separator && _iter != _root) && (_iter + 1 == _last))) {
3288 _current.clear();
3289 }
3290 else {
3291 _current.assign(_iter, increment(_iter));
3292 }
3293}
3294
3296{
3297 _iter = increment(_iter);
3298 while (_iter != _last && // we didn't reach the end
3299 _iter != _root && // this is not a root position
3300 *_iter == preferred_separator && // we are on a separator
3301 (_iter + 1) != _last // the slash is not the last char
3302 ) {
3303 ++_iter;
3304 }
3305 updateCurrent();
3306 return *this;
3307}
3308
3310{
3311 path::iterator i{*this};
3312 ++(*this);
3313 return i;
3314}
3315
3317{
3318 _iter = decrement(_iter);
3319 updateCurrent();
3320 return *this;
3321}
3322
3324{
3325 auto i = *this;
3326 --(*this);
3327 return i;
3328}
3329
3331{
3332 return _iter == other._iter;
3333}
3334
3336{
3337 return _iter != other._iter;
3338}
3339
3340GHC_INLINE path::iterator::reference path::iterator::operator*() const
3341{
3342 return _current;
3343}
3344
3345GHC_INLINE path::iterator::pointer path::iterator::operator->() const
3346{
3347 return &_current;
3348}
3349
3351{
3352 return iterator(*this, _path.begin());
3353}
3354
3356{
3357 return iterator(*this, _path.end());
3358}
3359
3360//-----------------------------------------------------------------------------
3361// [fs.path.nonmember] path non-member functions
3362GHC_INLINE void swap(path& lhs, path& rhs) noexcept
3363{
3364 swap(lhs._path, rhs._path);
3365}
3366
3367GHC_INLINE size_t hash_value(const path& p) noexcept
3368{
3369 return std::hash<std::string>()(p.generic_string());
3370}
3371
3372#ifdef GHC_HAS_THREEWAY_COMP
3373GHC_INLINE std::strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept
3374{
3375 return lhs.compare(rhs) <=> 0;
3376}
3377#endif
3378
3379GHC_INLINE bool operator==(const path& lhs, const path& rhs) noexcept
3380{
3381 return lhs.compare(rhs) == 0;
3382}
3383
3384GHC_INLINE bool operator!=(const path& lhs, const path& rhs) noexcept
3385{
3386 return !(lhs == rhs);
3387}
3388
3389GHC_INLINE bool operator<(const path& lhs, const path& rhs) noexcept
3390{
3391 return lhs.compare(rhs) < 0;
3392}
3393
3394GHC_INLINE bool operator<=(const path& lhs, const path& rhs) noexcept
3395{
3396 return lhs.compare(rhs) <= 0;
3397}
3398
3399GHC_INLINE bool operator>(const path& lhs, const path& rhs) noexcept
3400{
3401 return lhs.compare(rhs) > 0;
3402}
3403
3404GHC_INLINE bool operator>=(const path& lhs, const path& rhs) noexcept
3405{
3406 return lhs.compare(rhs) >= 0;
3407}
3408
3409GHC_INLINE path operator/(const path& lhs, const path& rhs)
3410{
3411 path result(lhs);
3412 result /= rhs;
3413 return result;
3414}
3415
3416#endif // GHC_EXPAND_IMPL
3417
3418//-----------------------------------------------------------------------------
3419// [fs.path.io] path inserter and extractor
3420template <class charT, class traits>
3421inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const path& p)
3422{
3423 os << "\"";
3424 auto ps = p.string<charT, traits>();
3425 for (auto c : ps) {
3426 if (c == '"' || c == '\\') {
3427 os << '\\';
3428 }
3429 os << c;
3430 }
3431 os << "\"";
3432 return os;
3433}
3434
3435template <class charT, class traits>
3436inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, path& p)
3437{
3438 std::basic_string<charT, traits> tmp;
3439 charT c;
3440 is >> c;
3441 if (c == '"') {
3442 auto sf = is.flags();
3443 is >> std::noskipws;
3444 while (is) {
3445 auto c2 = is.get();
3446 if (is) {
3447 if (c2 == '\\') {
3448 c2 = is.get();
3449 if (is) {
3450 tmp += static_cast<charT>(c2);
3451 }
3452 }
3453 else if (c2 == '"') {
3454 break;
3455 }
3456 else {
3457 tmp += static_cast<charT>(c2);
3458 }
3459 }
3460 }
3461 if ((sf & std::ios_base::skipws) == std::ios_base::skipws) {
3462 is >> std::skipws;
3463 }
3464 p = path(tmp);
3465 }
3466 else {
3467 is >> tmp;
3468 p = path(static_cast<charT>(c) + tmp);
3469 }
3470 return is;
3471}
3472
3473#ifdef GHC_EXPAND_IMPL
3474
3475//-----------------------------------------------------------------------------
3476// [fs.class.filesystem_error] Class filesystem_error
3477GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, std::error_code ec)
3478 : std::system_error(ec, what_arg)
3479 , _what_arg(what_arg)
3480 , _ec(ec)
3481{
3482}
3483
3484GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, std::error_code ec)
3485 : std::system_error(ec, what_arg)
3486 , _what_arg(what_arg)
3487 , _ec(ec)
3488 , _p1(p1)
3489{
3490 if (!_p1.empty()) {
3491 _what_arg += ": '" + _p1.string() + "'";
3492 }
3493}
3494
3495GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec)
3496 : std::system_error(ec, what_arg)
3497 , _what_arg(what_arg)
3498 , _ec(ec)
3499 , _p1(p1)
3500 , _p2(p2)
3501{
3502 if (!_p1.empty()) {
3503 _what_arg += ": '" + _p1.string() + "'";
3504 }
3505 if (!_p2.empty()) {
3506 _what_arg += ", '" + _p2.string() + "'";
3507 }
3508}
3509
3511{
3512 return _p1;
3513}
3514
3516{
3517 return _p2;
3518}
3519
3520GHC_INLINE const char* filesystem_error::what() const noexcept
3521{
3522 return _what_arg.c_str();
3523}
3524
3525//-----------------------------------------------------------------------------
3526// [fs.op.funcs] filesystem operations
3527#ifdef GHC_WITH_EXCEPTIONS
3528GHC_INLINE path absolute(const path& p)
3529{
3530 std::error_code ec;
3531 path result = absolute(p, ec);
3532 if (ec) {
3533 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3534 }
3535 return result;
3536}
3537#endif
3538
3539GHC_INLINE path absolute(const path& p, std::error_code& ec)
3540{
3541 ec.clear();
3542#ifdef GHC_OS_WINDOWS
3543 if (p.empty()) {
3544 return absolute(current_path(ec), ec) / "";
3545 }
3546 ULONG size = ::GetFullPathNameW(GHC_NATIVEWP(p), 0, 0, 0);
3547 if (size) {
3548 std::vector<wchar_t> buf(size, 0);
3549 ULONG s2 = GetFullPathNameW(GHC_NATIVEWP(p), size, buf.data(), nullptr);
3550 if (s2 && s2 < size) {
3551 path result = path(std::wstring(buf.data(), s2));
3552 if (p.filename() == ".") {
3553 result /= ".";
3554 }
3555 return result;
3556 }
3557 }
3559 return path();
3560#else
3561 path base = current_path(ec);
3562 if (!ec) {
3563 if (p.empty()) {
3564 return base / p;
3565 }
3566 if (p.has_root_name()) {
3567 if (p.has_root_directory()) {
3568 return p;
3569 }
3570 else {
3571 return p.root_name() / base.root_directory() / base.relative_path() / p.relative_path();
3572 }
3573 }
3574 else {
3575 if (p.has_root_directory()) {
3576 return base.root_name() / p;
3577 }
3578 else {
3579 return base / p;
3580 }
3581 }
3582 }
3584 return path();
3585#endif
3586}
3587
3588#ifdef GHC_WITH_EXCEPTIONS
3589GHC_INLINE path canonical(const path& p)
3590{
3591 std::error_code ec;
3592 auto result = canonical(p, ec);
3593 if (ec) {
3594 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3595 }
3596 return result;
3597}
3598#endif
3599
3600GHC_INLINE path canonical(const path& p, std::error_code& ec)
3601{
3602 if (p.empty()) {
3604 return path();
3605 }
3606 path work = p.is_absolute() ? p : absolute(p, ec);
3607 path result;
3608
3609 auto fs = status(work, ec);
3610 if (ec) {
3611 return path();
3612 }
3613 if (fs.type() == file_type::not_found) {
3615 return path();
3616 }
3617 bool redo;
3618 do {
3619 auto rootPathLen = work._prefixLength + work.root_name_length() + (work.has_root_directory() ? 1 : 0);
3620 redo = false;
3621 result.clear();
3622 for (auto pe : work) {
3623 if (pe.empty() || pe == ".") {
3624 continue;
3625 }
3626 else if (pe == "..") {
3627 result = result.parent_path();
3628 continue;
3629 }
3630 else if ((result / pe).string().length() <= rootPathLen) {
3631 result /= pe;
3632 continue;
3633 }
3634 auto sls = symlink_status(result / pe, ec);
3635 if (ec) {
3636 return path();
3637 }
3638 if (is_symlink(sls)) {
3639 redo = true;
3640 auto target = read_symlink(result / pe, ec);
3641 if (ec) {
3642 return path();
3643 }
3644 if (target.is_absolute()) {
3645 result = target;
3646 continue;
3647 }
3648 else {
3649 result /= target;
3650 continue;
3651 }
3652 }
3653 else {
3654 result /= pe;
3655 }
3656 }
3657 work = result;
3658 } while (redo);
3659 ec.clear();
3660 return result;
3661}
3662
3663#ifdef GHC_WITH_EXCEPTIONS
3664GHC_INLINE void copy(const path& from, const path& to)
3665{
3667}
3668
3669GHC_INLINE void copy(const path& from, const path& to, copy_options options)
3670{
3671 std::error_code ec;
3672 copy(from, to, options, ec);
3673 if (ec) {
3674 throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
3675 }
3676}
3677#endif
3678
3679GHC_INLINE void copy(const path& from, const path& to, std::error_code& ec) noexcept
3680{
3681 copy(from, to, copy_options::none, ec);
3682}
3683
3684GHC_INLINE void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept
3685{
3686 std::error_code tec;
3687 file_status fs_from, fs_to;
3688 ec.clear();
3690 fs_from = symlink_status(from, ec);
3691 }
3692 else {
3693 fs_from = status(from, ec);
3694 }
3695 if (!exists(fs_from)) {
3696 if (!ec) {
3698 }
3699 return;
3700 }
3702 fs_to = symlink_status(to, tec);
3703 }
3704 else {
3705 fs_to = status(to, tec);
3706 }
3707 if (is_other(fs_from) || is_other(fs_to) || (is_directory(fs_from) && is_regular_file(fs_to)) || (exists(fs_to) && equivalent(from, to, ec))) {
3709 }
3710 else if (is_symlink(fs_from)) {
3712 if (!exists(fs_to) && (options & copy_options::copy_symlinks) != copy_options::none) {
3713 copy_symlink(from, to, ec);
3714 }
3715 else {
3717 }
3718 }
3719 }
3720 else if (is_regular_file(fs_from)) {
3723 create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec);
3724 }
3725#ifndef GHC_OS_WEB
3726 else if ((options & copy_options::create_hard_links) != copy_options::none) {
3727 create_hard_link(from, to, ec);
3728 }
3729#endif
3730 else if (is_directory(fs_to)) {
3731 copy_file(from, to / from.filename(), options, ec);
3732 }
3733 else {
3734 copy_file(from, to, options, ec);
3735 }
3736 }
3737 }
3738#ifdef LWG_2682_BEHAVIOUR
3739 else if (is_directory(fs_from) && (options & copy_options::create_symlinks) != copy_options::none) {
3741 }
3742#endif
3743 else if (is_directory(fs_from) && (options == copy_options::none || (options & copy_options::recursive) != copy_options::none)) {
3744 if (!exists(fs_to)) {
3745 create_directory(to, from, ec);
3746 if (ec) {
3747 return;
3748 }
3749 }
3750 for (auto iter = directory_iterator(from, ec); iter != directory_iterator(); iter.increment(ec)) {
3751 if (!ec) {
3752 copy(iter->path(), to / iter->path().filename(), options | static_cast<copy_options>(0x8000), ec);
3753 }
3754 if (ec) {
3755 return;
3756 }
3757 }
3758 }
3759 return;
3760}
3761
3762#ifdef GHC_WITH_EXCEPTIONS
3763GHC_INLINE bool copy_file(const path& from, const path& to)
3764{
3765 return copy_file(from, to, copy_options::none);
3766}
3767
3768GHC_INLINE bool copy_file(const path& from, const path& to, copy_options option)
3769{
3770 std::error_code ec;
3771 auto result = copy_file(from, to, option, ec);
3772 if (ec) {
3773 throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
3774 }
3775 return result;
3776}
3777#endif
3778
3779GHC_INLINE bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept
3780{
3781 return copy_file(from, to, copy_options::none, ec);
3782}
3783
3784GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept
3785{
3786 std::error_code tecf, tect;
3787 auto sf = status(from, tecf);
3788 auto st = status(to, tect);
3789 bool overwrite = false;
3790 ec.clear();
3791 if (!is_regular_file(sf)) {
3792 ec = tecf;
3793 return false;
3794 }
3797 return false;
3798 }
3799 if (exists(st)) {
3801 auto from_time = last_write_time(from, ec);
3802 if (ec) {
3804 return false;
3805 }
3806 auto to_time = last_write_time(to, ec);
3807 if (ec) {
3809 return false;
3810 }
3811 if (from_time <= to_time) {
3812 return false;
3813 }
3814 }
3815 overwrite = true;
3816 }
3817#ifdef GHC_OS_WINDOWS
3818 if (!::CopyFileW(GHC_NATIVEWP(from), GHC_NATIVEWP(to), !overwrite)) {
3820 return false;
3821 }
3822 return true;
3823#else
3824 std::vector<char> buffer(16384, '\0');
3825 int in = -1, out = -1;
3826 if ((in = ::open(from.c_str(), O_RDONLY)) < 0) {
3828 return false;
3829 }
3830 int mode = O_CREAT | O_WRONLY | O_TRUNC;
3831 if (!overwrite) {
3832 mode |= O_EXCL;
3833 }
3834 if ((out = ::open(to.c_str(), mode, static_cast<int>(sf.permissions() & perms::all))) < 0) {
3836 ::close(in);
3837 return false;
3838 }
3839 ssize_t br, bw;
3840 while ((br = ::read(in, buffer.data(), buffer.size())) > 0) {
3841 ssize_t offset = 0;
3842 do {
3843 if ((bw = ::write(out, buffer.data() + offset, static_cast<size_t>(br))) > 0) {
3844 br -= bw;
3845 offset += bw;
3846 }
3847 else if (bw < 0) {
3849 ::close(in);
3850 ::close(out);
3851 return false;
3852 }
3853 } while (br);
3854 }
3855 ::close(in);
3856 ::close(out);
3857 return true;
3858#endif
3859}
3860
3861#ifdef GHC_WITH_EXCEPTIONS
3862GHC_INLINE void copy_symlink(const path& existing_symlink, const path& new_symlink)
3863{
3864 std::error_code ec;
3865 copy_symlink(existing_symlink, new_symlink, ec);
3866 if (ec) {
3867 throw filesystem_error(detail::systemErrorText(ec.value()), existing_symlink, new_symlink, ec);
3868 }
3869}
3870#endif
3871
3872GHC_INLINE void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept
3873{
3874 ec.clear();
3875 auto to = read_symlink(existing_symlink, ec);
3876 if (!ec) {
3877 if (exists(to, ec) && is_directory(to, ec)) {
3878 create_directory_symlink(to, new_symlink, ec);
3879 }
3880 else {
3881 create_symlink(to, new_symlink, ec);
3882 }
3883 }
3884}
3885
3886#ifdef GHC_WITH_EXCEPTIONS
3887GHC_INLINE bool create_directories(const path& p)
3888{
3889 std::error_code ec;
3890 auto result = create_directories(p, ec);
3891 if (ec) {
3892 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3893 }
3894 return result;
3895}
3896#endif
3897
3898GHC_INLINE bool create_directories(const path& p, std::error_code& ec) noexcept
3899{
3900 path current;
3901 ec.clear();
3902 bool didCreate = false;
3903 for (path::string_type part : p) {
3904 current /= part;
3905 if (current != p.root_name() && current != p.root_path()) {
3906 std::error_code tec;
3907 auto fs = status(current, tec);
3908 if (tec && fs.type() != file_type::not_found) {
3909 ec = tec;
3910 return false;
3911 }
3912 if (!exists(fs)) {
3913 create_directory(current, ec);
3914 if (ec) {
3915 std::error_code tmp_ec;
3916 if (is_directory(current, tmp_ec)) {
3917 ec.clear();
3918 }
3919 else {
3920 return false;
3921 }
3922 }
3923 didCreate = true;
3924 }
3925#ifndef LWG_2935_BEHAVIOUR
3926 else if (!is_directory(fs)) {
3928 return false;
3929 }
3930#endif
3931 }
3932 }
3933 return didCreate;
3934}
3935
3936#ifdef GHC_WITH_EXCEPTIONS
3937GHC_INLINE bool create_directory(const path& p)
3938{
3939 std::error_code ec;
3940 auto result = create_directory(p, path(), ec);
3941 if (ec) {
3942 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3943 }
3944 return result;
3945}
3946#endif
3947
3948GHC_INLINE bool create_directory(const path& p, std::error_code& ec) noexcept
3949{
3950 return create_directory(p, path(), ec);
3951}
3952
3953#ifdef GHC_WITH_EXCEPTIONS
3954GHC_INLINE bool create_directory(const path& p, const path& attributes)
3955{
3956 std::error_code ec;
3957 auto result = create_directory(p, attributes, ec);
3958 if (ec) {
3959 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3960 }
3961 return result;
3962}
3963#endif
3964
3965GHC_INLINE bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept
3966{
3967 std::error_code tec;
3968 ec.clear();
3969 auto fs = status(p, tec);
3970#ifdef LWG_2935_BEHAVIOUR
3971 if (status_known(fs) && exists(fs)) {
3972 return false;
3973 }
3974#else
3975 if (status_known(fs) && exists(fs) && is_directory(fs)) {
3976 return false;
3977 }
3978#endif
3979#ifdef GHC_OS_WINDOWS
3980 if (!attributes.empty()) {
3981 if (!::CreateDirectoryExW(GHC_NATIVEWP(attributes), GHC_NATIVEWP(p), NULL)) {
3983 return false;
3984 }
3985 }
3986 else if (!::CreateDirectoryW(GHC_NATIVEWP(p), NULL)) {
3988 return false;
3989 }
3990#else
3991 ::mode_t attribs = static_cast<mode_t>(perms::all);
3992 if (!attributes.empty()) {
3993 struct ::stat fileStat;
3994 if (::stat(attributes.c_str(), &fileStat) != 0) {
3996 return false;
3997 }
3998 attribs = fileStat.st_mode;
3999 }
4000 if (::mkdir(p.c_str(), attribs) != 0) {
4002 return false;
4003 }
4004#endif
4005 return true;
4006}
4007
4008#ifdef GHC_WITH_EXCEPTIONS
4009GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink)
4010{
4011 std::error_code ec;
4012 create_directory_symlink(to, new_symlink, ec);
4013 if (ec) {
4014 throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec);
4015 }
4016}
4017#endif
4018
4019GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept
4020{
4021 detail::create_symlink(to, new_symlink, true, ec);
4022}
4023
4024#ifndef GHC_OS_WEB
4025#ifdef GHC_WITH_EXCEPTIONS
4026GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link)
4027{
4028 std::error_code ec;
4029 create_hard_link(to, new_hard_link, ec);
4030 if (ec) {
4031 throw filesystem_error(detail::systemErrorText(ec.value()), to, new_hard_link, ec);
4032 }
4033}
4034#endif
4035
4036GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept
4037{
4038 detail::create_hardlink(to, new_hard_link, ec);
4039}
4040#endif
4041
4042#ifdef GHC_WITH_EXCEPTIONS
4043GHC_INLINE void create_symlink(const path& to, const path& new_symlink)
4044{
4045 std::error_code ec;
4046 create_symlink(to, new_symlink, ec);
4047 if (ec) {
4048 throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec);
4049 }
4050}
4051#endif
4052
4053GHC_INLINE void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept
4054{
4055 detail::create_symlink(to, new_symlink, false, ec);
4056}
4057
4058#ifdef GHC_WITH_EXCEPTIONS
4060{
4061 std::error_code ec;
4062 auto result = current_path(ec);
4063 if (ec) {
4064 throw filesystem_error(detail::systemErrorText(ec.value()), ec);
4065 }
4066 return result;
4067}
4068#endif
4069
4070GHC_INLINE path current_path(std::error_code& ec)
4071{
4072 ec.clear();
4073#ifdef GHC_OS_WINDOWS
4074 DWORD pathlen = ::GetCurrentDirectoryW(0, 0);
4075 std::unique_ptr<wchar_t[]> buffer(new wchar_t[size_t(pathlen) + 1]);
4076 if (::GetCurrentDirectoryW(pathlen, buffer.get()) == 0) {
4078 return path();
4079 }
4080 return path(std::wstring(buffer.get()), path::native_format);
4081#else
4082 size_t pathlen = static_cast<size_t>(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX)));
4083 std::unique_ptr<char[]> buffer(new char[pathlen + 1]);
4084 if (::getcwd(buffer.get(), pathlen) == nullptr) {
4086 return path();
4087 }
4088 return path(buffer.get());
4089#endif
4090}
4091
4092#ifdef GHC_WITH_EXCEPTIONS
4093GHC_INLINE void current_path(const path& p)
4094{
4095 std::error_code ec;
4096 current_path(p, ec);
4097 if (ec) {
4098 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4099 }
4100}
4101#endif
4102
4103GHC_INLINE void current_path(const path& p, std::error_code& ec) noexcept
4104{
4105 ec.clear();
4106#ifdef GHC_OS_WINDOWS
4107 if (!::SetCurrentDirectoryW(GHC_NATIVEWP(p))) {
4109 }
4110#else
4111 if (::chdir(p.string().c_str()) == -1) {
4113 }
4114#endif
4115}
4116
4118{
4119 return status_known(s) && s.type() != file_type::not_found;
4120}
4121
4122#ifdef GHC_WITH_EXCEPTIONS
4123GHC_INLINE bool exists(const path& p)
4124{
4125 return exists(status(p));
4126}
4127#endif
4128
4129GHC_INLINE bool exists(const path& p, std::error_code& ec) noexcept
4130{
4131 file_status s = status(p, ec);
4132 if (status_known(s)) {
4133 ec.clear();
4134 }
4135 return exists(s);
4136}
4137
4138#ifdef GHC_WITH_EXCEPTIONS
4139GHC_INLINE bool equivalent(const path& p1, const path& p2)
4140{
4141 std::error_code ec;
4142 bool result = equivalent(p1, p2, ec);
4143 if (ec) {
4144 throw filesystem_error(detail::systemErrorText(ec.value()), p1, p2, ec);
4145 }
4146 return result;
4147}
4148#endif
4149
4150GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept
4151{
4152 ec.clear();
4153#ifdef GHC_OS_WINDOWS
4154 std::shared_ptr<void> file1(::CreateFileW(GHC_NATIVEWP(p1), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
4155 auto e1 = ::GetLastError();
4156 std::shared_ptr<void> file2(::CreateFileW(GHC_NATIVEWP(p2), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
4157 if (file1.get() == INVALID_HANDLE_VALUE || file2.get() == INVALID_HANDLE_VALUE) {
4158#ifdef LWG_2937_BEHAVIOUR
4159 ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
4160#else
4161 if (file1 == file2) {
4162 ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
4163 }
4164#endif
4165 return false;
4166 }
4167 BY_HANDLE_FILE_INFORMATION inf1, inf2;
4168 if (!::GetFileInformationByHandle(file1.get(), &inf1)) {
4170 return false;
4171 }
4172 if (!::GetFileInformationByHandle(file2.get(), &inf2)) {
4174 return false;
4175 }
4176 return inf1.ftLastWriteTime.dwLowDateTime == inf2.ftLastWriteTime.dwLowDateTime && inf1.ftLastWriteTime.dwHighDateTime == inf2.ftLastWriteTime.dwHighDateTime && inf1.nFileIndexHigh == inf2.nFileIndexHigh && inf1.nFileIndexLow == inf2.nFileIndexLow &&
4177 inf1.nFileSizeHigh == inf2.nFileSizeHigh && inf1.nFileSizeLow == inf2.nFileSizeLow && inf1.dwVolumeSerialNumber == inf2.dwVolumeSerialNumber;
4178#else
4179 struct ::stat s1, s2;
4180 auto rc1 = ::stat(p1.c_str(), &s1);
4181 auto e1 = errno;
4182 auto rc2 = ::stat(p2.c_str(), &s2);
4183 if (rc1 || rc2) {
4184#ifdef LWG_2937_BEHAVIOUR
4185 ec = detail::make_system_error(e1 ? e1 : errno);
4186#else
4187 if (rc1 && rc2) {
4188 ec = detail::make_system_error(e1 ? e1 : errno);
4189 }
4190#endif
4191 return false;
4192 }
4193 return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime;
4194#endif
4195}
4196
4197#ifdef GHC_WITH_EXCEPTIONS
4198GHC_INLINE uintmax_t file_size(const path& p)
4199{
4200 std::error_code ec;
4201 auto result = file_size(p, ec);
4202 if (ec) {
4203 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4204 }
4205 return result;
4206}
4207#endif
4208
4209GHC_INLINE uintmax_t file_size(const path& p, std::error_code& ec) noexcept
4210{
4211 ec.clear();
4212#ifdef GHC_OS_WINDOWS
4213 WIN32_FILE_ATTRIBUTE_DATA attr;
4214 if (!GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) {
4216 return static_cast<uintmax_t>(-1);
4217 }
4218 return static_cast<uintmax_t>(attr.nFileSizeHigh) << (sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow;
4219#else
4220 struct ::stat fileStat;
4221 if (::stat(p.c_str(), &fileStat) == -1) {
4223 return static_cast<uintmax_t>(-1);
4224 }
4225 return static_cast<uintmax_t>(fileStat.st_size);
4226#endif
4227}
4228
4229#ifndef GHC_OS_WEB
4230#ifdef GHC_WITH_EXCEPTIONS
4231GHC_INLINE uintmax_t hard_link_count(const path& p)
4232{
4233 std::error_code ec;
4234 auto result = hard_link_count(p, ec);
4235 if (ec) {
4236 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4237 }
4238 return result;
4239}
4240#endif
4241
4242GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept
4243{
4244 ec.clear();
4245#ifdef GHC_OS_WINDOWS
4246 uintmax_t result = static_cast<uintmax_t>(-1);
4247 std::shared_ptr<void> file(::CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
4248 BY_HANDLE_FILE_INFORMATION inf;
4249 if (file.get() == INVALID_HANDLE_VALUE) {
4251 }
4252 else {
4253 if (!::GetFileInformationByHandle(file.get(), &inf)) {
4255 }
4256 else {
4257 result = inf.nNumberOfLinks;
4258 }
4259 }
4260 return result;
4261#else
4262 uintmax_t result = 0;
4263 file_status fs = detail::status_ex(p, ec, nullptr, nullptr, &result, nullptr);
4264 if (fs.type() == file_type::not_found) {
4266 }
4267 return ec ? static_cast<uintmax_t>(-1) : result;
4268#endif
4269}
4270#endif
4271
4273{
4274 return s.type() == file_type::block;
4275}
4276
4277#ifdef GHC_WITH_EXCEPTIONS
4278GHC_INLINE bool is_block_file(const path& p)
4279{
4280 return is_block_file(status(p));
4281}
4282#endif
4283
4284GHC_INLINE bool is_block_file(const path& p, std::error_code& ec) noexcept
4285{
4286 return is_block_file(status(p, ec));
4287}
4288
4290{
4291 return s.type() == file_type::character;
4292}
4293
4294#ifdef GHC_WITH_EXCEPTIONS
4295GHC_INLINE bool is_character_file(const path& p)
4296{
4297 return is_character_file(status(p));
4298}
4299#endif
4300
4301GHC_INLINE bool is_character_file(const path& p, std::error_code& ec) noexcept
4302{
4303 return is_character_file(status(p, ec));
4304}
4305
4307{
4308 return s.type() == file_type::directory;
4309}
4310
4311#ifdef GHC_WITH_EXCEPTIONS
4312GHC_INLINE bool is_directory(const path& p)
4313{
4314 return is_directory(status(p));
4315}
4316#endif
4317
4318GHC_INLINE bool is_directory(const path& p, std::error_code& ec) noexcept
4319{
4320 return is_directory(status(p, ec));
4321}
4322
4323#ifdef GHC_WITH_EXCEPTIONS
4324GHC_INLINE bool is_empty(const path& p)
4325{
4326 if (is_directory(p)) {
4327 return directory_iterator(p) == directory_iterator();
4328 }
4329 else {
4330 return file_size(p) == 0;
4331 }
4332}
4333#endif
4334
4335GHC_INLINE bool is_empty(const path& p, std::error_code& ec) noexcept
4336{
4337 auto fs = status(p, ec);
4338 if (ec) {
4339 return false;
4340 }
4341 if (is_directory(fs)) {
4342 directory_iterator iter(p, ec);
4343 if (ec) {
4344 return false;
4345 }
4346 return iter == directory_iterator();
4347 }
4348 else {
4349 auto sz = file_size(p, ec);
4350 if (ec) {
4351 return false;
4352 }
4353 return sz == 0;
4354 }
4355}
4356
4358{
4359 return s.type() == file_type::fifo;
4360}
4361
4362#ifdef GHC_WITH_EXCEPTIONS
4363GHC_INLINE bool is_fifo(const path& p)
4364{
4365 return is_fifo(status(p));
4366}
4367#endif
4368
4369GHC_INLINE bool is_fifo(const path& p, std::error_code& ec) noexcept
4370{
4371 return is_fifo(status(p, ec));
4372}
4373
4375{
4376 return exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s);
4377}
4378
4379#ifdef GHC_WITH_EXCEPTIONS
4380GHC_INLINE bool is_other(const path& p)
4381{
4382 return is_other(status(p));
4383}
4384#endif
4385
4386GHC_INLINE bool is_other(const path& p, std::error_code& ec) noexcept
4387{
4388 return is_other(status(p, ec));
4389}
4390
4392{
4393 return s.type() == file_type::regular;
4394}
4395
4396#ifdef GHC_WITH_EXCEPTIONS
4397GHC_INLINE bool is_regular_file(const path& p)
4398{
4399 return is_regular_file(status(p));
4400}
4401#endif
4402
4403GHC_INLINE bool is_regular_file(const path& p, std::error_code& ec) noexcept
4404{
4405 return is_regular_file(status(p, ec));
4406}
4407
4409{
4410 return s.type() == file_type::socket;
4411}
4412
4413#ifdef GHC_WITH_EXCEPTIONS
4414GHC_INLINE bool is_socket(const path& p)
4415{
4416 return is_socket(status(p));
4417}
4418#endif
4419
4420GHC_INLINE bool is_socket(const path& p, std::error_code& ec) noexcept
4421{
4422 return is_socket(status(p, ec));
4423}
4424
4426{
4427 return s.type() == file_type::symlink;
4428}
4429
4430#ifdef GHC_WITH_EXCEPTIONS
4431GHC_INLINE bool is_symlink(const path& p)
4432{
4433 return is_symlink(symlink_status(p));
4434}
4435#endif
4436
4437GHC_INLINE bool is_symlink(const path& p, std::error_code& ec) noexcept
4438{
4439 return is_symlink(symlink_status(p, ec));
4440}
4441
4442#ifdef GHC_WITH_EXCEPTIONS
4444{
4445 std::error_code ec;
4446 auto result = last_write_time(p, ec);
4447 if (ec) {
4448 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4449 }
4450 return result;
4451}
4452#endif
4453
4454GHC_INLINE file_time_type last_write_time(const path& p, std::error_code& ec) noexcept
4455{
4456 time_t result = 0;
4457 ec.clear();
4458 file_status fs = detail::status_ex(p, ec, nullptr, nullptr, nullptr, &result);
4459 return ec ? (file_time_type::min)() : std::chrono::system_clock::from_time_t(result);
4460}
4461
4462#ifdef GHC_WITH_EXCEPTIONS
4463GHC_INLINE void last_write_time(const path& p, file_time_type new_time)
4464{
4465 std::error_code ec;
4466 last_write_time(p, new_time, ec);
4467 if (ec) {
4468 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4469 }
4470}
4471#endif
4472
4473GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept
4474{
4475 ec.clear();
4476 auto d = new_time.time_since_epoch();
4477#ifdef GHC_OS_WINDOWS
4478 std::shared_ptr<void> file(::CreateFileW(GHC_NATIVEWP(p), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL), ::CloseHandle);
4479 FILETIME ft;
4480 auto tt = std::chrono::duration_cast<std::chrono::microseconds>(d).count() * 10 + 116444736000000000;
4481 ft.dwLowDateTime = static_cast<DWORD>(tt);
4482 ft.dwHighDateTime = static_cast<DWORD>(tt >> 32);
4483 if (!::SetFileTime(file.get(), 0, 0, &ft)) {
4485 }
4486#elif defined(GHC_OS_MACOS)
4487#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
4488#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
4489 struct ::stat fs;
4490 if (::stat(p.c_str(), &fs) == 0) {
4491 struct ::timeval tv[2];
4492 tv[0].tv_sec = fs.st_atimespec.tv_sec;
4493 tv[0].tv_usec = static_cast<int>(fs.st_atimespec.tv_nsec / 1000);
4494 tv[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
4495 tv[1].tv_usec = static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(d).count() % 1000000);
4496 if (::utimes(p.c_str(), tv) == 0) {
4497 return;
4498 }
4499 }
4501 return;
4502#else
4503 struct ::timespec times[2];
4504 times[0].tv_sec = 0;
4505 times[0].tv_nsec = UTIME_OMIT;
4506 times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
4507 times[1].tv_nsec = 0; // std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
4508 if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
4510 }
4511 return;
4512#endif
4513#endif
4514#else
4515#ifndef UTIME_OMIT
4516#define UTIME_OMIT ((1l << 30) - 2l)
4517#endif
4518 struct ::timespec times[2];
4519 times[0].tv_sec = 0;
4520 times[0].tv_nsec = UTIME_OMIT;
4521 times[1].tv_sec = static_cast<decltype(times[1].tv_sec)>(std::chrono::duration_cast<std::chrono::seconds>(d).count());
4522 times[1].tv_nsec = static_cast<decltype(times[1].tv_nsec)>(std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000);
4523#if defined(__ANDROID_API__) && __ANDROID_API__ < 12
4524 if (syscall(__NR_utimensat, AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
4525#else
4526 if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
4527#endif
4529 }
4530 return;
4531#endif
4532}
4533
4534#ifdef GHC_WITH_EXCEPTIONS
4535GHC_INLINE void permissions(const path& p, perms prms, perm_options opts)
4536{
4537 std::error_code ec;
4538 permissions(p, prms, opts, ec);
4539 if (ec) {
4540 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4541 }
4542}
4543#endif
4544
4545GHC_INLINE void permissions(const path& p, perms prms, std::error_code& ec) noexcept
4546{
4547 permissions(p, prms, perm_options::replace, ec);
4548}
4549
4550GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) noexcept
4551{
4552 if (static_cast<int>(opts & (perm_options::replace | perm_options::add | perm_options::remove)) == 0) {
4554 return;
4555 }
4556 auto fs = symlink_status(p, ec);
4558 if ((opts & perm_options::add) == perm_options::add) {
4559 prms = fs.permissions() | prms;
4560 }
4561 else {
4562 prms = fs.permissions() & ~prms;
4563 }
4564 }
4565#ifdef GHC_OS_WINDOWS
4566#ifdef __GNUC__
4567 auto oldAttr = GetFileAttributesW(GHC_NATIVEWP(p));
4568 if (oldAttr != INVALID_FILE_ATTRIBUTES) {
4569 DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~(static_cast<DWORD>(FILE_ATTRIBUTE_READONLY)) : oldAttr | FILE_ATTRIBUTE_READONLY;
4570 if (oldAttr == newAttr || SetFileAttributesW(GHC_NATIVEWP(p), newAttr)) {
4571 return;
4572 }
4573 }
4575#else
4576 int mode = 0;
4577 if ((prms & perms::owner_read) == perms::owner_read) {
4578 mode |= _S_IREAD;
4579 }
4580 if ((prms & perms::owner_write) == perms::owner_write) {
4581 mode |= _S_IWRITE;
4582 }
4583 if (::_wchmod(p.wstring().c_str(), mode) != 0) {
4585 }
4586#endif
4587#else
4589 if (::chmod(p.c_str(), static_cast<mode_t>(prms)) != 0) {
4591 }
4592 }
4593#endif
4594}
4595
4596#ifdef GHC_WITH_EXCEPTIONS
4597GHC_INLINE path proximate(const path& p, std::error_code& ec)
4598{
4599 auto cp = current_path(ec);
4600 if (!ec) {
4601 return proximate(p, cp, ec);
4602 }
4603 return path();
4604}
4605#endif
4606
4607#ifdef GHC_WITH_EXCEPTIONS
4608GHC_INLINE path proximate(const path& p, const path& base)
4609{
4611}
4612#endif
4613
4614GHC_INLINE path proximate(const path& p, const path& base, std::error_code& ec)
4615{
4616 return weakly_canonical(p, ec).lexically_proximate(weakly_canonical(base, ec));
4617}
4618
4619#ifdef GHC_WITH_EXCEPTIONS
4620GHC_INLINE path read_symlink(const path& p)
4621{
4622 std::error_code ec;
4623 auto result = read_symlink(p, ec);
4624 if (ec) {
4625 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4626 }
4627 return result;
4628}
4629#endif
4630
4631GHC_INLINE path read_symlink(const path& p, std::error_code& ec)
4632{
4633 file_status fs = symlink_status(p, ec);
4634 if (fs.type() != file_type::symlink) {
4636 return path();
4637 }
4638 auto result = detail::resolveSymlink(p, ec);
4639 return ec ? path() : result;
4640}
4641
4642GHC_INLINE path relative(const path& p, std::error_code& ec)
4643{
4644 return relative(p, current_path(ec), ec);
4645}
4646
4647#ifdef GHC_WITH_EXCEPTIONS
4648GHC_INLINE path relative(const path& p, const path& base)
4649{
4651}
4652#endif
4653
4654GHC_INLINE path relative(const path& p, const path& base, std::error_code& ec)
4655{
4656 return weakly_canonical(p, ec).lexically_relative(weakly_canonical(base, ec));
4657}
4658
4659#ifdef GHC_WITH_EXCEPTIONS
4660GHC_INLINE bool remove(const path& p)
4661{
4662 std::error_code ec;
4663 auto result = remove(p, ec);
4664 if (ec) {
4665 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4666 }
4667 return result;
4668}
4669#endif
4670
4671GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept
4672{
4673 ec.clear();
4674#ifdef GHC_OS_WINDOWS
4675#ifdef GHC_USE_WCHAR_T
4676 auto cstr = p.c_str();
4677#else
4678 std::wstring np = detail::fromUtf8<std::wstring>(p.u8string());
4679 auto cstr = np.c_str();
4680#endif
4681 DWORD attr = GetFileAttributesW(cstr);
4682 if (attr == INVALID_FILE_ATTRIBUTES) {
4683 auto error = ::GetLastError();
4684 if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) {
4685 return false;
4686 }
4688 }
4689 else if(attr & FILE_ATTRIBUTE_READONLY) {
4690 auto new_attr = attr & ~static_cast<DWORD>(FILE_ATTRIBUTE_READONLY);
4691 if(!SetFileAttributesW(cstr, new_attr)) {
4692 auto error = ::GetLastError();
4694 }
4695 }
4696 if (!ec) {
4697 if (attr & FILE_ATTRIBUTE_DIRECTORY) {
4698 if (!RemoveDirectoryW(cstr)) {
4700 }
4701 }
4702 else {
4703 if (!DeleteFileW(cstr)) {
4705 }
4706 }
4707 }
4708#else
4709 if (::remove(p.c_str()) == -1) {
4710 auto error = errno;
4711 if (error == ENOENT) {
4712 return false;
4713 }
4715 }
4716#endif
4717 return ec ? false : true;
4718}
4719
4720#ifdef GHC_WITH_EXCEPTIONS
4721GHC_INLINE uintmax_t remove_all(const path& p)
4722{
4723 std::error_code ec;
4724 auto result = remove_all(p, ec);
4725 if (ec) {
4726 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4727 }
4728 return result;
4729}
4730#endif
4731
4732GHC_INLINE uintmax_t remove_all(const path& p, std::error_code& ec) noexcept
4733{
4734 ec.clear();
4735 uintmax_t count = 0;
4736 if (p == "/") {
4738 return static_cast<uintmax_t>(-1);
4739 }
4740 std::error_code tec;
4741 auto fs = status(p, tec);
4742 if (exists(fs) && is_directory(fs)) {
4743 for (auto iter = directory_iterator(p, ec); iter != directory_iterator(); iter.increment(ec)) {
4744 if (ec && !detail::is_not_found_error(ec)) {
4745 break;
4746 }
4747 bool is_symlink_result = iter->is_symlink(ec);
4748 if (ec)
4749 return static_cast<uintmax_t>(-1);
4750 if (!is_symlink_result && iter->is_directory(ec)) {
4751 count += remove_all(iter->path(), ec);
4752 if (ec) {
4753 return static_cast<uintmax_t>(-1);
4754 }
4755 }
4756 else {
4757 if (!ec) {
4758 remove(iter->path(), ec);
4759 }
4760 if (ec) {
4761 return static_cast<uintmax_t>(-1);
4762 }
4763 ++count;
4764 }
4765 }
4766 }
4767 if (!ec) {
4768 if (remove(p, ec)) {
4769 ++count;
4770 }
4771 }
4772 if (ec) {
4773 return static_cast<uintmax_t>(-1);
4774 }
4775 return count;
4776}
4777
4778#ifdef GHC_WITH_EXCEPTIONS
4779GHC_INLINE void rename(const path& from, const path& to)
4780{
4781 std::error_code ec;
4782 rename(from, to, ec);
4783 if (ec) {
4784 throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
4785 }
4786}
4787#endif
4788
4789GHC_INLINE void rename(const path& from, const path& to, std::error_code& ec) noexcept
4790{
4791 ec.clear();
4792#ifdef GHC_OS_WINDOWS
4793 if (from != to) {
4794 if (!MoveFileExW(GHC_NATIVEWP(from), GHC_NATIVEWP(to), (DWORD)MOVEFILE_REPLACE_EXISTING)) {
4796 }
4797 }
4798#else
4799 if (from != to) {
4800 if (::rename(from.c_str(), to.c_str()) != 0) {
4802 }
4803 }
4804#endif
4805}
4806
4807#ifdef GHC_WITH_EXCEPTIONS
4808GHC_INLINE void resize_file(const path& p, uintmax_t size)
4809{
4810 std::error_code ec;
4811 resize_file(p, size, ec);
4812 if (ec) {
4813 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4814 }
4815}
4816#endif
4817
4818GHC_INLINE void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept
4819{
4820 ec.clear();
4821#ifdef GHC_OS_WINDOWS
4822 LARGE_INTEGER lisize;
4823 lisize.QuadPart = static_cast<LONGLONG>(size);
4824 if (lisize.QuadPart < 0) {
4825#ifdef ERROR_FILE_TOO_LARGE
4826 ec = detail::make_system_error(ERROR_FILE_TOO_LARGE);
4827#else
4828 ec = detail::make_system_error(223);
4829#endif
4830 return;
4831 }
4832 std::shared_ptr<void> file(CreateFileW(GHC_NATIVEWP(p), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle);
4833 if (file.get() == INVALID_HANDLE_VALUE) {
4835 }
4836 else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) {
4838 }
4839#else
4840 if (::truncate(p.c_str(), static_cast<off_t>(size)) != 0) {
4842 }
4843#endif
4844}
4845
4846#ifdef GHC_WITH_EXCEPTIONS
4847GHC_INLINE space_info space(const path& p)
4848{
4849 std::error_code ec;
4850 auto result = space(p, ec);
4851 if (ec) {
4852 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4853 }
4854 return result;
4855}
4856#endif
4857
4858GHC_INLINE space_info space(const path& p, std::error_code& ec) noexcept
4859{
4860 ec.clear();
4861#ifdef GHC_OS_WINDOWS
4862 ULARGE_INTEGER freeBytesAvailableToCaller = {{ 0, 0 }};
4863 ULARGE_INTEGER totalNumberOfBytes = {{ 0, 0 }};
4864 ULARGE_INTEGER totalNumberOfFreeBytes = {{ 0, 0 }};
4865 if (!GetDiskFreeSpaceExW(GHC_NATIVEWP(p), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) {
4867 return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)};
4868 }
4869 return {static_cast<uintmax_t>(totalNumberOfBytes.QuadPart), static_cast<uintmax_t>(totalNumberOfFreeBytes.QuadPart), static_cast<uintmax_t>(freeBytesAvailableToCaller.QuadPart)};
4870#else
4871 struct ::statvfs sfs;
4872 if (::statvfs(p.c_str(), &sfs) != 0) {
4874 return {static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1), static_cast<uintmax_t>(-1)};
4875 }
4876 return {static_cast<uintmax_t>(sfs.f_blocks * sfs.f_frsize), static_cast<uintmax_t>(sfs.f_bfree * sfs.f_frsize), static_cast<uintmax_t>(sfs.f_bavail * sfs.f_frsize)};
4877#endif
4878}
4879
4880#ifdef GHC_WITH_EXCEPTIONS
4881GHC_INLINE file_status status(const path& p)
4882{
4883 std::error_code ec;
4884 auto result = status(p, ec);
4885 if (result.type() == file_type::none) {
4886 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4887 }
4888 return result;
4889}
4890#endif
4891
4892GHC_INLINE file_status status(const path& p, std::error_code& ec) noexcept
4893{
4894 return detail::status_ex(p, ec);
4895}
4896
4898{
4899 return s.type() != file_type::none;
4900}
4901
4902#ifdef GHC_WITH_EXCEPTIONS
4903GHC_INLINE file_status symlink_status(const path& p)
4904{
4905 std::error_code ec;
4906 auto result = symlink_status(p, ec);
4907 if (result.type() == file_type::none) {
4908 throw filesystem_error(detail::systemErrorText(ec.value()), ec);
4909 }
4910 return result;
4911}
4912#endif
4913
4914GHC_INLINE file_status symlink_status(const path& p, std::error_code& ec) noexcept
4915{
4916 return detail::symlink_status_ex(p, ec);
4917}
4918
4919#ifdef GHC_WITH_EXCEPTIONS
4921{
4922 std::error_code ec;
4923 path result = temp_directory_path(ec);
4924 if (ec) {
4925 throw filesystem_error(detail::systemErrorText(ec.value()), ec);
4926 }
4927 return result;
4928}
4929#endif
4930
4931GHC_INLINE path temp_directory_path(std::error_code& ec) noexcept
4932{
4933 ec.clear();
4934#ifdef GHC_OS_WINDOWS
4935 wchar_t buffer[512];
4936 auto rc = GetTempPathW(511, buffer);
4937 if (!rc || rc > 511) {
4939 return path();
4940 }
4941 return path(std::wstring(buffer));
4942#else
4943 static const char* temp_vars[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR", nullptr};
4944 const char* temp_path = nullptr;
4945 for (auto temp_name = temp_vars; *temp_name != nullptr; ++temp_name) {
4946 temp_path = std::getenv(*temp_name);
4947 if (temp_path) {
4948 return path(temp_path);
4949 }
4950 }
4951 return path("/tmp");
4952#endif
4953}
4954
4955#ifdef GHC_WITH_EXCEPTIONS
4956GHC_INLINE path weakly_canonical(const path& p)
4957{
4958 std::error_code ec;
4959 auto result = weakly_canonical(p, ec);
4960 if (ec) {
4961 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4962 }
4963 return result;
4964}
4965#endif
4966
4967GHC_INLINE path weakly_canonical(const path& p, std::error_code& ec) noexcept
4968{
4969 path result;
4970 ec.clear();
4971 bool scan = true;
4972 for (auto pe : p) {
4973 if (scan) {
4974 std::error_code tec;
4975 if (exists(result / pe, tec)) {
4976 result /= pe;
4977 }
4978 else {
4979 if (ec) {
4980 return path();
4981 }
4982 scan = false;
4983 if (!result.empty()) {
4984 result = canonical(result, ec) / pe;
4985 if (ec) {
4986 break;
4987 }
4988 }
4989 else {
4990 result /= pe;
4991 }
4992 }
4993 }
4994 else {
4995 result /= pe;
4996 }
4997 }
4998 if (scan) {
4999 if (!result.empty()) {
5000 result = canonical(result, ec);
5001 }
5002 }
5003 return ec ? path() : result.lexically_normal();
5004}
5005
5006//-----------------------------------------------------------------------------
5007// [fs.class.file_status] class file_status
5008// [fs.file_status.cons] constructors and destructor
5010 : file_status(file_type::none)
5011{
5012}
5013
5015 : _type(ft)
5016 , _perms(prms)
5017{
5018}
5019
5021 : _type(other._type)
5022 , _perms(other._perms)
5023{
5024}
5025
5027 : _type(other._type)
5028 , _perms(other._perms)
5029{
5030}
5031
5033
5034// assignments:
5036{
5037 _type = rhs._type;
5038 _perms = rhs._perms;
5039 return *this;
5040}
5041
5043{
5044 _type = rhs._type;
5045 _perms = rhs._perms;
5046 return *this;
5047}
5048
5049// [fs.file_status.mods] modifiers
5051{
5052 _type = ft;
5053}
5054
5056{
5057 _perms = prms;
5058}
5059
5060// [fs.file_status.obs] observers
5062{
5063 return _type;
5064}
5065
5067{
5068 return _perms;
5069}
5070
5071//-----------------------------------------------------------------------------
5072// [fs.class.directory_entry] class directory_entry
5073// [fs.dir.entry.cons] constructors and destructor
5074// directory_entry::directory_entry() noexcept = default;
5075// directory_entry::directory_entry(const directory_entry&) = default;
5076// directory_entry::directory_entry(directory_entry&&) noexcept = default;
5077#ifdef GHC_WITH_EXCEPTIONS
5079 : _path(p)
5080 , _file_size(static_cast<uintmax_t>(-1))
5081#ifndef GHC_OS_WINDOWS
5082 , _hard_link_count(static_cast<uintmax_t>(-1))
5083#endif
5084 , _last_write_time(0)
5085{
5086 refresh();
5087}
5088#endif
5089
5091 : _path(p)
5092 , _file_size(static_cast<uintmax_t>(-1))
5093#ifndef GHC_OS_WINDOWS
5094 , _hard_link_count(static_cast<uintmax_t>(-1))
5095#endif
5096 , _last_write_time(0)
5097{
5098 refresh(ec);
5099}
5100
5102
5103// assignments:
5104// directory_entry& directory_entry::operator=(const directory_entry&) = default;
5105// directory_entry& directory_entry::operator=(directory_entry&&) noexcept = default;
5106
5107// [fs.dir.entry.mods] directory_entry modifiers
5108#ifdef GHC_WITH_EXCEPTIONS
5110{
5111 _path = p;
5112 refresh();
5113}
5114#endif
5115
5116GHC_INLINE void directory_entry::assign(const filesystem::path& p, std::error_code& ec)
5117{
5118 _path = p;
5119 refresh(ec);
5120}
5121
5122#ifdef GHC_WITH_EXCEPTIONS
5124{
5125 _path.replace_filename(p);
5126 refresh();
5127}
5128#endif
5129
5131{
5132 _path.replace_filename(p);
5133 refresh(ec);
5134}
5135
5136#ifdef GHC_WITH_EXCEPTIONS
5138{
5139 std::error_code ec;
5140 refresh(ec);
5141 if (ec) {
5142 throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec);
5143 }
5144}
5145#endif
5146
5147GHC_INLINE void directory_entry::refresh(std::error_code& ec) noexcept
5148{
5149#ifdef GHC_OS_WINDOWS
5150 _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, nullptr, &_last_write_time);
5151#else
5152 _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, &_hard_link_count, &_last_write_time);
5153#endif
5154}
5155
5156// [fs.dir.entry.obs] directory_entry observers
5158{
5159 return _path;
5160}
5161
5162GHC_INLINE directory_entry::operator const filesystem::path&() const noexcept
5163{
5164 return _path;
5165}
5166
5167#ifdef GHC_WITH_EXCEPTIONS
5168GHC_INLINE file_type directory_entry::status_file_type() const
5169{
5170 return _status.type() != file_type::none ? _status.type() : filesystem::status(path()).type();
5171}
5172#endif
5173
5174GHC_INLINE file_type directory_entry::status_file_type(std::error_code& ec) const noexcept
5175{
5176 if(_status.type() != file_type::none) {
5177 ec.clear();
5178 return _status.type();
5179 }
5180 return filesystem::status(path(), ec).type();
5181}
5182
5183#ifdef GHC_WITH_EXCEPTIONS
5185{
5186 return status_file_type() != file_type::not_found;
5187}
5188#endif
5189
5190GHC_INLINE bool directory_entry::exists(std::error_code& ec) const noexcept
5191{
5192 return status_file_type(ec) != file_type::not_found;
5193}
5194
5195#ifdef GHC_WITH_EXCEPTIONS
5197{
5198 return status_file_type() == file_type::block;
5199}
5200#endif
5201GHC_INLINE bool directory_entry::is_block_file(std::error_code& ec) const noexcept
5202{
5203 return status_file_type(ec) == file_type::block;
5204}
5205
5206#ifdef GHC_WITH_EXCEPTIONS
5208{
5209 return status_file_type() == file_type::character;
5210}
5211#endif
5212
5213GHC_INLINE bool directory_entry::is_character_file(std::error_code& ec) const noexcept
5214{
5215 return status_file_type(ec) == file_type::character;
5216}
5217
5218#ifdef GHC_WITH_EXCEPTIONS
5220{
5221 return status_file_type() == file_type::directory;
5222}
5223#endif
5224
5225GHC_INLINE bool directory_entry::is_directory(std::error_code& ec) const noexcept
5226{
5227 return status_file_type(ec) == file_type::directory;
5228}
5229
5230#ifdef GHC_WITH_EXCEPTIONS
5232{
5233 return status_file_type() == file_type::fifo;
5234}
5235#endif
5236
5237GHC_INLINE bool directory_entry::is_fifo(std::error_code& ec) const noexcept
5238{
5239 return status_file_type(ec) == file_type::fifo;
5240}
5241
5242#ifdef GHC_WITH_EXCEPTIONS
5244{
5245 auto ft = status_file_type();
5246 return ft != file_type::none && ft != file_type::not_found && ft != file_type::regular && ft != file_type::directory && !is_symlink();
5247}
5248#endif
5249
5250GHC_INLINE bool directory_entry::is_other(std::error_code& ec) const noexcept
5251{
5252 auto ft = status_file_type(ec);
5253 bool other = ft != file_type::none && ft != file_type::not_found && ft != file_type::regular && ft != file_type::directory && !is_symlink(ec);
5254 return !ec && other;
5255}
5256
5257#ifdef GHC_WITH_EXCEPTIONS
5259{
5260 return status_file_type() == file_type::regular;
5261}
5262#endif
5263
5264GHC_INLINE bool directory_entry::is_regular_file(std::error_code& ec) const noexcept
5265{
5266 return status_file_type(ec) == file_type::regular;
5267}
5268
5269#ifdef GHC_WITH_EXCEPTIONS
5271{
5272 return status_file_type() == file_type::socket;
5273}
5274#endif
5275
5276GHC_INLINE bool directory_entry::is_socket(std::error_code& ec) const noexcept
5277{
5278 return status_file_type(ec) == file_type::socket;
5279}
5280
5281#ifdef GHC_WITH_EXCEPTIONS
5283{
5284 return _symlink_status.type() != file_type::none ? _symlink_status.type() == file_type::symlink : filesystem::is_symlink(symlink_status());
5285}
5286#endif
5287
5288GHC_INLINE bool directory_entry::is_symlink(std::error_code& ec) const noexcept
5289{
5290 if(_symlink_status.type() != file_type::none) {
5291 ec.clear();
5292 return _symlink_status.type() == file_type::symlink;
5293 }
5295}
5296
5297#ifdef GHC_WITH_EXCEPTIONS
5298GHC_INLINE uintmax_t directory_entry::file_size() const
5299{
5300 if (_file_size != static_cast<uintmax_t>(-1)) {
5301 return _file_size;
5302 }
5303 return filesystem::file_size(path());
5304}
5305#endif
5306
5307GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexcept
5308{
5309 if (_file_size != static_cast<uintmax_t>(-1)) {
5310 ec.clear();
5311 return _file_size;
5312 }
5313 return filesystem::file_size(path(), ec);
5314}
5315
5316#ifndef GHC_OS_WEB
5317#ifdef GHC_WITH_EXCEPTIONS
5319{
5320#ifndef GHC_OS_WINDOWS
5321 if (_hard_link_count != static_cast<uintmax_t>(-1)) {
5322 return _hard_link_count;
5323 }
5324#endif
5326}
5327#endif
5328
5329GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const noexcept
5330{
5331#ifndef GHC_OS_WINDOWS
5332 if (_hard_link_count != static_cast<uintmax_t>(-1)) {
5333 ec.clear();
5334 return _hard_link_count;
5335 }
5336#endif
5337 return filesystem::hard_link_count(path(), ec);
5338}
5339#endif
5340
5341#ifdef GHC_WITH_EXCEPTIONS
5343{
5344 if (_last_write_time != 0) {
5345 return std::chrono::system_clock::from_time_t(_last_write_time);
5346 }
5348}
5349#endif
5350
5352{
5353 if (_last_write_time != 0) {
5354 ec.clear();
5355 return std::chrono::system_clock::from_time_t(_last_write_time);
5356 }
5357 return filesystem::last_write_time(path(), ec);
5358}
5359
5360#ifdef GHC_WITH_EXCEPTIONS
5362{
5363 if (_status.type() != file_type::none && _status.permissions() != perms::unknown) {
5364 return _status;
5365 }
5366 return filesystem::status(path());
5367}
5368#endif
5369
5370GHC_INLINE file_status directory_entry::status(std::error_code& ec) const noexcept
5371{
5372 if (_status.type() != file_type::none && _status.permissions() != perms::unknown) {
5373 ec.clear();
5374 return _status;
5375 }
5376 return filesystem::status(path(), ec);
5377}
5378
5379#ifdef GHC_WITH_EXCEPTIONS
5381{
5382 if (_symlink_status.type() != file_type::none && _symlink_status.permissions() != perms::unknown) {
5383 return _symlink_status;
5384 }
5386}
5387#endif
5388
5389GHC_INLINE file_status directory_entry::symlink_status(std::error_code& ec) const noexcept
5390{
5391 if (_symlink_status.type() != file_type::none && _symlink_status.permissions() != perms::unknown) {
5392 ec.clear();
5393 return _symlink_status;
5394 }
5395 return filesystem::symlink_status(path(), ec);
5396}
5397
5398#ifdef GHC_HAS_THREEWAY_COMP
5399GHC_INLINE std::strong_ordering directory_entry::operator<=>(const directory_entry& rhs) const noexcept
5400{
5401 return _path <=> rhs._path;
5402}
5403#endif
5404
5406{
5407 return _path < rhs._path;
5408}
5409
5411{
5412 return _path == rhs._path;
5413}
5414
5416{
5417 return _path != rhs._path;
5418}
5419
5421{
5422 return _path <= rhs._path;
5423}
5424
5426{
5427 return _path > rhs._path;
5428}
5429
5431{
5432 return _path >= rhs._path;
5433}
5434
5435//-----------------------------------------------------------------------------
5436// [fs.class.directory_iterator] class directory_iterator
5437
5438#ifdef GHC_OS_WINDOWS
5440{
5441public:
5442 impl(const path& p, directory_options options)
5443 : _base(p)
5444 , _options(options)
5445 , _dirHandle(INVALID_HANDLE_VALUE)
5446 {
5447 if (!_base.empty()) {
5448 ZeroMemory(&_findData, sizeof(WIN32_FIND_DATAW));
5449 if ((_dirHandle = FindFirstFileW(GHC_NATIVEWP((_base / "*")), &_findData)) != INVALID_HANDLE_VALUE) {
5450 if (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L"..") {
5451 increment(_ec);
5452 }
5453 else {
5454 _dir_entry._path = _base / std::wstring(_findData.cFileName);
5456 }
5457 }
5458 else {
5459 auto error = ::GetLastError();
5460 _base = filesystem::path();
5461 if (error != ERROR_ACCESS_DENIED || (options & directory_options::skip_permission_denied) == directory_options::none) {
5463 }
5464 }
5465 }
5466 }
5467 impl(const impl& other) = delete;
5468 ~impl()
5469 {
5470 if (_dirHandle != INVALID_HANDLE_VALUE) {
5471 FindClose(_dirHandle);
5472 _dirHandle = INVALID_HANDLE_VALUE;
5473 }
5474 }
5475 void increment(std::error_code& ec)
5476 {
5477 if (_dirHandle != INVALID_HANDLE_VALUE) {
5478 do {
5479 if (FindNextFileW(_dirHandle, &_findData)) {
5480 _dir_entry._path = _base;
5481#ifdef GHC_USE_WCHAR_T
5482 _dir_entry._path.append_name(_findData.cFileName);
5483#else
5484#ifdef GHC_RAISE_UNICODE_ERRORS
5485 try {
5486 _dir_entry._path.append_name(detail::toUtf8(_findData.cFileName).c_str());
5487 }
5488 catch (filesystem_error& fe) {
5489 ec = fe.code();
5490 return;
5491 }
5492#else
5493 _dir_entry._path.append_name(detail::toUtf8(_findData.cFileName).c_str());
5494#endif
5495#endif
5496 copyToDirEntry(ec);
5497 }
5498 else {
5499 auto err = ::GetLastError();
5500 if (err != ERROR_NO_MORE_FILES) {
5501 _ec = ec = detail::make_system_error(err);
5502 }
5503 FindClose(_dirHandle);
5504 _dirHandle = INVALID_HANDLE_VALUE;
5505 _dir_entry._path.clear();
5506 break;
5507 }
5508 } while (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L"..");
5509 }
5510 else {
5511 ec = _ec;
5512 }
5513 }
5514 void copyToDirEntry(std::error_code& ec)
5515 {
5516 if (_findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
5517 _dir_entry._status = detail::status_ex(_dir_entry._path, ec, &_dir_entry._symlink_status, &_dir_entry._file_size, nullptr, &_dir_entry._last_write_time);
5518 }
5519 else {
5520 _dir_entry._status = detail::status_from_INFO(_dir_entry._path, &_findData, ec, &_dir_entry._file_size, &_dir_entry._last_write_time);
5521 _dir_entry._symlink_status = _dir_entry._status;
5522 }
5523 if (ec) {
5524 if (_dir_entry._status.type() != file_type::none && _dir_entry._symlink_status.type() != file_type::none) {
5525 ec.clear();
5526 }
5527 else {
5528 _dir_entry._file_size = static_cast<uintmax_t>(-1);
5529 _dir_entry._last_write_time = 0;
5530 }
5531 }
5532 }
5533 path _base;
5535 WIN32_FIND_DATAW _findData;
5536 HANDLE _dirHandle;
5537 directory_entry _dir_entry;
5538 std::error_code _ec;
5539};
5540#else
5541// POSIX implementation
5543{
5544public:
5546 : _base(path)
5547 , _options(options)
5548 , _dir(nullptr)
5549 , _entry(nullptr)
5550 {
5551 if (!path.empty()) {
5552 _dir = ::opendir(path.native().c_str());
5553 if (!_dir) {
5554 auto error = errno;
5556 if ((error != EACCES && error != EPERM) || (options & directory_options::skip_permission_denied) == directory_options::none) {
5558 }
5559 }
5560 else {
5561 increment(_ec);
5562 }
5563 }
5564 }
5565 impl(const impl& other) = delete;
5567 {
5568 if (_dir) {
5569 ::closedir(_dir);
5570 }
5571 }
5572 void increment(std::error_code& ec)
5573 {
5574 if (_dir) {
5575 bool skip;
5576 do {
5577 skip = false;
5578 errno = 0;
5579 _entry = ::readdir(_dir);
5580 if (_entry) {
5581 _dir_entry._path = _base;
5582 _dir_entry._path.append_name(_entry->d_name);
5584 if (ec && (ec.value() == EACCES || ec.value() == EPERM) && (_options & directory_options::skip_permission_denied) == directory_options::skip_permission_denied) {
5585 ec.clear();
5586 skip = true;
5587 }
5588 }
5589 else {
5590 ::closedir(_dir);
5591 _dir = nullptr;
5592 _dir_entry._path.clear();
5593 if (errno) {
5595 }
5596 break;
5597 }
5598 } while (skip || std::strcmp(_entry->d_name, ".") == 0 || std::strcmp(_entry->d_name, "..") == 0);
5599 }
5600 }
5601
5603 {
5604#ifdef GHC_NO_DIRENT_D_TYPE
5605 _dir_entry._symlink_status = file_status();
5606 _dir_entry._status = file_status();
5607#else
5608 _dir_entry._symlink_status.permissions(perms::unknown);
5609 switch(_entry->d_type) {
5610 case DT_BLK: _dir_entry._symlink_status.type(file_type::block); break;
5611 case DT_CHR: _dir_entry._symlink_status.type(file_type::character); break;
5612 case DT_DIR: _dir_entry._symlink_status.type(file_type::directory); break;
5613 case DT_FIFO: _dir_entry._symlink_status.type(file_type::fifo); break;
5614 case DT_LNK: _dir_entry._symlink_status.type(file_type::symlink); break;
5615 case DT_REG: _dir_entry._symlink_status.type(file_type::regular); break;
5616 case DT_SOCK: _dir_entry._symlink_status.type(file_type::socket); break;
5617 case DT_UNKNOWN: _dir_entry._symlink_status.type(file_type::none); break;
5618 default: _dir_entry._symlink_status.type(file_type::unknown); break;
5619 }
5620 if (_entry->d_type != DT_LNK) {
5621 _dir_entry._status = _dir_entry._symlink_status;
5622 }
5623 else {
5626 }
5627#endif
5628 _dir_entry._file_size = static_cast<uintmax_t>(-1);
5629 _dir_entry._hard_link_count = static_cast<uintmax_t>(-1);
5630 _dir_entry._last_write_time = 0;
5631 }
5634 DIR* _dir;
5635 struct ::dirent* _entry;
5637 std::error_code _ec;
5638};
5639#endif
5640
5641// [fs.dir.itr.members] member functions
5643 : _impl(new impl(path(), directory_options::none))
5644{
5645}
5646
5647#ifdef GHC_WITH_EXCEPTIONS
5649 : _impl(new impl(p, directory_options::none))
5650{
5651 if (_impl->_ec) {
5652 throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec);
5653 }
5654 _impl->_ec.clear();
5655}
5656
5658 : _impl(new impl(p, options))
5659{
5660 if (_impl->_ec) {
5661 throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec);
5662 }
5663}
5664#endif
5665
5666GHC_INLINE directory_iterator::directory_iterator(const path& p, std::error_code& ec) noexcept
5667 : _impl(new impl(p, directory_options::none))
5668{
5669 if (_impl->_ec) {
5670 ec = _impl->_ec;
5671 }
5672}
5673
5674GHC_INLINE directory_iterator::directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept
5675 : _impl(new impl(p, options))
5676{
5677 if (_impl->_ec) {
5678 ec = _impl->_ec;
5679 }
5680}
5681
5683 : _impl(rhs._impl)
5684{
5685}
5686
5688 : _impl(std::move(rhs._impl))
5689{
5690}
5691
5693
5695{
5696 _impl = rhs._impl;
5697 return *this;
5698}
5699
5701{
5702 _impl = std::move(rhs._impl);
5703 return *this;
5704}
5705
5707{
5708 return _impl->_dir_entry;
5709}
5710
5712{
5713 return &_impl->_dir_entry;
5714}
5715
5716#ifdef GHC_WITH_EXCEPTIONS
5718{
5719 std::error_code ec;
5720 _impl->increment(ec);
5721 if (ec) {
5722 throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_entry._path, ec);
5723 }
5724 return *this;
5725}
5726#endif
5727
5729{
5730 _impl->increment(ec);
5731 return *this;
5732}
5733
5735{
5736 return _impl->_dir_entry._path == rhs._impl->_dir_entry._path;
5737}
5738
5740{
5741 return _impl->_dir_entry._path != rhs._impl->_dir_entry._path;
5742}
5743
5744// [fs.dir.itr.nonmembers] directory_iterator non-member functions
5745
5747{
5748 return iter;
5749}
5750
5752{
5753 return directory_iterator();
5754}
5755
5756//-----------------------------------------------------------------------------
5757// [fs.class.rec.dir.itr] class recursive_directory_iterator
5758
5760 : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
5761{
5762 _impl->_dir_iter_stack.push(directory_iterator());
5763}
5764
5765#ifdef GHC_WITH_EXCEPTIONS
5767 : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
5768{
5769 _impl->_dir_iter_stack.push(directory_iterator(p));
5770}
5771
5773 : _impl(new recursive_directory_iterator_impl(options, true))
5774{
5775 _impl->_dir_iter_stack.push(directory_iterator(p, options));
5776}
5777#endif
5778
5780 : _impl(new recursive_directory_iterator_impl(options, true))
5781{
5782 _impl->_dir_iter_stack.push(directory_iterator(p, options, ec));
5783}
5784
5786 : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
5787{
5788 _impl->_dir_iter_stack.push(directory_iterator(p, ec));
5789}
5790
5792 : _impl(rhs._impl)
5793{
5794}
5795
5797 : _impl(std::move(rhs._impl))
5798{
5799}
5800
5802
5803// [fs.rec.dir.itr.members] observers
5805{
5806 return _impl->_options;
5807}
5808
5810{
5811 return static_cast<int>(_impl->_dir_iter_stack.size() - 1);
5812}
5813
5815{
5816 return _impl->_recursion_pending;
5817}
5818
5820{
5821 return *(_impl->_dir_iter_stack.top());
5822}
5823
5825{
5826 return &(*(_impl->_dir_iter_stack.top()));
5827}
5828
5829// [fs.rec.dir.itr.members] modifiers recursive_directory_iterator&
5831{
5832 _impl = rhs._impl;
5833 return *this;
5834}
5835
5837{
5838 _impl = std::move(rhs._impl);
5839 return *this;
5840}
5841
5842#ifdef GHC_WITH_EXCEPTIONS
5844{
5845 std::error_code ec;
5846 increment(ec);
5847 if (ec) {
5848 throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec);
5849 }
5850 return *this;
5851}
5852#endif
5853
5855{
5856 bool isSymLink = (*this)->is_symlink(ec);
5857 bool isDir = !ec && (*this)->is_directory(ec);
5858 if(isSymLink && detail::is_not_found_error(ec)) {
5859 ec.clear();
5860 }
5861 if(!ec) {
5862 if (recursion_pending() && isDir && (!isSymLink || (options() & directory_options::follow_directory_symlink) != directory_options::none)) {
5863 _impl->_dir_iter_stack.push(directory_iterator((*this)->path(), _impl->_options, ec));
5864 }
5865 else {
5866 _impl->_dir_iter_stack.top().increment(ec);
5867 }
5868 if (!ec) {
5869 while (depth() && _impl->_dir_iter_stack.top() == directory_iterator()) {
5870 _impl->_dir_iter_stack.pop();
5871 _impl->_dir_iter_stack.top().increment(ec);
5872 }
5873 }
5874 else if (!_impl->_dir_iter_stack.empty()) {
5875 _impl->_dir_iter_stack.pop();
5876 }
5877 _impl->_recursion_pending = true;
5878 }
5879 return *this;
5880}
5881
5882#ifdef GHC_WITH_EXCEPTIONS
5884{
5885 std::error_code ec;
5886 pop(ec);
5887 if (ec) {
5888 throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec);
5889 }
5890}
5891#endif
5892
5894{
5895 if (depth() == 0) {
5897 }
5898 else {
5899 do {
5900 _impl->_dir_iter_stack.pop();
5901 _impl->_dir_iter_stack.top().increment(ec);
5902 } while (depth() && _impl->_dir_iter_stack.top() == directory_iterator());
5903 }
5904}
5905
5907{
5908 _impl->_recursion_pending = false;
5909}
5910
5911// other members as required by [input.iterators]
5913{
5914 return _impl->_dir_iter_stack.top() == rhs._impl->_dir_iter_stack.top();
5915}
5916
5918{
5919 return _impl->_dir_iter_stack.top() != rhs._impl->_dir_iter_stack.top();
5920}
5921
5922// [fs.rec.dir.itr.nonmembers] directory_iterator non-member functions
5924{
5925 return iter;
5926}
5927
5929{
5931}
5932
5933#endif // GHC_EXPAND_IMPL
5934
5935} // namespace filesystem
5936} // namespace ghc
5937
5938// cleanup some macros
5939#undef GHC_INLINE
5940#undef GHC_EXPAND_IMPL
5941
5942#endif // GHC_FILESYSTEM_H
EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE FixedBlockXpr< internal::get_fixed_value< NRowsType >::value, internal::get_fixed_value< NColsType >::value >::Type block(Index startRow, Index startCol, NRowsType blockRows, NColsType blockCols)
Definition: BlockMethods.h:96
you may not use this file except in compliance with the License You may obtain a copy of the License at software distributed under the License is distributed on an AS IS WITHOUT WARRANTIES OR CONDITIONS OF ANY either express or implied See the License for the specific language governing permissions and limitations under the License LLVM Exceptions to the Apache License As an if
Definition: ThirdPartyNotices.txt:292
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable or merely the Work and Derivative Works thereof Contribution shall mean any work of including the original version of the Work and any modifications or additions to that Work or Derivative Works that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner For the purposes of this submitted means any form of or written communication sent to the Licensor or its including but not limited to communication on electronic mailing source code control and issue tracking systems that are managed or on behalf the Licensor for the purpose of discussing and improving the but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as Not a Contribution Contributor shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work Grant of Copyright License Subject to the terms and conditions of this each Contributor hereby grants to You a non no royalty free
Definition: ThirdPartyNotices.txt:154
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable or merely link(or bind by name) to the interfaces of
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the work(an example is provided in the Appendix below). "Derivative Works" shall mean any work
then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file
Definition: ThirdPartyNotices.txt:195
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation source
Definition: ThirdPartyNotices.txt:114
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source code
Definition: ThirdPartyNotices.txt:113
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
Definition: ThirdPartyNotices.txt:131
An implementation of std::basic_string_view for pre-C++17.
Definition: core.h:430
\rst A contiguous memory buffer with an optional growing ability.
Definition: core.h:862
FMT_CONSTEXPR auto data() noexcept -> T *
Returns a pointer to the buffer data.
Definition: core.h:908
constexpr auto size() const noexcept -> size_t
Returns the size of this buffer.
Definition: core.h:902
Definition: filesystem.hpp:1155
const basic_filebuf & operator=(const basic_filebuf &)=delete
~basic_filebuf() override
Definition: filesystem.hpp:1158
basic_filebuf< charT, traits > * open(const path &p, std::ios_base::openmode mode)
Definition: filesystem.hpp:1161
basic_filebuf()
Definition: filesystem.hpp:1157
basic_filebuf(const basic_filebuf &)=delete
Definition: filesystem.hpp:1219
const basic_fstream & operator=(const basic_fstream &)=delete
basic_fstream(const basic_fstream &)=delete
~basic_fstream() override
Definition: filesystem.hpp:1237
basic_fstream(const path &p, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
Definition: filesystem.hpp:1229
basic_fstream()
Definition: filesystem.hpp:1221
void open(const path &p, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
Definition: filesystem.hpp:1233
Definition: filesystem.hpp:1173
basic_ifstream(const path &p, std::ios_base::openmode mode=std::ios_base::in)
Definition: filesystem.hpp:1183
basic_ifstream(const basic_ifstream &)=delete
~basic_ifstream() override
Definition: filesystem.hpp:1191
void open(const path &p, std::ios_base::openmode mode=std::ios_base::in)
Definition: filesystem.hpp:1187
basic_ifstream()
Definition: filesystem.hpp:1175
const basic_ifstream & operator=(const basic_ifstream &)=delete
Definition: filesystem.hpp:1196
const basic_ofstream & operator=(const basic_ofstream &)=delete
basic_ofstream(const basic_ofstream &)=delete
basic_ofstream()
Definition: filesystem.hpp:1198
~basic_ofstream() override
Definition: filesystem.hpp:1214
basic_ofstream(const path &p, std::ios_base::openmode mode=std::ios_base::out)
Definition: filesystem.hpp:1206
void open(const path &p, std::ios_base::openmode mode=std::ios_base::out)
Definition: filesystem.hpp:1210
Definition: filesystem.hpp:811
uintmax_t file_size(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5307
bool operator<(const directory_entry &rhs) const noexcept
Definition: filesystem.hpp:5405
file_status symlink_status(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5389
bool is_regular_file(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5264
bool is_block_file(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5201
uintmax_t hard_link_count(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5329
bool is_fifo(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5237
void assign(const path &p, std::error_code &ec)
Definition: filesystem.hpp:5116
bool operator>(const directory_entry &rhs) const noexcept
Definition: filesystem.hpp:5425
directory_entry() noexcept=default
bool exists(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5190
bool is_character_file(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5213
bool is_directory(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5225
bool is_other(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5250
void refresh(std::error_code &ec) noexcept
Definition: filesystem.hpp:5147
bool operator>=(const directory_entry &rhs) const noexcept
Definition: filesystem.hpp:5430
directory_entry & operator=(directory_entry &&) noexcept=default
bool operator<=(const directory_entry &rhs) const noexcept
Definition: filesystem.hpp:5420
file_time_type last_write_time(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5351
~directory_entry()
Definition: filesystem.hpp:5101
void replace_filename(const path &p, std::error_code &ec)
Definition: filesystem.hpp:5130
bool is_symlink(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5288
bool operator!=(const directory_entry &rhs) const noexcept
Definition: filesystem.hpp:5415
directory_entry & operator=(const directory_entry &)=default
file_status status(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5370
bool operator==(const directory_entry &rhs) const noexcept
Definition: filesystem.hpp:5410
const filesystem::path & path() const noexcept
Definition: filesystem.hpp:5157
bool is_socket(std::error_code &ec) const noexcept
Definition: filesystem.hpp:5276
Definition: filesystem.hpp:5543
~impl()
Definition: filesystem.hpp:5566
impl(const path &path, directory_options options)
Definition: filesystem.hpp:5545
std::error_code _ec
Definition: filesystem.hpp:5637
void copyToDirEntry()
Definition: filesystem.hpp:5602
struct::dirent * _entry
Definition: filesystem.hpp:5635
directory_options _options
Definition: filesystem.hpp:5633
directory_entry _dir_entry
Definition: filesystem.hpp:5636
DIR * _dir
Definition: filesystem.hpp:5634
void increment(std::error_code &ec)
Definition: filesystem.hpp:5572
path _base
Definition: filesystem.hpp:5632
Definition: filesystem.hpp:907
const directory_entry & operator*() const &noexcept
Definition: filesystem.hpp:909
directory_entry operator*() &&noexcept
Definition: filesystem.hpp:910
Definition: filesystem.hpp:904
directory_iterator & operator=(const directory_iterator &rhs)
Definition: filesystem.hpp:5694
directory_iterator() noexcept
Definition: filesystem.hpp:5642
bool operator!=(const directory_iterator &rhs) const
Definition: filesystem.hpp:5739
std::ptrdiff_t difference_type
Definition: filesystem.hpp:923
const directory_entry * operator->() const
Definition: filesystem.hpp:5711
~directory_iterator()
Definition: filesystem.hpp:5692
std::input_iterator_tag iterator_category
Definition: filesystem.hpp:921
bool operator==(const directory_iterator &rhs) const
Definition: filesystem.hpp:5734
directory_iterator & increment(std::error_code &ec) noexcept
Definition: filesystem.hpp:5728
const directory_entry & operator*() const
Definition: filesystem.hpp:5706
Definition: filesystem.hpp:784
friend bool operator==(const file_status &lhs, const file_status &rhs) noexcept
Definition: filesystem.hpp:801
~file_status()
Definition: filesystem.hpp:5032
file_status() noexcept
Definition: filesystem.hpp:5009
perms permissions() const noexcept
Definition: filesystem.hpp:5066
void type(file_type ft) noexcept
Definition: filesystem.hpp:5050
void permissions(perms prms) noexcept
Definition: filesystem.hpp:5055
file_status & operator=(const file_status &) noexcept
Definition: filesystem.hpp:5035
file_type type() const noexcept
Definition: filesystem.hpp:5061
Definition: filesystem.hpp:649
const path & path2() const noexcept
Definition: filesystem.hpp:3515
filesystem_error(const std::string &what_arg, std::error_code ec)
Definition: filesystem.hpp:3477
const char * what() const noexcept override
Definition: filesystem.hpp:3520
const path & path1() const noexcept
Definition: filesystem.hpp:3510
Definition: filesystem.hpp:328
not_implemented_exception()
Definition: filesystem.hpp:330
Definition: filesystem.hpp:338
static constexpr value_type preferred_separator
Definition: filesystem.hpp:344
char_type value_type
Definition: filesystem.hpp:340
Definition: filesystem.hpp:374
path & replace_filename(const path &replacement)
Definition: filesystem.hpp:2674
std::string u8string() const
Definition: filesystem.hpp:2758
bool has_root_directory() const
Definition: filesystem.hpp:3080
iterator const_iterator
Definition: filesystem.hpp:564
std::basic_string< value_type > string_type
Definition: filesystem.hpp:378
void clear() noexcept
Definition: filesystem.hpp:2651
path stem() const
Definition: filesystem.hpp:3022
path & remove_filename()
Definition: filesystem.hpp:2666
std::u32string u32string() const
Definition: filesystem.hpp:2774
path & make_preferred()
Definition: filesystem.hpp:2659
int compare(const path &p) const noexcept
Definition: filesystem.hpp:2864
typename std::enable_if<!std::is_same< path, T1 >::value, path >::type path_type
Definition: filesystem.hpp:415
path filename() const
Definition: filesystem.hpp:3017
bool operator==(const iterator &other) const
std::ptrdiff_t difference_type
Definition: filesystem.hpp:668
path root_name() const
Definition: filesystem.hpp:2971
bool is_relative() const
Definition: filesystem.hpp:3126
std::string generic_string() const
Definition: filesystem.hpp:2806
const path value_type
Definition: filesystem.hpp:667
typename std::enable_if< _is_basic_string< T >::value||std::is_same< char const *, typename std::decay< T >::type >::value||std::is_same< char *, typename std::decay< T >::type >::value||std::is_same< char16_t const *, typename std::decay< T >::type >::value||std::is_same< char16_t *, typename std::decay< T >::type >::value||std::is_same< char32_t const *, typename std::decay< T >::type >::value||std::is_same< char32_t *, typename std::decay< T >::type >::value||std::is_same< wchar_t const *, typename std::decay< T >::type >::value||std::is_same< wchar_t *, typename std::decay< T >::type >::value, path >::type path_from_string
Definition: filesystem.hpp:430
iterator end() const
Definition: filesystem.hpp:3355
path & append(const Source &source)
Definition: filesystem.hpp:2547
format
The path format in which the constructor argument is given.
Definition: filesystem.hpp:383
@ native_format
The format native to the current platform this code is build for.
Definition: filesystem.hpp:386
@ auto_format
Try to auto-detect the format, fallback to native.
Definition: filesystem.hpp:388
@ generic_format
The generic format, internally used by ghc::filesystem::path with slashes.
Definition: filesystem.hpp:384
std::bidirectional_iterator_tag iterator_category
Definition: filesystem.hpp:671
std::u16string generic_u16string() const
Definition: filesystem.hpp:2844
iterator operator++(int)
path extension() const
Definition: filesystem.hpp:3034
bool has_extension() const
Definition: filesystem.hpp:3112
iterator operator--(int)
bool has_stem() const
Definition: filesystem.hpp:3107
path lexically_proximate(const path &base) const
Definition: filesystem.hpp:3201
bool operator!=(const iterator &other) const
std::string generic_u8string() const
Definition: filesystem.hpp:2834
bool has_root_name() const
Definition: filesystem.hpp:3075
bool has_filename() const
Definition: filesystem.hpp:3102
std::wstring wstring() const
Definition: filesystem.hpp:2739
path & concat(const Source &x)
Definition: filesystem.hpp:2632
path relative_path() const
Definition: filesystem.hpp:2990
iterator begin() const
Definition: filesystem.hpp:3350
iterator(const path &p, const impl_string_type::const_iterator &pos)
iterator & operator--()
std::string string() const
Definition: filesystem.hpp:2730
path lexically_normal() const
Definition: filesystem.hpp:3133
path parent_path() const
Definition: filesystem.hpp:2996
bool is_absolute() const
Definition: filesystem.hpp:3117
path & replace_extension(const path &replacement=path())
Definition: filesystem.hpp:2680
~path()
Definition: filesystem.hpp:2411
void swap(path &rhs) noexcept
Definition: filesystem.hpp:2691
pointer operator->() const
bool has_parent_path() const
Definition: filesystem.hpp:3097
reference operator*() const
std::u32string generic_u32string() const
Definition: filesystem.hpp:2853
path root_directory() const
Definition: filesystem.hpp:2976
iterator & operator++()
path root_path() const
Definition: filesystem.hpp:2985
path & operator=(const path &p)
Definition: filesystem.hpp:2416
std::basic_string< EcharT, traits, Allocator > string(const Allocator &a=Allocator()) const
Definition: filesystem.hpp:2719
typename std::enable_if< std::is_same< T, char >::value||std::is_same< T, char16_t >::value||std::is_same< T, char32_t >::value||std::is_same< T, wchar_t >::value, path >::type path_type_EcharT
Definition: filesystem.hpp:432
path & operator/=(const path &p)
Definition: filesystem.hpp:2489
std::u16string u16string() const
Definition: filesystem.hpp:2768
std::wstring generic_wstring() const
Definition: filesystem.hpp:2815
path lexically_relative(const path &base) const
Definition: filesystem.hpp:3166
path & operator+=(const path &x)
Definition: filesystem.hpp:2570
const string_type & native() const noexcept
Definition: filesystem.hpp:2701
friend class path
Definition: filesystem.hpp:685
const value_type * c_str() const noexcept
Definition: filesystem.hpp:2706
path & assign(string_type &&source)
Definition: filesystem.hpp:2439
bool has_root_path() const
Definition: filesystem.hpp:3086
bool has_relative_path() const
Definition: filesystem.hpp:3091
bool empty() const noexcept
Definition: filesystem.hpp:3070
Definition: filesystem.hpp:971
recursive_directory_iterator() noexcept
Definition: filesystem.hpp:5759
void disable_recursion_pending()
Definition: filesystem.hpp:5906
std::ptrdiff_t difference_type
Definition: filesystem.hpp:975
recursive_directory_iterator & operator=(const recursive_directory_iterator &rhs)
Definition: filesystem.hpp:5830
const directory_entry * operator->() const
Definition: filesystem.hpp:5824
directory_options options() const
Definition: filesystem.hpp:5804
recursive_directory_iterator & increment(std::error_code &ec) noexcept
Definition: filesystem.hpp:5854
bool operator==(const recursive_directory_iterator &rhs) const
Definition: filesystem.hpp:5912
~recursive_directory_iterator()
Definition: filesystem.hpp:5801
int depth() const
Definition: filesystem.hpp:5809
void pop(std::error_code &ec)
Definition: filesystem.hpp:5893
bool operator!=(const recursive_directory_iterator &rhs) const
Definition: filesystem.hpp:5917
const directory_entry & operator*() const
Definition: filesystem.hpp:5819
bool recursion_pending() const
Definition: filesystem.hpp:5814
std::input_iterator_tag iterator_category
Definition: filesystem.hpp:973
Definition: filesystem.hpp:1250
~u8arguments()
Definition: filesystem.hpp:1253
bool valid() const
Definition: filesystem.hpp:1259
u8arguments(int &argc, char **&argv)
Definition: filesystem.hpp:2327
Definition: core.h:1240
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2318
constexpr auto count() -> size_t
Definition: core.h:1204
type
Definition: core.h:575
@ string_type
@ char_type
#define GHC_INLINE
Definition: filesystem.hpp:136
#define GHC_WIN_AUTO_PREFIX_LONG_PATH
Definition: filesystem.hpp:299
#define GHC_NATIVEWP(p)
#define UTIME_OMIT
#define GHC_PLATFORM_LITERAL(str)
#define GHC_FS_API_CLASS
Definition: filesystem.hpp:141
#define GHC_FS_API
Definition: filesystem.hpp:138
auto system_error(int error_code, format_string< T... > fmt, T &&... args) -> std::system_error
\rst Constructs :class:std::system_error with a message formatted with fmt::format(fmt,...
Definition: format.h:3622
FMT_CONSTEXPR fp operator*(fp x, fp y)
Definition: format.h:1474
constexpr auto underlying(Enum e) noexcept -> underlying_t< Enum >
\rst Converts e to the underlying type.
Definition: format.h:3830
static const symbolic::SymbolExpr< internal::symbolic_last_tag > last
Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last...
Definition: IndexedViewHelper.h:38
constexpr common_t< T1, T2 > max(const T1 x, const T2 y) noexcept
Compile-time pairwise maximum function.
Definition: max.hpp:35
constexpr common_t< T1, T2 > min(const T1 x, const T2 y) noexcept
Compile-time pairwise minimum function.
Definition: min.hpp:35
EIGEN_CONSTEXPR Index size(const T &x)
Definition: Meta.h:479
EIGEN_CONSTEXPR Index first(const T &x) EIGEN_NOEXCEPT
Definition: IndexedViewHelper.h:81
::uint16_t uint16_t
Definition: Meta.h:54
::uint32_t uint32_t
Definition: Meta.h:56
::uint8_t uint8_t
Definition: Meta.h:52
Definition: chrono.h:303
auto write(OutputIt out, const std::tm &time, const std::locale &loc, char format, char modifier=0) -> OutputIt
Definition: chrono.h:426
result
Definition: format.h:2556
@ error
Definition: format.h:2559
Definition: fs.h:44
GHC_FS_API bool is_high_surrogate(uint32_t c)
Definition: filesystem.hpp:1430
StringType fromUtf8(const Utf8String &utf8String, const typename StringType::allocator_type &alloc=typename StringType::allocator_type())
Definition: filesystem.hpp:1507
GHC_INLINE void create_hardlink(const path &target_name, const path &new_hardlink, std::error_code &ec)
Definition: filesystem.hpp:1953
GHC_INLINE file_status file_status_from_st_mode(T mode)
Definition: filesystem.hpp:1963
GHC_INLINE const char * strerror_adapter(char *gnu, char *)
Definition: filesystem.hpp:1847
GHC_INLINE int compare_simple_insensitive(const path::value_type *str1, size_t len1, const path::value_type *str2, size_t len2)
Definition: filesystem.hpp:1830
GHC_INLINE file_status symlink_status_ex(const path &p, std::error_code &ec, uintmax_t *sz=nullptr, uintmax_t *nhl=nullptr, time_t *lwt=nullptr) noexcept
Definition: filesystem.hpp:2207
GHC_INLINE bool equals_simple_insensitive(const path::value_type *str1, const path::value_type *str2)
Definition: filesystem.hpp:1809
GHC_FS_API unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t &codepoint)
Definition: filesystem.hpp:1472
portable_error
Definition: filesystem.hpp:1284
GHC_INLINE bool is_not_found_error(std::error_code &ec)
Definition: filesystem.hpp:2198
GHC_INLINE std::string systemErrorText(ErrorNumber code=0)
Definition: filesystem.hpp:1861
GHC_FS_API std::error_code make_error_code(portable_error err)
Definition: filesystem.hpp:1305
GHC_INLINE file_status status_ex(const path &p, std::error_code &ec, file_status *sls=nullptr, uintmax_t *sz=nullptr, uintmax_t *nhl=nullptr, time_t *lwt=nullptr, int recurse_count=0) noexcept
Definition: filesystem.hpp:2245
GHC_FS_API void appendUTF8(std::string &str, uint32_t unicode)
Definition: filesystem.hpp:1440
typename std::enable_if< std::is_same< Enum, perms >::value||std::is_same< Enum, perm_options >::value||std::is_same< Enum, copy_options >::value||std::is_same< Enum, directory_options >::value, Enum >::type EnableBitmask
Definition: filesystem.hpp:1364
GHC_INLINE bool endsWith(const strT &what, const strT &with)
Definition: filesystem.hpp:1714
GHC_FS_API bool is_low_surrogate(uint32_t c)
Definition: filesystem.hpp:1435
GHC_INLINE path resolveSymlink(const path &p, std::error_code &ec)
Definition: filesystem.hpp:2063
std::string toUtf8(const strT &unicodeString)
Definition: filesystem.hpp:1596
GHC_FS_API bool is_surrogate(uint32_t c)
Definition: filesystem.hpp:1425
GHC_INLINE bool validUtf8(const std::string &utf8String)
Definition: filesystem.hpp:1484
GHC_INLINE bool in_range(uint32_t c, uint32_t lo, uint32_t hi)
Definition: filesystem.hpp:1420
utf8_states_t
Definition: filesystem.hpp:1278
@ S_STRT
Definition: filesystem.hpp:1278
@ S_RJCT
Definition: filesystem.hpp:1278
GHC_FS_API std::error_code make_system_error(int err=0)
Definition: filesystem.hpp:1355
GHC_INLINE bool startsWith(const strT &what, const strT &with)
Definition: filesystem.hpp:1708
GHC_INLINE void create_symlink(const path &target_name, const path &new_symlink, bool, std::error_code &ec)
Definition: filesystem.hpp:1945
GHC_FS_API file_status status(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4892
GHC_FS_API bool equivalent(const path &p1, const path &p2, std::error_code &ec) noexcept
Definition: filesystem.hpp:4150
constexpr detail::EnableBitmask< Enum > operator&(Enum X, Enum Y)
Definition: filesystem.hpp:1368
GHC_FS_API path proximate(const path &p, std::error_code &ec)
GHC_FS_API file_time_type last_write_time(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4454
GHC_FS_API size_t hash_value(const path &p) noexcept
Definition: filesystem.hpp:3367
GHC_FS_API path current_path(std::error_code &ec)
Definition: filesystem.hpp:4070
perms
Definition: filesystem.hpp:720
GHC_FS_API bool exists(file_status s) noexcept
Definition: filesystem.hpp:4117
GHC_FS_API path read_symlink(const path &p, std::error_code &ec)
Definition: filesystem.hpp:4631
GHC_FS_API path canonical(const path &p, std::error_code &ec)
Definition: filesystem.hpp:3600
GHC_FS_API bool is_socket(file_status s) noexcept
Definition: filesystem.hpp:4408
GHC_FS_API path absolute(const path &p, std::error_code &ec)
Definition: filesystem.hpp:3539
std::basic_ostream< charT, traits > & operator<<(std::basic_ostream< charT, traits > &os, const path &p)
Definition: filesystem.hpp:3421
path u8path(const Source &source)
Definition: filesystem.hpp:1788
constexpr detail::EnableBitmask< Enum > operator^(Enum X, Enum Y)
Definition: filesystem.hpp:1382
GHC_FS_API bool is_symlink(file_status s) noexcept
Definition: filesystem.hpp:4425
directory_options
Definition: filesystem.hpp:776
GHC_FS_API uintmax_t remove_all(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4732
file_type
Definition: filesystem.hpp:706
GHC_FS_API bool is_block_file(file_status s) noexcept
Definition: filesystem.hpp:4272
GHC_FS_API directory_iterator begin(directory_iterator iter) noexcept
Definition: filesystem.hpp:5746
GHC_FS_API bool is_regular_file(file_status s) noexcept
Definition: filesystem.hpp:4391
GHC_FS_API space_info space(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4858
GHC_FS_API directory_iterator end(const directory_iterator &) noexcept
Definition: filesystem.hpp:5751
GHC_FS_API void permissions(const path &p, perms prms, std::error_code &ec) noexcept
Definition: filesystem.hpp:4545
detail::EnableBitmask< Enum > & operator&=(Enum &X, Enum Y)
Definition: filesystem.hpp:1396
std::chrono::time_point< std::chrono::system_clock > file_time_type
Definition: filesystem.hpp:807
GHC_FS_API file_status symlink_status(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4914
constexpr detail::EnableBitmask< Enum > operator~(Enum X)
Definition: filesystem.hpp:1389
basic_fstream< wchar_t > wfstream
Definition: filesystem.hpp:1247
constexpr detail::EnableBitmask< Enum > operator|(Enum X, Enum Y)
Definition: filesystem.hpp:1375
GHC_FS_API path weakly_canonical(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4967
GHC_FS_API bool is_fifo(file_status s) noexcept
Definition: filesystem.hpp:4357
GHC_FS_API bool is_empty(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4335
GHC_FS_API bool operator<=(const path &lhs, const path &rhs) noexcept
Definition: filesystem.hpp:3394
GHC_FS_API bool create_directory(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:3948
GHC_FS_API bool operator==(const path &lhs, const path &rhs) noexcept
Definition: filesystem.hpp:3379
basic_filebuf< char > filebuf
Definition: filesystem.hpp:1240
GHC_FS_API uintmax_t hard_link_count(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4242
GHC_FS_API void resize_file(const path &p, uintmax_t size, std::error_code &ec) noexcept
Definition: filesystem.hpp:4818
GHC_FS_API void create_hard_link(const path &to, const path &new_hard_link, std::error_code &ec) noexcept
Definition: filesystem.hpp:4036
copy_options
Definition: filesystem.hpp:756
std::basic_istream< charT, traits > & operator>>(std::basic_istream< charT, traits > &is, path &p)
Definition: filesystem.hpp:3436
basic_filebuf< wchar_t > wfilebuf
Definition: filesystem.hpp:1241
GHC_FS_API void copy_symlink(const path &existing_symlink, const path &new_symlink, std::error_code &ec) noexcept
Definition: filesystem.hpp:3872
basic_ifstream< wchar_t > wifstream
Definition: filesystem.hpp:1243
detail::EnableBitmask< Enum > & operator|=(Enum &X, Enum Y)
Definition: filesystem.hpp:1403
GHC_FS_API bool operator>(const path &lhs, const path &rhs) noexcept
Definition: filesystem.hpp:3399
GHC_FS_API bool create_directories(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:3898
basic_ofstream< char > ofstream
Definition: filesystem.hpp:1244
GHC_FS_API path operator/(const path &lhs, const path &rhs)
Definition: filesystem.hpp:3409
basic_fstream< char > fstream
Definition: filesystem.hpp:1246
GHC_FS_API bool operator<(const path &lhs, const path &rhs) noexcept
Definition: filesystem.hpp:3389
GHC_FS_API path relative(const path &p, std::error_code &ec)
Definition: filesystem.hpp:4642
GHC_FS_API uintmax_t file_size(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4209
GHC_FS_API void swap(path &lhs, path &rhs) noexcept
Definition: filesystem.hpp:3362
GHC_FS_API void copy(const path &from, const path &to, std::error_code &ec) noexcept
Definition: filesystem.hpp:3679
GHC_FS_API bool is_directory(file_status s) noexcept
Definition: filesystem.hpp:4306
perm_options
Definition: filesystem.hpp:748
GHC_FS_API bool is_other(file_status s) noexcept
Definition: filesystem.hpp:4374
GHC_FS_API bool is_character_file(file_status s) noexcept
Definition: filesystem.hpp:4289
basic_ofstream< wchar_t > wofstream
Definition: filesystem.hpp:1245
GHC_FS_API bool operator!=(const path &lhs, const path &rhs) noexcept
Definition: filesystem.hpp:3384
GHC_FS_API bool copy_file(const path &from, const path &to, std::error_code &ec) noexcept
Definition: filesystem.hpp:3779
GHC_FS_API path temp_directory_path(std::error_code &ec) noexcept
Definition: filesystem.hpp:4931
basic_ifstream< char > ifstream
Definition: filesystem.hpp:1242
GHC_FS_API bool operator>=(const path &lhs, const path &rhs) noexcept
Definition: filesystem.hpp:3404
detail::EnableBitmask< Enum > & operator^=(Enum &X, Enum Y)
Definition: filesystem.hpp:1410
GHC_FS_API void create_symlink(const path &to, const path &new_symlink, std::error_code &ec) noexcept
Definition: filesystem.hpp:4053
GHC_FS_API bool remove(const path &p, std::error_code &ec) noexcept
Definition: filesystem.hpp:4671
GHC_FS_API void create_directory_symlink(const path &to, const path &new_symlink, std::error_code &ec) noexcept
Definition: filesystem.hpp:4019
GHC_FS_API void rename(const path &from, const path &to, std::error_code &ec) noexcept
Definition: filesystem.hpp:4789
GHC_FS_API bool status_known(file_status s) noexcept
Definition: filesystem.hpp:4897
Definition: filesystem.hpp:313
Definition: StdDeque.h:50
void swap(wpi::SmallVectorImpl< T > &LHS, wpi::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
Definition: SmallVector.h:1299
static constexpr const velocity::meters_per_second_t c(299792458.0)
Speed of light in vacuum.
cubed< length::millimeter > L
Definition: volume.h:49
unit_t< Units, T, NonLinearScale > & operator/=(unit_t< Units, T, NonLinearScale > &lhs, const RhsType &rhs) noexcept
Definition: base.h:2313
unit_t< Units, T, NonLinearScale > & operator+=(unit_t< Units, T, NonLinearScale > &lhs, const RhsType &rhs) noexcept
Definition: base.h:2281
b
Definition: data.h:44
unit_t< Units, T, NonLinearScale > & operator++(unit_t< Units, T, NonLinearScale > &u) noexcept
Definition: base.h:2335
unit_t< Units, T, NonLinearScale > & operator--(unit_t< Units, T, NonLinearScale > &u) noexcept
Definition: base.h:2359
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition: Endian.h:65
@ native
Definition: Endian.h:27
const std::error_category & system_category() noexcept
Definition: os.h:210
Definition: filesystem.hpp:393
Definition: filesystem.hpp:698
uintmax_t free
Definition: filesystem.hpp:700
uintmax_t available
Definition: filesystem.hpp:701
uintmax_t capacity
Definition: filesystem.hpp:699
intptr_t ssize_t
Definition: win.h:27
auto format(wformat_string< T... > fmt, T &&... args) -> std::wstring
Definition: xchar.h:87