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