blob: d24751b716e30cac0e3e6edde4904c40f25bd8f5 [file] [log] [blame]
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001// -*- C++ -*-
2//===--------------------------- filesystem -------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier02cea5e2018-07-27 03:07:09 +00007//
8//===----------------------------------------------------------------------===//
9#ifndef _LIBCPP_FILESYSTEM
10#define _LIBCPP_FILESYSTEM
11/*
12 filesystem synopsis
13
14 namespace std { namespace filesystem {
15
16 class path;
17
18 void swap(path& lhs, path& rhs) noexcept;
19 size_t hash_value(const path& p) noexcept;
20
21 bool operator==(const path& lhs, const path& rhs) noexcept;
22 bool operator!=(const path& lhs, const path& rhs) noexcept;
23 bool operator< (const path& lhs, const path& rhs) noexcept;
24 bool operator<=(const path& lhs, const path& rhs) noexcept;
25 bool operator> (const path& lhs, const path& rhs) noexcept;
26 bool operator>=(const path& lhs, const path& rhs) noexcept;
27
28 path operator/ (const path& lhs, const path& rhs);
29
30 // fs.path.io operators are friends of path.
31 template <class charT, class traits>
32 friend basic_ostream<charT, traits>&
33 operator<<(basic_ostream<charT, traits>& os, const path& p);
34
35 template <class charT, class traits>
36 friend basic_istream<charT, traits>&
37 operator>>(basic_istream<charT, traits>& is, path& p);
38
39 template <class Source>
40 path u8path(const Source& source);
41 template <class InputIterator>
42 path u8path(InputIterator first, InputIterator last);
43
44 class filesystem_error;
45 class directory_entry;
46
47 class directory_iterator;
48
49 // enable directory_iterator range-based for statements
50 directory_iterator begin(directory_iterator iter) noexcept;
51 directory_iterator end(const directory_iterator&) noexcept;
52
53 class recursive_directory_iterator;
54
55 // enable recursive_directory_iterator range-based for statements
56 recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
57 recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
58
59 class file_status;
60
61 struct space_info
62 {
63 uintmax_t capacity;
64 uintmax_t free;
65 uintmax_t available;
66 };
67
68 enum class file_type;
69 enum class perms;
70 enum class perm_options;
71 enum class copy_options;
72 enum class directory_options;
73
74 typedef chrono::time_point<trivial-clock> file_time_type;
75
76 // operational functions
77
78 path absolute(const path& p);
79 path absolute(const path& p, error_code &ec);
80
81 path canonical(const path& p);
82 path canonical(const path& p, error_code& ec);
83
84 void copy(const path& from, const path& to);
85 void copy(const path& from, const path& to, error_code& ec);
86 void copy(const path& from, const path& to, copy_options options);
87 void copy(const path& from, const path& to, copy_options options,
88 error_code& ec);
89
90 bool copy_file(const path& from, const path& to);
91 bool copy_file(const path& from, const path& to, error_code& ec);
92 bool copy_file(const path& from, const path& to, copy_options option);
93 bool copy_file(const path& from, const path& to, copy_options option,
94 error_code& ec);
95
96 void copy_symlink(const path& existing_symlink, const path& new_symlink);
97 void copy_symlink(const path& existing_symlink, const path& new_symlink,
98 error_code& ec) noexcept;
99
100 bool create_directories(const path& p);
101 bool create_directories(const path& p, error_code& ec);
102
103 bool create_directory(const path& p);
104 bool create_directory(const path& p, error_code& ec) noexcept;
105
106 bool create_directory(const path& p, const path& attributes);
107 bool create_directory(const path& p, const path& attributes,
108 error_code& ec) noexcept;
109
110 void create_directory_symlink(const path& to, const path& new_symlink);
111 void create_directory_symlink(const path& to, const path& new_symlink,
112 error_code& ec) noexcept;
113
114 void create_hard_link(const path& to, const path& new_hard_link);
115 void create_hard_link(const path& to, const path& new_hard_link,
116 error_code& ec) noexcept;
117
118 void create_symlink(const path& to, const path& new_symlink);
119 void create_symlink(const path& to, const path& new_symlink,
120 error_code& ec) noexcept;
121
122 path current_path();
123 path current_path(error_code& ec);
124 void current_path(const path& p);
125 void current_path(const path& p, error_code& ec) noexcept;
126
127 bool exists(file_status s) noexcept;
128 bool exists(const path& p);
129 bool exists(const path& p, error_code& ec) noexcept;
130
131 bool equivalent(const path& p1, const path& p2);
132 bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
133
134 uintmax_t file_size(const path& p);
135 uintmax_t file_size(const path& p, error_code& ec) noexcept;
136
137 uintmax_t hard_link_count(const path& p);
138 uintmax_t hard_link_count(const path& p, error_code& ec) noexcept;
139
140 bool is_block_file(file_status s) noexcept;
141 bool is_block_file(const path& p);
142 bool is_block_file(const path& p, error_code& ec) noexcept;
143
144 bool is_character_file(file_status s) noexcept;
145 bool is_character_file(const path& p);
146 bool is_character_file(const path& p, error_code& ec) noexcept;
147
148 bool is_directory(file_status s) noexcept;
149 bool is_directory(const path& p);
150 bool is_directory(const path& p, error_code& ec) noexcept;
151
152 bool is_empty(const path& p);
153 bool is_empty(const path& p, error_code& ec) noexcept;
154
155 bool is_fifo(file_status s) noexcept;
156 bool is_fifo(const path& p);
157 bool is_fifo(const path& p, error_code& ec) noexcept;
158
159 bool is_other(file_status s) noexcept;
160 bool is_other(const path& p);
161 bool is_other(const path& p, error_code& ec) noexcept;
162
163 bool is_regular_file(file_status s) noexcept;
164 bool is_regular_file(const path& p);
165 bool is_regular_file(const path& p, error_code& ec) noexcept;
166
167 bool is_socket(file_status s) noexcept;
168 bool is_socket(const path& p);
169 bool is_socket(const path& p, error_code& ec) noexcept;
170
171 bool is_symlink(file_status s) noexcept;
172 bool is_symlink(const path& p);
173 bool is_symlink(const path& p, error_code& ec) noexcept;
174
175 file_time_type last_write_time(const path& p);
176 file_time_type last_write_time(const path& p, error_code& ec) noexcept;
177 void last_write_time(const path& p, file_time_type new_time);
178 void last_write_time(const path& p, file_time_type new_time,
179 error_code& ec) noexcept;
180
181 void permissions(const path& p, perms prms,
182 perm_options opts=perm_options::replace);
183 void permissions(const path& p, perms prms, error_code& ec) noexcept;
184 void permissions(const path& p, perms prms, perm_options opts,
185 error_code& ec);
186
187 path proximate(const path& p, error_code& ec);
188 path proximate(const path& p, const path& base = current_path());
189 path proximate(const path& p, const path& base, error_code &ec);
190
191 path read_symlink(const path& p);
192 path read_symlink(const path& p, error_code& ec);
193
194 path relative(const path& p, error_code& ec);
195 path relative(const path& p, const path& base=current_path());
196 path relative(const path& p, const path& base, error_code& ec);
197
198 bool remove(const path& p);
199 bool remove(const path& p, error_code& ec) noexcept;
200
201 uintmax_t remove_all(const path& p);
202 uintmax_t remove_all(const path& p, error_code& ec);
203
204 void rename(const path& from, const path& to);
205 void rename(const path& from, const path& to, error_code& ec) noexcept;
206
207 void resize_file(const path& p, uintmax_t size);
208 void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept;
209
210 space_info space(const path& p);
211 space_info space(const path& p, error_code& ec) noexcept;
212
213 file_status status(const path& p);
214 file_status status(const path& p, error_code& ec) noexcept;
215
216 bool status_known(file_status s) noexcept;
217
218 file_status symlink_status(const path& p);
219 file_status symlink_status(const path& p, error_code& ec) noexcept;
220
221 path temp_directory_path();
222 path temp_directory_path(error_code& ec);
223
224 path weakly_canonical(path const& p);
225 path weakly_canonical(path const& p, error_code& ec);
226
227
228} } // namespaces std::filesystem
229
230*/
231
232#include <__config>
Louis Dionne73912b22020-11-04 15:01:25 -0500233#include <__availability>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000234#include <cstddef>
235#include <cstdlib>
236#include <chrono>
237#include <iterator>
238#include <iosfwd>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000239#include <memory>
240#include <stack>
241#include <string>
242#include <system_error>
243#include <utility>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000244#include <string_view>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000245#include <version>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000246
Louis Dionne8d053eb2020-10-09 15:31:05 -0400247#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
248# include <locale>
249# include <iomanip> // for quoted
250#endif
251
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000252#include <__debug>
253
254#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
255#pragma GCC system_header
256#endif
257
258_LIBCPP_PUSH_MACROS
259#include <__undef_macros>
260
261#ifndef _LIBCPP_CXX03_LANG
262
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000263_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
264
Louis Dionnef6bf76a2019-03-20 21:18:14 +0000265_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
266
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000267typedef chrono::time_point<_FilesystemClock> file_time_type;
268
269struct _LIBCPP_TYPE_VIS space_info {
270 uintmax_t capacity;
271 uintmax_t free;
272 uintmax_t available;
273};
274
275enum class _LIBCPP_ENUM_VIS file_type : signed char {
276 none = 0,
277 not_found = -1,
278 regular = 1,
279 directory = 2,
280 symlink = 3,
281 block = 4,
282 character = 5,
283 fifo = 6,
284 socket = 7,
285 unknown = 8
286};
287
288enum class _LIBCPP_ENUM_VIS perms : unsigned {
289 none = 0,
290
291 owner_read = 0400,
292 owner_write = 0200,
293 owner_exec = 0100,
294 owner_all = 0700,
295
296 group_read = 040,
297 group_write = 020,
298 group_exec = 010,
299 group_all = 070,
300
301 others_read = 04,
302 others_write = 02,
303 others_exec = 01,
304 others_all = 07,
305
306 all = 0777,
307
308 set_uid = 04000,
309 set_gid = 02000,
310 sticky_bit = 01000,
311 mask = 07777,
312 unknown = 0xFFFF,
313};
314
315_LIBCPP_INLINE_VISIBILITY
316inline constexpr perms operator&(perms _LHS, perms _RHS) {
317 return static_cast<perms>(static_cast<unsigned>(_LHS) &
318 static_cast<unsigned>(_RHS));
319}
320
321_LIBCPP_INLINE_VISIBILITY
322inline constexpr perms operator|(perms _LHS, perms _RHS) {
323 return static_cast<perms>(static_cast<unsigned>(_LHS) |
324 static_cast<unsigned>(_RHS));
325}
326
327_LIBCPP_INLINE_VISIBILITY
328inline constexpr perms operator^(perms _LHS, perms _RHS) {
329 return static_cast<perms>(static_cast<unsigned>(_LHS) ^
330 static_cast<unsigned>(_RHS));
331}
332
333_LIBCPP_INLINE_VISIBILITY
334inline constexpr perms operator~(perms _LHS) {
335 return static_cast<perms>(~static_cast<unsigned>(_LHS));
336}
337
338_LIBCPP_INLINE_VISIBILITY
339inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
340
341_LIBCPP_INLINE_VISIBILITY
342inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
343
344_LIBCPP_INLINE_VISIBILITY
345inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
346
347enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
348 replace = 1,
349 add = 2,
350 remove = 4,
351 nofollow = 8
352};
353
354_LIBCPP_INLINE_VISIBILITY
355inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) {
356 return static_cast<perm_options>(static_cast<unsigned>(_LHS) &
357 static_cast<unsigned>(_RHS));
358}
359
360_LIBCPP_INLINE_VISIBILITY
361inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) {
362 return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
363 static_cast<unsigned>(_RHS));
364}
365
366_LIBCPP_INLINE_VISIBILITY
367inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) {
368 return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
369 static_cast<unsigned>(_RHS));
370}
371
372_LIBCPP_INLINE_VISIBILITY
373inline constexpr perm_options operator~(perm_options _LHS) {
374 return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
375}
376
377_LIBCPP_INLINE_VISIBILITY
378inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
379 return _LHS = _LHS & _RHS;
380}
381
382_LIBCPP_INLINE_VISIBILITY
383inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
384 return _LHS = _LHS | _RHS;
385}
386
387_LIBCPP_INLINE_VISIBILITY
388inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
389 return _LHS = _LHS ^ _RHS;
390}
391
392enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
393 none = 0,
394 skip_existing = 1,
395 overwrite_existing = 2,
396 update_existing = 4,
397 recursive = 8,
398 copy_symlinks = 16,
399 skip_symlinks = 32,
400 directories_only = 64,
401 create_symlinks = 128,
402 create_hard_links = 256,
403 __in_recursive_copy = 512,
404};
405
406_LIBCPP_INLINE_VISIBILITY
407inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) {
408 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) &
409 static_cast<unsigned short>(_RHS));
410}
411
412_LIBCPP_INLINE_VISIBILITY
413inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) {
414 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
415 static_cast<unsigned short>(_RHS));
416}
417
418_LIBCPP_INLINE_VISIBILITY
419inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) {
420 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
421 static_cast<unsigned short>(_RHS));
422}
423
424_LIBCPP_INLINE_VISIBILITY
425inline constexpr copy_options operator~(copy_options _LHS) {
426 return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
427}
428
429_LIBCPP_INLINE_VISIBILITY
430inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
431 return _LHS = _LHS & _RHS;
432}
433
434_LIBCPP_INLINE_VISIBILITY
435inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
436 return _LHS = _LHS | _RHS;
437}
438
439_LIBCPP_INLINE_VISIBILITY
440inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
441 return _LHS = _LHS ^ _RHS;
442}
443
444enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
445 none = 0,
446 follow_directory_symlink = 1,
447 skip_permission_denied = 2
448};
449
450_LIBCPP_INLINE_VISIBILITY
451inline constexpr directory_options operator&(directory_options _LHS,
452 directory_options _RHS) {
453 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
454 static_cast<unsigned char>(_RHS));
455}
456
457_LIBCPP_INLINE_VISIBILITY
458inline constexpr directory_options operator|(directory_options _LHS,
459 directory_options _RHS) {
460 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
461 static_cast<unsigned char>(_RHS));
462}
463
464_LIBCPP_INLINE_VISIBILITY
465inline constexpr directory_options operator^(directory_options _LHS,
466 directory_options _RHS) {
467 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
468 static_cast<unsigned char>(_RHS));
469}
470
471_LIBCPP_INLINE_VISIBILITY
472inline constexpr directory_options operator~(directory_options _LHS) {
473 return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
474}
475
476_LIBCPP_INLINE_VISIBILITY
477inline directory_options& operator&=(directory_options& _LHS,
478 directory_options _RHS) {
479 return _LHS = _LHS & _RHS;
480}
481
482_LIBCPP_INLINE_VISIBILITY
483inline directory_options& operator|=(directory_options& _LHS,
484 directory_options _RHS) {
485 return _LHS = _LHS | _RHS;
486}
487
488_LIBCPP_INLINE_VISIBILITY
489inline directory_options& operator^=(directory_options& _LHS,
490 directory_options _RHS) {
491 return _LHS = _LHS ^ _RHS;
492}
493
494class _LIBCPP_TYPE_VIS file_status {
495public:
496 // constructors
497 _LIBCPP_INLINE_VISIBILITY
498 file_status() noexcept : file_status(file_type::none) {}
499 _LIBCPP_INLINE_VISIBILITY
500 explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
501 : __ft_(__ft),
502 __prms_(__prms) {}
503
504 file_status(const file_status&) noexcept = default;
505 file_status(file_status&&) noexcept = default;
506
507 _LIBCPP_INLINE_VISIBILITY
508 ~file_status() {}
509
510 file_status& operator=(const file_status&) noexcept = default;
511 file_status& operator=(file_status&&) noexcept = default;
512
513 // observers
514 _LIBCPP_INLINE_VISIBILITY
515 file_type type() const noexcept { return __ft_; }
516
517 _LIBCPP_INLINE_VISIBILITY
518 perms permissions() const noexcept { return __prms_; }
519
520 // modifiers
521 _LIBCPP_INLINE_VISIBILITY
522 void type(file_type __ft) noexcept { __ft_ = __ft; }
523
524 _LIBCPP_INLINE_VISIBILITY
525 void permissions(perms __p) noexcept { __prms_ = __p; }
526
527private:
528 file_type __ft_;
529 perms __prms_;
530};
531
532class _LIBCPP_TYPE_VIS directory_entry;
533
534template <class _Tp>
535struct __can_convert_char {
536 static const bool value = false;
537};
538template <class _Tp>
539struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
540template <>
541struct __can_convert_char<char> {
542 static const bool value = true;
543 using __char_type = char;
544};
545template <>
546struct __can_convert_char<wchar_t> {
547 static const bool value = true;
548 using __char_type = wchar_t;
549};
Martin Storsjöe3a71972020-10-26 13:18:46 +0200550#ifndef _LIBCPP_NO_HAS_CHAR8_T
551template <>
552struct __can_convert_char<char8_t> {
553 static const bool value = true;
554 using __char_type = char8_t;
555};
556#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000557template <>
558struct __can_convert_char<char16_t> {
559 static const bool value = true;
560 using __char_type = char16_t;
561};
562template <>
563struct __can_convert_char<char32_t> {
564 static const bool value = true;
565 using __char_type = char32_t;
566};
567
568template <class _ECharT>
569typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
570__is_separator(_ECharT __e) {
571 return __e == _ECharT('/');
Eric Fiselierb41db9a2018-10-01 01:59:37 +0000572}
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000573
Martin Storsjö2ae96532020-10-27 11:46:06 +0200574struct _NullSentinel {};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000575
576template <class _Tp>
577using _Void = void;
578
579template <class _Tp, class = void>
580struct __is_pathable_string : public false_type {};
581
582template <class _ECharT, class _Traits, class _Alloc>
583struct __is_pathable_string<
584 basic_string<_ECharT, _Traits, _Alloc>,
585 _Void<typename __can_convert_char<_ECharT>::__char_type> >
586 : public __can_convert_char<_ECharT> {
587 using _Str = basic_string<_ECharT, _Traits, _Alloc>;
588 using _Base = __can_convert_char<_ECharT>;
589 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
590 static _ECharT const* __range_end(_Str const& __s) {
591 return __s.data() + __s.length();
592 }
593 static _ECharT __first_or_null(_Str const& __s) {
594 return __s.empty() ? _ECharT{} : __s[0];
595 }
596};
597
598template <class _ECharT, class _Traits>
599struct __is_pathable_string<
600 basic_string_view<_ECharT, _Traits>,
601 _Void<typename __can_convert_char<_ECharT>::__char_type> >
602 : public __can_convert_char<_ECharT> {
603 using _Str = basic_string_view<_ECharT, _Traits>;
604 using _Base = __can_convert_char<_ECharT>;
605 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
606 static _ECharT const* __range_end(_Str const& __s) {
607 return __s.data() + __s.length();
608 }
609 static _ECharT __first_or_null(_Str const& __s) {
610 return __s.empty() ? _ECharT{} : __s[0];
611 }
612};
613
614template <class _Source, class _DS = typename decay<_Source>::type,
615 class _UnqualPtrType =
616 typename remove_const<typename remove_pointer<_DS>::type>::type,
617 bool _IsCharPtr = is_pointer<_DS>::value&&
618 __can_convert_char<_UnqualPtrType>::value>
619struct __is_pathable_char_array : false_type {};
620
621template <class _Source, class _ECharT, class _UPtr>
622struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
623 : __can_convert_char<typename remove_const<_ECharT>::type> {
624 using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
625
626 static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
627 static _ECharT const* __range_end(const _ECharT* __b) {
628 using _Iter = const _ECharT*;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200629 const _ECharT __sentinel = _ECharT{};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000630 _Iter __e = __b;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200631 for (; *__e != __sentinel; ++__e)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000632 ;
633 return __e;
634 }
635
636 static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
637};
638
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500639template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000640 class = void>
641struct __is_pathable_iter : false_type {};
642
643template <class _Iter>
644struct __is_pathable_iter<
645 _Iter, true,
646 _Void<typename __can_convert_char<
647 typename iterator_traits<_Iter>::value_type>::__char_type> >
648 : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
649 using _ECharT = typename iterator_traits<_Iter>::value_type;
650 using _Base = __can_convert_char<_ECharT>;
651
652 static _Iter __range_begin(_Iter __b) { return __b; }
Martin Storsjö2ae96532020-10-27 11:46:06 +0200653 static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000654
655 static _ECharT __first_or_null(_Iter __b) { return *__b; }
656};
657
658template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
659 bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
660 bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
661struct __is_pathable : false_type {
662 static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
663};
664
665template <class _Tp>
666struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
667
668template <class _Tp>
669struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
670};
671
672template <class _Tp>
673struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
674
675template <class _ECharT>
Louis Dionne8d053eb2020-10-09 15:31:05 -0400676struct _PathCVT;
677
678#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
679template <class _ECharT>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000680struct _PathCVT {
681 static_assert(__can_convert_char<_ECharT>::value,
682 "Char type not convertible");
683
684 typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
685
686 static void __append_range(string& __dest, _ECharT const* __b,
687 _ECharT const* __e) {
688 _Narrower()(back_inserter(__dest), __b, __e);
689 }
690
691 template <class _Iter>
692 static void __append_range(string& __dest, _Iter __b, _Iter __e) {
693 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
694 if (__b == __e)
695 return;
696 basic_string<_ECharT> __tmp(__b, __e);
697 _Narrower()(back_inserter(__dest), __tmp.data(),
698 __tmp.data() + __tmp.length());
699 }
700
701 template <class _Iter>
Martin Storsjö2ae96532020-10-27 11:46:06 +0200702 static void __append_range(string& __dest, _Iter __b, _NullSentinel) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000703 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
Martin Storsjö2ae96532020-10-27 11:46:06 +0200704 const _ECharT __sentinel = _ECharT{};
705 if (*__b == __sentinel)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000706 return;
707 basic_string<_ECharT> __tmp;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200708 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000709 __tmp.push_back(*__b);
710 _Narrower()(back_inserter(__dest), __tmp.data(),
711 __tmp.data() + __tmp.length());
712 }
713
714 template <class _Source>
715 static void __append_source(string& __dest, _Source const& __s) {
716 using _Traits = __is_pathable<_Source>;
717 __append_range(__dest, _Traits::__range_begin(__s),
718 _Traits::__range_end(__s));
719 }
720};
Louis Dionne8d053eb2020-10-09 15:31:05 -0400721#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000722
723template <>
724struct _PathCVT<char> {
725
726 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500727 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000728 __append_range(string& __dest, _Iter __b, _Iter __e) {
729 for (; __b != __e; ++__b)
730 __dest.push_back(*__b);
731 }
732
733 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500734 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000735 __append_range(string& __dest, _Iter __b, _Iter __e) {
736 __dest.__append_forward_unsafe(__b, __e);
737 }
738
739 template <class _Iter>
Martin Storsjö2ae96532020-10-27 11:46:06 +0200740 static void __append_range(string& __dest, _Iter __b, _NullSentinel) {
741 const char __sentinel = char{};
742 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000743 __dest.push_back(*__b);
744 }
745
746 template <class _Source>
747 static void __append_source(string& __dest, _Source const& __s) {
748 using _Traits = __is_pathable<_Source>;
749 __append_range(__dest, _Traits::__range_begin(__s),
750 _Traits::__range_end(__s));
751 }
752};
753
754class _LIBCPP_TYPE_VIS path {
755 template <class _SourceOrIter, class _Tp = path&>
756 using _EnableIfPathable =
757 typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
758
759 template <class _Tp>
760 using _SourceChar = typename __is_pathable<_Tp>::__char_type;
761
762 template <class _Tp>
763 using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
764
765public:
766 typedef char value_type;
767 typedef basic_string<value_type> string_type;
768 typedef _VSTD::string_view __string_view;
769 static constexpr value_type preferred_separator = '/';
770
771 enum class _LIBCPP_ENUM_VIS format : unsigned char {
772 auto_format,
773 native_format,
774 generic_format
775 };
776
777 // constructors and destructor
778 _LIBCPP_INLINE_VISIBILITY path() noexcept {}
779 _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
780 _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
781 : __pn_(_VSTD::move(__p.__pn_)) {}
782
783 _LIBCPP_INLINE_VISIBILITY
784 path(string_type&& __s, format = format::auto_format) noexcept
785 : __pn_(_VSTD::move(__s)) {}
786
787 template <class _Source, class = _EnableIfPathable<_Source, void> >
788 path(const _Source& __src, format = format::auto_format) {
789 _SourceCVT<_Source>::__append_source(__pn_, __src);
790 }
791
792 template <class _InputIt>
793 path(_InputIt __first, _InputIt __last, format = format::auto_format) {
794 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
795 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
796 }
797
Louis Dionne8d053eb2020-10-09 15:31:05 -0400798#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000799 // TODO Implement locale conversions.
800 template <class _Source, class = _EnableIfPathable<_Source, void> >
801 path(const _Source& __src, const locale& __loc, format = format::auto_format);
802 template <class _InputIt>
803 path(_InputIt __first, _InputIt _last, const locale& __loc,
804 format = format::auto_format);
Louis Dionne8d053eb2020-10-09 15:31:05 -0400805#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000806
807 _LIBCPP_INLINE_VISIBILITY
808 ~path() = default;
809
810 // assignments
811 _LIBCPP_INLINE_VISIBILITY
812 path& operator=(const path& __p) {
813 __pn_ = __p.__pn_;
814 return *this;
815 }
816
817 _LIBCPP_INLINE_VISIBILITY
818 path& operator=(path&& __p) noexcept {
819 __pn_ = _VSTD::move(__p.__pn_);
820 return *this;
821 }
822
823 template <class = void>
824 _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept {
825 __pn_ = _VSTD::move(__s);
826 return *this;
827 }
828
829 _LIBCPP_INLINE_VISIBILITY
830 path& assign(string_type&& __s) noexcept {
831 __pn_ = _VSTD::move(__s);
832 return *this;
833 }
834
835 template <class _Source>
836 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
837 operator=(const _Source& __src) {
838 return this->assign(__src);
839 }
840
841 template <class _Source>
842 _EnableIfPathable<_Source> assign(const _Source& __src) {
843 __pn_.clear();
844 _SourceCVT<_Source>::__append_source(__pn_, __src);
845 return *this;
846 }
847
848 template <class _InputIt>
849 path& assign(_InputIt __first, _InputIt __last) {
850 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
851 __pn_.clear();
852 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
853 return *this;
854 }
855
856private:
857 template <class _ECharT>
858 static bool __source_is_absolute(_ECharT __first_or_null) {
859 return __is_separator(__first_or_null);
860 }
861
862public:
863 // appends
864 path& operator/=(const path& __p) {
865 if (__p.is_absolute()) {
866 __pn_ = __p.__pn_;
867 return *this;
868 }
869 if (has_filename())
870 __pn_ += preferred_separator;
871 __pn_ += __p.native();
872 return *this;
873 }
874
875 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
876 // is known at compile time to be "/' since the user almost certainly intended
877 // to append a separator instead of overwriting the path with "/"
878 template <class _Source>
879 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
880 operator/=(const _Source& __src) {
881 return this->append(__src);
882 }
883
884 template <class _Source>
885 _EnableIfPathable<_Source> append(const _Source& __src) {
886 using _Traits = __is_pathable<_Source>;
887 using _CVT = _PathCVT<_SourceChar<_Source> >;
888 if (__source_is_absolute(_Traits::__first_or_null(__src)))
889 __pn_.clear();
890 else if (has_filename())
891 __pn_ += preferred_separator;
892 _CVT::__append_source(__pn_, __src);
893 return *this;
894 }
895
896 template <class _InputIt>
897 path& append(_InputIt __first, _InputIt __last) {
898 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
899 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
900 using _CVT = _PathCVT<_ItVal>;
901 if (__first != __last && __source_is_absolute(*__first))
902 __pn_.clear();
903 else if (has_filename())
904 __pn_ += preferred_separator;
905 _CVT::__append_range(__pn_, __first, __last);
906 return *this;
907 }
908
909 // concatenation
910 _LIBCPP_INLINE_VISIBILITY
911 path& operator+=(const path& __x) {
912 __pn_ += __x.__pn_;
913 return *this;
914 }
915
916 _LIBCPP_INLINE_VISIBILITY
917 path& operator+=(const string_type& __x) {
918 __pn_ += __x;
919 return *this;
920 }
921
922 _LIBCPP_INLINE_VISIBILITY
923 path& operator+=(__string_view __x) {
924 __pn_ += __x;
925 return *this;
926 }
927
928 _LIBCPP_INLINE_VISIBILITY
929 path& operator+=(const value_type* __x) {
930 __pn_ += __x;
931 return *this;
932 }
933
934 _LIBCPP_INLINE_VISIBILITY
935 path& operator+=(value_type __x) {
936 __pn_ += __x;
937 return *this;
938 }
939
940 template <class _ECharT>
941 typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
942 operator+=(_ECharT __x) {
943 basic_string<_ECharT> __tmp;
944 __tmp += __x;
945 _PathCVT<_ECharT>::__append_source(__pn_, __tmp);
946 return *this;
947 }
948
949 template <class _Source>
950 _EnableIfPathable<_Source> operator+=(const _Source& __x) {
951 return this->concat(__x);
952 }
953
954 template <class _Source>
955 _EnableIfPathable<_Source> concat(const _Source& __x) {
956 _SourceCVT<_Source>::__append_source(__pn_, __x);
957 return *this;
958 }
959
960 template <class _InputIt>
961 path& concat(_InputIt __first, _InputIt __last) {
962 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
963 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
964 return *this;
965 }
966
967 // modifiers
968 _LIBCPP_INLINE_VISIBILITY
969 void clear() noexcept { __pn_.clear(); }
970
971 path& make_preferred() { return *this; }
972
973 _LIBCPP_INLINE_VISIBILITY
974 path& remove_filename() {
975 auto __fname = __filename();
976 if (!__fname.empty())
977 __pn_.erase(__fname.data() - __pn_.data());
978 return *this;
979 }
980
981 path& replace_filename(const path& __replacement) {
982 remove_filename();
983 return (*this /= __replacement);
984 }
985
986 path& replace_extension(const path& __replacement = path());
987
988 _LIBCPP_INLINE_VISIBILITY
989 void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
990
991 // private helper to allow reserving memory in the path
992 _LIBCPP_INLINE_VISIBILITY
993 void __reserve(size_t __s) { __pn_.reserve(__s); }
994
995 // native format observers
996 _LIBCPP_INLINE_VISIBILITY
997 const string_type& native() const noexcept { return __pn_; }
998
999 _LIBCPP_INLINE_VISIBILITY
1000 const value_type* c_str() const noexcept { return __pn_.c_str(); }
1001
1002 _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
1003
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001004 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001005#ifndef _LIBCPP_NO_HAS_CHAR8_T
1006 _LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1007#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001008 _LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001009#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001010
1011#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001012 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1013 class _Allocator = allocator<_ECharT> >
1014 basic_string<_ECharT, _Traits, _Allocator>
1015 string(const _Allocator& __a = _Allocator()) const {
1016 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
1017 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1018 _Str __s(__a);
1019 __s.reserve(__pn_.size());
1020 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1021 return __s;
1022 }
1023
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001024 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001025 return string<wchar_t>();
1026 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001027 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001028 return string<char16_t>();
1029 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001030 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001031 return string<char32_t>();
1032 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001033#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001034
1035 // generic format observers
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001036 _VSTD::string generic_string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001037#ifndef _LIBCPP_NO_HAS_CHAR8_T
1038 _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1039#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001040 _VSTD::string generic_u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001041#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001042
1043#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001044 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1045 class _Allocator = allocator<_ECharT> >
1046 basic_string<_ECharT, _Traits, _Allocator>
1047 generic_string(const _Allocator& __a = _Allocator()) const {
1048 return string<_ECharT, _Traits, _Allocator>(__a);
1049 }
1050
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001051 _VSTD::wstring generic_wstring() const { return string<wchar_t>(); }
1052 _VSTD::u16string generic_u16string() const { return string<char16_t>(); }
1053 _VSTD::u32string generic_u32string() const { return string<char32_t>(); }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001054#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001055
1056private:
1057 int __compare(__string_view) const;
1058 __string_view __root_name() const;
1059 __string_view __root_directory() const;
1060 __string_view __root_path_raw() const;
1061 __string_view __relative_path() const;
1062 __string_view __parent_path() const;
1063 __string_view __filename() const;
1064 __string_view __stem() const;
1065 __string_view __extension() const;
1066
1067public:
1068 // compare
1069 _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
1070 return __compare(__p.__pn_);
1071 }
1072 _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
1073 return __compare(__s);
1074 }
1075 _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
1076 return __compare(__s);
1077 }
1078 _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
1079 return __compare(__s);
1080 }
1081
1082 // decomposition
1083 _LIBCPP_INLINE_VISIBILITY path root_name() const {
1084 return string_type(__root_name());
1085 }
1086 _LIBCPP_INLINE_VISIBILITY path root_directory() const {
1087 return string_type(__root_directory());
1088 }
1089 _LIBCPP_INLINE_VISIBILITY path root_path() const {
1090 return root_name().append(string_type(__root_directory()));
1091 }
1092 _LIBCPP_INLINE_VISIBILITY path relative_path() const {
1093 return string_type(__relative_path());
1094 }
1095 _LIBCPP_INLINE_VISIBILITY path parent_path() const {
1096 return string_type(__parent_path());
1097 }
1098 _LIBCPP_INLINE_VISIBILITY path filename() const {
1099 return string_type(__filename());
1100 }
1101 _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
1102 _LIBCPP_INLINE_VISIBILITY path extension() const {
1103 return string_type(__extension());
1104 }
1105
1106 // query
1107 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
1108 empty() const noexcept {
1109 return __pn_.empty();
1110 }
1111
1112 _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
1113 return !__root_name().empty();
1114 }
1115 _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
1116 return !__root_directory().empty();
1117 }
1118 _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
1119 return !__root_path_raw().empty();
1120 }
1121 _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
1122 return !__relative_path().empty();
1123 }
1124 _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
1125 return !__parent_path().empty();
1126 }
1127 _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
1128 return !__filename().empty();
1129 }
1130 _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
1131 _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
1132 return !__extension().empty();
1133 }
1134
1135 _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
1136 return has_root_directory();
1137 }
1138 _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
1139
1140 // relative paths
1141 path lexically_normal() const;
1142 path lexically_relative(const path& __base) const;
1143
1144 _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
1145 path __result = this->lexically_relative(__base);
1146 if (__result.native().empty())
1147 return *this;
1148 return __result;
1149 }
1150
1151 // iterators
1152 class _LIBCPP_TYPE_VIS iterator;
1153 typedef iterator const_iterator;
1154
1155 iterator begin() const;
1156 iterator end() const;
1157
Louis Dionne8d053eb2020-10-09 15:31:05 -04001158#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001159 template <class _CharT, class _Traits>
1160 _LIBCPP_INLINE_VISIBILITY friend
1161 typename enable_if<is_same<_CharT, char>::value &&
1162 is_same<_Traits, char_traits<char> >::value,
1163 basic_ostream<_CharT, _Traits>&>::type
1164 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001165 __os << _VSTD::__quoted(__p.native());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001166 return __os;
1167 }
1168
1169 template <class _CharT, class _Traits>
1170 _LIBCPP_INLINE_VISIBILITY friend
1171 typename enable_if<!is_same<_CharT, char>::value ||
1172 !is_same<_Traits, char_traits<char> >::value,
1173 basic_ostream<_CharT, _Traits>&>::type
1174 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001175 __os << _VSTD::__quoted(__p.string<_CharT, _Traits>());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001176 return __os;
1177 }
1178
1179 template <class _CharT, class _Traits>
1180 _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
1181 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
1182 basic_string<_CharT, _Traits> __tmp;
1183 __is >> __quoted(__tmp);
1184 __p = __tmp;
1185 return __is;
1186 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001187#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001188
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001189 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
1190 return __lhs.compare(__rhs) == 0;
1191 }
1192 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
1193 return __lhs.compare(__rhs) != 0;
1194 }
1195 friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
1196 return __lhs.compare(__rhs) < 0;
1197 }
1198 friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
1199 return __lhs.compare(__rhs) <= 0;
1200 }
1201 friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
1202 return __lhs.compare(__rhs) > 0;
1203 }
1204 friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
1205 return __lhs.compare(__rhs) >= 0;
1206 }
1207
1208 friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
1209 const path& __rhs) {
1210 path __result(__lhs);
1211 __result /= __rhs;
1212 return __result;
1213 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001214private:
1215 inline _LIBCPP_INLINE_VISIBILITY path&
1216 __assign_view(__string_view const& __s) noexcept {
1217 __pn_ = string_type(__s);
1218 return *this;
1219 }
1220 string_type __pn_;
1221};
1222
1223inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
1224 __lhs.swap(__rhs);
1225}
1226
1227_LIBCPP_FUNC_VIS
1228size_t hash_value(const path& __p) noexcept;
1229
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001230template <class _Source>
Martin Storsjöe3a71972020-10-26 13:18:46 +02001231_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001232 typename enable_if<__is_pathable<_Source>::value, path>::type
1233 u8path(const _Source& __s) {
1234 static_assert(
Martin Storsjöe3a71972020-10-26 13:18:46 +02001235#ifndef _LIBCPP_NO_HAS_CHAR8_T
1236 is_same<typename __is_pathable<_Source>::__char_type, char8_t>::value ||
1237#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001238 is_same<typename __is_pathable<_Source>::__char_type, char>::value,
1239 "u8path(Source const&) requires Source have a character type of type "
Martin Storsjöe3a71972020-10-26 13:18:46 +02001240 "'char'"
1241#ifndef _LIBCPP_NO_HAS_CHAR8_T
1242 " or 'char8_t'"
1243#endif
1244 );
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001245 return path(__s);
1246}
1247
1248template <class _InputIt>
Martin Storsjöe3a71972020-10-26 13:18:46 +02001249_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001250 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1251 u8path(_InputIt __f, _InputIt __l) {
1252 static_assert(
Martin Storsjöe3a71972020-10-26 13:18:46 +02001253#ifndef _LIBCPP_NO_HAS_CHAR8_T
1254 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1255#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001256 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
Martin Storsjöe3a71972020-10-26 13:18:46 +02001257 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
1258#ifndef _LIBCPP_NO_HAS_CHAR8_T
1259 " or 'char8_t'"
1260#endif
1261 );
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001262 return path(__f, __l);
1263}
1264
1265class _LIBCPP_TYPE_VIS path::iterator {
1266public:
1267 enum _ParserState : unsigned char {
1268 _Singular,
1269 _BeforeBegin,
1270 _InRootName,
1271 _InRootDir,
1272 _InFilenames,
1273 _InTrailingSep,
1274 _AtEnd
1275 };
1276
1277public:
1278 typedef bidirectional_iterator_tag iterator_category;
1279
1280 typedef path value_type;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001281 typedef ptrdiff_t difference_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001282 typedef const path* pointer;
1283 typedef const path& reference;
1284
1285 typedef void
1286 __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
1287
1288public:
1289 _LIBCPP_INLINE_VISIBILITY
1290 iterator()
1291 : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
1292 __state_(_Singular) {}
1293
1294 iterator(const iterator&) = default;
1295 ~iterator() = default;
1296
1297 iterator& operator=(const iterator&) = default;
1298
1299 _LIBCPP_INLINE_VISIBILITY
1300 reference operator*() const { return __stashed_elem_; }
1301
1302 _LIBCPP_INLINE_VISIBILITY
1303 pointer operator->() const { return &__stashed_elem_; }
1304
1305 _LIBCPP_INLINE_VISIBILITY
1306 iterator& operator++() {
1307 _LIBCPP_ASSERT(__state_ != _Singular,
1308 "attempting to increment a singular iterator");
1309 _LIBCPP_ASSERT(__state_ != _AtEnd,
1310 "attempting to increment the end iterator");
1311 return __increment();
1312 }
1313
1314 _LIBCPP_INLINE_VISIBILITY
1315 iterator operator++(int) {
1316 iterator __it(*this);
1317 this->operator++();
1318 return __it;
1319 }
1320
1321 _LIBCPP_INLINE_VISIBILITY
1322 iterator& operator--() {
1323 _LIBCPP_ASSERT(__state_ != _Singular,
1324 "attempting to decrement a singular iterator");
1325 _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
1326 "attempting to decrement the begin iterator");
1327 return __decrement();
1328 }
1329
1330 _LIBCPP_INLINE_VISIBILITY
1331 iterator operator--(int) {
1332 iterator __it(*this);
1333 this->operator--();
1334 return __it;
1335 }
1336
1337private:
1338 friend class path;
1339
1340 inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
1341 const iterator&);
1342
1343 iterator& __increment();
1344 iterator& __decrement();
1345
1346 path __stashed_elem_;
1347 const path* __path_ptr_;
1348 path::__string_view __entry_;
1349 _ParserState __state_;
1350};
1351
1352inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
1353 const path::iterator& __rhs) {
1354 return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
1355 __lhs.__entry_.data() == __rhs.__entry_.data();
1356}
1357
1358inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
1359 const path::iterator& __rhs) {
1360 return !(__lhs == __rhs);
1361}
1362
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001363// TODO(ldionne): We need to pop the pragma and push it again after
1364// filesystem_error to work around PR41078.
1365_LIBCPP_AVAILABILITY_FILESYSTEM_POP
1366
1367class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001368public:
1369 _LIBCPP_INLINE_VISIBILITY
1370 filesystem_error(const string& __what, error_code __ec)
1371 : system_error(__ec, __what),
1372 __storage_(make_shared<_Storage>(path(), path())) {
1373 __create_what(0);
1374 }
1375
1376 _LIBCPP_INLINE_VISIBILITY
1377 filesystem_error(const string& __what, const path& __p1, error_code __ec)
1378 : system_error(__ec, __what),
1379 __storage_(make_shared<_Storage>(__p1, path())) {
1380 __create_what(1);
1381 }
1382
1383 _LIBCPP_INLINE_VISIBILITY
1384 filesystem_error(const string& __what, const path& __p1, const path& __p2,
1385 error_code __ec)
1386 : system_error(__ec, __what),
1387 __storage_(make_shared<_Storage>(__p1, __p2)) {
1388 __create_what(2);
1389 }
1390
1391 _LIBCPP_INLINE_VISIBILITY
1392 const path& path1() const noexcept { return __storage_->__p1_; }
1393
1394 _LIBCPP_INLINE_VISIBILITY
1395 const path& path2() const noexcept { return __storage_->__p2_; }
1396
Dimitry Andric47269ce2020-03-13 19:36:26 +01001397 filesystem_error(const filesystem_error&) = default;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001398 ~filesystem_error() override; // key function
1399
1400 _LIBCPP_INLINE_VISIBILITY
1401 const char* what() const noexcept override {
1402 return __storage_->__what_.c_str();
1403 }
1404
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001405 void __create_what(int __num_paths);
1406
1407private:
Louis Dionne48ae8892019-03-19 17:47:53 +00001408 struct _LIBCPP_HIDDEN _Storage {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001409 _LIBCPP_INLINE_VISIBILITY
1410 _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
1411
1412 path __p1_;
1413 path __p2_;
1414 string __what_;
1415 };
1416 shared_ptr<_Storage> __storage_;
1417};
1418
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001419_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
1420
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001421template <class... _Args>
1422_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
1423#ifndef _LIBCPP_NO_EXCEPTIONS
Louis Dionne6251ef02019-02-05 15:46:52 +00001424void __throw_filesystem_error(_Args&&... __args) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001425 throw filesystem_error(_VSTD::forward<_Args>(__args)...);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001426}
1427#else
Louis Dionne6251ef02019-02-05 15:46:52 +00001428void __throw_filesystem_error(_Args&&...) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001429 _VSTD::abort();
1430}
1431#endif
1432
1433// operational functions
1434
1435_LIBCPP_FUNC_VIS
1436path __absolute(const path&, error_code* __ec = nullptr);
1437_LIBCPP_FUNC_VIS
1438path __canonical(const path&, error_code* __ec = nullptr);
1439_LIBCPP_FUNC_VIS
1440void __copy(const path& __from, const path& __to, copy_options __opt,
1441 error_code* __ec = nullptr);
1442_LIBCPP_FUNC_VIS
1443bool __copy_file(const path& __from, const path& __to, copy_options __opt,
1444 error_code* __ec = nullptr);
1445_LIBCPP_FUNC_VIS
1446void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
1447 error_code* __ec = nullptr);
1448_LIBCPP_FUNC_VIS
1449bool __create_directories(const path& p, error_code* ec = nullptr);
1450_LIBCPP_FUNC_VIS
1451bool __create_directory(const path& p, error_code* ec = nullptr);
1452_LIBCPP_FUNC_VIS
1453bool __create_directory(const path& p, const path& attributes,
1454 error_code* ec = nullptr);
1455_LIBCPP_FUNC_VIS
1456void __create_directory_symlink(const path& __to, const path& __new_symlink,
1457 error_code* __ec = nullptr);
1458_LIBCPP_FUNC_VIS
1459void __create_hard_link(const path& __to, const path& __new_hard_link,
1460 error_code* __ec = nullptr);
1461_LIBCPP_FUNC_VIS
1462void __create_symlink(const path& __to, const path& __new_symlink,
1463 error_code* __ec = nullptr);
1464_LIBCPP_FUNC_VIS
1465path __current_path(error_code* __ec = nullptr);
1466_LIBCPP_FUNC_VIS
1467void __current_path(const path&, error_code* __ec = nullptr);
1468_LIBCPP_FUNC_VIS
1469bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
1470_LIBCPP_FUNC_VIS
1471uintmax_t __file_size(const path&, error_code* __ec = nullptr);
1472_LIBCPP_FUNC_VIS
1473uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
1474_LIBCPP_FUNC_VIS
1475bool __fs_is_empty(const path& p, error_code* ec = nullptr);
1476_LIBCPP_FUNC_VIS
1477file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
1478_LIBCPP_FUNC_VIS
1479void __last_write_time(const path& p, file_time_type new_time,
1480 error_code* ec = nullptr);
1481_LIBCPP_FUNC_VIS
1482void __permissions(const path&, perms, perm_options, error_code* = nullptr);
1483_LIBCPP_FUNC_VIS
1484path __read_symlink(const path& p, error_code* ec = nullptr);
1485_LIBCPP_FUNC_VIS
1486bool __remove(const path& p, error_code* ec = nullptr);
1487_LIBCPP_FUNC_VIS
1488uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
1489_LIBCPP_FUNC_VIS
1490void __rename(const path& from, const path& to, error_code* ec = nullptr);
1491_LIBCPP_FUNC_VIS
1492void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
1493_LIBCPP_FUNC_VIS
1494space_info __space(const path&, error_code* __ec = nullptr);
1495_LIBCPP_FUNC_VIS
1496file_status __status(const path&, error_code* __ec = nullptr);
1497_LIBCPP_FUNC_VIS
1498file_status __symlink_status(const path&, error_code* __ec = nullptr);
1499_LIBCPP_FUNC_VIS
1500path __system_complete(const path&, error_code* __ec = nullptr);
1501_LIBCPP_FUNC_VIS
1502path __temp_directory_path(error_code* __ec = nullptr);
1503_LIBCPP_FUNC_VIS
1504path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
1505
1506inline _LIBCPP_INLINE_VISIBILITY path current_path() {
1507 return __current_path();
1508}
1509
1510inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
1511 return __current_path(&__ec);
1512}
1513
1514inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
1515 __current_path(__p);
1516}
1517
1518inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
1519 error_code& __ec) noexcept {
1520 __current_path(__p, &__ec);
1521}
1522
1523inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
1524 return __absolute(__p);
1525}
1526
1527inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
1528 error_code& __ec) {
1529 return __absolute(__p, &__ec);
1530}
1531
1532inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
1533 return __canonical(__p);
1534}
1535
1536inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
1537 error_code& __ec) {
1538 return __canonical(__p, &__ec);
1539}
1540
1541inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
1542 const path& __to) {
1543 __copy(__from, __to, copy_options::none);
1544}
1545
1546inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1547 error_code& __ec) {
1548 __copy(__from, __to, copy_options::none, &__ec);
1549}
1550
1551inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1552 copy_options __opt) {
1553 __copy(__from, __to, __opt);
1554}
1555
1556inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1557 copy_options __opt,
1558 error_code& __ec) {
1559 __copy(__from, __to, __opt, &__ec);
1560}
1561
1562inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1563 const path& __to) {
1564 return __copy_file(__from, __to, copy_options::none);
1565}
1566
1567inline _LIBCPP_INLINE_VISIBILITY bool
1568copy_file(const path& __from, const path& __to, error_code& __ec) {
1569 return __copy_file(__from, __to, copy_options::none, &__ec);
1570}
1571
1572inline _LIBCPP_INLINE_VISIBILITY bool
1573copy_file(const path& __from, const path& __to, copy_options __opt) {
1574 return __copy_file(__from, __to, __opt);
1575}
1576
1577inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1578 const path& __to,
1579 copy_options __opt,
1580 error_code& __ec) {
1581 return __copy_file(__from, __to, __opt, &__ec);
1582}
1583
1584inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
1585 const path& __new) {
1586 __copy_symlink(__existing, __new);
1587}
1588
1589inline _LIBCPP_INLINE_VISIBILITY void
1590copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
1591 __copy_symlink(__ext, __new, &__ec);
1592}
1593
1594inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
1595 return __create_directories(__p);
1596}
1597
1598inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
1599 error_code& __ec) {
1600 return __create_directories(__p, &__ec);
1601}
1602
1603inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
1604 return __create_directory(__p);
1605}
1606
1607inline _LIBCPP_INLINE_VISIBILITY bool
1608create_directory(const path& __p, error_code& __ec) noexcept {
1609 return __create_directory(__p, &__ec);
1610}
1611
1612inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
1613 const path& __attrs) {
1614 return __create_directory(__p, __attrs);
1615}
1616
1617inline _LIBCPP_INLINE_VISIBILITY bool
1618create_directory(const path& __p, const path& __attrs,
1619 error_code& __ec) noexcept {
1620 return __create_directory(__p, __attrs, &__ec);
1621}
1622
1623inline _LIBCPP_INLINE_VISIBILITY void
1624create_directory_symlink(const path& __to, const path& __new) {
1625 __create_directory_symlink(__to, __new);
1626}
1627
1628inline _LIBCPP_INLINE_VISIBILITY void
1629create_directory_symlink(const path& __to, const path& __new,
1630 error_code& __ec) noexcept {
1631 __create_directory_symlink(__to, __new, &__ec);
1632}
1633
1634inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
1635 const path& __new) {
1636 __create_hard_link(__to, __new);
1637}
1638
1639inline _LIBCPP_INLINE_VISIBILITY void
1640create_hard_link(const path& __to, const path& __new,
1641 error_code& __ec) noexcept {
1642 __create_hard_link(__to, __new, &__ec);
1643}
1644
1645inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
1646 const path& __new) {
1647 __create_symlink(__to, __new);
1648}
1649
1650inline _LIBCPP_INLINE_VISIBILITY void
1651create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
1652 return __create_symlink(__to, __new, &__ec);
1653}
1654
1655inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
1656 return __s.type() != file_type::none;
1657}
1658
1659inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
1660 return status_known(__s) && __s.type() != file_type::not_found;
1661}
1662
1663inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
1664 return exists(__status(__p));
1665}
1666
1667inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
1668 error_code& __ec) noexcept {
1669 auto __s = __status(__p, &__ec);
1670 if (status_known(__s))
1671 __ec.clear();
1672 return exists(__s);
1673}
1674
1675inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
1676 const path& __p2) {
1677 return __equivalent(__p1, __p2);
1678}
1679
1680inline _LIBCPP_INLINE_VISIBILITY bool
1681equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
1682 return __equivalent(__p1, __p2, &__ec);
1683}
1684
1685inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
1686 return __file_size(__p);
1687}
1688
1689inline _LIBCPP_INLINE_VISIBILITY uintmax_t
1690file_size(const path& __p, error_code& __ec) noexcept {
1691 return __file_size(__p, &__ec);
1692}
1693
1694inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
1695 return __hard_link_count(__p);
1696}
1697
1698inline _LIBCPP_INLINE_VISIBILITY uintmax_t
1699hard_link_count(const path& __p, error_code& __ec) noexcept {
1700 return __hard_link_count(__p, &__ec);
1701}
1702
1703inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
1704 return __s.type() == file_type::block;
1705}
1706
1707inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
1708 return is_block_file(__status(__p));
1709}
1710
1711inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
1712 error_code& __ec) noexcept {
1713 return is_block_file(__status(__p, &__ec));
1714}
1715
1716inline _LIBCPP_INLINE_VISIBILITY bool
1717is_character_file(file_status __s) noexcept {
1718 return __s.type() == file_type::character;
1719}
1720
1721inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
1722 return is_character_file(__status(__p));
1723}
1724
1725inline _LIBCPP_INLINE_VISIBILITY bool
1726is_character_file(const path& __p, error_code& __ec) noexcept {
1727 return is_character_file(__status(__p, &__ec));
1728}
1729
1730inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
1731 return __s.type() == file_type::directory;
1732}
1733
1734inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
1735 return is_directory(__status(__p));
1736}
1737
1738inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
1739 error_code& __ec) noexcept {
1740 return is_directory(__status(__p, &__ec));
1741}
1742
1743inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
1744 return __fs_is_empty(__p);
1745}
1746
1747inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
1748 error_code& __ec) {
1749 return __fs_is_empty(__p, &__ec);
1750}
1751
1752inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
1753 return __s.type() == file_type::fifo;
1754}
1755inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
1756 return is_fifo(__status(__p));
1757}
1758
1759inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
1760 error_code& __ec) noexcept {
1761 return is_fifo(__status(__p, &__ec));
1762}
1763
1764inline _LIBCPP_INLINE_VISIBILITY bool
1765is_regular_file(file_status __s) noexcept {
1766 return __s.type() == file_type::regular;
1767}
1768
1769inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
1770 return is_regular_file(__status(__p));
1771}
1772
1773inline _LIBCPP_INLINE_VISIBILITY bool
1774is_regular_file(const path& __p, error_code& __ec) noexcept {
1775 return is_regular_file(__status(__p, &__ec));
1776}
1777
1778inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
1779 return __s.type() == file_type::socket;
1780}
1781
1782inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
1783 return is_socket(__status(__p));
1784}
1785
1786inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
1787 error_code& __ec) noexcept {
1788 return is_socket(__status(__p, &__ec));
1789}
1790
1791inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
1792 return __s.type() == file_type::symlink;
1793}
1794
1795inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
1796 return is_symlink(__symlink_status(__p));
1797}
1798
1799inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
1800 error_code& __ec) noexcept {
1801 return is_symlink(__symlink_status(__p, &__ec));
1802}
1803
1804inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
1805 return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
1806 !is_symlink(__s);
1807}
1808
1809inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
1810 return is_other(__status(__p));
1811}
1812
1813inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
1814 error_code& __ec) noexcept {
1815 return is_other(__status(__p, &__ec));
1816}
1817
1818inline _LIBCPP_INLINE_VISIBILITY file_time_type
1819last_write_time(const path& __p) {
1820 return __last_write_time(__p);
1821}
1822
1823inline _LIBCPP_INLINE_VISIBILITY file_time_type
1824last_write_time(const path& __p, error_code& __ec) noexcept {
1825 return __last_write_time(__p, &__ec);
1826}
1827
1828inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
1829 file_time_type __t) {
1830 __last_write_time(__p, __t);
1831}
1832
1833inline _LIBCPP_INLINE_VISIBILITY void
1834last_write_time(const path& __p, file_time_type __t,
1835 error_code& __ec) noexcept {
1836 __last_write_time(__p, __t, &__ec);
1837}
1838
1839inline _LIBCPP_INLINE_VISIBILITY void
1840permissions(const path& __p, perms __prms,
1841 perm_options __opts = perm_options::replace) {
1842 __permissions(__p, __prms, __opts);
1843}
1844
1845inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
1846 error_code& __ec) noexcept {
1847 __permissions(__p, __prms, perm_options::replace, &__ec);
1848}
1849
1850inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
1851 perm_options __opts,
1852 error_code& __ec) {
1853 __permissions(__p, __prms, __opts, &__ec);
1854}
1855
1856inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
1857 const path& __base,
1858 error_code& __ec) {
1859 path __tmp = __weakly_canonical(__p, &__ec);
1860 if (__ec)
1861 return {};
1862 path __tmp_base = __weakly_canonical(__base, &__ec);
1863 if (__ec)
1864 return {};
1865 return __tmp.lexically_proximate(__tmp_base);
1866}
1867
1868inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
1869 error_code& __ec) {
1870 return proximate(__p, current_path(), __ec);
1871}
1872
1873inline _LIBCPP_INLINE_VISIBILITY path
1874proximate(const path& __p, const path& __base = current_path()) {
1875 return __weakly_canonical(__p).lexically_proximate(
1876 __weakly_canonical(__base));
1877}
1878
1879inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
1880 return __read_symlink(__p);
1881}
1882
1883inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
1884 error_code& __ec) {
1885 return __read_symlink(__p, &__ec);
1886}
1887
1888inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
1889 const path& __base,
1890 error_code& __ec) {
1891 path __tmp = __weakly_canonical(__p, &__ec);
1892 if (__ec)
1893 return path();
1894 path __tmpbase = __weakly_canonical(__base, &__ec);
1895 if (__ec)
1896 return path();
1897 return __tmp.lexically_relative(__tmpbase);
1898}
1899
1900inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
1901 error_code& __ec) {
1902 return relative(__p, current_path(), __ec);
1903}
1904
1905inline _LIBCPP_INLINE_VISIBILITY path
1906relative(const path& __p, const path& __base = current_path()) {
1907 return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
1908}
1909
1910inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
1911 return __remove(__p);
1912}
1913
1914inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
1915 error_code& __ec) noexcept {
1916 return __remove(__p, &__ec);
1917}
1918
1919inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
1920 return __remove_all(__p);
1921}
1922
1923inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
1924 error_code& __ec) {
1925 return __remove_all(__p, &__ec);
1926}
1927
1928inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
1929 const path& __to) {
1930 return __rename(__from, __to);
1931}
1932
1933inline _LIBCPP_INLINE_VISIBILITY void
1934rename(const path& __from, const path& __to, error_code& __ec) noexcept {
1935 return __rename(__from, __to, &__ec);
1936}
1937
1938inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
1939 uintmax_t __ns) {
1940 return __resize_file(__p, __ns);
1941}
1942
1943inline _LIBCPP_INLINE_VISIBILITY void
1944resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
1945 return __resize_file(__p, __ns, &__ec);
1946}
1947
1948inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
1949 return __space(__p);
1950}
1951
1952inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
1953 error_code& __ec) noexcept {
1954 return __space(__p, &__ec);
1955}
1956
1957inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
1958 return __status(__p);
1959}
1960
1961inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
1962 error_code& __ec) noexcept {
1963 return __status(__p, &__ec);
1964}
1965
1966inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
1967 return __symlink_status(__p);
1968}
1969
1970inline _LIBCPP_INLINE_VISIBILITY file_status
1971symlink_status(const path& __p, error_code& __ec) noexcept {
1972 return __symlink_status(__p, &__ec);
1973}
1974
1975inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
1976 return __temp_directory_path();
1977}
1978
1979inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
1980 return __temp_directory_path(&__ec);
1981}
1982
1983inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
1984 return __weakly_canonical(__p);
1985}
1986
1987inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
1988 error_code& __ec) {
1989 return __weakly_canonical(__p, &__ec);
1990}
1991
1992class directory_iterator;
1993class recursive_directory_iterator;
Louis Dionne48ae8892019-03-19 17:47:53 +00001994class _LIBCPP_HIDDEN __dir_stream;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001995
1996class directory_entry {
1997 typedef _VSTD_FS::path _Path;
1998
1999public:
2000 // constructors and destructors
2001 directory_entry() noexcept = default;
2002 directory_entry(directory_entry const&) = default;
2003 directory_entry(directory_entry&&) noexcept = default;
2004
2005 _LIBCPP_INLINE_VISIBILITY
2006 explicit directory_entry(_Path const& __p) : __p_(__p) {
2007 error_code __ec;
2008 __refresh(&__ec);
2009 }
2010
2011 _LIBCPP_INLINE_VISIBILITY
2012 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
2013 __refresh(&__ec);
2014 }
2015
2016 ~directory_entry() {}
2017
2018 directory_entry& operator=(directory_entry const&) = default;
2019 directory_entry& operator=(directory_entry&&) noexcept = default;
2020
2021 _LIBCPP_INLINE_VISIBILITY
2022 void assign(_Path const& __p) {
2023 __p_ = __p;
2024 error_code __ec;
2025 __refresh(&__ec);
2026 }
2027
2028 _LIBCPP_INLINE_VISIBILITY
2029 void assign(_Path const& __p, error_code& __ec) {
2030 __p_ = __p;
2031 __refresh(&__ec);
2032 }
2033
2034 _LIBCPP_INLINE_VISIBILITY
2035 void replace_filename(_Path const& __p) {
2036 __p_.replace_filename(__p);
2037 error_code __ec;
2038 __refresh(&__ec);
2039 }
2040
2041 _LIBCPP_INLINE_VISIBILITY
2042 void replace_filename(_Path const& __p, error_code& __ec) {
2043 __p_ = __p_.parent_path() / __p;
2044 __refresh(&__ec);
2045 }
2046
2047 _LIBCPP_INLINE_VISIBILITY
2048 void refresh() { __refresh(); }
2049
2050 _LIBCPP_INLINE_VISIBILITY
2051 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
2052
2053 _LIBCPP_INLINE_VISIBILITY
2054 _Path const& path() const noexcept { return __p_; }
2055
2056 _LIBCPP_INLINE_VISIBILITY
2057 operator const _Path&() const noexcept { return __p_; }
2058
2059 _LIBCPP_INLINE_VISIBILITY
2060 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
2061
2062 _LIBCPP_INLINE_VISIBILITY
2063 bool exists(error_code& __ec) const noexcept {
2064 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
2065 }
2066
2067 _LIBCPP_INLINE_VISIBILITY
2068 bool is_block_file() const { return __get_ft() == file_type::block; }
2069
2070 _LIBCPP_INLINE_VISIBILITY
2071 bool is_block_file(error_code& __ec) const noexcept {
2072 return __get_ft(&__ec) == file_type::block;
2073 }
2074
2075 _LIBCPP_INLINE_VISIBILITY
2076 bool is_character_file() const { return __get_ft() == file_type::character; }
2077
2078 _LIBCPP_INLINE_VISIBILITY
2079 bool is_character_file(error_code& __ec) const noexcept {
2080 return __get_ft(&__ec) == file_type::character;
2081 }
2082
2083 _LIBCPP_INLINE_VISIBILITY
2084 bool is_directory() const { return __get_ft() == file_type::directory; }
2085
2086 _LIBCPP_INLINE_VISIBILITY
2087 bool is_directory(error_code& __ec) const noexcept {
2088 return __get_ft(&__ec) == file_type::directory;
2089 }
2090
2091 _LIBCPP_INLINE_VISIBILITY
2092 bool is_fifo() const { return __get_ft() == file_type::fifo; }
2093
2094 _LIBCPP_INLINE_VISIBILITY
2095 bool is_fifo(error_code& __ec) const noexcept {
2096 return __get_ft(&__ec) == file_type::fifo;
2097 }
2098
2099 _LIBCPP_INLINE_VISIBILITY
2100 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
2101
2102 _LIBCPP_INLINE_VISIBILITY
2103 bool is_other(error_code& __ec) const noexcept {
2104 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
2105 }
2106
2107 _LIBCPP_INLINE_VISIBILITY
2108 bool is_regular_file() const { return __get_ft() == file_type::regular; }
2109
2110 _LIBCPP_INLINE_VISIBILITY
2111 bool is_regular_file(error_code& __ec) const noexcept {
2112 return __get_ft(&__ec) == file_type::regular;
2113 }
2114
2115 _LIBCPP_INLINE_VISIBILITY
2116 bool is_socket() const { return __get_ft() == file_type::socket; }
2117
2118 _LIBCPP_INLINE_VISIBILITY
2119 bool is_socket(error_code& __ec) const noexcept {
2120 return __get_ft(&__ec) == file_type::socket;
2121 }
2122
2123 _LIBCPP_INLINE_VISIBILITY
2124 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
2125
2126 _LIBCPP_INLINE_VISIBILITY
2127 bool is_symlink(error_code& __ec) const noexcept {
2128 return __get_sym_ft(&__ec) == file_type::symlink;
2129 }
2130 _LIBCPP_INLINE_VISIBILITY
2131 uintmax_t file_size() const { return __get_size(); }
2132
2133 _LIBCPP_INLINE_VISIBILITY
2134 uintmax_t file_size(error_code& __ec) const noexcept {
2135 return __get_size(&__ec);
2136 }
2137
2138 _LIBCPP_INLINE_VISIBILITY
2139 uintmax_t hard_link_count() const { return __get_nlink(); }
2140
2141 _LIBCPP_INLINE_VISIBILITY
2142 uintmax_t hard_link_count(error_code& __ec) const noexcept {
2143 return __get_nlink(&__ec);
2144 }
2145
2146 _LIBCPP_INLINE_VISIBILITY
2147 file_time_type last_write_time() const { return __get_write_time(); }
2148
2149 _LIBCPP_INLINE_VISIBILITY
2150 file_time_type last_write_time(error_code& __ec) const noexcept {
2151 return __get_write_time(&__ec);
2152 }
2153
2154 _LIBCPP_INLINE_VISIBILITY
2155 file_status status() const { return __get_status(); }
2156
2157 _LIBCPP_INLINE_VISIBILITY
2158 file_status status(error_code& __ec) const noexcept {
2159 return __get_status(&__ec);
2160 }
2161
2162 _LIBCPP_INLINE_VISIBILITY
2163 file_status symlink_status() const { return __get_symlink_status(); }
2164
2165 _LIBCPP_INLINE_VISIBILITY
2166 file_status symlink_status(error_code& __ec) const noexcept {
2167 return __get_symlink_status(&__ec);
2168 }
2169
2170 _LIBCPP_INLINE_VISIBILITY
2171 bool operator<(directory_entry const& __rhs) const noexcept {
2172 return __p_ < __rhs.__p_;
2173 }
2174
2175 _LIBCPP_INLINE_VISIBILITY
2176 bool operator==(directory_entry const& __rhs) const noexcept {
2177 return __p_ == __rhs.__p_;
2178 }
2179
2180 _LIBCPP_INLINE_VISIBILITY
2181 bool operator!=(directory_entry const& __rhs) const noexcept {
2182 return __p_ != __rhs.__p_;
2183 }
2184
2185 _LIBCPP_INLINE_VISIBILITY
2186 bool operator<=(directory_entry const& __rhs) const noexcept {
2187 return __p_ <= __rhs.__p_;
2188 }
2189
2190 _LIBCPP_INLINE_VISIBILITY
2191 bool operator>(directory_entry const& __rhs) const noexcept {
2192 return __p_ > __rhs.__p_;
2193 }
2194
2195 _LIBCPP_INLINE_VISIBILITY
2196 bool operator>=(directory_entry const& __rhs) const noexcept {
2197 return __p_ >= __rhs.__p_;
2198 }
2199
2200private:
2201 friend class directory_iterator;
2202 friend class recursive_directory_iterator;
2203 friend class __dir_stream;
2204
2205 enum _CacheType : unsigned char {
2206 _Empty,
2207 _IterSymlink,
2208 _IterNonSymlink,
2209 _RefreshSymlink,
2210 _RefreshSymlinkUnresolved,
2211 _RefreshNonSymlink
2212 };
2213
2214 struct __cached_data {
2215 uintmax_t __size_;
2216 uintmax_t __nlink_;
2217 file_time_type __write_time_;
2218 perms __sym_perms_;
2219 perms __non_sym_perms_;
2220 file_type __type_;
2221 _CacheType __cache_type_;
2222
2223 _LIBCPP_INLINE_VISIBILITY
2224 __cached_data() noexcept { __reset(); }
2225
2226 _LIBCPP_INLINE_VISIBILITY
2227 void __reset() {
2228 __cache_type_ = _Empty;
2229 __type_ = file_type::none;
2230 __sym_perms_ = __non_sym_perms_ = perms::unknown;
2231 __size_ = __nlink_ = uintmax_t(-1);
2232 __write_time_ = file_time_type::min();
2233 }
2234 };
2235
2236 _LIBCPP_INLINE_VISIBILITY
2237 static __cached_data __create_iter_result(file_type __ft) {
2238 __cached_data __data;
2239 __data.__type_ = __ft;
2240 __data.__cache_type_ = [&]() {
2241 switch (__ft) {
2242 case file_type::none:
2243 return _Empty;
2244 case file_type::symlink:
2245 return _IterSymlink;
2246 default:
2247 return _IterNonSymlink;
2248 }
2249 }();
2250 return __data;
2251 }
2252
2253 _LIBCPP_INLINE_VISIBILITY
2254 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002255 __p_ = _VSTD::move(__p);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002256 __data_ = __dt;
2257 }
2258
2259 _LIBCPP_FUNC_VIS
2260 error_code __do_refresh() noexcept;
2261
2262 _LIBCPP_INLINE_VISIBILITY
2263 static bool __is_dne_error(error_code const& __ec) {
2264 if (!__ec)
2265 return true;
2266 switch (static_cast<errc>(__ec.value())) {
2267 case errc::no_such_file_or_directory:
2268 case errc::not_a_directory:
2269 return true;
2270 default:
2271 return false;
2272 }
2273 }
2274
2275 _LIBCPP_INLINE_VISIBILITY
2276 void __handle_error(const char* __msg, error_code* __dest_ec,
2277 error_code const& __ec, bool __allow_dne = false) const {
2278 if (__dest_ec) {
2279 *__dest_ec = __ec;
2280 return;
2281 }
2282 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
2283 __throw_filesystem_error(__msg, __p_, __ec);
2284 }
2285
2286 _LIBCPP_INLINE_VISIBILITY
2287 void __refresh(error_code* __ec = nullptr) {
2288 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
2289 /*allow_dne*/ true);
2290 }
2291
2292 _LIBCPP_INLINE_VISIBILITY
2293 file_type __get_sym_ft(error_code* __ec = nullptr) const {
2294 switch (__data_.__cache_type_) {
2295 case _Empty:
2296 return __symlink_status(__p_, __ec).type();
2297 case _IterSymlink:
2298 case _RefreshSymlink:
2299 case _RefreshSymlinkUnresolved:
2300 if (__ec)
2301 __ec->clear();
2302 return file_type::symlink;
2303 case _IterNonSymlink:
2304 case _RefreshNonSymlink:
2305 file_status __st(__data_.__type_);
2306 if (__ec && !_VSTD_FS::exists(__st))
2307 *__ec = make_error_code(errc::no_such_file_or_directory);
2308 else if (__ec)
2309 __ec->clear();
2310 return __data_.__type_;
2311 }
2312 _LIBCPP_UNREACHABLE();
2313 }
2314
2315 _LIBCPP_INLINE_VISIBILITY
2316 file_type __get_ft(error_code* __ec = nullptr) const {
2317 switch (__data_.__cache_type_) {
2318 case _Empty:
2319 case _IterSymlink:
2320 case _RefreshSymlinkUnresolved:
2321 return __status(__p_, __ec).type();
2322 case _IterNonSymlink:
2323 case _RefreshNonSymlink:
2324 case _RefreshSymlink: {
2325 file_status __st(__data_.__type_);
2326 if (__ec && !_VSTD_FS::exists(__st))
2327 *__ec = make_error_code(errc::no_such_file_or_directory);
2328 else if (__ec)
2329 __ec->clear();
2330 return __data_.__type_;
2331 }
2332 }
2333 _LIBCPP_UNREACHABLE();
2334 }
2335
2336 _LIBCPP_INLINE_VISIBILITY
2337 file_status __get_status(error_code* __ec = nullptr) const {
2338 switch (__data_.__cache_type_) {
2339 case _Empty:
2340 case _IterNonSymlink:
2341 case _IterSymlink:
2342 case _RefreshSymlinkUnresolved:
2343 return __status(__p_, __ec);
2344 case _RefreshNonSymlink:
2345 case _RefreshSymlink:
2346 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
2347 }
2348 _LIBCPP_UNREACHABLE();
2349 }
2350
2351 _LIBCPP_INLINE_VISIBILITY
2352 file_status __get_symlink_status(error_code* __ec = nullptr) const {
2353 switch (__data_.__cache_type_) {
2354 case _Empty:
2355 case _IterNonSymlink:
2356 case _IterSymlink:
2357 return __symlink_status(__p_, __ec);
2358 case _RefreshNonSymlink:
2359 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
2360 case _RefreshSymlink:
2361 case _RefreshSymlinkUnresolved:
2362 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
2363 }
2364 _LIBCPP_UNREACHABLE();
2365 }
2366
2367 _LIBCPP_INLINE_VISIBILITY
2368 uintmax_t __get_size(error_code* __ec = nullptr) const {
2369 switch (__data_.__cache_type_) {
2370 case _Empty:
2371 case _IterNonSymlink:
2372 case _IterSymlink:
2373 case _RefreshSymlinkUnresolved:
2374 return _VSTD_FS::__file_size(__p_, __ec);
2375 case _RefreshSymlink:
2376 case _RefreshNonSymlink: {
2377 error_code __m_ec;
2378 file_status __st(__get_ft(&__m_ec));
2379 __handle_error("in directory_entry::file_size", __ec, __m_ec);
2380 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
2381 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
2382 : errc::not_supported;
2383 __handle_error("in directory_entry::file_size", __ec,
2384 make_error_code(__err_kind));
2385 }
2386 return __data_.__size_;
2387 }
2388 }
2389 _LIBCPP_UNREACHABLE();
2390 }
2391
2392 _LIBCPP_INLINE_VISIBILITY
2393 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
2394 switch (__data_.__cache_type_) {
2395 case _Empty:
2396 case _IterNonSymlink:
2397 case _IterSymlink:
2398 case _RefreshSymlinkUnresolved:
2399 return _VSTD_FS::__hard_link_count(__p_, __ec);
2400 case _RefreshSymlink:
2401 case _RefreshNonSymlink: {
2402 error_code __m_ec;
2403 (void)__get_ft(&__m_ec);
2404 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
2405 return __data_.__nlink_;
2406 }
2407 }
2408 _LIBCPP_UNREACHABLE();
2409 }
2410
2411 _LIBCPP_INLINE_VISIBILITY
2412 file_time_type __get_write_time(error_code* __ec = nullptr) const {
2413 switch (__data_.__cache_type_) {
2414 case _Empty:
2415 case _IterNonSymlink:
2416 case _IterSymlink:
2417 case _RefreshSymlinkUnresolved:
2418 return _VSTD_FS::__last_write_time(__p_, __ec);
2419 case _RefreshSymlink:
2420 case _RefreshNonSymlink: {
2421 error_code __m_ec;
2422 file_status __st(__get_ft(&__m_ec));
2423 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
2424 if (_VSTD_FS::exists(__st) &&
2425 __data_.__write_time_ == file_time_type::min())
2426 __handle_error("in directory_entry::last_write_time", __ec,
2427 make_error_code(errc::value_too_large));
2428 return __data_.__write_time_;
2429 }
2430 }
2431 _LIBCPP_UNREACHABLE();
2432 }
2433
2434private:
2435 _Path __p_;
2436 __cached_data __data_;
2437};
2438
2439class __dir_element_proxy {
2440public:
2441 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
2442 return _VSTD::move(__elem_);
2443 }
2444
2445private:
2446 friend class directory_iterator;
2447 friend class recursive_directory_iterator;
2448 explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
2449 __dir_element_proxy(__dir_element_proxy&& __o)
2450 : __elem_(_VSTD::move(__o.__elem_)) {}
2451 directory_entry __elem_;
2452};
2453
2454class directory_iterator {
2455public:
2456 typedef directory_entry value_type;
2457 typedef ptrdiff_t difference_type;
2458 typedef value_type const* pointer;
2459 typedef value_type const& reference;
2460 typedef input_iterator_tag iterator_category;
2461
2462public:
2463 //ctor & dtor
2464 directory_iterator() noexcept {}
2465
2466 explicit directory_iterator(const path& __p)
2467 : directory_iterator(__p, nullptr) {}
2468
2469 directory_iterator(const path& __p, directory_options __opts)
2470 : directory_iterator(__p, nullptr, __opts) {}
2471
2472 directory_iterator(const path& __p, error_code& __ec)
2473 : directory_iterator(__p, &__ec) {}
2474
2475 directory_iterator(const path& __p, directory_options __opts,
2476 error_code& __ec)
2477 : directory_iterator(__p, &__ec, __opts) {}
2478
2479 directory_iterator(const directory_iterator&) = default;
2480 directory_iterator(directory_iterator&&) = default;
2481 directory_iterator& operator=(const directory_iterator&) = default;
2482
2483 directory_iterator& operator=(directory_iterator&& __o) noexcept {
2484 // non-default implementation provided to support self-move assign.
2485 if (this != &__o) {
2486 __imp_ = _VSTD::move(__o.__imp_);
2487 }
2488 return *this;
2489 }
2490
2491 ~directory_iterator() = default;
2492
2493 const directory_entry& operator*() const {
2494 _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
2495 return __dereference();
2496 }
2497
2498 const directory_entry* operator->() const { return &**this; }
2499
2500 directory_iterator& operator++() { return __increment(); }
2501
2502 __dir_element_proxy operator++(int) {
2503 __dir_element_proxy __p(**this);
2504 __increment();
2505 return __p;
2506 }
2507
2508 directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
2509
2510private:
2511 inline _LIBCPP_INLINE_VISIBILITY friend bool
2512 operator==(const directory_iterator& __lhs,
2513 const directory_iterator& __rhs) noexcept;
2514
2515 // construct the dir_stream
2516 _LIBCPP_FUNC_VIS
2517 directory_iterator(const path&, error_code*,
2518 directory_options = directory_options::none);
2519
2520 _LIBCPP_FUNC_VIS
2521 directory_iterator& __increment(error_code* __ec = nullptr);
2522
2523 _LIBCPP_FUNC_VIS
2524 const directory_entry& __dereference() const;
2525
2526private:
2527 shared_ptr<__dir_stream> __imp_;
2528};
2529
2530inline _LIBCPP_INLINE_VISIBILITY bool
2531operator==(const directory_iterator& __lhs,
2532 const directory_iterator& __rhs) noexcept {
2533 return __lhs.__imp_ == __rhs.__imp_;
2534}
2535
2536inline _LIBCPP_INLINE_VISIBILITY bool
2537operator!=(const directory_iterator& __lhs,
2538 const directory_iterator& __rhs) noexcept {
2539 return !(__lhs == __rhs);
2540}
2541
2542// enable directory_iterator range-based for statements
2543inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2544begin(directory_iterator __iter) noexcept {
2545 return __iter;
2546}
2547
2548inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2549end(const directory_iterator&) noexcept {
2550 return directory_iterator();
2551}
2552
2553class recursive_directory_iterator {
2554public:
2555 using value_type = directory_entry;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002556 using difference_type = ptrdiff_t;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002557 using pointer = directory_entry const*;
2558 using reference = directory_entry const&;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002559 using iterator_category = input_iterator_tag;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002560
2561public:
2562 // constructors and destructor
2563 _LIBCPP_INLINE_VISIBILITY
2564 recursive_directory_iterator() noexcept : __rec_(false) {}
2565
2566 _LIBCPP_INLINE_VISIBILITY
2567 explicit recursive_directory_iterator(
2568 const path& __p, directory_options __xoptions = directory_options::none)
2569 : recursive_directory_iterator(__p, __xoptions, nullptr) {}
2570
2571 _LIBCPP_INLINE_VISIBILITY
2572 recursive_directory_iterator(const path& __p, directory_options __xoptions,
2573 error_code& __ec)
2574 : recursive_directory_iterator(__p, __xoptions, &__ec) {}
2575
2576 _LIBCPP_INLINE_VISIBILITY
2577 recursive_directory_iterator(const path& __p, error_code& __ec)
2578 : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
2579
2580 recursive_directory_iterator(const recursive_directory_iterator&) = default;
2581 recursive_directory_iterator(recursive_directory_iterator&&) = default;
2582
2583 recursive_directory_iterator&
2584 operator=(const recursive_directory_iterator&) = default;
2585
2586 _LIBCPP_INLINE_VISIBILITY
2587 recursive_directory_iterator&
2588 operator=(recursive_directory_iterator&& __o) noexcept {
2589 // non-default implementation provided to support self-move assign.
2590 if (this != &__o) {
2591 __imp_ = _VSTD::move(__o.__imp_);
2592 __rec_ = __o.__rec_;
2593 }
2594 return *this;
2595 }
2596
2597 ~recursive_directory_iterator() = default;
2598
2599 _LIBCPP_INLINE_VISIBILITY
2600 const directory_entry& operator*() const { return __dereference(); }
2601
2602 _LIBCPP_INLINE_VISIBILITY
2603 const directory_entry* operator->() const { return &__dereference(); }
2604
2605 recursive_directory_iterator& operator++() { return __increment(); }
2606
2607 _LIBCPP_INLINE_VISIBILITY
2608 __dir_element_proxy operator++(int) {
2609 __dir_element_proxy __p(**this);
2610 __increment();
2611 return __p;
2612 }
2613
2614 _LIBCPP_INLINE_VISIBILITY
2615 recursive_directory_iterator& increment(error_code& __ec) {
2616 return __increment(&__ec);
2617 }
2618
2619 _LIBCPP_FUNC_VIS directory_options options() const;
2620 _LIBCPP_FUNC_VIS int depth() const;
2621
2622 _LIBCPP_INLINE_VISIBILITY
2623 void pop() { __pop(); }
2624
2625 _LIBCPP_INLINE_VISIBILITY
2626 void pop(error_code& __ec) { __pop(&__ec); }
2627
2628 _LIBCPP_INLINE_VISIBILITY
2629 bool recursion_pending() const { return __rec_; }
2630
2631 _LIBCPP_INLINE_VISIBILITY
2632 void disable_recursion_pending() { __rec_ = false; }
2633
2634private:
Louis Dionne0ba10dc2019-08-13 15:02:53 +00002635 _LIBCPP_FUNC_VIS
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002636 recursive_directory_iterator(const path& __p, directory_options __opt,
2637 error_code* __ec);
2638
2639 _LIBCPP_FUNC_VIS
2640 const directory_entry& __dereference() const;
2641
2642 _LIBCPP_FUNC_VIS
2643 bool __try_recursion(error_code* __ec);
2644
2645 _LIBCPP_FUNC_VIS
2646 void __advance(error_code* __ec = nullptr);
2647
2648 _LIBCPP_FUNC_VIS
2649 recursive_directory_iterator& __increment(error_code* __ec = nullptr);
2650
2651 _LIBCPP_FUNC_VIS
2652 void __pop(error_code* __ec = nullptr);
2653
2654 inline _LIBCPP_INLINE_VISIBILITY friend bool
2655 operator==(const recursive_directory_iterator&,
2656 const recursive_directory_iterator&) noexcept;
2657
Louis Dionne48ae8892019-03-19 17:47:53 +00002658 struct _LIBCPP_HIDDEN __shared_imp;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002659 shared_ptr<__shared_imp> __imp_;
2660 bool __rec_;
2661}; // class recursive_directory_iterator
2662
2663inline _LIBCPP_INLINE_VISIBILITY bool
2664operator==(const recursive_directory_iterator& __lhs,
2665 const recursive_directory_iterator& __rhs) noexcept {
2666 return __lhs.__imp_ == __rhs.__imp_;
2667}
2668
2669_LIBCPP_INLINE_VISIBILITY
2670inline bool operator!=(const recursive_directory_iterator& __lhs,
2671 const recursive_directory_iterator& __rhs) noexcept {
2672 return !(__lhs == __rhs);
2673}
2674// enable recursive_directory_iterator range-based for statements
2675inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2676begin(recursive_directory_iterator __iter) noexcept {
2677 return __iter;
2678}
2679
2680inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2681end(const recursive_directory_iterator&) noexcept {
2682 return recursive_directory_iterator();
2683}
2684
Louis Dionnef6bf76a2019-03-20 21:18:14 +00002685_LIBCPP_AVAILABILITY_FILESYSTEM_POP
2686
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002687_LIBCPP_END_NAMESPACE_FILESYSTEM
2688
2689#endif // !_LIBCPP_CXX03_LANG
2690
2691_LIBCPP_POP_MACROS
2692
2693#endif // _LIBCPP_FILESYSTEM