blob: a39184c4a27dc9338f9aee4f950834d86b0250b9 [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};
550template <>
551struct __can_convert_char<char16_t> {
552 static const bool value = true;
553 using __char_type = char16_t;
554};
555template <>
556struct __can_convert_char<char32_t> {
557 static const bool value = true;
558 using __char_type = char32_t;
559};
560
561template <class _ECharT>
562typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
563__is_separator(_ECharT __e) {
564 return __e == _ECharT('/');
Eric Fiselierb41db9a2018-10-01 01:59:37 +0000565}
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000566
Martin Storsjö2ae96532020-10-27 11:46:06 +0200567struct _NullSentinel {};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000568
569template <class _Tp>
570using _Void = void;
571
572template <class _Tp, class = void>
573struct __is_pathable_string : public false_type {};
574
575template <class _ECharT, class _Traits, class _Alloc>
576struct __is_pathable_string<
577 basic_string<_ECharT, _Traits, _Alloc>,
578 _Void<typename __can_convert_char<_ECharT>::__char_type> >
579 : public __can_convert_char<_ECharT> {
580 using _Str = basic_string<_ECharT, _Traits, _Alloc>;
581 using _Base = __can_convert_char<_ECharT>;
582 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
583 static _ECharT const* __range_end(_Str const& __s) {
584 return __s.data() + __s.length();
585 }
586 static _ECharT __first_or_null(_Str const& __s) {
587 return __s.empty() ? _ECharT{} : __s[0];
588 }
589};
590
591template <class _ECharT, class _Traits>
592struct __is_pathable_string<
593 basic_string_view<_ECharT, _Traits>,
594 _Void<typename __can_convert_char<_ECharT>::__char_type> >
595 : public __can_convert_char<_ECharT> {
596 using _Str = basic_string_view<_ECharT, _Traits>;
597 using _Base = __can_convert_char<_ECharT>;
598 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
599 static _ECharT const* __range_end(_Str const& __s) {
600 return __s.data() + __s.length();
601 }
602 static _ECharT __first_or_null(_Str const& __s) {
603 return __s.empty() ? _ECharT{} : __s[0];
604 }
605};
606
607template <class _Source, class _DS = typename decay<_Source>::type,
608 class _UnqualPtrType =
609 typename remove_const<typename remove_pointer<_DS>::type>::type,
610 bool _IsCharPtr = is_pointer<_DS>::value&&
611 __can_convert_char<_UnqualPtrType>::value>
612struct __is_pathable_char_array : false_type {};
613
614template <class _Source, class _ECharT, class _UPtr>
615struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
616 : __can_convert_char<typename remove_const<_ECharT>::type> {
617 using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
618
619 static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
620 static _ECharT const* __range_end(const _ECharT* __b) {
621 using _Iter = const _ECharT*;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200622 const _ECharT __sentinel = _ECharT{};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000623 _Iter __e = __b;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200624 for (; *__e != __sentinel; ++__e)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000625 ;
626 return __e;
627 }
628
629 static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
630};
631
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500632template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000633 class = void>
634struct __is_pathable_iter : false_type {};
635
636template <class _Iter>
637struct __is_pathable_iter<
638 _Iter, true,
639 _Void<typename __can_convert_char<
640 typename iterator_traits<_Iter>::value_type>::__char_type> >
641 : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
642 using _ECharT = typename iterator_traits<_Iter>::value_type;
643 using _Base = __can_convert_char<_ECharT>;
644
645 static _Iter __range_begin(_Iter __b) { return __b; }
Martin Storsjö2ae96532020-10-27 11:46:06 +0200646 static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000647
648 static _ECharT __first_or_null(_Iter __b) { return *__b; }
649};
650
651template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
652 bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
653 bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
654struct __is_pathable : false_type {
655 static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
656};
657
658template <class _Tp>
659struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
660
661template <class _Tp>
662struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
663};
664
665template <class _Tp>
666struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
667
668template <class _ECharT>
Louis Dionne8d053eb2020-10-09 15:31:05 -0400669struct _PathCVT;
670
671#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
672template <class _ECharT>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000673struct _PathCVT {
674 static_assert(__can_convert_char<_ECharT>::value,
675 "Char type not convertible");
676
677 typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
678
679 static void __append_range(string& __dest, _ECharT const* __b,
680 _ECharT const* __e) {
681 _Narrower()(back_inserter(__dest), __b, __e);
682 }
683
684 template <class _Iter>
685 static void __append_range(string& __dest, _Iter __b, _Iter __e) {
686 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
687 if (__b == __e)
688 return;
689 basic_string<_ECharT> __tmp(__b, __e);
690 _Narrower()(back_inserter(__dest), __tmp.data(),
691 __tmp.data() + __tmp.length());
692 }
693
694 template <class _Iter>
Martin Storsjö2ae96532020-10-27 11:46:06 +0200695 static void __append_range(string& __dest, _Iter __b, _NullSentinel) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000696 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
Martin Storsjö2ae96532020-10-27 11:46:06 +0200697 const _ECharT __sentinel = _ECharT{};
698 if (*__b == __sentinel)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000699 return;
700 basic_string<_ECharT> __tmp;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200701 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000702 __tmp.push_back(*__b);
703 _Narrower()(back_inserter(__dest), __tmp.data(),
704 __tmp.data() + __tmp.length());
705 }
706
707 template <class _Source>
708 static void __append_source(string& __dest, _Source const& __s) {
709 using _Traits = __is_pathable<_Source>;
710 __append_range(__dest, _Traits::__range_begin(__s),
711 _Traits::__range_end(__s));
712 }
713};
Louis Dionne8d053eb2020-10-09 15:31:05 -0400714#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000715
716template <>
717struct _PathCVT<char> {
718
719 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500720 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000721 __append_range(string& __dest, _Iter __b, _Iter __e) {
722 for (; __b != __e; ++__b)
723 __dest.push_back(*__b);
724 }
725
726 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500727 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000728 __append_range(string& __dest, _Iter __b, _Iter __e) {
729 __dest.__append_forward_unsafe(__b, __e);
730 }
731
732 template <class _Iter>
Martin Storsjö2ae96532020-10-27 11:46:06 +0200733 static void __append_range(string& __dest, _Iter __b, _NullSentinel) {
734 const char __sentinel = char{};
735 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000736 __dest.push_back(*__b);
737 }
738
739 template <class _Source>
740 static void __append_source(string& __dest, _Source const& __s) {
741 using _Traits = __is_pathable<_Source>;
742 __append_range(__dest, _Traits::__range_begin(__s),
743 _Traits::__range_end(__s));
744 }
745};
746
747class _LIBCPP_TYPE_VIS path {
748 template <class _SourceOrIter, class _Tp = path&>
749 using _EnableIfPathable =
750 typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
751
752 template <class _Tp>
753 using _SourceChar = typename __is_pathable<_Tp>::__char_type;
754
755 template <class _Tp>
756 using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
757
758public:
759 typedef char value_type;
760 typedef basic_string<value_type> string_type;
761 typedef _VSTD::string_view __string_view;
762 static constexpr value_type preferred_separator = '/';
763
764 enum class _LIBCPP_ENUM_VIS format : unsigned char {
765 auto_format,
766 native_format,
767 generic_format
768 };
769
770 // constructors and destructor
771 _LIBCPP_INLINE_VISIBILITY path() noexcept {}
772 _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
773 _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
774 : __pn_(_VSTD::move(__p.__pn_)) {}
775
776 _LIBCPP_INLINE_VISIBILITY
777 path(string_type&& __s, format = format::auto_format) noexcept
778 : __pn_(_VSTD::move(__s)) {}
779
780 template <class _Source, class = _EnableIfPathable<_Source, void> >
781 path(const _Source& __src, format = format::auto_format) {
782 _SourceCVT<_Source>::__append_source(__pn_, __src);
783 }
784
785 template <class _InputIt>
786 path(_InputIt __first, _InputIt __last, format = format::auto_format) {
787 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
788 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
789 }
790
Louis Dionne8d053eb2020-10-09 15:31:05 -0400791#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000792 // TODO Implement locale conversions.
793 template <class _Source, class = _EnableIfPathable<_Source, void> >
794 path(const _Source& __src, const locale& __loc, format = format::auto_format);
795 template <class _InputIt>
796 path(_InputIt __first, _InputIt _last, const locale& __loc,
797 format = format::auto_format);
Louis Dionne8d053eb2020-10-09 15:31:05 -0400798#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000799
800 _LIBCPP_INLINE_VISIBILITY
801 ~path() = default;
802
803 // assignments
804 _LIBCPP_INLINE_VISIBILITY
805 path& operator=(const path& __p) {
806 __pn_ = __p.__pn_;
807 return *this;
808 }
809
810 _LIBCPP_INLINE_VISIBILITY
811 path& operator=(path&& __p) noexcept {
812 __pn_ = _VSTD::move(__p.__pn_);
813 return *this;
814 }
815
816 template <class = void>
817 _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept {
818 __pn_ = _VSTD::move(__s);
819 return *this;
820 }
821
822 _LIBCPP_INLINE_VISIBILITY
823 path& assign(string_type&& __s) noexcept {
824 __pn_ = _VSTD::move(__s);
825 return *this;
826 }
827
828 template <class _Source>
829 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
830 operator=(const _Source& __src) {
831 return this->assign(__src);
832 }
833
834 template <class _Source>
835 _EnableIfPathable<_Source> assign(const _Source& __src) {
836 __pn_.clear();
837 _SourceCVT<_Source>::__append_source(__pn_, __src);
838 return *this;
839 }
840
841 template <class _InputIt>
842 path& assign(_InputIt __first, _InputIt __last) {
843 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
844 __pn_.clear();
845 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
846 return *this;
847 }
848
849private:
850 template <class _ECharT>
851 static bool __source_is_absolute(_ECharT __first_or_null) {
852 return __is_separator(__first_or_null);
853 }
854
855public:
856 // appends
857 path& operator/=(const path& __p) {
858 if (__p.is_absolute()) {
859 __pn_ = __p.__pn_;
860 return *this;
861 }
862 if (has_filename())
863 __pn_ += preferred_separator;
864 __pn_ += __p.native();
865 return *this;
866 }
867
868 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
869 // is known at compile time to be "/' since the user almost certainly intended
870 // to append a separator instead of overwriting the path with "/"
871 template <class _Source>
872 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
873 operator/=(const _Source& __src) {
874 return this->append(__src);
875 }
876
877 template <class _Source>
878 _EnableIfPathable<_Source> append(const _Source& __src) {
879 using _Traits = __is_pathable<_Source>;
880 using _CVT = _PathCVT<_SourceChar<_Source> >;
881 if (__source_is_absolute(_Traits::__first_or_null(__src)))
882 __pn_.clear();
883 else if (has_filename())
884 __pn_ += preferred_separator;
885 _CVT::__append_source(__pn_, __src);
886 return *this;
887 }
888
889 template <class _InputIt>
890 path& append(_InputIt __first, _InputIt __last) {
891 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
892 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
893 using _CVT = _PathCVT<_ItVal>;
894 if (__first != __last && __source_is_absolute(*__first))
895 __pn_.clear();
896 else if (has_filename())
897 __pn_ += preferred_separator;
898 _CVT::__append_range(__pn_, __first, __last);
899 return *this;
900 }
901
902 // concatenation
903 _LIBCPP_INLINE_VISIBILITY
904 path& operator+=(const path& __x) {
905 __pn_ += __x.__pn_;
906 return *this;
907 }
908
909 _LIBCPP_INLINE_VISIBILITY
910 path& operator+=(const string_type& __x) {
911 __pn_ += __x;
912 return *this;
913 }
914
915 _LIBCPP_INLINE_VISIBILITY
916 path& operator+=(__string_view __x) {
917 __pn_ += __x;
918 return *this;
919 }
920
921 _LIBCPP_INLINE_VISIBILITY
922 path& operator+=(const value_type* __x) {
923 __pn_ += __x;
924 return *this;
925 }
926
927 _LIBCPP_INLINE_VISIBILITY
928 path& operator+=(value_type __x) {
929 __pn_ += __x;
930 return *this;
931 }
932
933 template <class _ECharT>
934 typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
935 operator+=(_ECharT __x) {
936 basic_string<_ECharT> __tmp;
937 __tmp += __x;
938 _PathCVT<_ECharT>::__append_source(__pn_, __tmp);
939 return *this;
940 }
941
942 template <class _Source>
943 _EnableIfPathable<_Source> operator+=(const _Source& __x) {
944 return this->concat(__x);
945 }
946
947 template <class _Source>
948 _EnableIfPathable<_Source> concat(const _Source& __x) {
949 _SourceCVT<_Source>::__append_source(__pn_, __x);
950 return *this;
951 }
952
953 template <class _InputIt>
954 path& concat(_InputIt __first, _InputIt __last) {
955 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
956 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
957 return *this;
958 }
959
960 // modifiers
961 _LIBCPP_INLINE_VISIBILITY
962 void clear() noexcept { __pn_.clear(); }
963
964 path& make_preferred() { return *this; }
965
966 _LIBCPP_INLINE_VISIBILITY
967 path& remove_filename() {
968 auto __fname = __filename();
969 if (!__fname.empty())
970 __pn_.erase(__fname.data() - __pn_.data());
971 return *this;
972 }
973
974 path& replace_filename(const path& __replacement) {
975 remove_filename();
976 return (*this /= __replacement);
977 }
978
979 path& replace_extension(const path& __replacement = path());
980
981 _LIBCPP_INLINE_VISIBILITY
982 void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
983
984 // private helper to allow reserving memory in the path
985 _LIBCPP_INLINE_VISIBILITY
986 void __reserve(size_t __s) { __pn_.reserve(__s); }
987
988 // native format observers
989 _LIBCPP_INLINE_VISIBILITY
990 const string_type& native() const noexcept { return __pn_; }
991
992 _LIBCPP_INLINE_VISIBILITY
993 const value_type* c_str() const noexcept { return __pn_.c_str(); }
994
995 _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
996
Louis Dionne8d053eb2020-10-09 15:31:05 -0400997 _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; }
998 _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; }
999
1000#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001001 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1002 class _Allocator = allocator<_ECharT> >
1003 basic_string<_ECharT, _Traits, _Allocator>
1004 string(const _Allocator& __a = _Allocator()) const {
1005 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
1006 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1007 _Str __s(__a);
1008 __s.reserve(__pn_.size());
1009 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1010 return __s;
1011 }
1012
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001013 _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const {
1014 return string<wchar_t>();
1015 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001016 _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const {
1017 return string<char16_t>();
1018 }
1019 _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const {
1020 return string<char32_t>();
1021 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001022#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001023
1024 // generic format observers
Louis Dionne8d053eb2020-10-09 15:31:05 -04001025 std::string generic_string() const { return __pn_; }
1026 std::string generic_u8string() const { return __pn_; }
1027
1028#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001029 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1030 class _Allocator = allocator<_ECharT> >
1031 basic_string<_ECharT, _Traits, _Allocator>
1032 generic_string(const _Allocator& __a = _Allocator()) const {
1033 return string<_ECharT, _Traits, _Allocator>(__a);
1034 }
1035
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001036 std::wstring generic_wstring() const { return string<wchar_t>(); }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001037 std::u16string generic_u16string() const { return string<char16_t>(); }
1038 std::u32string generic_u32string() const { return string<char32_t>(); }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001039#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001040
1041private:
1042 int __compare(__string_view) const;
1043 __string_view __root_name() const;
1044 __string_view __root_directory() const;
1045 __string_view __root_path_raw() const;
1046 __string_view __relative_path() const;
1047 __string_view __parent_path() const;
1048 __string_view __filename() const;
1049 __string_view __stem() const;
1050 __string_view __extension() const;
1051
1052public:
1053 // compare
1054 _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
1055 return __compare(__p.__pn_);
1056 }
1057 _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
1058 return __compare(__s);
1059 }
1060 _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
1061 return __compare(__s);
1062 }
1063 _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
1064 return __compare(__s);
1065 }
1066
1067 // decomposition
1068 _LIBCPP_INLINE_VISIBILITY path root_name() const {
1069 return string_type(__root_name());
1070 }
1071 _LIBCPP_INLINE_VISIBILITY path root_directory() const {
1072 return string_type(__root_directory());
1073 }
1074 _LIBCPP_INLINE_VISIBILITY path root_path() const {
1075 return root_name().append(string_type(__root_directory()));
1076 }
1077 _LIBCPP_INLINE_VISIBILITY path relative_path() const {
1078 return string_type(__relative_path());
1079 }
1080 _LIBCPP_INLINE_VISIBILITY path parent_path() const {
1081 return string_type(__parent_path());
1082 }
1083 _LIBCPP_INLINE_VISIBILITY path filename() const {
1084 return string_type(__filename());
1085 }
1086 _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
1087 _LIBCPP_INLINE_VISIBILITY path extension() const {
1088 return string_type(__extension());
1089 }
1090
1091 // query
1092 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
1093 empty() const noexcept {
1094 return __pn_.empty();
1095 }
1096
1097 _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
1098 return !__root_name().empty();
1099 }
1100 _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
1101 return !__root_directory().empty();
1102 }
1103 _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
1104 return !__root_path_raw().empty();
1105 }
1106 _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
1107 return !__relative_path().empty();
1108 }
1109 _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
1110 return !__parent_path().empty();
1111 }
1112 _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
1113 return !__filename().empty();
1114 }
1115 _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
1116 _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
1117 return !__extension().empty();
1118 }
1119
1120 _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
1121 return has_root_directory();
1122 }
1123 _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
1124
1125 // relative paths
1126 path lexically_normal() const;
1127 path lexically_relative(const path& __base) const;
1128
1129 _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
1130 path __result = this->lexically_relative(__base);
1131 if (__result.native().empty())
1132 return *this;
1133 return __result;
1134 }
1135
1136 // iterators
1137 class _LIBCPP_TYPE_VIS iterator;
1138 typedef iterator const_iterator;
1139
1140 iterator begin() const;
1141 iterator end() const;
1142
Louis Dionne8d053eb2020-10-09 15:31:05 -04001143#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001144 template <class _CharT, class _Traits>
1145 _LIBCPP_INLINE_VISIBILITY friend
1146 typename enable_if<is_same<_CharT, char>::value &&
1147 is_same<_Traits, char_traits<char> >::value,
1148 basic_ostream<_CharT, _Traits>&>::type
1149 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
1150 __os << std::__quoted(__p.native());
1151 return __os;
1152 }
1153
1154 template <class _CharT, class _Traits>
1155 _LIBCPP_INLINE_VISIBILITY friend
1156 typename enable_if<!is_same<_CharT, char>::value ||
1157 !is_same<_Traits, char_traits<char> >::value,
1158 basic_ostream<_CharT, _Traits>&>::type
1159 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
1160 __os << std::__quoted(__p.string<_CharT, _Traits>());
1161 return __os;
1162 }
1163
1164 template <class _CharT, class _Traits>
1165 _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
1166 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
1167 basic_string<_CharT, _Traits> __tmp;
1168 __is >> __quoted(__tmp);
1169 __p = __tmp;
1170 return __is;
1171 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001172#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001173
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001174 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
1175 return __lhs.compare(__rhs) == 0;
1176 }
1177 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
1178 return __lhs.compare(__rhs) != 0;
1179 }
1180 friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
1181 return __lhs.compare(__rhs) < 0;
1182 }
1183 friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
1184 return __lhs.compare(__rhs) <= 0;
1185 }
1186 friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
1187 return __lhs.compare(__rhs) > 0;
1188 }
1189 friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
1190 return __lhs.compare(__rhs) >= 0;
1191 }
1192
1193 friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
1194 const path& __rhs) {
1195 path __result(__lhs);
1196 __result /= __rhs;
1197 return __result;
1198 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001199private:
1200 inline _LIBCPP_INLINE_VISIBILITY path&
1201 __assign_view(__string_view const& __s) noexcept {
1202 __pn_ = string_type(__s);
1203 return *this;
1204 }
1205 string_type __pn_;
1206};
1207
1208inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
1209 __lhs.swap(__rhs);
1210}
1211
1212_LIBCPP_FUNC_VIS
1213size_t hash_value(const path& __p) noexcept;
1214
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001215template <class _Source>
1216_LIBCPP_INLINE_VISIBILITY
1217 typename enable_if<__is_pathable<_Source>::value, path>::type
1218 u8path(const _Source& __s) {
1219 static_assert(
1220 is_same<typename __is_pathable<_Source>::__char_type, char>::value,
1221 "u8path(Source const&) requires Source have a character type of type "
1222 "'char'");
1223 return path(__s);
1224}
1225
1226template <class _InputIt>
1227_LIBCPP_INLINE_VISIBILITY
1228 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1229 u8path(_InputIt __f, _InputIt __l) {
1230 static_assert(
1231 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
1232 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'");
1233 return path(__f, __l);
1234}
1235
1236class _LIBCPP_TYPE_VIS path::iterator {
1237public:
1238 enum _ParserState : unsigned char {
1239 _Singular,
1240 _BeforeBegin,
1241 _InRootName,
1242 _InRootDir,
1243 _InFilenames,
1244 _InTrailingSep,
1245 _AtEnd
1246 };
1247
1248public:
1249 typedef bidirectional_iterator_tag iterator_category;
1250
1251 typedef path value_type;
1252 typedef std::ptrdiff_t difference_type;
1253 typedef const path* pointer;
1254 typedef const path& reference;
1255
1256 typedef void
1257 __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
1258
1259public:
1260 _LIBCPP_INLINE_VISIBILITY
1261 iterator()
1262 : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
1263 __state_(_Singular) {}
1264
1265 iterator(const iterator&) = default;
1266 ~iterator() = default;
1267
1268 iterator& operator=(const iterator&) = default;
1269
1270 _LIBCPP_INLINE_VISIBILITY
1271 reference operator*() const { return __stashed_elem_; }
1272
1273 _LIBCPP_INLINE_VISIBILITY
1274 pointer operator->() const { return &__stashed_elem_; }
1275
1276 _LIBCPP_INLINE_VISIBILITY
1277 iterator& operator++() {
1278 _LIBCPP_ASSERT(__state_ != _Singular,
1279 "attempting to increment a singular iterator");
1280 _LIBCPP_ASSERT(__state_ != _AtEnd,
1281 "attempting to increment the end iterator");
1282 return __increment();
1283 }
1284
1285 _LIBCPP_INLINE_VISIBILITY
1286 iterator operator++(int) {
1287 iterator __it(*this);
1288 this->operator++();
1289 return __it;
1290 }
1291
1292 _LIBCPP_INLINE_VISIBILITY
1293 iterator& operator--() {
1294 _LIBCPP_ASSERT(__state_ != _Singular,
1295 "attempting to decrement a singular iterator");
1296 _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
1297 "attempting to decrement the begin iterator");
1298 return __decrement();
1299 }
1300
1301 _LIBCPP_INLINE_VISIBILITY
1302 iterator operator--(int) {
1303 iterator __it(*this);
1304 this->operator--();
1305 return __it;
1306 }
1307
1308private:
1309 friend class path;
1310
1311 inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
1312 const iterator&);
1313
1314 iterator& __increment();
1315 iterator& __decrement();
1316
1317 path __stashed_elem_;
1318 const path* __path_ptr_;
1319 path::__string_view __entry_;
1320 _ParserState __state_;
1321};
1322
1323inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
1324 const path::iterator& __rhs) {
1325 return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
1326 __lhs.__entry_.data() == __rhs.__entry_.data();
1327}
1328
1329inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
1330 const path::iterator& __rhs) {
1331 return !(__lhs == __rhs);
1332}
1333
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001334// TODO(ldionne): We need to pop the pragma and push it again after
1335// filesystem_error to work around PR41078.
1336_LIBCPP_AVAILABILITY_FILESYSTEM_POP
1337
1338class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001339public:
1340 _LIBCPP_INLINE_VISIBILITY
1341 filesystem_error(const string& __what, error_code __ec)
1342 : system_error(__ec, __what),
1343 __storage_(make_shared<_Storage>(path(), path())) {
1344 __create_what(0);
1345 }
1346
1347 _LIBCPP_INLINE_VISIBILITY
1348 filesystem_error(const string& __what, const path& __p1, error_code __ec)
1349 : system_error(__ec, __what),
1350 __storage_(make_shared<_Storage>(__p1, path())) {
1351 __create_what(1);
1352 }
1353
1354 _LIBCPP_INLINE_VISIBILITY
1355 filesystem_error(const string& __what, const path& __p1, const path& __p2,
1356 error_code __ec)
1357 : system_error(__ec, __what),
1358 __storage_(make_shared<_Storage>(__p1, __p2)) {
1359 __create_what(2);
1360 }
1361
1362 _LIBCPP_INLINE_VISIBILITY
1363 const path& path1() const noexcept { return __storage_->__p1_; }
1364
1365 _LIBCPP_INLINE_VISIBILITY
1366 const path& path2() const noexcept { return __storage_->__p2_; }
1367
Dimitry Andric47269ce2020-03-13 19:36:26 +01001368 filesystem_error(const filesystem_error&) = default;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001369 ~filesystem_error() override; // key function
1370
1371 _LIBCPP_INLINE_VISIBILITY
1372 const char* what() const noexcept override {
1373 return __storage_->__what_.c_str();
1374 }
1375
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001376 void __create_what(int __num_paths);
1377
1378private:
Louis Dionne48ae8892019-03-19 17:47:53 +00001379 struct _LIBCPP_HIDDEN _Storage {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001380 _LIBCPP_INLINE_VISIBILITY
1381 _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
1382
1383 path __p1_;
1384 path __p2_;
1385 string __what_;
1386 };
1387 shared_ptr<_Storage> __storage_;
1388};
1389
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001390_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
1391
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001392template <class... _Args>
1393_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
1394#ifndef _LIBCPP_NO_EXCEPTIONS
Louis Dionne6251ef02019-02-05 15:46:52 +00001395void __throw_filesystem_error(_Args&&... __args) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001396 throw filesystem_error(std::forward<_Args>(__args)...);
1397}
1398#else
Louis Dionne6251ef02019-02-05 15:46:52 +00001399void __throw_filesystem_error(_Args&&...) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001400 _VSTD::abort();
1401}
1402#endif
1403
1404// operational functions
1405
1406_LIBCPP_FUNC_VIS
1407path __absolute(const path&, error_code* __ec = nullptr);
1408_LIBCPP_FUNC_VIS
1409path __canonical(const path&, error_code* __ec = nullptr);
1410_LIBCPP_FUNC_VIS
1411void __copy(const path& __from, const path& __to, copy_options __opt,
1412 error_code* __ec = nullptr);
1413_LIBCPP_FUNC_VIS
1414bool __copy_file(const path& __from, const path& __to, copy_options __opt,
1415 error_code* __ec = nullptr);
1416_LIBCPP_FUNC_VIS
1417void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
1418 error_code* __ec = nullptr);
1419_LIBCPP_FUNC_VIS
1420bool __create_directories(const path& p, error_code* ec = nullptr);
1421_LIBCPP_FUNC_VIS
1422bool __create_directory(const path& p, error_code* ec = nullptr);
1423_LIBCPP_FUNC_VIS
1424bool __create_directory(const path& p, const path& attributes,
1425 error_code* ec = nullptr);
1426_LIBCPP_FUNC_VIS
1427void __create_directory_symlink(const path& __to, const path& __new_symlink,
1428 error_code* __ec = nullptr);
1429_LIBCPP_FUNC_VIS
1430void __create_hard_link(const path& __to, const path& __new_hard_link,
1431 error_code* __ec = nullptr);
1432_LIBCPP_FUNC_VIS
1433void __create_symlink(const path& __to, const path& __new_symlink,
1434 error_code* __ec = nullptr);
1435_LIBCPP_FUNC_VIS
1436path __current_path(error_code* __ec = nullptr);
1437_LIBCPP_FUNC_VIS
1438void __current_path(const path&, error_code* __ec = nullptr);
1439_LIBCPP_FUNC_VIS
1440bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
1441_LIBCPP_FUNC_VIS
1442uintmax_t __file_size(const path&, error_code* __ec = nullptr);
1443_LIBCPP_FUNC_VIS
1444uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
1445_LIBCPP_FUNC_VIS
1446bool __fs_is_empty(const path& p, error_code* ec = nullptr);
1447_LIBCPP_FUNC_VIS
1448file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
1449_LIBCPP_FUNC_VIS
1450void __last_write_time(const path& p, file_time_type new_time,
1451 error_code* ec = nullptr);
1452_LIBCPP_FUNC_VIS
1453void __permissions(const path&, perms, perm_options, error_code* = nullptr);
1454_LIBCPP_FUNC_VIS
1455path __read_symlink(const path& p, error_code* ec = nullptr);
1456_LIBCPP_FUNC_VIS
1457bool __remove(const path& p, error_code* ec = nullptr);
1458_LIBCPP_FUNC_VIS
1459uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
1460_LIBCPP_FUNC_VIS
1461void __rename(const path& from, const path& to, error_code* ec = nullptr);
1462_LIBCPP_FUNC_VIS
1463void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
1464_LIBCPP_FUNC_VIS
1465space_info __space(const path&, error_code* __ec = nullptr);
1466_LIBCPP_FUNC_VIS
1467file_status __status(const path&, error_code* __ec = nullptr);
1468_LIBCPP_FUNC_VIS
1469file_status __symlink_status(const path&, error_code* __ec = nullptr);
1470_LIBCPP_FUNC_VIS
1471path __system_complete(const path&, error_code* __ec = nullptr);
1472_LIBCPP_FUNC_VIS
1473path __temp_directory_path(error_code* __ec = nullptr);
1474_LIBCPP_FUNC_VIS
1475path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
1476
1477inline _LIBCPP_INLINE_VISIBILITY path current_path() {
1478 return __current_path();
1479}
1480
1481inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
1482 return __current_path(&__ec);
1483}
1484
1485inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
1486 __current_path(__p);
1487}
1488
1489inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
1490 error_code& __ec) noexcept {
1491 __current_path(__p, &__ec);
1492}
1493
1494inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
1495 return __absolute(__p);
1496}
1497
1498inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
1499 error_code& __ec) {
1500 return __absolute(__p, &__ec);
1501}
1502
1503inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
1504 return __canonical(__p);
1505}
1506
1507inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
1508 error_code& __ec) {
1509 return __canonical(__p, &__ec);
1510}
1511
1512inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
1513 const path& __to) {
1514 __copy(__from, __to, copy_options::none);
1515}
1516
1517inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1518 error_code& __ec) {
1519 __copy(__from, __to, copy_options::none, &__ec);
1520}
1521
1522inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1523 copy_options __opt) {
1524 __copy(__from, __to, __opt);
1525}
1526
1527inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1528 copy_options __opt,
1529 error_code& __ec) {
1530 __copy(__from, __to, __opt, &__ec);
1531}
1532
1533inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1534 const path& __to) {
1535 return __copy_file(__from, __to, copy_options::none);
1536}
1537
1538inline _LIBCPP_INLINE_VISIBILITY bool
1539copy_file(const path& __from, const path& __to, error_code& __ec) {
1540 return __copy_file(__from, __to, copy_options::none, &__ec);
1541}
1542
1543inline _LIBCPP_INLINE_VISIBILITY bool
1544copy_file(const path& __from, const path& __to, copy_options __opt) {
1545 return __copy_file(__from, __to, __opt);
1546}
1547
1548inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1549 const path& __to,
1550 copy_options __opt,
1551 error_code& __ec) {
1552 return __copy_file(__from, __to, __opt, &__ec);
1553}
1554
1555inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
1556 const path& __new) {
1557 __copy_symlink(__existing, __new);
1558}
1559
1560inline _LIBCPP_INLINE_VISIBILITY void
1561copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
1562 __copy_symlink(__ext, __new, &__ec);
1563}
1564
1565inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
1566 return __create_directories(__p);
1567}
1568
1569inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
1570 error_code& __ec) {
1571 return __create_directories(__p, &__ec);
1572}
1573
1574inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
1575 return __create_directory(__p);
1576}
1577
1578inline _LIBCPP_INLINE_VISIBILITY bool
1579create_directory(const path& __p, error_code& __ec) noexcept {
1580 return __create_directory(__p, &__ec);
1581}
1582
1583inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
1584 const path& __attrs) {
1585 return __create_directory(__p, __attrs);
1586}
1587
1588inline _LIBCPP_INLINE_VISIBILITY bool
1589create_directory(const path& __p, const path& __attrs,
1590 error_code& __ec) noexcept {
1591 return __create_directory(__p, __attrs, &__ec);
1592}
1593
1594inline _LIBCPP_INLINE_VISIBILITY void
1595create_directory_symlink(const path& __to, const path& __new) {
1596 __create_directory_symlink(__to, __new);
1597}
1598
1599inline _LIBCPP_INLINE_VISIBILITY void
1600create_directory_symlink(const path& __to, const path& __new,
1601 error_code& __ec) noexcept {
1602 __create_directory_symlink(__to, __new, &__ec);
1603}
1604
1605inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
1606 const path& __new) {
1607 __create_hard_link(__to, __new);
1608}
1609
1610inline _LIBCPP_INLINE_VISIBILITY void
1611create_hard_link(const path& __to, const path& __new,
1612 error_code& __ec) noexcept {
1613 __create_hard_link(__to, __new, &__ec);
1614}
1615
1616inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
1617 const path& __new) {
1618 __create_symlink(__to, __new);
1619}
1620
1621inline _LIBCPP_INLINE_VISIBILITY void
1622create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
1623 return __create_symlink(__to, __new, &__ec);
1624}
1625
1626inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
1627 return __s.type() != file_type::none;
1628}
1629
1630inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
1631 return status_known(__s) && __s.type() != file_type::not_found;
1632}
1633
1634inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
1635 return exists(__status(__p));
1636}
1637
1638inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
1639 error_code& __ec) noexcept {
1640 auto __s = __status(__p, &__ec);
1641 if (status_known(__s))
1642 __ec.clear();
1643 return exists(__s);
1644}
1645
1646inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
1647 const path& __p2) {
1648 return __equivalent(__p1, __p2);
1649}
1650
1651inline _LIBCPP_INLINE_VISIBILITY bool
1652equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
1653 return __equivalent(__p1, __p2, &__ec);
1654}
1655
1656inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
1657 return __file_size(__p);
1658}
1659
1660inline _LIBCPP_INLINE_VISIBILITY uintmax_t
1661file_size(const path& __p, error_code& __ec) noexcept {
1662 return __file_size(__p, &__ec);
1663}
1664
1665inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
1666 return __hard_link_count(__p);
1667}
1668
1669inline _LIBCPP_INLINE_VISIBILITY uintmax_t
1670hard_link_count(const path& __p, error_code& __ec) noexcept {
1671 return __hard_link_count(__p, &__ec);
1672}
1673
1674inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
1675 return __s.type() == file_type::block;
1676}
1677
1678inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
1679 return is_block_file(__status(__p));
1680}
1681
1682inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
1683 error_code& __ec) noexcept {
1684 return is_block_file(__status(__p, &__ec));
1685}
1686
1687inline _LIBCPP_INLINE_VISIBILITY bool
1688is_character_file(file_status __s) noexcept {
1689 return __s.type() == file_type::character;
1690}
1691
1692inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
1693 return is_character_file(__status(__p));
1694}
1695
1696inline _LIBCPP_INLINE_VISIBILITY bool
1697is_character_file(const path& __p, error_code& __ec) noexcept {
1698 return is_character_file(__status(__p, &__ec));
1699}
1700
1701inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
1702 return __s.type() == file_type::directory;
1703}
1704
1705inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
1706 return is_directory(__status(__p));
1707}
1708
1709inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
1710 error_code& __ec) noexcept {
1711 return is_directory(__status(__p, &__ec));
1712}
1713
1714inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
1715 return __fs_is_empty(__p);
1716}
1717
1718inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
1719 error_code& __ec) {
1720 return __fs_is_empty(__p, &__ec);
1721}
1722
1723inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
1724 return __s.type() == file_type::fifo;
1725}
1726inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
1727 return is_fifo(__status(__p));
1728}
1729
1730inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
1731 error_code& __ec) noexcept {
1732 return is_fifo(__status(__p, &__ec));
1733}
1734
1735inline _LIBCPP_INLINE_VISIBILITY bool
1736is_regular_file(file_status __s) noexcept {
1737 return __s.type() == file_type::regular;
1738}
1739
1740inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
1741 return is_regular_file(__status(__p));
1742}
1743
1744inline _LIBCPP_INLINE_VISIBILITY bool
1745is_regular_file(const path& __p, error_code& __ec) noexcept {
1746 return is_regular_file(__status(__p, &__ec));
1747}
1748
1749inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
1750 return __s.type() == file_type::socket;
1751}
1752
1753inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
1754 return is_socket(__status(__p));
1755}
1756
1757inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
1758 error_code& __ec) noexcept {
1759 return is_socket(__status(__p, &__ec));
1760}
1761
1762inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
1763 return __s.type() == file_type::symlink;
1764}
1765
1766inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
1767 return is_symlink(__symlink_status(__p));
1768}
1769
1770inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
1771 error_code& __ec) noexcept {
1772 return is_symlink(__symlink_status(__p, &__ec));
1773}
1774
1775inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
1776 return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
1777 !is_symlink(__s);
1778}
1779
1780inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
1781 return is_other(__status(__p));
1782}
1783
1784inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
1785 error_code& __ec) noexcept {
1786 return is_other(__status(__p, &__ec));
1787}
1788
1789inline _LIBCPP_INLINE_VISIBILITY file_time_type
1790last_write_time(const path& __p) {
1791 return __last_write_time(__p);
1792}
1793
1794inline _LIBCPP_INLINE_VISIBILITY file_time_type
1795last_write_time(const path& __p, error_code& __ec) noexcept {
1796 return __last_write_time(__p, &__ec);
1797}
1798
1799inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
1800 file_time_type __t) {
1801 __last_write_time(__p, __t);
1802}
1803
1804inline _LIBCPP_INLINE_VISIBILITY void
1805last_write_time(const path& __p, file_time_type __t,
1806 error_code& __ec) noexcept {
1807 __last_write_time(__p, __t, &__ec);
1808}
1809
1810inline _LIBCPP_INLINE_VISIBILITY void
1811permissions(const path& __p, perms __prms,
1812 perm_options __opts = perm_options::replace) {
1813 __permissions(__p, __prms, __opts);
1814}
1815
1816inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
1817 error_code& __ec) noexcept {
1818 __permissions(__p, __prms, perm_options::replace, &__ec);
1819}
1820
1821inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
1822 perm_options __opts,
1823 error_code& __ec) {
1824 __permissions(__p, __prms, __opts, &__ec);
1825}
1826
1827inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
1828 const path& __base,
1829 error_code& __ec) {
1830 path __tmp = __weakly_canonical(__p, &__ec);
1831 if (__ec)
1832 return {};
1833 path __tmp_base = __weakly_canonical(__base, &__ec);
1834 if (__ec)
1835 return {};
1836 return __tmp.lexically_proximate(__tmp_base);
1837}
1838
1839inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
1840 error_code& __ec) {
1841 return proximate(__p, current_path(), __ec);
1842}
1843
1844inline _LIBCPP_INLINE_VISIBILITY path
1845proximate(const path& __p, const path& __base = current_path()) {
1846 return __weakly_canonical(__p).lexically_proximate(
1847 __weakly_canonical(__base));
1848}
1849
1850inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
1851 return __read_symlink(__p);
1852}
1853
1854inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
1855 error_code& __ec) {
1856 return __read_symlink(__p, &__ec);
1857}
1858
1859inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
1860 const path& __base,
1861 error_code& __ec) {
1862 path __tmp = __weakly_canonical(__p, &__ec);
1863 if (__ec)
1864 return path();
1865 path __tmpbase = __weakly_canonical(__base, &__ec);
1866 if (__ec)
1867 return path();
1868 return __tmp.lexically_relative(__tmpbase);
1869}
1870
1871inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
1872 error_code& __ec) {
1873 return relative(__p, current_path(), __ec);
1874}
1875
1876inline _LIBCPP_INLINE_VISIBILITY path
1877relative(const path& __p, const path& __base = current_path()) {
1878 return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
1879}
1880
1881inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
1882 return __remove(__p);
1883}
1884
1885inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
1886 error_code& __ec) noexcept {
1887 return __remove(__p, &__ec);
1888}
1889
1890inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
1891 return __remove_all(__p);
1892}
1893
1894inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
1895 error_code& __ec) {
1896 return __remove_all(__p, &__ec);
1897}
1898
1899inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
1900 const path& __to) {
1901 return __rename(__from, __to);
1902}
1903
1904inline _LIBCPP_INLINE_VISIBILITY void
1905rename(const path& __from, const path& __to, error_code& __ec) noexcept {
1906 return __rename(__from, __to, &__ec);
1907}
1908
1909inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
1910 uintmax_t __ns) {
1911 return __resize_file(__p, __ns);
1912}
1913
1914inline _LIBCPP_INLINE_VISIBILITY void
1915resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
1916 return __resize_file(__p, __ns, &__ec);
1917}
1918
1919inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
1920 return __space(__p);
1921}
1922
1923inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
1924 error_code& __ec) noexcept {
1925 return __space(__p, &__ec);
1926}
1927
1928inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
1929 return __status(__p);
1930}
1931
1932inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
1933 error_code& __ec) noexcept {
1934 return __status(__p, &__ec);
1935}
1936
1937inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
1938 return __symlink_status(__p);
1939}
1940
1941inline _LIBCPP_INLINE_VISIBILITY file_status
1942symlink_status(const path& __p, error_code& __ec) noexcept {
1943 return __symlink_status(__p, &__ec);
1944}
1945
1946inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
1947 return __temp_directory_path();
1948}
1949
1950inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
1951 return __temp_directory_path(&__ec);
1952}
1953
1954inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
1955 return __weakly_canonical(__p);
1956}
1957
1958inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
1959 error_code& __ec) {
1960 return __weakly_canonical(__p, &__ec);
1961}
1962
1963class directory_iterator;
1964class recursive_directory_iterator;
Louis Dionne48ae8892019-03-19 17:47:53 +00001965class _LIBCPP_HIDDEN __dir_stream;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001966
1967class directory_entry {
1968 typedef _VSTD_FS::path _Path;
1969
1970public:
1971 // constructors and destructors
1972 directory_entry() noexcept = default;
1973 directory_entry(directory_entry const&) = default;
1974 directory_entry(directory_entry&&) noexcept = default;
1975
1976 _LIBCPP_INLINE_VISIBILITY
1977 explicit directory_entry(_Path const& __p) : __p_(__p) {
1978 error_code __ec;
1979 __refresh(&__ec);
1980 }
1981
1982 _LIBCPP_INLINE_VISIBILITY
1983 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
1984 __refresh(&__ec);
1985 }
1986
1987 ~directory_entry() {}
1988
1989 directory_entry& operator=(directory_entry const&) = default;
1990 directory_entry& operator=(directory_entry&&) noexcept = default;
1991
1992 _LIBCPP_INLINE_VISIBILITY
1993 void assign(_Path const& __p) {
1994 __p_ = __p;
1995 error_code __ec;
1996 __refresh(&__ec);
1997 }
1998
1999 _LIBCPP_INLINE_VISIBILITY
2000 void assign(_Path const& __p, error_code& __ec) {
2001 __p_ = __p;
2002 __refresh(&__ec);
2003 }
2004
2005 _LIBCPP_INLINE_VISIBILITY
2006 void replace_filename(_Path const& __p) {
2007 __p_.replace_filename(__p);
2008 error_code __ec;
2009 __refresh(&__ec);
2010 }
2011
2012 _LIBCPP_INLINE_VISIBILITY
2013 void replace_filename(_Path const& __p, error_code& __ec) {
2014 __p_ = __p_.parent_path() / __p;
2015 __refresh(&__ec);
2016 }
2017
2018 _LIBCPP_INLINE_VISIBILITY
2019 void refresh() { __refresh(); }
2020
2021 _LIBCPP_INLINE_VISIBILITY
2022 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
2023
2024 _LIBCPP_INLINE_VISIBILITY
2025 _Path const& path() const noexcept { return __p_; }
2026
2027 _LIBCPP_INLINE_VISIBILITY
2028 operator const _Path&() const noexcept { return __p_; }
2029
2030 _LIBCPP_INLINE_VISIBILITY
2031 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
2032
2033 _LIBCPP_INLINE_VISIBILITY
2034 bool exists(error_code& __ec) const noexcept {
2035 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
2036 }
2037
2038 _LIBCPP_INLINE_VISIBILITY
2039 bool is_block_file() const { return __get_ft() == file_type::block; }
2040
2041 _LIBCPP_INLINE_VISIBILITY
2042 bool is_block_file(error_code& __ec) const noexcept {
2043 return __get_ft(&__ec) == file_type::block;
2044 }
2045
2046 _LIBCPP_INLINE_VISIBILITY
2047 bool is_character_file() const { return __get_ft() == file_type::character; }
2048
2049 _LIBCPP_INLINE_VISIBILITY
2050 bool is_character_file(error_code& __ec) const noexcept {
2051 return __get_ft(&__ec) == file_type::character;
2052 }
2053
2054 _LIBCPP_INLINE_VISIBILITY
2055 bool is_directory() const { return __get_ft() == file_type::directory; }
2056
2057 _LIBCPP_INLINE_VISIBILITY
2058 bool is_directory(error_code& __ec) const noexcept {
2059 return __get_ft(&__ec) == file_type::directory;
2060 }
2061
2062 _LIBCPP_INLINE_VISIBILITY
2063 bool is_fifo() const { return __get_ft() == file_type::fifo; }
2064
2065 _LIBCPP_INLINE_VISIBILITY
2066 bool is_fifo(error_code& __ec) const noexcept {
2067 return __get_ft(&__ec) == file_type::fifo;
2068 }
2069
2070 _LIBCPP_INLINE_VISIBILITY
2071 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
2072
2073 _LIBCPP_INLINE_VISIBILITY
2074 bool is_other(error_code& __ec) const noexcept {
2075 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
2076 }
2077
2078 _LIBCPP_INLINE_VISIBILITY
2079 bool is_regular_file() const { return __get_ft() == file_type::regular; }
2080
2081 _LIBCPP_INLINE_VISIBILITY
2082 bool is_regular_file(error_code& __ec) const noexcept {
2083 return __get_ft(&__ec) == file_type::regular;
2084 }
2085
2086 _LIBCPP_INLINE_VISIBILITY
2087 bool is_socket() const { return __get_ft() == file_type::socket; }
2088
2089 _LIBCPP_INLINE_VISIBILITY
2090 bool is_socket(error_code& __ec) const noexcept {
2091 return __get_ft(&__ec) == file_type::socket;
2092 }
2093
2094 _LIBCPP_INLINE_VISIBILITY
2095 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
2096
2097 _LIBCPP_INLINE_VISIBILITY
2098 bool is_symlink(error_code& __ec) const noexcept {
2099 return __get_sym_ft(&__ec) == file_type::symlink;
2100 }
2101 _LIBCPP_INLINE_VISIBILITY
2102 uintmax_t file_size() const { return __get_size(); }
2103
2104 _LIBCPP_INLINE_VISIBILITY
2105 uintmax_t file_size(error_code& __ec) const noexcept {
2106 return __get_size(&__ec);
2107 }
2108
2109 _LIBCPP_INLINE_VISIBILITY
2110 uintmax_t hard_link_count() const { return __get_nlink(); }
2111
2112 _LIBCPP_INLINE_VISIBILITY
2113 uintmax_t hard_link_count(error_code& __ec) const noexcept {
2114 return __get_nlink(&__ec);
2115 }
2116
2117 _LIBCPP_INLINE_VISIBILITY
2118 file_time_type last_write_time() const { return __get_write_time(); }
2119
2120 _LIBCPP_INLINE_VISIBILITY
2121 file_time_type last_write_time(error_code& __ec) const noexcept {
2122 return __get_write_time(&__ec);
2123 }
2124
2125 _LIBCPP_INLINE_VISIBILITY
2126 file_status status() const { return __get_status(); }
2127
2128 _LIBCPP_INLINE_VISIBILITY
2129 file_status status(error_code& __ec) const noexcept {
2130 return __get_status(&__ec);
2131 }
2132
2133 _LIBCPP_INLINE_VISIBILITY
2134 file_status symlink_status() const { return __get_symlink_status(); }
2135
2136 _LIBCPP_INLINE_VISIBILITY
2137 file_status symlink_status(error_code& __ec) const noexcept {
2138 return __get_symlink_status(&__ec);
2139 }
2140
2141 _LIBCPP_INLINE_VISIBILITY
2142 bool operator<(directory_entry const& __rhs) const noexcept {
2143 return __p_ < __rhs.__p_;
2144 }
2145
2146 _LIBCPP_INLINE_VISIBILITY
2147 bool operator==(directory_entry const& __rhs) const noexcept {
2148 return __p_ == __rhs.__p_;
2149 }
2150
2151 _LIBCPP_INLINE_VISIBILITY
2152 bool operator!=(directory_entry const& __rhs) const noexcept {
2153 return __p_ != __rhs.__p_;
2154 }
2155
2156 _LIBCPP_INLINE_VISIBILITY
2157 bool operator<=(directory_entry const& __rhs) const noexcept {
2158 return __p_ <= __rhs.__p_;
2159 }
2160
2161 _LIBCPP_INLINE_VISIBILITY
2162 bool operator>(directory_entry const& __rhs) const noexcept {
2163 return __p_ > __rhs.__p_;
2164 }
2165
2166 _LIBCPP_INLINE_VISIBILITY
2167 bool operator>=(directory_entry const& __rhs) const noexcept {
2168 return __p_ >= __rhs.__p_;
2169 }
2170
2171private:
2172 friend class directory_iterator;
2173 friend class recursive_directory_iterator;
2174 friend class __dir_stream;
2175
2176 enum _CacheType : unsigned char {
2177 _Empty,
2178 _IterSymlink,
2179 _IterNonSymlink,
2180 _RefreshSymlink,
2181 _RefreshSymlinkUnresolved,
2182 _RefreshNonSymlink
2183 };
2184
2185 struct __cached_data {
2186 uintmax_t __size_;
2187 uintmax_t __nlink_;
2188 file_time_type __write_time_;
2189 perms __sym_perms_;
2190 perms __non_sym_perms_;
2191 file_type __type_;
2192 _CacheType __cache_type_;
2193
2194 _LIBCPP_INLINE_VISIBILITY
2195 __cached_data() noexcept { __reset(); }
2196
2197 _LIBCPP_INLINE_VISIBILITY
2198 void __reset() {
2199 __cache_type_ = _Empty;
2200 __type_ = file_type::none;
2201 __sym_perms_ = __non_sym_perms_ = perms::unknown;
2202 __size_ = __nlink_ = uintmax_t(-1);
2203 __write_time_ = file_time_type::min();
2204 }
2205 };
2206
2207 _LIBCPP_INLINE_VISIBILITY
2208 static __cached_data __create_iter_result(file_type __ft) {
2209 __cached_data __data;
2210 __data.__type_ = __ft;
2211 __data.__cache_type_ = [&]() {
2212 switch (__ft) {
2213 case file_type::none:
2214 return _Empty;
2215 case file_type::symlink:
2216 return _IterSymlink;
2217 default:
2218 return _IterNonSymlink;
2219 }
2220 }();
2221 return __data;
2222 }
2223
2224 _LIBCPP_INLINE_VISIBILITY
2225 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
2226 __p_ = std::move(__p);
2227 __data_ = __dt;
2228 }
2229
2230 _LIBCPP_FUNC_VIS
2231 error_code __do_refresh() noexcept;
2232
2233 _LIBCPP_INLINE_VISIBILITY
2234 static bool __is_dne_error(error_code const& __ec) {
2235 if (!__ec)
2236 return true;
2237 switch (static_cast<errc>(__ec.value())) {
2238 case errc::no_such_file_or_directory:
2239 case errc::not_a_directory:
2240 return true;
2241 default:
2242 return false;
2243 }
2244 }
2245
2246 _LIBCPP_INLINE_VISIBILITY
2247 void __handle_error(const char* __msg, error_code* __dest_ec,
2248 error_code const& __ec, bool __allow_dne = false) const {
2249 if (__dest_ec) {
2250 *__dest_ec = __ec;
2251 return;
2252 }
2253 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
2254 __throw_filesystem_error(__msg, __p_, __ec);
2255 }
2256
2257 _LIBCPP_INLINE_VISIBILITY
2258 void __refresh(error_code* __ec = nullptr) {
2259 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
2260 /*allow_dne*/ true);
2261 }
2262
2263 _LIBCPP_INLINE_VISIBILITY
2264 file_type __get_sym_ft(error_code* __ec = nullptr) const {
2265 switch (__data_.__cache_type_) {
2266 case _Empty:
2267 return __symlink_status(__p_, __ec).type();
2268 case _IterSymlink:
2269 case _RefreshSymlink:
2270 case _RefreshSymlinkUnresolved:
2271 if (__ec)
2272 __ec->clear();
2273 return file_type::symlink;
2274 case _IterNonSymlink:
2275 case _RefreshNonSymlink:
2276 file_status __st(__data_.__type_);
2277 if (__ec && !_VSTD_FS::exists(__st))
2278 *__ec = make_error_code(errc::no_such_file_or_directory);
2279 else if (__ec)
2280 __ec->clear();
2281 return __data_.__type_;
2282 }
2283 _LIBCPP_UNREACHABLE();
2284 }
2285
2286 _LIBCPP_INLINE_VISIBILITY
2287 file_type __get_ft(error_code* __ec = nullptr) const {
2288 switch (__data_.__cache_type_) {
2289 case _Empty:
2290 case _IterSymlink:
2291 case _RefreshSymlinkUnresolved:
2292 return __status(__p_, __ec).type();
2293 case _IterNonSymlink:
2294 case _RefreshNonSymlink:
2295 case _RefreshSymlink: {
2296 file_status __st(__data_.__type_);
2297 if (__ec && !_VSTD_FS::exists(__st))
2298 *__ec = make_error_code(errc::no_such_file_or_directory);
2299 else if (__ec)
2300 __ec->clear();
2301 return __data_.__type_;
2302 }
2303 }
2304 _LIBCPP_UNREACHABLE();
2305 }
2306
2307 _LIBCPP_INLINE_VISIBILITY
2308 file_status __get_status(error_code* __ec = nullptr) const {
2309 switch (__data_.__cache_type_) {
2310 case _Empty:
2311 case _IterNonSymlink:
2312 case _IterSymlink:
2313 case _RefreshSymlinkUnresolved:
2314 return __status(__p_, __ec);
2315 case _RefreshNonSymlink:
2316 case _RefreshSymlink:
2317 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
2318 }
2319 _LIBCPP_UNREACHABLE();
2320 }
2321
2322 _LIBCPP_INLINE_VISIBILITY
2323 file_status __get_symlink_status(error_code* __ec = nullptr) const {
2324 switch (__data_.__cache_type_) {
2325 case _Empty:
2326 case _IterNonSymlink:
2327 case _IterSymlink:
2328 return __symlink_status(__p_, __ec);
2329 case _RefreshNonSymlink:
2330 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
2331 case _RefreshSymlink:
2332 case _RefreshSymlinkUnresolved:
2333 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
2334 }
2335 _LIBCPP_UNREACHABLE();
2336 }
2337
2338 _LIBCPP_INLINE_VISIBILITY
2339 uintmax_t __get_size(error_code* __ec = nullptr) const {
2340 switch (__data_.__cache_type_) {
2341 case _Empty:
2342 case _IterNonSymlink:
2343 case _IterSymlink:
2344 case _RefreshSymlinkUnresolved:
2345 return _VSTD_FS::__file_size(__p_, __ec);
2346 case _RefreshSymlink:
2347 case _RefreshNonSymlink: {
2348 error_code __m_ec;
2349 file_status __st(__get_ft(&__m_ec));
2350 __handle_error("in directory_entry::file_size", __ec, __m_ec);
2351 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
2352 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
2353 : errc::not_supported;
2354 __handle_error("in directory_entry::file_size", __ec,
2355 make_error_code(__err_kind));
2356 }
2357 return __data_.__size_;
2358 }
2359 }
2360 _LIBCPP_UNREACHABLE();
2361 }
2362
2363 _LIBCPP_INLINE_VISIBILITY
2364 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
2365 switch (__data_.__cache_type_) {
2366 case _Empty:
2367 case _IterNonSymlink:
2368 case _IterSymlink:
2369 case _RefreshSymlinkUnresolved:
2370 return _VSTD_FS::__hard_link_count(__p_, __ec);
2371 case _RefreshSymlink:
2372 case _RefreshNonSymlink: {
2373 error_code __m_ec;
2374 (void)__get_ft(&__m_ec);
2375 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
2376 return __data_.__nlink_;
2377 }
2378 }
2379 _LIBCPP_UNREACHABLE();
2380 }
2381
2382 _LIBCPP_INLINE_VISIBILITY
2383 file_time_type __get_write_time(error_code* __ec = nullptr) const {
2384 switch (__data_.__cache_type_) {
2385 case _Empty:
2386 case _IterNonSymlink:
2387 case _IterSymlink:
2388 case _RefreshSymlinkUnresolved:
2389 return _VSTD_FS::__last_write_time(__p_, __ec);
2390 case _RefreshSymlink:
2391 case _RefreshNonSymlink: {
2392 error_code __m_ec;
2393 file_status __st(__get_ft(&__m_ec));
2394 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
2395 if (_VSTD_FS::exists(__st) &&
2396 __data_.__write_time_ == file_time_type::min())
2397 __handle_error("in directory_entry::last_write_time", __ec,
2398 make_error_code(errc::value_too_large));
2399 return __data_.__write_time_;
2400 }
2401 }
2402 _LIBCPP_UNREACHABLE();
2403 }
2404
2405private:
2406 _Path __p_;
2407 __cached_data __data_;
2408};
2409
2410class __dir_element_proxy {
2411public:
2412 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
2413 return _VSTD::move(__elem_);
2414 }
2415
2416private:
2417 friend class directory_iterator;
2418 friend class recursive_directory_iterator;
2419 explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
2420 __dir_element_proxy(__dir_element_proxy&& __o)
2421 : __elem_(_VSTD::move(__o.__elem_)) {}
2422 directory_entry __elem_;
2423};
2424
2425class directory_iterator {
2426public:
2427 typedef directory_entry value_type;
2428 typedef ptrdiff_t difference_type;
2429 typedef value_type const* pointer;
2430 typedef value_type const& reference;
2431 typedef input_iterator_tag iterator_category;
2432
2433public:
2434 //ctor & dtor
2435 directory_iterator() noexcept {}
2436
2437 explicit directory_iterator(const path& __p)
2438 : directory_iterator(__p, nullptr) {}
2439
2440 directory_iterator(const path& __p, directory_options __opts)
2441 : directory_iterator(__p, nullptr, __opts) {}
2442
2443 directory_iterator(const path& __p, error_code& __ec)
2444 : directory_iterator(__p, &__ec) {}
2445
2446 directory_iterator(const path& __p, directory_options __opts,
2447 error_code& __ec)
2448 : directory_iterator(__p, &__ec, __opts) {}
2449
2450 directory_iterator(const directory_iterator&) = default;
2451 directory_iterator(directory_iterator&&) = default;
2452 directory_iterator& operator=(const directory_iterator&) = default;
2453
2454 directory_iterator& operator=(directory_iterator&& __o) noexcept {
2455 // non-default implementation provided to support self-move assign.
2456 if (this != &__o) {
2457 __imp_ = _VSTD::move(__o.__imp_);
2458 }
2459 return *this;
2460 }
2461
2462 ~directory_iterator() = default;
2463
2464 const directory_entry& operator*() const {
2465 _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
2466 return __dereference();
2467 }
2468
2469 const directory_entry* operator->() const { return &**this; }
2470
2471 directory_iterator& operator++() { return __increment(); }
2472
2473 __dir_element_proxy operator++(int) {
2474 __dir_element_proxy __p(**this);
2475 __increment();
2476 return __p;
2477 }
2478
2479 directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
2480
2481private:
2482 inline _LIBCPP_INLINE_VISIBILITY friend bool
2483 operator==(const directory_iterator& __lhs,
2484 const directory_iterator& __rhs) noexcept;
2485
2486 // construct the dir_stream
2487 _LIBCPP_FUNC_VIS
2488 directory_iterator(const path&, error_code*,
2489 directory_options = directory_options::none);
2490
2491 _LIBCPP_FUNC_VIS
2492 directory_iterator& __increment(error_code* __ec = nullptr);
2493
2494 _LIBCPP_FUNC_VIS
2495 const directory_entry& __dereference() const;
2496
2497private:
2498 shared_ptr<__dir_stream> __imp_;
2499};
2500
2501inline _LIBCPP_INLINE_VISIBILITY bool
2502operator==(const directory_iterator& __lhs,
2503 const directory_iterator& __rhs) noexcept {
2504 return __lhs.__imp_ == __rhs.__imp_;
2505}
2506
2507inline _LIBCPP_INLINE_VISIBILITY bool
2508operator!=(const directory_iterator& __lhs,
2509 const directory_iterator& __rhs) noexcept {
2510 return !(__lhs == __rhs);
2511}
2512
2513// enable directory_iterator range-based for statements
2514inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2515begin(directory_iterator __iter) noexcept {
2516 return __iter;
2517}
2518
2519inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2520end(const directory_iterator&) noexcept {
2521 return directory_iterator();
2522}
2523
2524class recursive_directory_iterator {
2525public:
2526 using value_type = directory_entry;
2527 using difference_type = std::ptrdiff_t;
2528 using pointer = directory_entry const*;
2529 using reference = directory_entry const&;
2530 using iterator_category = std::input_iterator_tag;
2531
2532public:
2533 // constructors and destructor
2534 _LIBCPP_INLINE_VISIBILITY
2535 recursive_directory_iterator() noexcept : __rec_(false) {}
2536
2537 _LIBCPP_INLINE_VISIBILITY
2538 explicit recursive_directory_iterator(
2539 const path& __p, directory_options __xoptions = directory_options::none)
2540 : recursive_directory_iterator(__p, __xoptions, nullptr) {}
2541
2542 _LIBCPP_INLINE_VISIBILITY
2543 recursive_directory_iterator(const path& __p, directory_options __xoptions,
2544 error_code& __ec)
2545 : recursive_directory_iterator(__p, __xoptions, &__ec) {}
2546
2547 _LIBCPP_INLINE_VISIBILITY
2548 recursive_directory_iterator(const path& __p, error_code& __ec)
2549 : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
2550
2551 recursive_directory_iterator(const recursive_directory_iterator&) = default;
2552 recursive_directory_iterator(recursive_directory_iterator&&) = default;
2553
2554 recursive_directory_iterator&
2555 operator=(const recursive_directory_iterator&) = default;
2556
2557 _LIBCPP_INLINE_VISIBILITY
2558 recursive_directory_iterator&
2559 operator=(recursive_directory_iterator&& __o) noexcept {
2560 // non-default implementation provided to support self-move assign.
2561 if (this != &__o) {
2562 __imp_ = _VSTD::move(__o.__imp_);
2563 __rec_ = __o.__rec_;
2564 }
2565 return *this;
2566 }
2567
2568 ~recursive_directory_iterator() = default;
2569
2570 _LIBCPP_INLINE_VISIBILITY
2571 const directory_entry& operator*() const { return __dereference(); }
2572
2573 _LIBCPP_INLINE_VISIBILITY
2574 const directory_entry* operator->() const { return &__dereference(); }
2575
2576 recursive_directory_iterator& operator++() { return __increment(); }
2577
2578 _LIBCPP_INLINE_VISIBILITY
2579 __dir_element_proxy operator++(int) {
2580 __dir_element_proxy __p(**this);
2581 __increment();
2582 return __p;
2583 }
2584
2585 _LIBCPP_INLINE_VISIBILITY
2586 recursive_directory_iterator& increment(error_code& __ec) {
2587 return __increment(&__ec);
2588 }
2589
2590 _LIBCPP_FUNC_VIS directory_options options() const;
2591 _LIBCPP_FUNC_VIS int depth() const;
2592
2593 _LIBCPP_INLINE_VISIBILITY
2594 void pop() { __pop(); }
2595
2596 _LIBCPP_INLINE_VISIBILITY
2597 void pop(error_code& __ec) { __pop(&__ec); }
2598
2599 _LIBCPP_INLINE_VISIBILITY
2600 bool recursion_pending() const { return __rec_; }
2601
2602 _LIBCPP_INLINE_VISIBILITY
2603 void disable_recursion_pending() { __rec_ = false; }
2604
2605private:
Louis Dionne0ba10dc2019-08-13 15:02:53 +00002606 _LIBCPP_FUNC_VIS
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002607 recursive_directory_iterator(const path& __p, directory_options __opt,
2608 error_code* __ec);
2609
2610 _LIBCPP_FUNC_VIS
2611 const directory_entry& __dereference() const;
2612
2613 _LIBCPP_FUNC_VIS
2614 bool __try_recursion(error_code* __ec);
2615
2616 _LIBCPP_FUNC_VIS
2617 void __advance(error_code* __ec = nullptr);
2618
2619 _LIBCPP_FUNC_VIS
2620 recursive_directory_iterator& __increment(error_code* __ec = nullptr);
2621
2622 _LIBCPP_FUNC_VIS
2623 void __pop(error_code* __ec = nullptr);
2624
2625 inline _LIBCPP_INLINE_VISIBILITY friend bool
2626 operator==(const recursive_directory_iterator&,
2627 const recursive_directory_iterator&) noexcept;
2628
Louis Dionne48ae8892019-03-19 17:47:53 +00002629 struct _LIBCPP_HIDDEN __shared_imp;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002630 shared_ptr<__shared_imp> __imp_;
2631 bool __rec_;
2632}; // class recursive_directory_iterator
2633
2634inline _LIBCPP_INLINE_VISIBILITY bool
2635operator==(const recursive_directory_iterator& __lhs,
2636 const recursive_directory_iterator& __rhs) noexcept {
2637 return __lhs.__imp_ == __rhs.__imp_;
2638}
2639
2640_LIBCPP_INLINE_VISIBILITY
2641inline bool operator!=(const recursive_directory_iterator& __lhs,
2642 const recursive_directory_iterator& __rhs) noexcept {
2643 return !(__lhs == __rhs);
2644}
2645// enable recursive_directory_iterator range-based for statements
2646inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2647begin(recursive_directory_iterator __iter) noexcept {
2648 return __iter;
2649}
2650
2651inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2652end(const recursive_directory_iterator&) noexcept {
2653 return recursive_directory_iterator();
2654}
2655
Louis Dionnef6bf76a2019-03-20 21:18:14 +00002656_LIBCPP_AVAILABILITY_FILESYSTEM_POP
2657
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002658_LIBCPP_END_NAMESPACE_FILESYSTEM
2659
2660#endif // !_LIBCPP_CXX03_LANG
2661
2662_LIBCPP_POP_MACROS
2663
2664#endif // _LIBCPP_FILESYSTEM