blob: d333d02ef06b96a93f2658eb2f2de09f2d713176 [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
Louis Dionnedb84e122021-01-18 12:18:18 -0500254#if defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
255# error "The Filesystem library is not supported by this configuration of libc++"
256#endif
257
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000258#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
259#pragma GCC system_header
260#endif
261
262_LIBCPP_PUSH_MACROS
263#include <__undef_macros>
264
265#ifndef _LIBCPP_CXX03_LANG
266
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000267_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
268
Louis Dionnef6bf76a2019-03-20 21:18:14 +0000269_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
270
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000271typedef chrono::time_point<_FilesystemClock> file_time_type;
272
273struct _LIBCPP_TYPE_VIS space_info {
274 uintmax_t capacity;
275 uintmax_t free;
276 uintmax_t available;
277};
278
279enum class _LIBCPP_ENUM_VIS file_type : signed char {
280 none = 0,
281 not_found = -1,
282 regular = 1,
283 directory = 2,
284 symlink = 3,
285 block = 4,
286 character = 5,
287 fifo = 6,
288 socket = 7,
289 unknown = 8
290};
291
292enum class _LIBCPP_ENUM_VIS perms : unsigned {
293 none = 0,
294
295 owner_read = 0400,
296 owner_write = 0200,
297 owner_exec = 0100,
298 owner_all = 0700,
299
300 group_read = 040,
301 group_write = 020,
302 group_exec = 010,
303 group_all = 070,
304
305 others_read = 04,
306 others_write = 02,
307 others_exec = 01,
308 others_all = 07,
309
310 all = 0777,
311
312 set_uid = 04000,
313 set_gid = 02000,
314 sticky_bit = 01000,
315 mask = 07777,
316 unknown = 0xFFFF,
317};
318
319_LIBCPP_INLINE_VISIBILITY
320inline constexpr perms operator&(perms _LHS, perms _RHS) {
321 return static_cast<perms>(static_cast<unsigned>(_LHS) &
322 static_cast<unsigned>(_RHS));
323}
324
325_LIBCPP_INLINE_VISIBILITY
326inline constexpr perms operator|(perms _LHS, perms _RHS) {
327 return static_cast<perms>(static_cast<unsigned>(_LHS) |
328 static_cast<unsigned>(_RHS));
329}
330
331_LIBCPP_INLINE_VISIBILITY
332inline constexpr perms operator^(perms _LHS, perms _RHS) {
333 return static_cast<perms>(static_cast<unsigned>(_LHS) ^
334 static_cast<unsigned>(_RHS));
335}
336
337_LIBCPP_INLINE_VISIBILITY
338inline constexpr perms operator~(perms _LHS) {
339 return static_cast<perms>(~static_cast<unsigned>(_LHS));
340}
341
342_LIBCPP_INLINE_VISIBILITY
343inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
344
345_LIBCPP_INLINE_VISIBILITY
346inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
347
348_LIBCPP_INLINE_VISIBILITY
349inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
350
351enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
352 replace = 1,
353 add = 2,
354 remove = 4,
355 nofollow = 8
356};
357
358_LIBCPP_INLINE_VISIBILITY
359inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) {
360 return static_cast<perm_options>(static_cast<unsigned>(_LHS) &
361 static_cast<unsigned>(_RHS));
362}
363
364_LIBCPP_INLINE_VISIBILITY
365inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) {
366 return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
367 static_cast<unsigned>(_RHS));
368}
369
370_LIBCPP_INLINE_VISIBILITY
371inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) {
372 return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
373 static_cast<unsigned>(_RHS));
374}
375
376_LIBCPP_INLINE_VISIBILITY
377inline constexpr perm_options operator~(perm_options _LHS) {
378 return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
379}
380
381_LIBCPP_INLINE_VISIBILITY
382inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
383 return _LHS = _LHS & _RHS;
384}
385
386_LIBCPP_INLINE_VISIBILITY
387inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
388 return _LHS = _LHS | _RHS;
389}
390
391_LIBCPP_INLINE_VISIBILITY
392inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
393 return _LHS = _LHS ^ _RHS;
394}
395
396enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
397 none = 0,
398 skip_existing = 1,
399 overwrite_existing = 2,
400 update_existing = 4,
401 recursive = 8,
402 copy_symlinks = 16,
403 skip_symlinks = 32,
404 directories_only = 64,
405 create_symlinks = 128,
406 create_hard_links = 256,
407 __in_recursive_copy = 512,
408};
409
410_LIBCPP_INLINE_VISIBILITY
411inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) {
412 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) &
413 static_cast<unsigned short>(_RHS));
414}
415
416_LIBCPP_INLINE_VISIBILITY
417inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) {
418 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
419 static_cast<unsigned short>(_RHS));
420}
421
422_LIBCPP_INLINE_VISIBILITY
423inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) {
424 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
425 static_cast<unsigned short>(_RHS));
426}
427
428_LIBCPP_INLINE_VISIBILITY
429inline constexpr copy_options operator~(copy_options _LHS) {
430 return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
431}
432
433_LIBCPP_INLINE_VISIBILITY
434inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
435 return _LHS = _LHS & _RHS;
436}
437
438_LIBCPP_INLINE_VISIBILITY
439inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
440 return _LHS = _LHS | _RHS;
441}
442
443_LIBCPP_INLINE_VISIBILITY
444inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
445 return _LHS = _LHS ^ _RHS;
446}
447
448enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
449 none = 0,
450 follow_directory_symlink = 1,
451 skip_permission_denied = 2
452};
453
454_LIBCPP_INLINE_VISIBILITY
455inline constexpr directory_options operator&(directory_options _LHS,
456 directory_options _RHS) {
457 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
458 static_cast<unsigned char>(_RHS));
459}
460
461_LIBCPP_INLINE_VISIBILITY
462inline constexpr directory_options operator|(directory_options _LHS,
463 directory_options _RHS) {
464 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
465 static_cast<unsigned char>(_RHS));
466}
467
468_LIBCPP_INLINE_VISIBILITY
469inline constexpr directory_options operator^(directory_options _LHS,
470 directory_options _RHS) {
471 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
472 static_cast<unsigned char>(_RHS));
473}
474
475_LIBCPP_INLINE_VISIBILITY
476inline constexpr directory_options operator~(directory_options _LHS) {
477 return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
478}
479
480_LIBCPP_INLINE_VISIBILITY
481inline directory_options& operator&=(directory_options& _LHS,
482 directory_options _RHS) {
483 return _LHS = _LHS & _RHS;
484}
485
486_LIBCPP_INLINE_VISIBILITY
487inline directory_options& operator|=(directory_options& _LHS,
488 directory_options _RHS) {
489 return _LHS = _LHS | _RHS;
490}
491
492_LIBCPP_INLINE_VISIBILITY
493inline directory_options& operator^=(directory_options& _LHS,
494 directory_options _RHS) {
495 return _LHS = _LHS ^ _RHS;
496}
497
498class _LIBCPP_TYPE_VIS file_status {
499public:
500 // constructors
501 _LIBCPP_INLINE_VISIBILITY
502 file_status() noexcept : file_status(file_type::none) {}
503 _LIBCPP_INLINE_VISIBILITY
504 explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
505 : __ft_(__ft),
506 __prms_(__prms) {}
507
508 file_status(const file_status&) noexcept = default;
509 file_status(file_status&&) noexcept = default;
510
511 _LIBCPP_INLINE_VISIBILITY
512 ~file_status() {}
513
514 file_status& operator=(const file_status&) noexcept = default;
515 file_status& operator=(file_status&&) noexcept = default;
516
517 // observers
518 _LIBCPP_INLINE_VISIBILITY
519 file_type type() const noexcept { return __ft_; }
520
521 _LIBCPP_INLINE_VISIBILITY
522 perms permissions() const noexcept { return __prms_; }
523
524 // modifiers
525 _LIBCPP_INLINE_VISIBILITY
526 void type(file_type __ft) noexcept { __ft_ = __ft; }
527
528 _LIBCPP_INLINE_VISIBILITY
529 void permissions(perms __p) noexcept { __prms_ = __p; }
530
531private:
532 file_type __ft_;
533 perms __prms_;
534};
535
536class _LIBCPP_TYPE_VIS directory_entry;
537
538template <class _Tp>
539struct __can_convert_char {
540 static const bool value = false;
541};
542template <class _Tp>
543struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
544template <>
545struct __can_convert_char<char> {
546 static const bool value = true;
547 using __char_type = char;
548};
549template <>
550struct __can_convert_char<wchar_t> {
551 static const bool value = true;
552 using __char_type = wchar_t;
553};
Martin Storsjöe3a71972020-10-26 13:18:46 +0200554#ifndef _LIBCPP_NO_HAS_CHAR8_T
555template <>
556struct __can_convert_char<char8_t> {
557 static const bool value = true;
558 using __char_type = char8_t;
559};
560#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000561template <>
562struct __can_convert_char<char16_t> {
563 static const bool value = true;
564 using __char_type = char16_t;
565};
566template <>
567struct __can_convert_char<char32_t> {
568 static const bool value = true;
569 using __char_type = char32_t;
570};
571
572template <class _ECharT>
573typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
574__is_separator(_ECharT __e) {
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200575#if defined(_LIBCPP_WIN32API)
576 return __e == _ECharT('/') || __e == _ECharT('\\');
577#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000578 return __e == _ECharT('/');
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200579#endif
Eric Fiselierb41db9a2018-10-01 01:59:37 +0000580}
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000581
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200582#ifndef _LIBCPP_NO_HAS_CHAR8_T
583typedef u8string __u8_string;
584#else
585typedef string __u8_string;
586#endif
587
Martin Storsjö2ae96532020-10-27 11:46:06 +0200588struct _NullSentinel {};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000589
590template <class _Tp>
591using _Void = void;
592
593template <class _Tp, class = void>
594struct __is_pathable_string : public false_type {};
595
596template <class _ECharT, class _Traits, class _Alloc>
597struct __is_pathable_string<
598 basic_string<_ECharT, _Traits, _Alloc>,
599 _Void<typename __can_convert_char<_ECharT>::__char_type> >
600 : public __can_convert_char<_ECharT> {
601 using _Str = basic_string<_ECharT, _Traits, _Alloc>;
602 using _Base = __can_convert_char<_ECharT>;
603 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
604 static _ECharT const* __range_end(_Str const& __s) {
605 return __s.data() + __s.length();
606 }
607 static _ECharT __first_or_null(_Str const& __s) {
608 return __s.empty() ? _ECharT{} : __s[0];
609 }
610};
611
612template <class _ECharT, class _Traits>
613struct __is_pathable_string<
614 basic_string_view<_ECharT, _Traits>,
615 _Void<typename __can_convert_char<_ECharT>::__char_type> >
616 : public __can_convert_char<_ECharT> {
617 using _Str = basic_string_view<_ECharT, _Traits>;
618 using _Base = __can_convert_char<_ECharT>;
619 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
620 static _ECharT const* __range_end(_Str const& __s) {
621 return __s.data() + __s.length();
622 }
623 static _ECharT __first_or_null(_Str const& __s) {
624 return __s.empty() ? _ECharT{} : __s[0];
625 }
626};
627
628template <class _Source, class _DS = typename decay<_Source>::type,
629 class _UnqualPtrType =
630 typename remove_const<typename remove_pointer<_DS>::type>::type,
631 bool _IsCharPtr = is_pointer<_DS>::value&&
632 __can_convert_char<_UnqualPtrType>::value>
633struct __is_pathable_char_array : false_type {};
634
635template <class _Source, class _ECharT, class _UPtr>
636struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
637 : __can_convert_char<typename remove_const<_ECharT>::type> {
638 using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
639
640 static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
641 static _ECharT const* __range_end(const _ECharT* __b) {
642 using _Iter = const _ECharT*;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200643 const _ECharT __sentinel = _ECharT{};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000644 _Iter __e = __b;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200645 for (; *__e != __sentinel; ++__e)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000646 ;
647 return __e;
648 }
649
650 static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
651};
652
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500653template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000654 class = void>
655struct __is_pathable_iter : false_type {};
656
657template <class _Iter>
658struct __is_pathable_iter<
659 _Iter, true,
660 _Void<typename __can_convert_char<
661 typename iterator_traits<_Iter>::value_type>::__char_type> >
662 : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
663 using _ECharT = typename iterator_traits<_Iter>::value_type;
664 using _Base = __can_convert_char<_ECharT>;
665
666 static _Iter __range_begin(_Iter __b) { return __b; }
Martin Storsjö2ae96532020-10-27 11:46:06 +0200667 static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000668
669 static _ECharT __first_or_null(_Iter __b) { return *__b; }
670};
671
672template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
673 bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
674 bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
675struct __is_pathable : false_type {
676 static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
677};
678
679template <class _Tp>
680struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
681
682template <class _Tp>
683struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
684};
685
686template <class _Tp>
687struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
688
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200689#if defined(_LIBCPP_WIN32API)
690typedef wstring __path_string;
691typedef wchar_t __path_value;
692#else
693typedef string __path_string;
694typedef char __path_value;
695#endif
696
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200697#if defined(_LIBCPP_WIN32API)
698_LIBCPP_FUNC_VIS
699size_t __wide_to_char(const wstring&, char*, size_t);
700_LIBCPP_FUNC_VIS
701size_t __char_to_wide(const string&, wchar_t*, size_t);
702#endif
703
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000704template <class _ECharT>
Louis Dionne8d053eb2020-10-09 15:31:05 -0400705struct _PathCVT;
706
707#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
708template <class _ECharT>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000709struct _PathCVT {
710 static_assert(__can_convert_char<_ECharT>::value,
711 "Char type not convertible");
712
713 typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200714#if defined(_LIBCPP_WIN32API)
715 typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
716#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000717
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200718 static void __append_range(__path_string& __dest, _ECharT const* __b,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000719 _ECharT const* __e) {
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200720#if defined(_LIBCPP_WIN32API)
721 string __utf8;
722 _Narrower()(back_inserter(__utf8), __b, __e);
723 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
724#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000725 _Narrower()(back_inserter(__dest), __b, __e);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200726#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000727 }
728
729 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200730 static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000731 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
732 if (__b == __e)
733 return;
734 basic_string<_ECharT> __tmp(__b, __e);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200735#if defined(_LIBCPP_WIN32API)
736 string __utf8;
737 _Narrower()(back_inserter(__utf8), __tmp.data(),
738 __tmp.data() + __tmp.length());
739 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
740#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000741 _Narrower()(back_inserter(__dest), __tmp.data(),
742 __tmp.data() + __tmp.length());
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200743#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000744 }
745
746 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200747 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000748 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
Martin Storsjö2ae96532020-10-27 11:46:06 +0200749 const _ECharT __sentinel = _ECharT{};
750 if (*__b == __sentinel)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000751 return;
752 basic_string<_ECharT> __tmp;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200753 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000754 __tmp.push_back(*__b);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200755#if defined(_LIBCPP_WIN32API)
756 string __utf8;
757 _Narrower()(back_inserter(__utf8), __tmp.data(),
758 __tmp.data() + __tmp.length());
759 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
760#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000761 _Narrower()(back_inserter(__dest), __tmp.data(),
762 __tmp.data() + __tmp.length());
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200763#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000764 }
765
766 template <class _Source>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200767 static void __append_source(__path_string& __dest, _Source const& __s) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000768 using _Traits = __is_pathable<_Source>;
769 __append_range(__dest, _Traits::__range_begin(__s),
770 _Traits::__range_end(__s));
771 }
772};
Louis Dionne8d053eb2020-10-09 15:31:05 -0400773#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000774
775template <>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200776struct _PathCVT<__path_value> {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000777
778 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500779 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200780 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000781 for (; __b != __e; ++__b)
782 __dest.push_back(*__b);
783 }
784
785 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500786 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200787 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000788 __dest.__append_forward_unsafe(__b, __e);
789 }
790
791 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200792 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
Martin Storsjö2ae96532020-10-27 11:46:06 +0200793 const char __sentinel = char{};
794 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000795 __dest.push_back(*__b);
796 }
797
798 template <class _Source>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200799 static void __append_source(__path_string& __dest, _Source const& __s) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000800 using _Traits = __is_pathable<_Source>;
801 __append_range(__dest, _Traits::__range_begin(__s),
802 _Traits::__range_end(__s));
803 }
804};
805
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200806#if defined(_LIBCPP_WIN32API)
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200807template <>
808struct _PathCVT<char> {
809
810 static void
811 __append_string(__path_string& __dest, const basic_string<char> &__str) {
812 size_t __size = __char_to_wide(__str, nullptr, 0);
813 size_t __pos = __dest.size();
814 __dest.resize(__pos + __size);
815 __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
816 }
817
818 template <class _Iter>
819 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
820 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
821 basic_string<char> __tmp(__b, __e);
822 __append_string(__dest, __tmp);
823 }
824
825 template <class _Iter>
826 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
827 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
828 basic_string<char> __tmp(__b, __e);
829 __append_string(__dest, __tmp);
830 }
831
832 template <class _Iter>
833 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
834 const char __sentinel = char{};
835 basic_string<char> __tmp;
836 for (; *__b != __sentinel; ++__b)
837 __tmp.push_back(*__b);
838 __append_string(__dest, __tmp);
839 }
840
841 template <class _Source>
842 static void __append_source(__path_string& __dest, _Source const& __s) {
843 using _Traits = __is_pathable<_Source>;
844 __append_range(__dest, _Traits::__range_begin(__s),
845 _Traits::__range_end(__s));
846 }
847};
848
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200849template <class _ECharT>
850struct _PathExport {
851 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
852 typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
853
854 template <class _Str>
855 static void __append(_Str& __dest, const __path_string& __src) {
856 string __utf8;
857 _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
858 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
859 }
860};
861
862template <>
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200863struct _PathExport<char> {
864 template <class _Str>
865 static void __append(_Str& __dest, const __path_string& __src) {
866 size_t __size = __wide_to_char(__src, nullptr, 0);
867 size_t __pos = __dest.size();
868 __dest.resize(__size);
869 __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
870 }
871};
872
873template <>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200874struct _PathExport<wchar_t> {
875 template <class _Str>
876 static void __append(_Str& __dest, const __path_string& __src) {
877 __dest.append(__src.begin(), __src.end());
878 }
879};
880
881template <>
882struct _PathExport<char16_t> {
883 template <class _Str>
884 static void __append(_Str& __dest, const __path_string& __src) {
885 __dest.append(__src.begin(), __src.end());
886 }
887};
888
889#ifndef _LIBCPP_NO_HAS_CHAR8_T
890template <>
891struct _PathExport<char8_t> {
892 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
893
894 template <class _Str>
895 static void __append(_Str& __dest, const __path_string& __src) {
896 _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
897 }
898};
899#endif /* !_LIBCPP_NO_HAS_CHAR8_T */
900#endif /* _LIBCPP_WIN32API */
901
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000902class _LIBCPP_TYPE_VIS path {
903 template <class _SourceOrIter, class _Tp = path&>
904 using _EnableIfPathable =
905 typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
906
907 template <class _Tp>
908 using _SourceChar = typename __is_pathable<_Tp>::__char_type;
909
910 template <class _Tp>
911 using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
912
913public:
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200914#if defined(_LIBCPP_WIN32API)
915 typedef wchar_t value_type;
916 static constexpr value_type preferred_separator = L'\\';
917#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000918 typedef char value_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000919 static constexpr value_type preferred_separator = '/';
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200920#endif
921 typedef basic_string<value_type> string_type;
922 typedef basic_string_view<value_type> __string_view;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000923
924 enum class _LIBCPP_ENUM_VIS format : unsigned char {
925 auto_format,
926 native_format,
927 generic_format
928 };
929
930 // constructors and destructor
931 _LIBCPP_INLINE_VISIBILITY path() noexcept {}
932 _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
933 _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
934 : __pn_(_VSTD::move(__p.__pn_)) {}
935
936 _LIBCPP_INLINE_VISIBILITY
937 path(string_type&& __s, format = format::auto_format) noexcept
938 : __pn_(_VSTD::move(__s)) {}
939
940 template <class _Source, class = _EnableIfPathable<_Source, void> >
941 path(const _Source& __src, format = format::auto_format) {
942 _SourceCVT<_Source>::__append_source(__pn_, __src);
943 }
944
945 template <class _InputIt>
946 path(_InputIt __first, _InputIt __last, format = format::auto_format) {
947 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
948 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
949 }
950
Louis Dionne8d053eb2020-10-09 15:31:05 -0400951#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000952 // TODO Implement locale conversions.
953 template <class _Source, class = _EnableIfPathable<_Source, void> >
954 path(const _Source& __src, const locale& __loc, format = format::auto_format);
955 template <class _InputIt>
956 path(_InputIt __first, _InputIt _last, const locale& __loc,
957 format = format::auto_format);
Louis Dionne8d053eb2020-10-09 15:31:05 -0400958#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000959
960 _LIBCPP_INLINE_VISIBILITY
961 ~path() = default;
962
963 // assignments
964 _LIBCPP_INLINE_VISIBILITY
965 path& operator=(const path& __p) {
966 __pn_ = __p.__pn_;
967 return *this;
968 }
969
970 _LIBCPP_INLINE_VISIBILITY
971 path& operator=(path&& __p) noexcept {
972 __pn_ = _VSTD::move(__p.__pn_);
973 return *this;
974 }
975
Louis Dionne5da71d22021-02-03 16:40:41 -0500976 _LIBCPP_INLINE_VISIBILITY
977 path& operator=(string_type&& __s) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000978 __pn_ = _VSTD::move(__s);
979 return *this;
980 }
981
982 _LIBCPP_INLINE_VISIBILITY
983 path& assign(string_type&& __s) noexcept {
984 __pn_ = _VSTD::move(__s);
985 return *this;
986 }
987
988 template <class _Source>
989 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
990 operator=(const _Source& __src) {
991 return this->assign(__src);
992 }
993
994 template <class _Source>
995 _EnableIfPathable<_Source> assign(const _Source& __src) {
996 __pn_.clear();
997 _SourceCVT<_Source>::__append_source(__pn_, __src);
998 return *this;
999 }
1000
1001 template <class _InputIt>
1002 path& assign(_InputIt __first, _InputIt __last) {
1003 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1004 __pn_.clear();
1005 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1006 return *this;
1007 }
1008
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001009public:
1010 // appends
Martin Storsjö98770152020-11-04 15:59:56 +02001011#if defined(_LIBCPP_WIN32API)
1012 path& operator/=(const path& __p) {
1013 auto __p_root_name = __p.__root_name();
1014 auto __p_root_name_size = __p_root_name.size();
1015 if (__p.is_absolute() ||
1016 (!__p_root_name.empty() && __p_root_name != root_name())) {
1017 __pn_ = __p.__pn_;
1018 return *this;
1019 }
1020 if (__p.has_root_directory()) {
1021 path __root_name_str = root_name();
1022 __pn_ = __root_name_str.native();
1023 __pn_ += __p.__pn_.substr(__p_root_name_size);
1024 return *this;
1025 }
1026 if (has_filename() || (!has_root_directory() && is_absolute()))
1027 __pn_ += preferred_separator;
1028 __pn_ += __p.__pn_.substr(__p_root_name_size);
1029 return *this;
1030 }
1031 template <class _Source>
1032 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1033 operator/=(const _Source& __src) {
1034 return operator/=(path(__src));
1035 }
1036
1037 template <class _Source>
1038 _EnableIfPathable<_Source> append(const _Source& __src) {
1039 return operator/=(path(__src));
1040 }
1041
1042 template <class _InputIt>
1043 path& append(_InputIt __first, _InputIt __last) {
1044 return operator/=(path(__first, __last));
1045 }
1046#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001047 path& operator/=(const path& __p) {
1048 if (__p.is_absolute()) {
1049 __pn_ = __p.__pn_;
1050 return *this;
1051 }
1052 if (has_filename())
1053 __pn_ += preferred_separator;
1054 __pn_ += __p.native();
1055 return *this;
1056 }
1057
1058 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
1059 // is known at compile time to be "/' since the user almost certainly intended
1060 // to append a separator instead of overwriting the path with "/"
1061 template <class _Source>
1062 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1063 operator/=(const _Source& __src) {
1064 return this->append(__src);
1065 }
1066
1067 template <class _Source>
1068 _EnableIfPathable<_Source> append(const _Source& __src) {
1069 using _Traits = __is_pathable<_Source>;
1070 using _CVT = _PathCVT<_SourceChar<_Source> >;
Martin Storsjö98770152020-11-04 15:59:56 +02001071 bool __source_is_absolute = __is_separator(_Traits::__first_or_null(__src));
1072 if (__source_is_absolute)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001073 __pn_.clear();
1074 else if (has_filename())
1075 __pn_ += preferred_separator;
1076 _CVT::__append_source(__pn_, __src);
1077 return *this;
1078 }
1079
1080 template <class _InputIt>
1081 path& append(_InputIt __first, _InputIt __last) {
1082 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1083 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
1084 using _CVT = _PathCVT<_ItVal>;
Martin Storsjö98770152020-11-04 15:59:56 +02001085 if (__first != __last && __is_separator(*__first))
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001086 __pn_.clear();
1087 else if (has_filename())
1088 __pn_ += preferred_separator;
1089 _CVT::__append_range(__pn_, __first, __last);
1090 return *this;
1091 }
Martin Storsjö98770152020-11-04 15:59:56 +02001092#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001093
1094 // concatenation
1095 _LIBCPP_INLINE_VISIBILITY
1096 path& operator+=(const path& __x) {
1097 __pn_ += __x.__pn_;
1098 return *this;
1099 }
1100
1101 _LIBCPP_INLINE_VISIBILITY
1102 path& operator+=(const string_type& __x) {
1103 __pn_ += __x;
1104 return *this;
1105 }
1106
1107 _LIBCPP_INLINE_VISIBILITY
1108 path& operator+=(__string_view __x) {
1109 __pn_ += __x;
1110 return *this;
1111 }
1112
1113 _LIBCPP_INLINE_VISIBILITY
1114 path& operator+=(const value_type* __x) {
1115 __pn_ += __x;
1116 return *this;
1117 }
1118
1119 _LIBCPP_INLINE_VISIBILITY
1120 path& operator+=(value_type __x) {
1121 __pn_ += __x;
1122 return *this;
1123 }
1124
1125 template <class _ECharT>
1126 typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
1127 operator+=(_ECharT __x) {
Marek Kurdej306a1b02020-12-07 20:07:25 +01001128 _PathCVT<_ECharT>::__append_source(__pn_,
1129 basic_string_view<_ECharT>(&__x, 1));
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001130 return *this;
1131 }
1132
1133 template <class _Source>
1134 _EnableIfPathable<_Source> operator+=(const _Source& __x) {
1135 return this->concat(__x);
1136 }
1137
1138 template <class _Source>
1139 _EnableIfPathable<_Source> concat(const _Source& __x) {
1140 _SourceCVT<_Source>::__append_source(__pn_, __x);
1141 return *this;
1142 }
1143
1144 template <class _InputIt>
1145 path& concat(_InputIt __first, _InputIt __last) {
1146 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1147 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1148 return *this;
1149 }
1150
1151 // modifiers
1152 _LIBCPP_INLINE_VISIBILITY
1153 void clear() noexcept { __pn_.clear(); }
1154
Martin Storsjöf543c7a2020-10-28 12:24:11 +02001155 path& make_preferred() {
1156#if defined(_LIBCPP_WIN32API)
1157 _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
1158#endif
1159 return *this;
1160 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001161
1162 _LIBCPP_INLINE_VISIBILITY
1163 path& remove_filename() {
1164 auto __fname = __filename();
1165 if (!__fname.empty())
1166 __pn_.erase(__fname.data() - __pn_.data());
1167 return *this;
1168 }
1169
1170 path& replace_filename(const path& __replacement) {
1171 remove_filename();
1172 return (*this /= __replacement);
1173 }
1174
1175 path& replace_extension(const path& __replacement = path());
1176
1177 _LIBCPP_INLINE_VISIBILITY
1178 void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
1179
1180 // private helper to allow reserving memory in the path
1181 _LIBCPP_INLINE_VISIBILITY
1182 void __reserve(size_t __s) { __pn_.reserve(__s); }
1183
1184 // native format observers
1185 _LIBCPP_INLINE_VISIBILITY
1186 const string_type& native() const noexcept { return __pn_; }
1187
1188 _LIBCPP_INLINE_VISIBILITY
1189 const value_type* c_str() const noexcept { return __pn_.c_str(); }
1190
1191 _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
1192
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001193#if defined(_LIBCPP_WIN32API)
1194 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; }
1195
1196 _VSTD::wstring generic_wstring() const { return __pn_; }
1197
1198#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
1199 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1200 class _Allocator = allocator<_ECharT> >
1201 basic_string<_ECharT, _Traits, _Allocator>
1202 string(const _Allocator& __a = _Allocator()) const {
1203 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1204 _Str __s(__a);
1205 __s.reserve(__pn_.size());
1206 _PathExport<_ECharT>::__append(__s, __pn_);
1207 return __s;
1208 }
1209
1210 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const {
1211 return string<char>();
1212 }
1213 _LIBCPP_INLINE_VISIBILITY __u8_string u8string() const {
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001214 using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1215 __u8_string __s;
1216 __s.reserve(__pn_.size());
1217 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1218 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001219 }
1220
1221 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
1222 return string<char16_t>();
1223 }
1224 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
1225 return string<char32_t>();
1226 }
1227
1228 // generic format observers
1229 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1230 class _Allocator = allocator<_ECharT> >
1231 basic_string<_ECharT, _Traits, _Allocator>
1232 generic_string(const _Allocator& __a = _Allocator()) const {
1233 return string<_ECharT, _Traits, _Allocator>(__a);
1234 }
1235
1236 _VSTD::string generic_string() const { return generic_string<char>(); }
1237 _VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); }
1238 _VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); }
1239 __u8_string generic_u8string() const { return u8string(); }
1240#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1241#else /* _LIBCPP_WIN32API */
1242
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001243 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001244#ifndef _LIBCPP_NO_HAS_CHAR8_T
1245 _LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1246#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001247 _LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001248#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001249
1250#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001251 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1252 class _Allocator = allocator<_ECharT> >
1253 basic_string<_ECharT, _Traits, _Allocator>
1254 string(const _Allocator& __a = _Allocator()) const {
1255 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
1256 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1257 _Str __s(__a);
1258 __s.reserve(__pn_.size());
1259 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1260 return __s;
1261 }
1262
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001263 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001264 return string<wchar_t>();
1265 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001266 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001267 return string<char16_t>();
1268 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001269 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001270 return string<char32_t>();
1271 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001272#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001273
1274 // generic format observers
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001275 _VSTD::string generic_string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001276#ifndef _LIBCPP_NO_HAS_CHAR8_T
1277 _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1278#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001279 _VSTD::string generic_u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001280#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001281
1282#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001283 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1284 class _Allocator = allocator<_ECharT> >
1285 basic_string<_ECharT, _Traits, _Allocator>
1286 generic_string(const _Allocator& __a = _Allocator()) const {
1287 return string<_ECharT, _Traits, _Allocator>(__a);
1288 }
1289
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001290 _VSTD::wstring generic_wstring() const { return string<wchar_t>(); }
1291 _VSTD::u16string generic_u16string() const { return string<char16_t>(); }
1292 _VSTD::u32string generic_u32string() const { return string<char32_t>(); }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001293#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1294#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001295
1296private:
1297 int __compare(__string_view) const;
1298 __string_view __root_name() const;
1299 __string_view __root_directory() const;
1300 __string_view __root_path_raw() const;
1301 __string_view __relative_path() const;
1302 __string_view __parent_path() const;
1303 __string_view __filename() const;
1304 __string_view __stem() const;
1305 __string_view __extension() const;
1306
1307public:
1308 // compare
1309 _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
1310 return __compare(__p.__pn_);
1311 }
1312 _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
1313 return __compare(__s);
1314 }
1315 _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
1316 return __compare(__s);
1317 }
1318 _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
1319 return __compare(__s);
1320 }
1321
1322 // decomposition
1323 _LIBCPP_INLINE_VISIBILITY path root_name() const {
1324 return string_type(__root_name());
1325 }
1326 _LIBCPP_INLINE_VISIBILITY path root_directory() const {
1327 return string_type(__root_directory());
1328 }
1329 _LIBCPP_INLINE_VISIBILITY path root_path() const {
Martin Storsjö98770152020-11-04 15:59:56 +02001330#if defined(_LIBCPP_WIN32API)
1331 return string_type(__root_path_raw());
1332#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001333 return root_name().append(string_type(__root_directory()));
Martin Storsjö98770152020-11-04 15:59:56 +02001334#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001335 }
1336 _LIBCPP_INLINE_VISIBILITY path relative_path() const {
1337 return string_type(__relative_path());
1338 }
1339 _LIBCPP_INLINE_VISIBILITY path parent_path() const {
1340 return string_type(__parent_path());
1341 }
1342 _LIBCPP_INLINE_VISIBILITY path filename() const {
1343 return string_type(__filename());
1344 }
1345 _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
1346 _LIBCPP_INLINE_VISIBILITY path extension() const {
1347 return string_type(__extension());
1348 }
1349
1350 // query
1351 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
1352 empty() const noexcept {
1353 return __pn_.empty();
1354 }
1355
1356 _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
1357 return !__root_name().empty();
1358 }
1359 _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
1360 return !__root_directory().empty();
1361 }
1362 _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
1363 return !__root_path_raw().empty();
1364 }
1365 _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
1366 return !__relative_path().empty();
1367 }
1368 _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
1369 return !__parent_path().empty();
1370 }
1371 _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
1372 return !__filename().empty();
1373 }
1374 _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
1375 _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
1376 return !__extension().empty();
1377 }
1378
1379 _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
Martin Storsjöef6b7422020-11-01 23:39:03 +02001380#if defined(_LIBCPP_WIN32API)
1381 __string_view __root_name_str = __root_name();
1382 __string_view __root_dir = __root_directory();
1383 if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
1384 // A drive letter with no root directory is relative, e.g. x:example.
1385 return !__root_dir.empty();
1386 }
1387 // If no root name, it's relative, e.g. \example is relative to the current drive
1388 if (__root_name_str.empty())
1389 return false;
1390 if (__root_name_str.size() < 3)
1391 return false;
1392 // A server root name, like \\server, is always absolute
1393 if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
1394 return false;
1395 if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
1396 return false;
1397 // Seems to be a server root name
1398 return true;
1399#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001400 return has_root_directory();
Martin Storsjöef6b7422020-11-01 23:39:03 +02001401#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001402 }
1403 _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
1404
1405 // relative paths
1406 path lexically_normal() const;
1407 path lexically_relative(const path& __base) const;
1408
1409 _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
1410 path __result = this->lexically_relative(__base);
1411 if (__result.native().empty())
1412 return *this;
1413 return __result;
1414 }
1415
1416 // iterators
1417 class _LIBCPP_TYPE_VIS iterator;
1418 typedef iterator const_iterator;
1419
1420 iterator begin() const;
1421 iterator end() const;
1422
Louis Dionne8d053eb2020-10-09 15:31:05 -04001423#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001424 template <class _CharT, class _Traits>
1425 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001426 typename enable_if<is_same<_CharT, value_type>::value &&
1427 is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001428 basic_ostream<_CharT, _Traits>&>::type
1429 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001430 __os << _VSTD::__quoted(__p.native());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001431 return __os;
1432 }
1433
1434 template <class _CharT, class _Traits>
1435 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001436 typename enable_if<!is_same<_CharT, value_type>::value ||
1437 !is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001438 basic_ostream<_CharT, _Traits>&>::type
1439 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001440 __os << _VSTD::__quoted(__p.string<_CharT, _Traits>());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001441 return __os;
1442 }
1443
1444 template <class _CharT, class _Traits>
1445 _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
1446 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
1447 basic_string<_CharT, _Traits> __tmp;
1448 __is >> __quoted(__tmp);
1449 __p = __tmp;
1450 return __is;
1451 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001452#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001453
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001454 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
1455 return __lhs.compare(__rhs) == 0;
1456 }
1457 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
1458 return __lhs.compare(__rhs) != 0;
1459 }
1460 friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
1461 return __lhs.compare(__rhs) < 0;
1462 }
1463 friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
1464 return __lhs.compare(__rhs) <= 0;
1465 }
1466 friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
1467 return __lhs.compare(__rhs) > 0;
1468 }
1469 friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
1470 return __lhs.compare(__rhs) >= 0;
1471 }
1472
1473 friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
1474 const path& __rhs) {
1475 path __result(__lhs);
1476 __result /= __rhs;
1477 return __result;
1478 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001479private:
1480 inline _LIBCPP_INLINE_VISIBILITY path&
1481 __assign_view(__string_view const& __s) noexcept {
1482 __pn_ = string_type(__s);
1483 return *this;
1484 }
1485 string_type __pn_;
1486};
1487
1488inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
1489 __lhs.swap(__rhs);
1490}
1491
1492_LIBCPP_FUNC_VIS
1493size_t hash_value(const path& __p) noexcept;
1494
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001495template <class _InputIt>
Martin Storsjöe3a71972020-10-26 13:18:46 +02001496_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001497 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1498 u8path(_InputIt __f, _InputIt __l) {
1499 static_assert(
Martin Storsjöe3a71972020-10-26 13:18:46 +02001500#ifndef _LIBCPP_NO_HAS_CHAR8_T
1501 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1502#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001503 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
Martin Storsjöe3a71972020-10-26 13:18:46 +02001504 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
Martin Storsjö929dff92020-12-15 09:15:37 +02001505 " or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001506#if defined(_LIBCPP_WIN32API)
1507 string __tmp(__f, __l);
1508 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1509 _VSTD::wstring __w;
1510 __w.reserve(__tmp.size());
1511 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1512 return path(__w);
1513#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001514 return path(__f, __l);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001515#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001516}
1517
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001518#if defined(_LIBCPP_WIN32API)
1519template <class _InputIt>
1520_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1521 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1522 u8path(_InputIt __f, _NullSentinel) {
1523 static_assert(
1524#ifndef _LIBCPP_NO_HAS_CHAR8_T
1525 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1526#endif
1527 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
1528 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
1529 " or 'char8_t'");
1530 string __tmp;
1531 const char __sentinel = char{};
1532 for (; *__f != __sentinel; ++__f)
1533 __tmp.push_back(*__f);
1534 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1535 _VSTD::wstring __w;
1536 __w.reserve(__tmp.size());
1537 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1538 return path(__w);
1539}
1540#endif /* _LIBCPP_WIN32API */
1541
Martin Storsjö367d7f02020-11-05 00:21:30 +02001542template <class _Source>
1543_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1544 typename enable_if<__is_pathable<_Source>::value, path>::type
1545 u8path(const _Source& __s) {
1546 static_assert(
1547#ifndef _LIBCPP_NO_HAS_CHAR8_T
1548 is_same<typename __is_pathable<_Source>::__char_type, char8_t>::value ||
1549#endif
1550 is_same<typename __is_pathable<_Source>::__char_type, char>::value,
1551 "u8path(Source const&) requires Source have a character type of type "
1552 "'char' or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001553#if defined(_LIBCPP_WIN32API)
1554 using _Traits = __is_pathable<_Source>;
Arthur O'Dwyer1ac9f092021-01-15 12:59:56 -05001555 return u8path(_VSTD::__unwrap_iter(_Traits::__range_begin(__s)), _VSTD::__unwrap_iter(_Traits::__range_end(__s)));
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001556#else
Martin Storsjö367d7f02020-11-05 00:21:30 +02001557 return path(__s);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001558#endif
Martin Storsjö367d7f02020-11-05 00:21:30 +02001559}
1560
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001561class _LIBCPP_TYPE_VIS path::iterator {
1562public:
1563 enum _ParserState : unsigned char {
1564 _Singular,
1565 _BeforeBegin,
1566 _InRootName,
1567 _InRootDir,
1568 _InFilenames,
1569 _InTrailingSep,
1570 _AtEnd
1571 };
1572
1573public:
1574 typedef bidirectional_iterator_tag iterator_category;
1575
1576 typedef path value_type;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001577 typedef ptrdiff_t difference_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001578 typedef const path* pointer;
1579 typedef const path& reference;
1580
1581 typedef void
1582 __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
1583
1584public:
1585 _LIBCPP_INLINE_VISIBILITY
1586 iterator()
1587 : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
1588 __state_(_Singular) {}
1589
1590 iterator(const iterator&) = default;
1591 ~iterator() = default;
1592
1593 iterator& operator=(const iterator&) = default;
1594
1595 _LIBCPP_INLINE_VISIBILITY
1596 reference operator*() const { return __stashed_elem_; }
1597
1598 _LIBCPP_INLINE_VISIBILITY
1599 pointer operator->() const { return &__stashed_elem_; }
1600
1601 _LIBCPP_INLINE_VISIBILITY
1602 iterator& operator++() {
1603 _LIBCPP_ASSERT(__state_ != _Singular,
1604 "attempting to increment a singular iterator");
1605 _LIBCPP_ASSERT(__state_ != _AtEnd,
1606 "attempting to increment the end iterator");
1607 return __increment();
1608 }
1609
1610 _LIBCPP_INLINE_VISIBILITY
1611 iterator operator++(int) {
1612 iterator __it(*this);
1613 this->operator++();
1614 return __it;
1615 }
1616
1617 _LIBCPP_INLINE_VISIBILITY
1618 iterator& operator--() {
1619 _LIBCPP_ASSERT(__state_ != _Singular,
1620 "attempting to decrement a singular iterator");
1621 _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
1622 "attempting to decrement the begin iterator");
1623 return __decrement();
1624 }
1625
1626 _LIBCPP_INLINE_VISIBILITY
1627 iterator operator--(int) {
1628 iterator __it(*this);
1629 this->operator--();
1630 return __it;
1631 }
1632
1633private:
1634 friend class path;
1635
1636 inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
1637 const iterator&);
1638
1639 iterator& __increment();
1640 iterator& __decrement();
1641
1642 path __stashed_elem_;
1643 const path* __path_ptr_;
1644 path::__string_view __entry_;
1645 _ParserState __state_;
1646};
1647
1648inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
1649 const path::iterator& __rhs) {
1650 return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
1651 __lhs.__entry_.data() == __rhs.__entry_.data();
1652}
1653
1654inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
1655 const path::iterator& __rhs) {
1656 return !(__lhs == __rhs);
1657}
1658
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001659// TODO(ldionne): We need to pop the pragma and push it again after
1660// filesystem_error to work around PR41078.
1661_LIBCPP_AVAILABILITY_FILESYSTEM_POP
1662
1663class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001664public:
1665 _LIBCPP_INLINE_VISIBILITY
1666 filesystem_error(const string& __what, error_code __ec)
1667 : system_error(__ec, __what),
1668 __storage_(make_shared<_Storage>(path(), path())) {
1669 __create_what(0);
1670 }
1671
1672 _LIBCPP_INLINE_VISIBILITY
1673 filesystem_error(const string& __what, const path& __p1, error_code __ec)
1674 : system_error(__ec, __what),
1675 __storage_(make_shared<_Storage>(__p1, path())) {
1676 __create_what(1);
1677 }
1678
1679 _LIBCPP_INLINE_VISIBILITY
1680 filesystem_error(const string& __what, const path& __p1, const path& __p2,
1681 error_code __ec)
1682 : system_error(__ec, __what),
1683 __storage_(make_shared<_Storage>(__p1, __p2)) {
1684 __create_what(2);
1685 }
1686
1687 _LIBCPP_INLINE_VISIBILITY
1688 const path& path1() const noexcept { return __storage_->__p1_; }
1689
1690 _LIBCPP_INLINE_VISIBILITY
1691 const path& path2() const noexcept { return __storage_->__p2_; }
1692
Dimitry Andric47269ce2020-03-13 19:36:26 +01001693 filesystem_error(const filesystem_error&) = default;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001694 ~filesystem_error() override; // key function
1695
1696 _LIBCPP_INLINE_VISIBILITY
1697 const char* what() const noexcept override {
1698 return __storage_->__what_.c_str();
1699 }
1700
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001701 void __create_what(int __num_paths);
1702
1703private:
Louis Dionne48ae8892019-03-19 17:47:53 +00001704 struct _LIBCPP_HIDDEN _Storage {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001705 _LIBCPP_INLINE_VISIBILITY
1706 _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
1707
1708 path __p1_;
1709 path __p2_;
1710 string __what_;
1711 };
1712 shared_ptr<_Storage> __storage_;
1713};
1714
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001715_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
1716
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001717template <class... _Args>
1718_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
1719#ifndef _LIBCPP_NO_EXCEPTIONS
Louis Dionne6251ef02019-02-05 15:46:52 +00001720void __throw_filesystem_error(_Args&&... __args) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001721 throw filesystem_error(_VSTD::forward<_Args>(__args)...);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001722}
1723#else
Louis Dionne6251ef02019-02-05 15:46:52 +00001724void __throw_filesystem_error(_Args&&...) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001725 _VSTD::abort();
1726}
1727#endif
1728
1729// operational functions
1730
1731_LIBCPP_FUNC_VIS
1732path __absolute(const path&, error_code* __ec = nullptr);
1733_LIBCPP_FUNC_VIS
1734path __canonical(const path&, error_code* __ec = nullptr);
1735_LIBCPP_FUNC_VIS
1736void __copy(const path& __from, const path& __to, copy_options __opt,
1737 error_code* __ec = nullptr);
1738_LIBCPP_FUNC_VIS
1739bool __copy_file(const path& __from, const path& __to, copy_options __opt,
1740 error_code* __ec = nullptr);
1741_LIBCPP_FUNC_VIS
1742void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
1743 error_code* __ec = nullptr);
1744_LIBCPP_FUNC_VIS
1745bool __create_directories(const path& p, error_code* ec = nullptr);
1746_LIBCPP_FUNC_VIS
1747bool __create_directory(const path& p, error_code* ec = nullptr);
1748_LIBCPP_FUNC_VIS
1749bool __create_directory(const path& p, const path& attributes,
1750 error_code* ec = nullptr);
1751_LIBCPP_FUNC_VIS
1752void __create_directory_symlink(const path& __to, const path& __new_symlink,
1753 error_code* __ec = nullptr);
1754_LIBCPP_FUNC_VIS
1755void __create_hard_link(const path& __to, const path& __new_hard_link,
1756 error_code* __ec = nullptr);
1757_LIBCPP_FUNC_VIS
1758void __create_symlink(const path& __to, const path& __new_symlink,
1759 error_code* __ec = nullptr);
1760_LIBCPP_FUNC_VIS
1761path __current_path(error_code* __ec = nullptr);
1762_LIBCPP_FUNC_VIS
1763void __current_path(const path&, error_code* __ec = nullptr);
1764_LIBCPP_FUNC_VIS
1765bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
1766_LIBCPP_FUNC_VIS
1767uintmax_t __file_size(const path&, error_code* __ec = nullptr);
1768_LIBCPP_FUNC_VIS
1769uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
1770_LIBCPP_FUNC_VIS
1771bool __fs_is_empty(const path& p, error_code* ec = nullptr);
1772_LIBCPP_FUNC_VIS
1773file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
1774_LIBCPP_FUNC_VIS
1775void __last_write_time(const path& p, file_time_type new_time,
1776 error_code* ec = nullptr);
1777_LIBCPP_FUNC_VIS
1778void __permissions(const path&, perms, perm_options, error_code* = nullptr);
1779_LIBCPP_FUNC_VIS
1780path __read_symlink(const path& p, error_code* ec = nullptr);
1781_LIBCPP_FUNC_VIS
1782bool __remove(const path& p, error_code* ec = nullptr);
1783_LIBCPP_FUNC_VIS
1784uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
1785_LIBCPP_FUNC_VIS
1786void __rename(const path& from, const path& to, error_code* ec = nullptr);
1787_LIBCPP_FUNC_VIS
1788void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
1789_LIBCPP_FUNC_VIS
1790space_info __space(const path&, error_code* __ec = nullptr);
1791_LIBCPP_FUNC_VIS
1792file_status __status(const path&, error_code* __ec = nullptr);
1793_LIBCPP_FUNC_VIS
1794file_status __symlink_status(const path&, error_code* __ec = nullptr);
1795_LIBCPP_FUNC_VIS
1796path __system_complete(const path&, error_code* __ec = nullptr);
1797_LIBCPP_FUNC_VIS
1798path __temp_directory_path(error_code* __ec = nullptr);
1799_LIBCPP_FUNC_VIS
1800path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
1801
1802inline _LIBCPP_INLINE_VISIBILITY path current_path() {
1803 return __current_path();
1804}
1805
1806inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
1807 return __current_path(&__ec);
1808}
1809
1810inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
1811 __current_path(__p);
1812}
1813
1814inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
1815 error_code& __ec) noexcept {
1816 __current_path(__p, &__ec);
1817}
1818
1819inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
1820 return __absolute(__p);
1821}
1822
1823inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
1824 error_code& __ec) {
1825 return __absolute(__p, &__ec);
1826}
1827
1828inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
1829 return __canonical(__p);
1830}
1831
1832inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
1833 error_code& __ec) {
1834 return __canonical(__p, &__ec);
1835}
1836
1837inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
1838 const path& __to) {
1839 __copy(__from, __to, copy_options::none);
1840}
1841
1842inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1843 error_code& __ec) {
1844 __copy(__from, __to, copy_options::none, &__ec);
1845}
1846
1847inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1848 copy_options __opt) {
1849 __copy(__from, __to, __opt);
1850}
1851
1852inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1853 copy_options __opt,
1854 error_code& __ec) {
1855 __copy(__from, __to, __opt, &__ec);
1856}
1857
1858inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1859 const path& __to) {
1860 return __copy_file(__from, __to, copy_options::none);
1861}
1862
1863inline _LIBCPP_INLINE_VISIBILITY bool
1864copy_file(const path& __from, const path& __to, error_code& __ec) {
1865 return __copy_file(__from, __to, copy_options::none, &__ec);
1866}
1867
1868inline _LIBCPP_INLINE_VISIBILITY bool
1869copy_file(const path& __from, const path& __to, copy_options __opt) {
1870 return __copy_file(__from, __to, __opt);
1871}
1872
1873inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1874 const path& __to,
1875 copy_options __opt,
1876 error_code& __ec) {
1877 return __copy_file(__from, __to, __opt, &__ec);
1878}
1879
1880inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
1881 const path& __new) {
1882 __copy_symlink(__existing, __new);
1883}
1884
1885inline _LIBCPP_INLINE_VISIBILITY void
1886copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
1887 __copy_symlink(__ext, __new, &__ec);
1888}
1889
1890inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
1891 return __create_directories(__p);
1892}
1893
1894inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
1895 error_code& __ec) {
1896 return __create_directories(__p, &__ec);
1897}
1898
1899inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
1900 return __create_directory(__p);
1901}
1902
1903inline _LIBCPP_INLINE_VISIBILITY bool
1904create_directory(const path& __p, error_code& __ec) noexcept {
1905 return __create_directory(__p, &__ec);
1906}
1907
1908inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
1909 const path& __attrs) {
1910 return __create_directory(__p, __attrs);
1911}
1912
1913inline _LIBCPP_INLINE_VISIBILITY bool
1914create_directory(const path& __p, const path& __attrs,
1915 error_code& __ec) noexcept {
1916 return __create_directory(__p, __attrs, &__ec);
1917}
1918
1919inline _LIBCPP_INLINE_VISIBILITY void
1920create_directory_symlink(const path& __to, const path& __new) {
1921 __create_directory_symlink(__to, __new);
1922}
1923
1924inline _LIBCPP_INLINE_VISIBILITY void
1925create_directory_symlink(const path& __to, const path& __new,
1926 error_code& __ec) noexcept {
1927 __create_directory_symlink(__to, __new, &__ec);
1928}
1929
1930inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
1931 const path& __new) {
1932 __create_hard_link(__to, __new);
1933}
1934
1935inline _LIBCPP_INLINE_VISIBILITY void
1936create_hard_link(const path& __to, const path& __new,
1937 error_code& __ec) noexcept {
1938 __create_hard_link(__to, __new, &__ec);
1939}
1940
1941inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
1942 const path& __new) {
1943 __create_symlink(__to, __new);
1944}
1945
1946inline _LIBCPP_INLINE_VISIBILITY void
1947create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
1948 return __create_symlink(__to, __new, &__ec);
1949}
1950
1951inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
1952 return __s.type() != file_type::none;
1953}
1954
1955inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
1956 return status_known(__s) && __s.type() != file_type::not_found;
1957}
1958
1959inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
1960 return exists(__status(__p));
1961}
1962
1963inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
1964 error_code& __ec) noexcept {
1965 auto __s = __status(__p, &__ec);
1966 if (status_known(__s))
1967 __ec.clear();
1968 return exists(__s);
1969}
1970
1971inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
1972 const path& __p2) {
1973 return __equivalent(__p1, __p2);
1974}
1975
1976inline _LIBCPP_INLINE_VISIBILITY bool
1977equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
1978 return __equivalent(__p1, __p2, &__ec);
1979}
1980
1981inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
1982 return __file_size(__p);
1983}
1984
1985inline _LIBCPP_INLINE_VISIBILITY uintmax_t
1986file_size(const path& __p, error_code& __ec) noexcept {
1987 return __file_size(__p, &__ec);
1988}
1989
1990inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
1991 return __hard_link_count(__p);
1992}
1993
1994inline _LIBCPP_INLINE_VISIBILITY uintmax_t
1995hard_link_count(const path& __p, error_code& __ec) noexcept {
1996 return __hard_link_count(__p, &__ec);
1997}
1998
1999inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
2000 return __s.type() == file_type::block;
2001}
2002
2003inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
2004 return is_block_file(__status(__p));
2005}
2006
2007inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
2008 error_code& __ec) noexcept {
2009 return is_block_file(__status(__p, &__ec));
2010}
2011
2012inline _LIBCPP_INLINE_VISIBILITY bool
2013is_character_file(file_status __s) noexcept {
2014 return __s.type() == file_type::character;
2015}
2016
2017inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
2018 return is_character_file(__status(__p));
2019}
2020
2021inline _LIBCPP_INLINE_VISIBILITY bool
2022is_character_file(const path& __p, error_code& __ec) noexcept {
2023 return is_character_file(__status(__p, &__ec));
2024}
2025
2026inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
2027 return __s.type() == file_type::directory;
2028}
2029
2030inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
2031 return is_directory(__status(__p));
2032}
2033
2034inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
2035 error_code& __ec) noexcept {
2036 return is_directory(__status(__p, &__ec));
2037}
2038
2039inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
2040 return __fs_is_empty(__p);
2041}
2042
2043inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
2044 error_code& __ec) {
2045 return __fs_is_empty(__p, &__ec);
2046}
2047
2048inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
2049 return __s.type() == file_type::fifo;
2050}
2051inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
2052 return is_fifo(__status(__p));
2053}
2054
2055inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
2056 error_code& __ec) noexcept {
2057 return is_fifo(__status(__p, &__ec));
2058}
2059
2060inline _LIBCPP_INLINE_VISIBILITY bool
2061is_regular_file(file_status __s) noexcept {
2062 return __s.type() == file_type::regular;
2063}
2064
2065inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
2066 return is_regular_file(__status(__p));
2067}
2068
2069inline _LIBCPP_INLINE_VISIBILITY bool
2070is_regular_file(const path& __p, error_code& __ec) noexcept {
2071 return is_regular_file(__status(__p, &__ec));
2072}
2073
2074inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
2075 return __s.type() == file_type::socket;
2076}
2077
2078inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
2079 return is_socket(__status(__p));
2080}
2081
2082inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
2083 error_code& __ec) noexcept {
2084 return is_socket(__status(__p, &__ec));
2085}
2086
2087inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
2088 return __s.type() == file_type::symlink;
2089}
2090
2091inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
2092 return is_symlink(__symlink_status(__p));
2093}
2094
2095inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
2096 error_code& __ec) noexcept {
2097 return is_symlink(__symlink_status(__p, &__ec));
2098}
2099
2100inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
2101 return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
2102 !is_symlink(__s);
2103}
2104
2105inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
2106 return is_other(__status(__p));
2107}
2108
2109inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
2110 error_code& __ec) noexcept {
2111 return is_other(__status(__p, &__ec));
2112}
2113
2114inline _LIBCPP_INLINE_VISIBILITY file_time_type
2115last_write_time(const path& __p) {
2116 return __last_write_time(__p);
2117}
2118
2119inline _LIBCPP_INLINE_VISIBILITY file_time_type
2120last_write_time(const path& __p, error_code& __ec) noexcept {
2121 return __last_write_time(__p, &__ec);
2122}
2123
2124inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
2125 file_time_type __t) {
2126 __last_write_time(__p, __t);
2127}
2128
2129inline _LIBCPP_INLINE_VISIBILITY void
2130last_write_time(const path& __p, file_time_type __t,
2131 error_code& __ec) noexcept {
2132 __last_write_time(__p, __t, &__ec);
2133}
2134
2135inline _LIBCPP_INLINE_VISIBILITY void
2136permissions(const path& __p, perms __prms,
2137 perm_options __opts = perm_options::replace) {
2138 __permissions(__p, __prms, __opts);
2139}
2140
2141inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2142 error_code& __ec) noexcept {
2143 __permissions(__p, __prms, perm_options::replace, &__ec);
2144}
2145
2146inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2147 perm_options __opts,
2148 error_code& __ec) {
2149 __permissions(__p, __prms, __opts, &__ec);
2150}
2151
2152inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2153 const path& __base,
2154 error_code& __ec) {
2155 path __tmp = __weakly_canonical(__p, &__ec);
2156 if (__ec)
2157 return {};
2158 path __tmp_base = __weakly_canonical(__base, &__ec);
2159 if (__ec)
2160 return {};
2161 return __tmp.lexically_proximate(__tmp_base);
2162}
2163
2164inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2165 error_code& __ec) {
2166 return proximate(__p, current_path(), __ec);
2167}
2168
2169inline _LIBCPP_INLINE_VISIBILITY path
2170proximate(const path& __p, const path& __base = current_path()) {
2171 return __weakly_canonical(__p).lexically_proximate(
2172 __weakly_canonical(__base));
2173}
2174
2175inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
2176 return __read_symlink(__p);
2177}
2178
2179inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
2180 error_code& __ec) {
2181 return __read_symlink(__p, &__ec);
2182}
2183
2184inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2185 const path& __base,
2186 error_code& __ec) {
2187 path __tmp = __weakly_canonical(__p, &__ec);
2188 if (__ec)
2189 return path();
2190 path __tmpbase = __weakly_canonical(__base, &__ec);
2191 if (__ec)
2192 return path();
2193 return __tmp.lexically_relative(__tmpbase);
2194}
2195
2196inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2197 error_code& __ec) {
2198 return relative(__p, current_path(), __ec);
2199}
2200
2201inline _LIBCPP_INLINE_VISIBILITY path
2202relative(const path& __p, const path& __base = current_path()) {
2203 return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
2204}
2205
2206inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
2207 return __remove(__p);
2208}
2209
2210inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
2211 error_code& __ec) noexcept {
2212 return __remove(__p, &__ec);
2213}
2214
2215inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
2216 return __remove_all(__p);
2217}
2218
2219inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
2220 error_code& __ec) {
2221 return __remove_all(__p, &__ec);
2222}
2223
2224inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
2225 const path& __to) {
2226 return __rename(__from, __to);
2227}
2228
2229inline _LIBCPP_INLINE_VISIBILITY void
2230rename(const path& __from, const path& __to, error_code& __ec) noexcept {
2231 return __rename(__from, __to, &__ec);
2232}
2233
2234inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
2235 uintmax_t __ns) {
2236 return __resize_file(__p, __ns);
2237}
2238
2239inline _LIBCPP_INLINE_VISIBILITY void
2240resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
2241 return __resize_file(__p, __ns, &__ec);
2242}
2243
2244inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
2245 return __space(__p);
2246}
2247
2248inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
2249 error_code& __ec) noexcept {
2250 return __space(__p, &__ec);
2251}
2252
2253inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
2254 return __status(__p);
2255}
2256
2257inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
2258 error_code& __ec) noexcept {
2259 return __status(__p, &__ec);
2260}
2261
2262inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
2263 return __symlink_status(__p);
2264}
2265
2266inline _LIBCPP_INLINE_VISIBILITY file_status
2267symlink_status(const path& __p, error_code& __ec) noexcept {
2268 return __symlink_status(__p, &__ec);
2269}
2270
2271inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
2272 return __temp_directory_path();
2273}
2274
2275inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
2276 return __temp_directory_path(&__ec);
2277}
2278
2279inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
2280 return __weakly_canonical(__p);
2281}
2282
2283inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
2284 error_code& __ec) {
2285 return __weakly_canonical(__p, &__ec);
2286}
2287
2288class directory_iterator;
2289class recursive_directory_iterator;
Louis Dionne48ae8892019-03-19 17:47:53 +00002290class _LIBCPP_HIDDEN __dir_stream;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002291
2292class directory_entry {
2293 typedef _VSTD_FS::path _Path;
2294
2295public:
2296 // constructors and destructors
2297 directory_entry() noexcept = default;
2298 directory_entry(directory_entry const&) = default;
2299 directory_entry(directory_entry&&) noexcept = default;
2300
2301 _LIBCPP_INLINE_VISIBILITY
2302 explicit directory_entry(_Path const& __p) : __p_(__p) {
2303 error_code __ec;
2304 __refresh(&__ec);
2305 }
2306
2307 _LIBCPP_INLINE_VISIBILITY
2308 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
2309 __refresh(&__ec);
2310 }
2311
2312 ~directory_entry() {}
2313
2314 directory_entry& operator=(directory_entry const&) = default;
2315 directory_entry& operator=(directory_entry&&) noexcept = default;
2316
2317 _LIBCPP_INLINE_VISIBILITY
2318 void assign(_Path const& __p) {
2319 __p_ = __p;
2320 error_code __ec;
2321 __refresh(&__ec);
2322 }
2323
2324 _LIBCPP_INLINE_VISIBILITY
2325 void assign(_Path const& __p, error_code& __ec) {
2326 __p_ = __p;
2327 __refresh(&__ec);
2328 }
2329
2330 _LIBCPP_INLINE_VISIBILITY
2331 void replace_filename(_Path const& __p) {
2332 __p_.replace_filename(__p);
2333 error_code __ec;
2334 __refresh(&__ec);
2335 }
2336
2337 _LIBCPP_INLINE_VISIBILITY
2338 void replace_filename(_Path const& __p, error_code& __ec) {
2339 __p_ = __p_.parent_path() / __p;
2340 __refresh(&__ec);
2341 }
2342
2343 _LIBCPP_INLINE_VISIBILITY
2344 void refresh() { __refresh(); }
2345
2346 _LIBCPP_INLINE_VISIBILITY
2347 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
2348
2349 _LIBCPP_INLINE_VISIBILITY
2350 _Path const& path() const noexcept { return __p_; }
2351
2352 _LIBCPP_INLINE_VISIBILITY
2353 operator const _Path&() const noexcept { return __p_; }
2354
2355 _LIBCPP_INLINE_VISIBILITY
2356 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
2357
2358 _LIBCPP_INLINE_VISIBILITY
2359 bool exists(error_code& __ec) const noexcept {
2360 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
2361 }
2362
2363 _LIBCPP_INLINE_VISIBILITY
2364 bool is_block_file() const { return __get_ft() == file_type::block; }
2365
2366 _LIBCPP_INLINE_VISIBILITY
2367 bool is_block_file(error_code& __ec) const noexcept {
2368 return __get_ft(&__ec) == file_type::block;
2369 }
2370
2371 _LIBCPP_INLINE_VISIBILITY
2372 bool is_character_file() const { return __get_ft() == file_type::character; }
2373
2374 _LIBCPP_INLINE_VISIBILITY
2375 bool is_character_file(error_code& __ec) const noexcept {
2376 return __get_ft(&__ec) == file_type::character;
2377 }
2378
2379 _LIBCPP_INLINE_VISIBILITY
2380 bool is_directory() const { return __get_ft() == file_type::directory; }
2381
2382 _LIBCPP_INLINE_VISIBILITY
2383 bool is_directory(error_code& __ec) const noexcept {
2384 return __get_ft(&__ec) == file_type::directory;
2385 }
2386
2387 _LIBCPP_INLINE_VISIBILITY
2388 bool is_fifo() const { return __get_ft() == file_type::fifo; }
2389
2390 _LIBCPP_INLINE_VISIBILITY
2391 bool is_fifo(error_code& __ec) const noexcept {
2392 return __get_ft(&__ec) == file_type::fifo;
2393 }
2394
2395 _LIBCPP_INLINE_VISIBILITY
2396 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
2397
2398 _LIBCPP_INLINE_VISIBILITY
2399 bool is_other(error_code& __ec) const noexcept {
2400 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
2401 }
2402
2403 _LIBCPP_INLINE_VISIBILITY
2404 bool is_regular_file() const { return __get_ft() == file_type::regular; }
2405
2406 _LIBCPP_INLINE_VISIBILITY
2407 bool is_regular_file(error_code& __ec) const noexcept {
2408 return __get_ft(&__ec) == file_type::regular;
2409 }
2410
2411 _LIBCPP_INLINE_VISIBILITY
2412 bool is_socket() const { return __get_ft() == file_type::socket; }
2413
2414 _LIBCPP_INLINE_VISIBILITY
2415 bool is_socket(error_code& __ec) const noexcept {
2416 return __get_ft(&__ec) == file_type::socket;
2417 }
2418
2419 _LIBCPP_INLINE_VISIBILITY
2420 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
2421
2422 _LIBCPP_INLINE_VISIBILITY
2423 bool is_symlink(error_code& __ec) const noexcept {
2424 return __get_sym_ft(&__ec) == file_type::symlink;
2425 }
2426 _LIBCPP_INLINE_VISIBILITY
2427 uintmax_t file_size() const { return __get_size(); }
2428
2429 _LIBCPP_INLINE_VISIBILITY
2430 uintmax_t file_size(error_code& __ec) const noexcept {
2431 return __get_size(&__ec);
2432 }
2433
2434 _LIBCPP_INLINE_VISIBILITY
2435 uintmax_t hard_link_count() const { return __get_nlink(); }
2436
2437 _LIBCPP_INLINE_VISIBILITY
2438 uintmax_t hard_link_count(error_code& __ec) const noexcept {
2439 return __get_nlink(&__ec);
2440 }
2441
2442 _LIBCPP_INLINE_VISIBILITY
2443 file_time_type last_write_time() const { return __get_write_time(); }
2444
2445 _LIBCPP_INLINE_VISIBILITY
2446 file_time_type last_write_time(error_code& __ec) const noexcept {
2447 return __get_write_time(&__ec);
2448 }
2449
2450 _LIBCPP_INLINE_VISIBILITY
2451 file_status status() const { return __get_status(); }
2452
2453 _LIBCPP_INLINE_VISIBILITY
2454 file_status status(error_code& __ec) const noexcept {
2455 return __get_status(&__ec);
2456 }
2457
2458 _LIBCPP_INLINE_VISIBILITY
2459 file_status symlink_status() const { return __get_symlink_status(); }
2460
2461 _LIBCPP_INLINE_VISIBILITY
2462 file_status symlink_status(error_code& __ec) const noexcept {
2463 return __get_symlink_status(&__ec);
2464 }
2465
2466 _LIBCPP_INLINE_VISIBILITY
2467 bool operator<(directory_entry const& __rhs) const noexcept {
2468 return __p_ < __rhs.__p_;
2469 }
2470
2471 _LIBCPP_INLINE_VISIBILITY
2472 bool operator==(directory_entry const& __rhs) const noexcept {
2473 return __p_ == __rhs.__p_;
2474 }
2475
2476 _LIBCPP_INLINE_VISIBILITY
2477 bool operator!=(directory_entry const& __rhs) const noexcept {
2478 return __p_ != __rhs.__p_;
2479 }
2480
2481 _LIBCPP_INLINE_VISIBILITY
2482 bool operator<=(directory_entry const& __rhs) const noexcept {
2483 return __p_ <= __rhs.__p_;
2484 }
2485
2486 _LIBCPP_INLINE_VISIBILITY
2487 bool operator>(directory_entry const& __rhs) const noexcept {
2488 return __p_ > __rhs.__p_;
2489 }
2490
2491 _LIBCPP_INLINE_VISIBILITY
2492 bool operator>=(directory_entry const& __rhs) const noexcept {
2493 return __p_ >= __rhs.__p_;
2494 }
2495
2496private:
2497 friend class directory_iterator;
2498 friend class recursive_directory_iterator;
2499 friend class __dir_stream;
2500
2501 enum _CacheType : unsigned char {
2502 _Empty,
2503 _IterSymlink,
2504 _IterNonSymlink,
2505 _RefreshSymlink,
2506 _RefreshSymlinkUnresolved,
2507 _RefreshNonSymlink
2508 };
2509
2510 struct __cached_data {
2511 uintmax_t __size_;
2512 uintmax_t __nlink_;
2513 file_time_type __write_time_;
2514 perms __sym_perms_;
2515 perms __non_sym_perms_;
2516 file_type __type_;
2517 _CacheType __cache_type_;
2518
2519 _LIBCPP_INLINE_VISIBILITY
2520 __cached_data() noexcept { __reset(); }
2521
2522 _LIBCPP_INLINE_VISIBILITY
2523 void __reset() {
2524 __cache_type_ = _Empty;
2525 __type_ = file_type::none;
2526 __sym_perms_ = __non_sym_perms_ = perms::unknown;
2527 __size_ = __nlink_ = uintmax_t(-1);
2528 __write_time_ = file_time_type::min();
2529 }
2530 };
2531
2532 _LIBCPP_INLINE_VISIBILITY
2533 static __cached_data __create_iter_result(file_type __ft) {
2534 __cached_data __data;
2535 __data.__type_ = __ft;
2536 __data.__cache_type_ = [&]() {
2537 switch (__ft) {
2538 case file_type::none:
2539 return _Empty;
2540 case file_type::symlink:
2541 return _IterSymlink;
2542 default:
2543 return _IterNonSymlink;
2544 }
2545 }();
2546 return __data;
2547 }
2548
2549 _LIBCPP_INLINE_VISIBILITY
2550 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002551 __p_ = _VSTD::move(__p);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002552 __data_ = __dt;
2553 }
2554
2555 _LIBCPP_FUNC_VIS
2556 error_code __do_refresh() noexcept;
2557
2558 _LIBCPP_INLINE_VISIBILITY
2559 static bool __is_dne_error(error_code const& __ec) {
2560 if (!__ec)
2561 return true;
2562 switch (static_cast<errc>(__ec.value())) {
2563 case errc::no_such_file_or_directory:
2564 case errc::not_a_directory:
2565 return true;
2566 default:
2567 return false;
2568 }
2569 }
2570
2571 _LIBCPP_INLINE_VISIBILITY
2572 void __handle_error(const char* __msg, error_code* __dest_ec,
2573 error_code const& __ec, bool __allow_dne = false) const {
2574 if (__dest_ec) {
2575 *__dest_ec = __ec;
2576 return;
2577 }
2578 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
2579 __throw_filesystem_error(__msg, __p_, __ec);
2580 }
2581
2582 _LIBCPP_INLINE_VISIBILITY
2583 void __refresh(error_code* __ec = nullptr) {
2584 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
2585 /*allow_dne*/ true);
2586 }
2587
2588 _LIBCPP_INLINE_VISIBILITY
2589 file_type __get_sym_ft(error_code* __ec = nullptr) const {
2590 switch (__data_.__cache_type_) {
2591 case _Empty:
2592 return __symlink_status(__p_, __ec).type();
2593 case _IterSymlink:
2594 case _RefreshSymlink:
2595 case _RefreshSymlinkUnresolved:
2596 if (__ec)
2597 __ec->clear();
2598 return file_type::symlink;
2599 case _IterNonSymlink:
2600 case _RefreshNonSymlink:
2601 file_status __st(__data_.__type_);
2602 if (__ec && !_VSTD_FS::exists(__st))
2603 *__ec = make_error_code(errc::no_such_file_or_directory);
2604 else if (__ec)
2605 __ec->clear();
2606 return __data_.__type_;
2607 }
2608 _LIBCPP_UNREACHABLE();
2609 }
2610
2611 _LIBCPP_INLINE_VISIBILITY
2612 file_type __get_ft(error_code* __ec = nullptr) const {
2613 switch (__data_.__cache_type_) {
2614 case _Empty:
2615 case _IterSymlink:
2616 case _RefreshSymlinkUnresolved:
2617 return __status(__p_, __ec).type();
2618 case _IterNonSymlink:
2619 case _RefreshNonSymlink:
2620 case _RefreshSymlink: {
2621 file_status __st(__data_.__type_);
2622 if (__ec && !_VSTD_FS::exists(__st))
2623 *__ec = make_error_code(errc::no_such_file_or_directory);
2624 else if (__ec)
2625 __ec->clear();
2626 return __data_.__type_;
2627 }
2628 }
2629 _LIBCPP_UNREACHABLE();
2630 }
2631
2632 _LIBCPP_INLINE_VISIBILITY
2633 file_status __get_status(error_code* __ec = nullptr) const {
2634 switch (__data_.__cache_type_) {
2635 case _Empty:
2636 case _IterNonSymlink:
2637 case _IterSymlink:
2638 case _RefreshSymlinkUnresolved:
2639 return __status(__p_, __ec);
2640 case _RefreshNonSymlink:
2641 case _RefreshSymlink:
2642 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
2643 }
2644 _LIBCPP_UNREACHABLE();
2645 }
2646
2647 _LIBCPP_INLINE_VISIBILITY
2648 file_status __get_symlink_status(error_code* __ec = nullptr) const {
2649 switch (__data_.__cache_type_) {
2650 case _Empty:
2651 case _IterNonSymlink:
2652 case _IterSymlink:
2653 return __symlink_status(__p_, __ec);
2654 case _RefreshNonSymlink:
2655 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
2656 case _RefreshSymlink:
2657 case _RefreshSymlinkUnresolved:
2658 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
2659 }
2660 _LIBCPP_UNREACHABLE();
2661 }
2662
2663 _LIBCPP_INLINE_VISIBILITY
2664 uintmax_t __get_size(error_code* __ec = nullptr) const {
2665 switch (__data_.__cache_type_) {
2666 case _Empty:
2667 case _IterNonSymlink:
2668 case _IterSymlink:
2669 case _RefreshSymlinkUnresolved:
2670 return _VSTD_FS::__file_size(__p_, __ec);
2671 case _RefreshSymlink:
2672 case _RefreshNonSymlink: {
2673 error_code __m_ec;
2674 file_status __st(__get_ft(&__m_ec));
2675 __handle_error("in directory_entry::file_size", __ec, __m_ec);
2676 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
2677 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
2678 : errc::not_supported;
2679 __handle_error("in directory_entry::file_size", __ec,
2680 make_error_code(__err_kind));
2681 }
2682 return __data_.__size_;
2683 }
2684 }
2685 _LIBCPP_UNREACHABLE();
2686 }
2687
2688 _LIBCPP_INLINE_VISIBILITY
2689 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
2690 switch (__data_.__cache_type_) {
2691 case _Empty:
2692 case _IterNonSymlink:
2693 case _IterSymlink:
2694 case _RefreshSymlinkUnresolved:
2695 return _VSTD_FS::__hard_link_count(__p_, __ec);
2696 case _RefreshSymlink:
2697 case _RefreshNonSymlink: {
2698 error_code __m_ec;
2699 (void)__get_ft(&__m_ec);
2700 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
2701 return __data_.__nlink_;
2702 }
2703 }
2704 _LIBCPP_UNREACHABLE();
2705 }
2706
2707 _LIBCPP_INLINE_VISIBILITY
2708 file_time_type __get_write_time(error_code* __ec = nullptr) const {
2709 switch (__data_.__cache_type_) {
2710 case _Empty:
2711 case _IterNonSymlink:
2712 case _IterSymlink:
2713 case _RefreshSymlinkUnresolved:
2714 return _VSTD_FS::__last_write_time(__p_, __ec);
2715 case _RefreshSymlink:
2716 case _RefreshNonSymlink: {
2717 error_code __m_ec;
2718 file_status __st(__get_ft(&__m_ec));
2719 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
2720 if (_VSTD_FS::exists(__st) &&
2721 __data_.__write_time_ == file_time_type::min())
2722 __handle_error("in directory_entry::last_write_time", __ec,
2723 make_error_code(errc::value_too_large));
2724 return __data_.__write_time_;
2725 }
2726 }
2727 _LIBCPP_UNREACHABLE();
2728 }
2729
2730private:
2731 _Path __p_;
2732 __cached_data __data_;
2733};
2734
2735class __dir_element_proxy {
2736public:
2737 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
2738 return _VSTD::move(__elem_);
2739 }
2740
2741private:
2742 friend class directory_iterator;
2743 friend class recursive_directory_iterator;
2744 explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
2745 __dir_element_proxy(__dir_element_proxy&& __o)
2746 : __elem_(_VSTD::move(__o.__elem_)) {}
2747 directory_entry __elem_;
2748};
2749
2750class directory_iterator {
2751public:
2752 typedef directory_entry value_type;
2753 typedef ptrdiff_t difference_type;
2754 typedef value_type const* pointer;
2755 typedef value_type const& reference;
2756 typedef input_iterator_tag iterator_category;
2757
2758public:
2759 //ctor & dtor
2760 directory_iterator() noexcept {}
2761
2762 explicit directory_iterator(const path& __p)
2763 : directory_iterator(__p, nullptr) {}
2764
2765 directory_iterator(const path& __p, directory_options __opts)
2766 : directory_iterator(__p, nullptr, __opts) {}
2767
2768 directory_iterator(const path& __p, error_code& __ec)
2769 : directory_iterator(__p, &__ec) {}
2770
2771 directory_iterator(const path& __p, directory_options __opts,
2772 error_code& __ec)
2773 : directory_iterator(__p, &__ec, __opts) {}
2774
2775 directory_iterator(const directory_iterator&) = default;
2776 directory_iterator(directory_iterator&&) = default;
2777 directory_iterator& operator=(const directory_iterator&) = default;
2778
2779 directory_iterator& operator=(directory_iterator&& __o) noexcept {
2780 // non-default implementation provided to support self-move assign.
2781 if (this != &__o) {
2782 __imp_ = _VSTD::move(__o.__imp_);
2783 }
2784 return *this;
2785 }
2786
2787 ~directory_iterator() = default;
2788
2789 const directory_entry& operator*() const {
2790 _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
2791 return __dereference();
2792 }
2793
2794 const directory_entry* operator->() const { return &**this; }
2795
2796 directory_iterator& operator++() { return __increment(); }
2797
2798 __dir_element_proxy operator++(int) {
2799 __dir_element_proxy __p(**this);
2800 __increment();
2801 return __p;
2802 }
2803
2804 directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
2805
2806private:
2807 inline _LIBCPP_INLINE_VISIBILITY friend bool
2808 operator==(const directory_iterator& __lhs,
2809 const directory_iterator& __rhs) noexcept;
2810
2811 // construct the dir_stream
2812 _LIBCPP_FUNC_VIS
2813 directory_iterator(const path&, error_code*,
2814 directory_options = directory_options::none);
2815
2816 _LIBCPP_FUNC_VIS
2817 directory_iterator& __increment(error_code* __ec = nullptr);
2818
2819 _LIBCPP_FUNC_VIS
2820 const directory_entry& __dereference() const;
2821
2822private:
2823 shared_ptr<__dir_stream> __imp_;
2824};
2825
2826inline _LIBCPP_INLINE_VISIBILITY bool
2827operator==(const directory_iterator& __lhs,
2828 const directory_iterator& __rhs) noexcept {
2829 return __lhs.__imp_ == __rhs.__imp_;
2830}
2831
2832inline _LIBCPP_INLINE_VISIBILITY bool
2833operator!=(const directory_iterator& __lhs,
2834 const directory_iterator& __rhs) noexcept {
2835 return !(__lhs == __rhs);
2836}
2837
2838// enable directory_iterator range-based for statements
2839inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2840begin(directory_iterator __iter) noexcept {
2841 return __iter;
2842}
2843
2844inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2845end(const directory_iterator&) noexcept {
2846 return directory_iterator();
2847}
2848
2849class recursive_directory_iterator {
2850public:
2851 using value_type = directory_entry;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002852 using difference_type = ptrdiff_t;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002853 using pointer = directory_entry const*;
2854 using reference = directory_entry const&;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002855 using iterator_category = input_iterator_tag;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002856
2857public:
2858 // constructors and destructor
2859 _LIBCPP_INLINE_VISIBILITY
2860 recursive_directory_iterator() noexcept : __rec_(false) {}
2861
2862 _LIBCPP_INLINE_VISIBILITY
2863 explicit recursive_directory_iterator(
2864 const path& __p, directory_options __xoptions = directory_options::none)
2865 : recursive_directory_iterator(__p, __xoptions, nullptr) {}
2866
2867 _LIBCPP_INLINE_VISIBILITY
2868 recursive_directory_iterator(const path& __p, directory_options __xoptions,
2869 error_code& __ec)
2870 : recursive_directory_iterator(__p, __xoptions, &__ec) {}
2871
2872 _LIBCPP_INLINE_VISIBILITY
2873 recursive_directory_iterator(const path& __p, error_code& __ec)
2874 : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
2875
2876 recursive_directory_iterator(const recursive_directory_iterator&) = default;
2877 recursive_directory_iterator(recursive_directory_iterator&&) = default;
2878
2879 recursive_directory_iterator&
2880 operator=(const recursive_directory_iterator&) = default;
2881
2882 _LIBCPP_INLINE_VISIBILITY
2883 recursive_directory_iterator&
2884 operator=(recursive_directory_iterator&& __o) noexcept {
2885 // non-default implementation provided to support self-move assign.
2886 if (this != &__o) {
2887 __imp_ = _VSTD::move(__o.__imp_);
2888 __rec_ = __o.__rec_;
2889 }
2890 return *this;
2891 }
2892
2893 ~recursive_directory_iterator() = default;
2894
2895 _LIBCPP_INLINE_VISIBILITY
2896 const directory_entry& operator*() const { return __dereference(); }
2897
2898 _LIBCPP_INLINE_VISIBILITY
2899 const directory_entry* operator->() const { return &__dereference(); }
2900
2901 recursive_directory_iterator& operator++() { return __increment(); }
2902
2903 _LIBCPP_INLINE_VISIBILITY
2904 __dir_element_proxy operator++(int) {
2905 __dir_element_proxy __p(**this);
2906 __increment();
2907 return __p;
2908 }
2909
2910 _LIBCPP_INLINE_VISIBILITY
2911 recursive_directory_iterator& increment(error_code& __ec) {
2912 return __increment(&__ec);
2913 }
2914
2915 _LIBCPP_FUNC_VIS directory_options options() const;
2916 _LIBCPP_FUNC_VIS int depth() const;
2917
2918 _LIBCPP_INLINE_VISIBILITY
2919 void pop() { __pop(); }
2920
2921 _LIBCPP_INLINE_VISIBILITY
2922 void pop(error_code& __ec) { __pop(&__ec); }
2923
2924 _LIBCPP_INLINE_VISIBILITY
2925 bool recursion_pending() const { return __rec_; }
2926
2927 _LIBCPP_INLINE_VISIBILITY
2928 void disable_recursion_pending() { __rec_ = false; }
2929
2930private:
Louis Dionne0ba10dc2019-08-13 15:02:53 +00002931 _LIBCPP_FUNC_VIS
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002932 recursive_directory_iterator(const path& __p, directory_options __opt,
2933 error_code* __ec);
2934
2935 _LIBCPP_FUNC_VIS
2936 const directory_entry& __dereference() const;
2937
2938 _LIBCPP_FUNC_VIS
2939 bool __try_recursion(error_code* __ec);
2940
2941 _LIBCPP_FUNC_VIS
2942 void __advance(error_code* __ec = nullptr);
2943
2944 _LIBCPP_FUNC_VIS
2945 recursive_directory_iterator& __increment(error_code* __ec = nullptr);
2946
2947 _LIBCPP_FUNC_VIS
2948 void __pop(error_code* __ec = nullptr);
2949
2950 inline _LIBCPP_INLINE_VISIBILITY friend bool
2951 operator==(const recursive_directory_iterator&,
2952 const recursive_directory_iterator&) noexcept;
2953
Louis Dionne48ae8892019-03-19 17:47:53 +00002954 struct _LIBCPP_HIDDEN __shared_imp;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002955 shared_ptr<__shared_imp> __imp_;
2956 bool __rec_;
2957}; // class recursive_directory_iterator
2958
2959inline _LIBCPP_INLINE_VISIBILITY bool
2960operator==(const recursive_directory_iterator& __lhs,
2961 const recursive_directory_iterator& __rhs) noexcept {
2962 return __lhs.__imp_ == __rhs.__imp_;
2963}
2964
2965_LIBCPP_INLINE_VISIBILITY
2966inline bool operator!=(const recursive_directory_iterator& __lhs,
2967 const recursive_directory_iterator& __rhs) noexcept {
2968 return !(__lhs == __rhs);
2969}
2970// enable recursive_directory_iterator range-based for statements
2971inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2972begin(recursive_directory_iterator __iter) noexcept {
2973 return __iter;
2974}
2975
2976inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2977end(const recursive_directory_iterator&) noexcept {
2978 return recursive_directory_iterator();
2979}
2980
Louis Dionnef6bf76a2019-03-20 21:18:14 +00002981_LIBCPP_AVAILABILITY_FILESYSTEM_POP
2982
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002983_LIBCPP_END_NAMESPACE_FILESYSTEM
2984
2985#endif // !_LIBCPP_CXX03_LANG
2986
2987_LIBCPP_POP_MACROS
2988
2989#endif // _LIBCPP_FILESYSTEM