blob: 372b28f285b04cc721aa2a02faa4b4e62e612637 [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
Martin Storsjöb2485452021-03-07 23:49:56 +0200279// On Windows, the library never identifies files as block, character, fifo
280// or socket.
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000281enum class _LIBCPP_ENUM_VIS file_type : signed char {
282 none = 0,
283 not_found = -1,
284 regular = 1,
285 directory = 2,
286 symlink = 3,
287 block = 4,
288 character = 5,
289 fifo = 6,
290 socket = 7,
291 unknown = 8
292};
293
Martin Storsjöb2485452021-03-07 23:49:56 +0200294// On Windows, these permission bits map to one single readonly flag per
295// file, and the executable bit is always returned as set. When setting
296// permissions, as long as the write bit is set for either owner, group or
297// others, the readonly flag is cleared.
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000298enum class _LIBCPP_ENUM_VIS perms : unsigned {
299 none = 0,
300
301 owner_read = 0400,
302 owner_write = 0200,
303 owner_exec = 0100,
304 owner_all = 0700,
305
306 group_read = 040,
307 group_write = 020,
308 group_exec = 010,
309 group_all = 070,
310
311 others_read = 04,
312 others_write = 02,
313 others_exec = 01,
314 others_all = 07,
315
316 all = 0777,
317
318 set_uid = 04000,
319 set_gid = 02000,
320 sticky_bit = 01000,
321 mask = 07777,
322 unknown = 0xFFFF,
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, perms _RHS) {
339 return static_cast<perms>(static_cast<unsigned>(_LHS) ^
340 static_cast<unsigned>(_RHS));
341}
342
343_LIBCPP_INLINE_VISIBILITY
344inline constexpr perms operator~(perms _LHS) {
345 return static_cast<perms>(~static_cast<unsigned>(_LHS));
346}
347
348_LIBCPP_INLINE_VISIBILITY
349inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
350
351_LIBCPP_INLINE_VISIBILITY
352inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
353
354_LIBCPP_INLINE_VISIBILITY
355inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
356
357enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
358 replace = 1,
359 add = 2,
360 remove = 4,
361 nofollow = 8
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, perm_options _RHS) {
378 return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
379 static_cast<unsigned>(_RHS));
380}
381
382_LIBCPP_INLINE_VISIBILITY
383inline constexpr perm_options operator~(perm_options _LHS) {
384 return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
385}
386
387_LIBCPP_INLINE_VISIBILITY
388inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
389 return _LHS = _LHS & _RHS;
390}
391
392_LIBCPP_INLINE_VISIBILITY
393inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
394 return _LHS = _LHS | _RHS;
395}
396
397_LIBCPP_INLINE_VISIBILITY
398inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
399 return _LHS = _LHS ^ _RHS;
400}
401
402enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
403 none = 0,
404 skip_existing = 1,
405 overwrite_existing = 2,
406 update_existing = 4,
407 recursive = 8,
408 copy_symlinks = 16,
409 skip_symlinks = 32,
410 directories_only = 64,
411 create_symlinks = 128,
412 create_hard_links = 256,
413 __in_recursive_copy = 512,
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, copy_options _RHS) {
430 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
431 static_cast<unsigned short>(_RHS));
432}
433
434_LIBCPP_INLINE_VISIBILITY
435inline constexpr copy_options operator~(copy_options _LHS) {
436 return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
437}
438
439_LIBCPP_INLINE_VISIBILITY
440inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
441 return _LHS = _LHS & _RHS;
442}
443
444_LIBCPP_INLINE_VISIBILITY
445inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
446 return _LHS = _LHS | _RHS;
447}
448
449_LIBCPP_INLINE_VISIBILITY
450inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
451 return _LHS = _LHS ^ _RHS;
452}
453
454enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
455 none = 0,
456 follow_directory_symlink = 1,
457 skip_permission_denied = 2
458};
459
460_LIBCPP_INLINE_VISIBILITY
461inline constexpr directory_options operator&(directory_options _LHS,
462 directory_options _RHS) {
463 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
464 static_cast<unsigned char>(_RHS));
465}
466
467_LIBCPP_INLINE_VISIBILITY
468inline constexpr directory_options operator|(directory_options _LHS,
469 directory_options _RHS) {
470 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
471 static_cast<unsigned char>(_RHS));
472}
473
474_LIBCPP_INLINE_VISIBILITY
475inline constexpr directory_options operator^(directory_options _LHS,
476 directory_options _RHS) {
477 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
478 static_cast<unsigned char>(_RHS));
479}
480
481_LIBCPP_INLINE_VISIBILITY
482inline constexpr directory_options operator~(directory_options _LHS) {
483 return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
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
498_LIBCPP_INLINE_VISIBILITY
499inline directory_options& operator^=(directory_options& _LHS,
500 directory_options _RHS) {
501 return _LHS = _LHS ^ _RHS;
502}
503
504class _LIBCPP_TYPE_VIS file_status {
505public:
506 // constructors
507 _LIBCPP_INLINE_VISIBILITY
508 file_status() noexcept : file_status(file_type::none) {}
509 _LIBCPP_INLINE_VISIBILITY
510 explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
511 : __ft_(__ft),
512 __prms_(__prms) {}
513
514 file_status(const file_status&) noexcept = default;
515 file_status(file_status&&) noexcept = default;
516
517 _LIBCPP_INLINE_VISIBILITY
518 ~file_status() {}
519
520 file_status& operator=(const file_status&) noexcept = default;
521 file_status& operator=(file_status&&) noexcept = default;
522
523 // observers
524 _LIBCPP_INLINE_VISIBILITY
525 file_type type() const noexcept { return __ft_; }
526
527 _LIBCPP_INLINE_VISIBILITY
528 perms permissions() const noexcept { return __prms_; }
529
530 // modifiers
531 _LIBCPP_INLINE_VISIBILITY
532 void type(file_type __ft) noexcept { __ft_ = __ft; }
533
534 _LIBCPP_INLINE_VISIBILITY
535 void permissions(perms __p) noexcept { __prms_ = __p; }
536
537private:
538 file_type __ft_;
539 perms __prms_;
540};
541
542class _LIBCPP_TYPE_VIS directory_entry;
543
544template <class _Tp>
545struct __can_convert_char {
546 static const bool value = false;
547};
548template <class _Tp>
549struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
550template <>
551struct __can_convert_char<char> {
552 static const bool value = true;
553 using __char_type = char;
554};
555template <>
556struct __can_convert_char<wchar_t> {
557 static const bool value = true;
558 using __char_type = wchar_t;
559};
Martin Storsjöe3a71972020-10-26 13:18:46 +0200560#ifndef _LIBCPP_NO_HAS_CHAR8_T
561template <>
562struct __can_convert_char<char8_t> {
563 static const bool value = true;
564 using __char_type = char8_t;
565};
566#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000567template <>
568struct __can_convert_char<char16_t> {
569 static const bool value = true;
570 using __char_type = char16_t;
571};
572template <>
573struct __can_convert_char<char32_t> {
574 static const bool value = true;
575 using __char_type = char32_t;
576};
577
578template <class _ECharT>
579typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
580__is_separator(_ECharT __e) {
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200581#if defined(_LIBCPP_WIN32API)
582 return __e == _ECharT('/') || __e == _ECharT('\\');
583#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000584 return __e == _ECharT('/');
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200585#endif
Eric Fiselierb41db9a2018-10-01 01:59:37 +0000586}
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000587
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200588#ifndef _LIBCPP_NO_HAS_CHAR8_T
589typedef u8string __u8_string;
590#else
591typedef string __u8_string;
592#endif
593
Martin Storsjö2ae96532020-10-27 11:46:06 +0200594struct _NullSentinel {};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000595
596template <class _Tp>
597using _Void = void;
598
599template <class _Tp, class = void>
600struct __is_pathable_string : public false_type {};
601
602template <class _ECharT, class _Traits, class _Alloc>
603struct __is_pathable_string<
604 basic_string<_ECharT, _Traits, _Alloc>,
605 _Void<typename __can_convert_char<_ECharT>::__char_type> >
606 : public __can_convert_char<_ECharT> {
607 using _Str = basic_string<_ECharT, _Traits, _Alloc>;
608 using _Base = __can_convert_char<_ECharT>;
609 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
610 static _ECharT const* __range_end(_Str const& __s) {
611 return __s.data() + __s.length();
612 }
613 static _ECharT __first_or_null(_Str const& __s) {
614 return __s.empty() ? _ECharT{} : __s[0];
615 }
616};
617
618template <class _ECharT, class _Traits>
619struct __is_pathable_string<
620 basic_string_view<_ECharT, _Traits>,
621 _Void<typename __can_convert_char<_ECharT>::__char_type> >
622 : public __can_convert_char<_ECharT> {
623 using _Str = basic_string_view<_ECharT, _Traits>;
624 using _Base = __can_convert_char<_ECharT>;
625 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
626 static _ECharT const* __range_end(_Str const& __s) {
627 return __s.data() + __s.length();
628 }
629 static _ECharT __first_or_null(_Str const& __s) {
630 return __s.empty() ? _ECharT{} : __s[0];
631 }
632};
633
634template <class _Source, class _DS = typename decay<_Source>::type,
635 class _UnqualPtrType =
636 typename remove_const<typename remove_pointer<_DS>::type>::type,
637 bool _IsCharPtr = is_pointer<_DS>::value&&
638 __can_convert_char<_UnqualPtrType>::value>
639struct __is_pathable_char_array : false_type {};
640
641template <class _Source, class _ECharT, class _UPtr>
642struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
643 : __can_convert_char<typename remove_const<_ECharT>::type> {
644 using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
645
646 static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
647 static _ECharT const* __range_end(const _ECharT* __b) {
648 using _Iter = const _ECharT*;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200649 const _ECharT __sentinel = _ECharT{};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000650 _Iter __e = __b;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200651 for (; *__e != __sentinel; ++__e)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000652 ;
653 return __e;
654 }
655
656 static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
657};
658
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500659template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000660 class = void>
661struct __is_pathable_iter : false_type {};
662
663template <class _Iter>
664struct __is_pathable_iter<
665 _Iter, true,
666 _Void<typename __can_convert_char<
667 typename iterator_traits<_Iter>::value_type>::__char_type> >
668 : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
669 using _ECharT = typename iterator_traits<_Iter>::value_type;
670 using _Base = __can_convert_char<_ECharT>;
671
672 static _Iter __range_begin(_Iter __b) { return __b; }
Martin Storsjö2ae96532020-10-27 11:46:06 +0200673 static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000674
675 static _ECharT __first_or_null(_Iter __b) { return *__b; }
676};
677
678template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
679 bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
680 bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
681struct __is_pathable : false_type {
682 static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
683};
684
685template <class _Tp>
686struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
687
688template <class _Tp>
689struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
690};
691
692template <class _Tp>
693struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
694
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200695#if defined(_LIBCPP_WIN32API)
696typedef wstring __path_string;
697typedef wchar_t __path_value;
698#else
699typedef string __path_string;
700typedef char __path_value;
701#endif
702
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200703#if defined(_LIBCPP_WIN32API)
704_LIBCPP_FUNC_VIS
705size_t __wide_to_char(const wstring&, char*, size_t);
706_LIBCPP_FUNC_VIS
707size_t __char_to_wide(const string&, wchar_t*, size_t);
708#endif
709
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000710template <class _ECharT>
Louis Dionne8d053eb2020-10-09 15:31:05 -0400711struct _PathCVT;
712
713#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
714template <class _ECharT>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000715struct _PathCVT {
716 static_assert(__can_convert_char<_ECharT>::value,
717 "Char type not convertible");
718
719 typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200720#if defined(_LIBCPP_WIN32API)
721 typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
722#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000723
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200724 static void __append_range(__path_string& __dest, _ECharT const* __b,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000725 _ECharT const* __e) {
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200726#if defined(_LIBCPP_WIN32API)
727 string __utf8;
728 _Narrower()(back_inserter(__utf8), __b, __e);
729 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
730#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000731 _Narrower()(back_inserter(__dest), __b, __e);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200732#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000733 }
734
735 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200736 static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000737 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
738 if (__b == __e)
739 return;
740 basic_string<_ECharT> __tmp(__b, __e);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200741#if defined(_LIBCPP_WIN32API)
742 string __utf8;
743 _Narrower()(back_inserter(__utf8), __tmp.data(),
744 __tmp.data() + __tmp.length());
745 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
746#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000747 _Narrower()(back_inserter(__dest), __tmp.data(),
748 __tmp.data() + __tmp.length());
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200749#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000750 }
751
752 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200753 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000754 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
Martin Storsjö2ae96532020-10-27 11:46:06 +0200755 const _ECharT __sentinel = _ECharT{};
756 if (*__b == __sentinel)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000757 return;
758 basic_string<_ECharT> __tmp;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200759 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000760 __tmp.push_back(*__b);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200761#if defined(_LIBCPP_WIN32API)
762 string __utf8;
763 _Narrower()(back_inserter(__utf8), __tmp.data(),
764 __tmp.data() + __tmp.length());
765 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
766#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000767 _Narrower()(back_inserter(__dest), __tmp.data(),
768 __tmp.data() + __tmp.length());
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200769#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000770 }
771
772 template <class _Source>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200773 static void __append_source(__path_string& __dest, _Source const& __s) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000774 using _Traits = __is_pathable<_Source>;
775 __append_range(__dest, _Traits::__range_begin(__s),
776 _Traits::__range_end(__s));
777 }
778};
Louis Dionne8d053eb2020-10-09 15:31:05 -0400779#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000780
781template <>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200782struct _PathCVT<__path_value> {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000783
784 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500785 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200786 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000787 for (; __b != __e; ++__b)
788 __dest.push_back(*__b);
789 }
790
791 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500792 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200793 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000794 __dest.__append_forward_unsafe(__b, __e);
795 }
796
797 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200798 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
Martin Storsjö2ae96532020-10-27 11:46:06 +0200799 const char __sentinel = char{};
800 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000801 __dest.push_back(*__b);
802 }
803
804 template <class _Source>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200805 static void __append_source(__path_string& __dest, _Source const& __s) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000806 using _Traits = __is_pathable<_Source>;
807 __append_range(__dest, _Traits::__range_begin(__s),
808 _Traits::__range_end(__s));
809 }
810};
811
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200812#if defined(_LIBCPP_WIN32API)
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200813template <>
814struct _PathCVT<char> {
815
816 static void
817 __append_string(__path_string& __dest, const basic_string<char> &__str) {
818 size_t __size = __char_to_wide(__str, nullptr, 0);
819 size_t __pos = __dest.size();
820 __dest.resize(__pos + __size);
821 __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
822 }
823
824 template <class _Iter>
825 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
826 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
827 basic_string<char> __tmp(__b, __e);
828 __append_string(__dest, __tmp);
829 }
830
831 template <class _Iter>
832 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
833 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
834 basic_string<char> __tmp(__b, __e);
835 __append_string(__dest, __tmp);
836 }
837
838 template <class _Iter>
839 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
840 const char __sentinel = char{};
841 basic_string<char> __tmp;
842 for (; *__b != __sentinel; ++__b)
843 __tmp.push_back(*__b);
844 __append_string(__dest, __tmp);
845 }
846
847 template <class _Source>
848 static void __append_source(__path_string& __dest, _Source const& __s) {
849 using _Traits = __is_pathable<_Source>;
850 __append_range(__dest, _Traits::__range_begin(__s),
851 _Traits::__range_end(__s));
852 }
853};
854
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200855template <class _ECharT>
856struct _PathExport {
857 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
858 typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
859
860 template <class _Str>
861 static void __append(_Str& __dest, const __path_string& __src) {
862 string __utf8;
863 _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
864 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
865 }
866};
867
868template <>
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200869struct _PathExport<char> {
870 template <class _Str>
871 static void __append(_Str& __dest, const __path_string& __src) {
872 size_t __size = __wide_to_char(__src, nullptr, 0);
873 size_t __pos = __dest.size();
874 __dest.resize(__size);
875 __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
876 }
877};
878
879template <>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200880struct _PathExport<wchar_t> {
881 template <class _Str>
882 static void __append(_Str& __dest, const __path_string& __src) {
883 __dest.append(__src.begin(), __src.end());
884 }
885};
886
887template <>
888struct _PathExport<char16_t> {
889 template <class _Str>
890 static void __append(_Str& __dest, const __path_string& __src) {
891 __dest.append(__src.begin(), __src.end());
892 }
893};
894
895#ifndef _LIBCPP_NO_HAS_CHAR8_T
896template <>
897struct _PathExport<char8_t> {
898 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
899
900 template <class _Str>
901 static void __append(_Str& __dest, const __path_string& __src) {
902 _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
903 }
904};
905#endif /* !_LIBCPP_NO_HAS_CHAR8_T */
906#endif /* _LIBCPP_WIN32API */
907
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000908class _LIBCPP_TYPE_VIS path {
909 template <class _SourceOrIter, class _Tp = path&>
910 using _EnableIfPathable =
911 typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
912
913 template <class _Tp>
914 using _SourceChar = typename __is_pathable<_Tp>::__char_type;
915
916 template <class _Tp>
917 using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
918
919public:
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200920#if defined(_LIBCPP_WIN32API)
921 typedef wchar_t value_type;
922 static constexpr value_type preferred_separator = L'\\';
923#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000924 typedef char value_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000925 static constexpr value_type preferred_separator = '/';
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200926#endif
927 typedef basic_string<value_type> string_type;
928 typedef basic_string_view<value_type> __string_view;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000929
Martin Storsjö560291c2020-11-06 11:57:47 +0200930 enum _LIBCPP_ENUM_VIS format : unsigned char {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000931 auto_format,
932 native_format,
933 generic_format
934 };
935
936 // constructors and destructor
937 _LIBCPP_INLINE_VISIBILITY path() noexcept {}
938 _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
939 _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
940 : __pn_(_VSTD::move(__p.__pn_)) {}
941
942 _LIBCPP_INLINE_VISIBILITY
943 path(string_type&& __s, format = format::auto_format) noexcept
944 : __pn_(_VSTD::move(__s)) {}
945
946 template <class _Source, class = _EnableIfPathable<_Source, void> >
947 path(const _Source& __src, format = format::auto_format) {
948 _SourceCVT<_Source>::__append_source(__pn_, __src);
949 }
950
951 template <class _InputIt>
952 path(_InputIt __first, _InputIt __last, format = format::auto_format) {
953 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
954 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
955 }
956
Louis Dionne8d053eb2020-10-09 15:31:05 -0400957#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000958 // TODO Implement locale conversions.
959 template <class _Source, class = _EnableIfPathable<_Source, void> >
960 path(const _Source& __src, const locale& __loc, format = format::auto_format);
961 template <class _InputIt>
962 path(_InputIt __first, _InputIt _last, const locale& __loc,
963 format = format::auto_format);
Louis Dionne8d053eb2020-10-09 15:31:05 -0400964#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000965
966 _LIBCPP_INLINE_VISIBILITY
967 ~path() = default;
968
969 // assignments
970 _LIBCPP_INLINE_VISIBILITY
971 path& operator=(const path& __p) {
972 __pn_ = __p.__pn_;
973 return *this;
974 }
975
976 _LIBCPP_INLINE_VISIBILITY
977 path& operator=(path&& __p) noexcept {
978 __pn_ = _VSTD::move(__p.__pn_);
979 return *this;
980 }
981
Louis Dionne5da71d22021-02-03 16:40:41 -0500982 _LIBCPP_INLINE_VISIBILITY
983 path& operator=(string_type&& __s) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000984 __pn_ = _VSTD::move(__s);
985 return *this;
986 }
987
988 _LIBCPP_INLINE_VISIBILITY
989 path& assign(string_type&& __s) noexcept {
990 __pn_ = _VSTD::move(__s);
991 return *this;
992 }
993
994 template <class _Source>
995 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
996 operator=(const _Source& __src) {
997 return this->assign(__src);
998 }
999
1000 template <class _Source>
1001 _EnableIfPathable<_Source> assign(const _Source& __src) {
1002 __pn_.clear();
1003 _SourceCVT<_Source>::__append_source(__pn_, __src);
1004 return *this;
1005 }
1006
1007 template <class _InputIt>
1008 path& assign(_InputIt __first, _InputIt __last) {
1009 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1010 __pn_.clear();
1011 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1012 return *this;
1013 }
1014
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001015public:
1016 // appends
Martin Storsjö98770152020-11-04 15:59:56 +02001017#if defined(_LIBCPP_WIN32API)
1018 path& operator/=(const path& __p) {
1019 auto __p_root_name = __p.__root_name();
1020 auto __p_root_name_size = __p_root_name.size();
1021 if (__p.is_absolute() ||
1022 (!__p_root_name.empty() && __p_root_name != root_name())) {
1023 __pn_ = __p.__pn_;
1024 return *this;
1025 }
1026 if (__p.has_root_directory()) {
1027 path __root_name_str = root_name();
1028 __pn_ = __root_name_str.native();
1029 __pn_ += __p.__pn_.substr(__p_root_name_size);
1030 return *this;
1031 }
1032 if (has_filename() || (!has_root_directory() && is_absolute()))
1033 __pn_ += preferred_separator;
1034 __pn_ += __p.__pn_.substr(__p_root_name_size);
1035 return *this;
1036 }
1037 template <class _Source>
1038 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1039 operator/=(const _Source& __src) {
1040 return operator/=(path(__src));
1041 }
1042
1043 template <class _Source>
1044 _EnableIfPathable<_Source> append(const _Source& __src) {
1045 return operator/=(path(__src));
1046 }
1047
1048 template <class _InputIt>
1049 path& append(_InputIt __first, _InputIt __last) {
1050 return operator/=(path(__first, __last));
1051 }
1052#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001053 path& operator/=(const path& __p) {
1054 if (__p.is_absolute()) {
1055 __pn_ = __p.__pn_;
1056 return *this;
1057 }
1058 if (has_filename())
1059 __pn_ += preferred_separator;
1060 __pn_ += __p.native();
1061 return *this;
1062 }
1063
1064 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
1065 // is known at compile time to be "/' since the user almost certainly intended
1066 // to append a separator instead of overwriting the path with "/"
1067 template <class _Source>
1068 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1069 operator/=(const _Source& __src) {
1070 return this->append(__src);
1071 }
1072
1073 template <class _Source>
1074 _EnableIfPathable<_Source> append(const _Source& __src) {
1075 using _Traits = __is_pathable<_Source>;
1076 using _CVT = _PathCVT<_SourceChar<_Source> >;
Martin Storsjö98770152020-11-04 15:59:56 +02001077 bool __source_is_absolute = __is_separator(_Traits::__first_or_null(__src));
1078 if (__source_is_absolute)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001079 __pn_.clear();
1080 else if (has_filename())
1081 __pn_ += preferred_separator;
1082 _CVT::__append_source(__pn_, __src);
1083 return *this;
1084 }
1085
1086 template <class _InputIt>
1087 path& append(_InputIt __first, _InputIt __last) {
1088 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1089 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
1090 using _CVT = _PathCVT<_ItVal>;
Martin Storsjö98770152020-11-04 15:59:56 +02001091 if (__first != __last && __is_separator(*__first))
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001092 __pn_.clear();
1093 else if (has_filename())
1094 __pn_ += preferred_separator;
1095 _CVT::__append_range(__pn_, __first, __last);
1096 return *this;
1097 }
Martin Storsjö98770152020-11-04 15:59:56 +02001098#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001099
1100 // concatenation
1101 _LIBCPP_INLINE_VISIBILITY
1102 path& operator+=(const path& __x) {
1103 __pn_ += __x.__pn_;
1104 return *this;
1105 }
1106
1107 _LIBCPP_INLINE_VISIBILITY
1108 path& operator+=(const string_type& __x) {
1109 __pn_ += __x;
1110 return *this;
1111 }
1112
1113 _LIBCPP_INLINE_VISIBILITY
1114 path& operator+=(__string_view __x) {
1115 __pn_ += __x;
1116 return *this;
1117 }
1118
1119 _LIBCPP_INLINE_VISIBILITY
1120 path& operator+=(const value_type* __x) {
1121 __pn_ += __x;
1122 return *this;
1123 }
1124
1125 _LIBCPP_INLINE_VISIBILITY
1126 path& operator+=(value_type __x) {
1127 __pn_ += __x;
1128 return *this;
1129 }
1130
1131 template <class _ECharT>
1132 typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
1133 operator+=(_ECharT __x) {
Marek Kurdej306a1b02020-12-07 20:07:25 +01001134 _PathCVT<_ECharT>::__append_source(__pn_,
1135 basic_string_view<_ECharT>(&__x, 1));
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001136 return *this;
1137 }
1138
1139 template <class _Source>
1140 _EnableIfPathable<_Source> operator+=(const _Source& __x) {
1141 return this->concat(__x);
1142 }
1143
1144 template <class _Source>
1145 _EnableIfPathable<_Source> concat(const _Source& __x) {
1146 _SourceCVT<_Source>::__append_source(__pn_, __x);
1147 return *this;
1148 }
1149
1150 template <class _InputIt>
1151 path& concat(_InputIt __first, _InputIt __last) {
1152 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1153 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1154 return *this;
1155 }
1156
1157 // modifiers
1158 _LIBCPP_INLINE_VISIBILITY
1159 void clear() noexcept { __pn_.clear(); }
1160
Martin Storsjöf543c7a2020-10-28 12:24:11 +02001161 path& make_preferred() {
1162#if defined(_LIBCPP_WIN32API)
1163 _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
1164#endif
1165 return *this;
1166 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001167
1168 _LIBCPP_INLINE_VISIBILITY
1169 path& remove_filename() {
1170 auto __fname = __filename();
1171 if (!__fname.empty())
1172 __pn_.erase(__fname.data() - __pn_.data());
1173 return *this;
1174 }
1175
1176 path& replace_filename(const path& __replacement) {
1177 remove_filename();
1178 return (*this /= __replacement);
1179 }
1180
1181 path& replace_extension(const path& __replacement = path());
1182
1183 _LIBCPP_INLINE_VISIBILITY
1184 void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
1185
1186 // private helper to allow reserving memory in the path
1187 _LIBCPP_INLINE_VISIBILITY
1188 void __reserve(size_t __s) { __pn_.reserve(__s); }
1189
1190 // native format observers
1191 _LIBCPP_INLINE_VISIBILITY
1192 const string_type& native() const noexcept { return __pn_; }
1193
1194 _LIBCPP_INLINE_VISIBILITY
1195 const value_type* c_str() const noexcept { return __pn_.c_str(); }
1196
1197 _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
1198
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001199#if defined(_LIBCPP_WIN32API)
1200 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; }
1201
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001202 _VSTD::wstring generic_wstring() const {
1203 _VSTD::wstring __s;
1204 __s.resize(__pn_.size());
1205 _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
1206 return __s;
1207 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001208
1209#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
1210 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1211 class _Allocator = allocator<_ECharT> >
1212 basic_string<_ECharT, _Traits, _Allocator>
1213 string(const _Allocator& __a = _Allocator()) const {
1214 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1215 _Str __s(__a);
1216 __s.reserve(__pn_.size());
1217 _PathExport<_ECharT>::__append(__s, __pn_);
1218 return __s;
1219 }
1220
1221 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const {
1222 return string<char>();
1223 }
1224 _LIBCPP_INLINE_VISIBILITY __u8_string u8string() const {
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001225 using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1226 __u8_string __s;
1227 __s.reserve(__pn_.size());
1228 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1229 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001230 }
1231
1232 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
1233 return string<char16_t>();
1234 }
1235 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
1236 return string<char32_t>();
1237 }
1238
1239 // generic format observers
1240 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1241 class _Allocator = allocator<_ECharT> >
1242 basic_string<_ECharT, _Traits, _Allocator>
1243 generic_string(const _Allocator& __a = _Allocator()) const {
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001244 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1245 _Str __s = string<_ECharT, _Traits, _Allocator>(__a);
1246 // Note: This (and generic_u8string below) is slightly suboptimal as
1247 // it iterates twice over the string; once to convert it to the right
1248 // character type, and once to replace path delimiters.
1249 _VSTD::replace(__s.begin(), __s.end(),
1250 static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
1251 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001252 }
1253
1254 _VSTD::string generic_string() const { return generic_string<char>(); }
1255 _VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); }
1256 _VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); }
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001257 __u8_string generic_u8string() const {
1258 __u8_string __s = u8string();
1259 _VSTD::replace(__s.begin(), __s.end(), '\\', '/');
1260 return __s;
1261 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001262#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1263#else /* _LIBCPP_WIN32API */
1264
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001265 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001266#ifndef _LIBCPP_NO_HAS_CHAR8_T
1267 _LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1268#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001269 _LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001270#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001271
1272#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001273 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1274 class _Allocator = allocator<_ECharT> >
1275 basic_string<_ECharT, _Traits, _Allocator>
1276 string(const _Allocator& __a = _Allocator()) const {
1277 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
1278 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1279 _Str __s(__a);
1280 __s.reserve(__pn_.size());
1281 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1282 return __s;
1283 }
1284
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001285 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001286 return string<wchar_t>();
1287 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001288 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001289 return string<char16_t>();
1290 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001291 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001292 return string<char32_t>();
1293 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001294#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001295
1296 // generic format observers
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001297 _VSTD::string generic_string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001298#ifndef _LIBCPP_NO_HAS_CHAR8_T
1299 _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1300#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001301 _VSTD::string generic_u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001302#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001303
1304#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001305 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1306 class _Allocator = allocator<_ECharT> >
1307 basic_string<_ECharT, _Traits, _Allocator>
1308 generic_string(const _Allocator& __a = _Allocator()) const {
1309 return string<_ECharT, _Traits, _Allocator>(__a);
1310 }
1311
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001312 _VSTD::wstring generic_wstring() const { return string<wchar_t>(); }
1313 _VSTD::u16string generic_u16string() const { return string<char16_t>(); }
1314 _VSTD::u32string generic_u32string() const { return string<char32_t>(); }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001315#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1316#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001317
1318private:
1319 int __compare(__string_view) const;
1320 __string_view __root_name() const;
1321 __string_view __root_directory() const;
1322 __string_view __root_path_raw() const;
1323 __string_view __relative_path() const;
1324 __string_view __parent_path() const;
1325 __string_view __filename() const;
1326 __string_view __stem() const;
1327 __string_view __extension() const;
1328
1329public:
1330 // compare
1331 _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
1332 return __compare(__p.__pn_);
1333 }
1334 _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
1335 return __compare(__s);
1336 }
1337 _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
1338 return __compare(__s);
1339 }
1340 _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
1341 return __compare(__s);
1342 }
1343
1344 // decomposition
1345 _LIBCPP_INLINE_VISIBILITY path root_name() const {
1346 return string_type(__root_name());
1347 }
1348 _LIBCPP_INLINE_VISIBILITY path root_directory() const {
1349 return string_type(__root_directory());
1350 }
1351 _LIBCPP_INLINE_VISIBILITY path root_path() const {
Martin Storsjö98770152020-11-04 15:59:56 +02001352#if defined(_LIBCPP_WIN32API)
1353 return string_type(__root_path_raw());
1354#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001355 return root_name().append(string_type(__root_directory()));
Martin Storsjö98770152020-11-04 15:59:56 +02001356#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001357 }
1358 _LIBCPP_INLINE_VISIBILITY path relative_path() const {
1359 return string_type(__relative_path());
1360 }
1361 _LIBCPP_INLINE_VISIBILITY path parent_path() const {
1362 return string_type(__parent_path());
1363 }
1364 _LIBCPP_INLINE_VISIBILITY path filename() const {
1365 return string_type(__filename());
1366 }
1367 _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
1368 _LIBCPP_INLINE_VISIBILITY path extension() const {
1369 return string_type(__extension());
1370 }
1371
1372 // query
1373 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
1374 empty() const noexcept {
1375 return __pn_.empty();
1376 }
1377
1378 _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
1379 return !__root_name().empty();
1380 }
1381 _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
1382 return !__root_directory().empty();
1383 }
1384 _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
1385 return !__root_path_raw().empty();
1386 }
1387 _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
1388 return !__relative_path().empty();
1389 }
1390 _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
1391 return !__parent_path().empty();
1392 }
1393 _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
1394 return !__filename().empty();
1395 }
1396 _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
1397 _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
1398 return !__extension().empty();
1399 }
1400
1401 _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
Martin Storsjöef6b7422020-11-01 23:39:03 +02001402#if defined(_LIBCPP_WIN32API)
1403 __string_view __root_name_str = __root_name();
1404 __string_view __root_dir = __root_directory();
1405 if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
1406 // A drive letter with no root directory is relative, e.g. x:example.
1407 return !__root_dir.empty();
1408 }
1409 // If no root name, it's relative, e.g. \example is relative to the current drive
1410 if (__root_name_str.empty())
1411 return false;
1412 if (__root_name_str.size() < 3)
1413 return false;
1414 // A server root name, like \\server, is always absolute
1415 if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
1416 return false;
1417 if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
1418 return false;
1419 // Seems to be a server root name
1420 return true;
1421#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001422 return has_root_directory();
Martin Storsjöef6b7422020-11-01 23:39:03 +02001423#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001424 }
1425 _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
1426
1427 // relative paths
1428 path lexically_normal() const;
1429 path lexically_relative(const path& __base) const;
1430
1431 _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
1432 path __result = this->lexically_relative(__base);
1433 if (__result.native().empty())
1434 return *this;
1435 return __result;
1436 }
1437
1438 // iterators
1439 class _LIBCPP_TYPE_VIS iterator;
1440 typedef iterator const_iterator;
1441
1442 iterator begin() const;
1443 iterator end() const;
1444
Louis Dionne8d053eb2020-10-09 15:31:05 -04001445#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001446 template <class _CharT, class _Traits>
1447 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001448 typename enable_if<is_same<_CharT, value_type>::value &&
1449 is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001450 basic_ostream<_CharT, _Traits>&>::type
1451 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001452 __os << _VSTD::__quoted(__p.native());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001453 return __os;
1454 }
1455
1456 template <class _CharT, class _Traits>
1457 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001458 typename enable_if<!is_same<_CharT, value_type>::value ||
1459 !is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001460 basic_ostream<_CharT, _Traits>&>::type
1461 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001462 __os << _VSTD::__quoted(__p.string<_CharT, _Traits>());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001463 return __os;
1464 }
1465
1466 template <class _CharT, class _Traits>
1467 _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
1468 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
1469 basic_string<_CharT, _Traits> __tmp;
1470 __is >> __quoted(__tmp);
1471 __p = __tmp;
1472 return __is;
1473 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001474#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001475
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001476 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
1477 return __lhs.compare(__rhs) == 0;
1478 }
1479 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
1480 return __lhs.compare(__rhs) != 0;
1481 }
1482 friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
1483 return __lhs.compare(__rhs) < 0;
1484 }
1485 friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
1486 return __lhs.compare(__rhs) <= 0;
1487 }
1488 friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
1489 return __lhs.compare(__rhs) > 0;
1490 }
1491 friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
1492 return __lhs.compare(__rhs) >= 0;
1493 }
1494
1495 friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
1496 const path& __rhs) {
1497 path __result(__lhs);
1498 __result /= __rhs;
1499 return __result;
1500 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001501private:
1502 inline _LIBCPP_INLINE_VISIBILITY path&
1503 __assign_view(__string_view const& __s) noexcept {
1504 __pn_ = string_type(__s);
1505 return *this;
1506 }
1507 string_type __pn_;
1508};
1509
1510inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
1511 __lhs.swap(__rhs);
1512}
1513
1514_LIBCPP_FUNC_VIS
1515size_t hash_value(const path& __p) noexcept;
1516
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001517template <class _InputIt>
Martin Storsjöe3a71972020-10-26 13:18:46 +02001518_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001519 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1520 u8path(_InputIt __f, _InputIt __l) {
1521 static_assert(
Martin Storsjöe3a71972020-10-26 13:18:46 +02001522#ifndef _LIBCPP_NO_HAS_CHAR8_T
1523 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1524#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001525 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
Martin Storsjöe3a71972020-10-26 13:18:46 +02001526 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
Martin Storsjö929dff92020-12-15 09:15:37 +02001527 " or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001528#if defined(_LIBCPP_WIN32API)
1529 string __tmp(__f, __l);
1530 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1531 _VSTD::wstring __w;
1532 __w.reserve(__tmp.size());
1533 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1534 return path(__w);
1535#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001536 return path(__f, __l);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001537#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001538}
1539
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001540#if defined(_LIBCPP_WIN32API)
1541template <class _InputIt>
1542_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1543 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1544 u8path(_InputIt __f, _NullSentinel) {
1545 static_assert(
1546#ifndef _LIBCPP_NO_HAS_CHAR8_T
1547 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1548#endif
1549 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
1550 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
1551 " or 'char8_t'");
1552 string __tmp;
1553 const char __sentinel = char{};
1554 for (; *__f != __sentinel; ++__f)
1555 __tmp.push_back(*__f);
1556 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1557 _VSTD::wstring __w;
1558 __w.reserve(__tmp.size());
1559 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1560 return path(__w);
1561}
1562#endif /* _LIBCPP_WIN32API */
1563
Martin Storsjö367d7f02020-11-05 00:21:30 +02001564template <class _Source>
1565_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1566 typename enable_if<__is_pathable<_Source>::value, path>::type
1567 u8path(const _Source& __s) {
1568 static_assert(
1569#ifndef _LIBCPP_NO_HAS_CHAR8_T
1570 is_same<typename __is_pathable<_Source>::__char_type, char8_t>::value ||
1571#endif
1572 is_same<typename __is_pathable<_Source>::__char_type, char>::value,
1573 "u8path(Source const&) requires Source have a character type of type "
1574 "'char' or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001575#if defined(_LIBCPP_WIN32API)
1576 using _Traits = __is_pathable<_Source>;
Arthur O'Dwyer1ac9f092021-01-15 12:59:56 -05001577 return u8path(_VSTD::__unwrap_iter(_Traits::__range_begin(__s)), _VSTD::__unwrap_iter(_Traits::__range_end(__s)));
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001578#else
Martin Storsjö367d7f02020-11-05 00:21:30 +02001579 return path(__s);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001580#endif
Martin Storsjö367d7f02020-11-05 00:21:30 +02001581}
1582
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001583class _LIBCPP_TYPE_VIS path::iterator {
1584public:
1585 enum _ParserState : unsigned char {
1586 _Singular,
1587 _BeforeBegin,
1588 _InRootName,
1589 _InRootDir,
1590 _InFilenames,
1591 _InTrailingSep,
1592 _AtEnd
1593 };
1594
1595public:
1596 typedef bidirectional_iterator_tag iterator_category;
1597
1598 typedef path value_type;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001599 typedef ptrdiff_t difference_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001600 typedef const path* pointer;
1601 typedef const path& reference;
1602
1603 typedef void
1604 __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
1605
1606public:
1607 _LIBCPP_INLINE_VISIBILITY
1608 iterator()
1609 : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
1610 __state_(_Singular) {}
1611
1612 iterator(const iterator&) = default;
1613 ~iterator() = default;
1614
1615 iterator& operator=(const iterator&) = default;
1616
1617 _LIBCPP_INLINE_VISIBILITY
1618 reference operator*() const { return __stashed_elem_; }
1619
1620 _LIBCPP_INLINE_VISIBILITY
1621 pointer operator->() const { return &__stashed_elem_; }
1622
1623 _LIBCPP_INLINE_VISIBILITY
1624 iterator& operator++() {
1625 _LIBCPP_ASSERT(__state_ != _Singular,
1626 "attempting to increment a singular iterator");
1627 _LIBCPP_ASSERT(__state_ != _AtEnd,
1628 "attempting to increment the end iterator");
1629 return __increment();
1630 }
1631
1632 _LIBCPP_INLINE_VISIBILITY
1633 iterator operator++(int) {
1634 iterator __it(*this);
1635 this->operator++();
1636 return __it;
1637 }
1638
1639 _LIBCPP_INLINE_VISIBILITY
1640 iterator& operator--() {
1641 _LIBCPP_ASSERT(__state_ != _Singular,
1642 "attempting to decrement a singular iterator");
1643 _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
1644 "attempting to decrement the begin iterator");
1645 return __decrement();
1646 }
1647
1648 _LIBCPP_INLINE_VISIBILITY
1649 iterator operator--(int) {
1650 iterator __it(*this);
1651 this->operator--();
1652 return __it;
1653 }
1654
1655private:
1656 friend class path;
1657
1658 inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
1659 const iterator&);
1660
1661 iterator& __increment();
1662 iterator& __decrement();
1663
1664 path __stashed_elem_;
1665 const path* __path_ptr_;
1666 path::__string_view __entry_;
1667 _ParserState __state_;
1668};
1669
1670inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
1671 const path::iterator& __rhs) {
1672 return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
1673 __lhs.__entry_.data() == __rhs.__entry_.data();
1674}
1675
1676inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
1677 const path::iterator& __rhs) {
1678 return !(__lhs == __rhs);
1679}
1680
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001681// TODO(ldionne): We need to pop the pragma and push it again after
1682// filesystem_error to work around PR41078.
1683_LIBCPP_AVAILABILITY_FILESYSTEM_POP
1684
1685class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001686public:
1687 _LIBCPP_INLINE_VISIBILITY
1688 filesystem_error(const string& __what, error_code __ec)
1689 : system_error(__ec, __what),
1690 __storage_(make_shared<_Storage>(path(), path())) {
1691 __create_what(0);
1692 }
1693
1694 _LIBCPP_INLINE_VISIBILITY
1695 filesystem_error(const string& __what, const path& __p1, error_code __ec)
1696 : system_error(__ec, __what),
1697 __storage_(make_shared<_Storage>(__p1, path())) {
1698 __create_what(1);
1699 }
1700
1701 _LIBCPP_INLINE_VISIBILITY
1702 filesystem_error(const string& __what, const path& __p1, const path& __p2,
1703 error_code __ec)
1704 : system_error(__ec, __what),
1705 __storage_(make_shared<_Storage>(__p1, __p2)) {
1706 __create_what(2);
1707 }
1708
1709 _LIBCPP_INLINE_VISIBILITY
1710 const path& path1() const noexcept { return __storage_->__p1_; }
1711
1712 _LIBCPP_INLINE_VISIBILITY
1713 const path& path2() const noexcept { return __storage_->__p2_; }
1714
Dimitry Andric47269ce2020-03-13 19:36:26 +01001715 filesystem_error(const filesystem_error&) = default;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001716 ~filesystem_error() override; // key function
1717
1718 _LIBCPP_INLINE_VISIBILITY
1719 const char* what() const noexcept override {
1720 return __storage_->__what_.c_str();
1721 }
1722
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001723 void __create_what(int __num_paths);
1724
1725private:
Louis Dionne48ae8892019-03-19 17:47:53 +00001726 struct _LIBCPP_HIDDEN _Storage {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001727 _LIBCPP_INLINE_VISIBILITY
1728 _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
1729
1730 path __p1_;
1731 path __p2_;
1732 string __what_;
1733 };
1734 shared_ptr<_Storage> __storage_;
1735};
1736
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001737_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
1738
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001739template <class... _Args>
1740_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
1741#ifndef _LIBCPP_NO_EXCEPTIONS
Louis Dionne6251ef02019-02-05 15:46:52 +00001742void __throw_filesystem_error(_Args&&... __args) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001743 throw filesystem_error(_VSTD::forward<_Args>(__args)...);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001744}
1745#else
Louis Dionne6251ef02019-02-05 15:46:52 +00001746void __throw_filesystem_error(_Args&&...) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001747 _VSTD::abort();
1748}
1749#endif
1750
1751// operational functions
1752
1753_LIBCPP_FUNC_VIS
1754path __absolute(const path&, error_code* __ec = nullptr);
1755_LIBCPP_FUNC_VIS
1756path __canonical(const path&, error_code* __ec = nullptr);
1757_LIBCPP_FUNC_VIS
1758void __copy(const path& __from, const path& __to, copy_options __opt,
1759 error_code* __ec = nullptr);
1760_LIBCPP_FUNC_VIS
1761bool __copy_file(const path& __from, const path& __to, copy_options __opt,
1762 error_code* __ec = nullptr);
1763_LIBCPP_FUNC_VIS
1764void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
1765 error_code* __ec = nullptr);
1766_LIBCPP_FUNC_VIS
1767bool __create_directories(const path& p, error_code* ec = nullptr);
1768_LIBCPP_FUNC_VIS
1769bool __create_directory(const path& p, error_code* ec = nullptr);
1770_LIBCPP_FUNC_VIS
1771bool __create_directory(const path& p, const path& attributes,
1772 error_code* ec = nullptr);
1773_LIBCPP_FUNC_VIS
1774void __create_directory_symlink(const path& __to, const path& __new_symlink,
1775 error_code* __ec = nullptr);
1776_LIBCPP_FUNC_VIS
1777void __create_hard_link(const path& __to, const path& __new_hard_link,
1778 error_code* __ec = nullptr);
1779_LIBCPP_FUNC_VIS
1780void __create_symlink(const path& __to, const path& __new_symlink,
1781 error_code* __ec = nullptr);
1782_LIBCPP_FUNC_VIS
1783path __current_path(error_code* __ec = nullptr);
1784_LIBCPP_FUNC_VIS
1785void __current_path(const path&, error_code* __ec = nullptr);
1786_LIBCPP_FUNC_VIS
1787bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
1788_LIBCPP_FUNC_VIS
1789uintmax_t __file_size(const path&, error_code* __ec = nullptr);
1790_LIBCPP_FUNC_VIS
1791uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
1792_LIBCPP_FUNC_VIS
1793bool __fs_is_empty(const path& p, error_code* ec = nullptr);
1794_LIBCPP_FUNC_VIS
1795file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
1796_LIBCPP_FUNC_VIS
1797void __last_write_time(const path& p, file_time_type new_time,
1798 error_code* ec = nullptr);
1799_LIBCPP_FUNC_VIS
1800void __permissions(const path&, perms, perm_options, error_code* = nullptr);
1801_LIBCPP_FUNC_VIS
1802path __read_symlink(const path& p, error_code* ec = nullptr);
1803_LIBCPP_FUNC_VIS
1804bool __remove(const path& p, error_code* ec = nullptr);
1805_LIBCPP_FUNC_VIS
1806uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
1807_LIBCPP_FUNC_VIS
1808void __rename(const path& from, const path& to, error_code* ec = nullptr);
1809_LIBCPP_FUNC_VIS
1810void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
1811_LIBCPP_FUNC_VIS
1812space_info __space(const path&, error_code* __ec = nullptr);
1813_LIBCPP_FUNC_VIS
1814file_status __status(const path&, error_code* __ec = nullptr);
1815_LIBCPP_FUNC_VIS
1816file_status __symlink_status(const path&, error_code* __ec = nullptr);
1817_LIBCPP_FUNC_VIS
1818path __system_complete(const path&, error_code* __ec = nullptr);
1819_LIBCPP_FUNC_VIS
1820path __temp_directory_path(error_code* __ec = nullptr);
1821_LIBCPP_FUNC_VIS
1822path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
1823
1824inline _LIBCPP_INLINE_VISIBILITY path current_path() {
1825 return __current_path();
1826}
1827
1828inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
1829 return __current_path(&__ec);
1830}
1831
1832inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
1833 __current_path(__p);
1834}
1835
1836inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
1837 error_code& __ec) noexcept {
1838 __current_path(__p, &__ec);
1839}
1840
1841inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
1842 return __absolute(__p);
1843}
1844
1845inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
1846 error_code& __ec) {
1847 return __absolute(__p, &__ec);
1848}
1849
1850inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
1851 return __canonical(__p);
1852}
1853
1854inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
1855 error_code& __ec) {
1856 return __canonical(__p, &__ec);
1857}
1858
1859inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
1860 const path& __to) {
1861 __copy(__from, __to, copy_options::none);
1862}
1863
1864inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1865 error_code& __ec) {
1866 __copy(__from, __to, copy_options::none, &__ec);
1867}
1868
1869inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1870 copy_options __opt) {
1871 __copy(__from, __to, __opt);
1872}
1873
1874inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1875 copy_options __opt,
1876 error_code& __ec) {
1877 __copy(__from, __to, __opt, &__ec);
1878}
1879
1880inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1881 const path& __to) {
1882 return __copy_file(__from, __to, copy_options::none);
1883}
1884
1885inline _LIBCPP_INLINE_VISIBILITY bool
1886copy_file(const path& __from, const path& __to, error_code& __ec) {
1887 return __copy_file(__from, __to, copy_options::none, &__ec);
1888}
1889
1890inline _LIBCPP_INLINE_VISIBILITY bool
1891copy_file(const path& __from, const path& __to, copy_options __opt) {
1892 return __copy_file(__from, __to, __opt);
1893}
1894
1895inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1896 const path& __to,
1897 copy_options __opt,
1898 error_code& __ec) {
1899 return __copy_file(__from, __to, __opt, &__ec);
1900}
1901
1902inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
1903 const path& __new) {
1904 __copy_symlink(__existing, __new);
1905}
1906
1907inline _LIBCPP_INLINE_VISIBILITY void
1908copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
1909 __copy_symlink(__ext, __new, &__ec);
1910}
1911
1912inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
1913 return __create_directories(__p);
1914}
1915
1916inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
1917 error_code& __ec) {
1918 return __create_directories(__p, &__ec);
1919}
1920
1921inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
1922 return __create_directory(__p);
1923}
1924
1925inline _LIBCPP_INLINE_VISIBILITY bool
1926create_directory(const path& __p, error_code& __ec) noexcept {
1927 return __create_directory(__p, &__ec);
1928}
1929
1930inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
1931 const path& __attrs) {
1932 return __create_directory(__p, __attrs);
1933}
1934
1935inline _LIBCPP_INLINE_VISIBILITY bool
1936create_directory(const path& __p, const path& __attrs,
1937 error_code& __ec) noexcept {
1938 return __create_directory(__p, __attrs, &__ec);
1939}
1940
1941inline _LIBCPP_INLINE_VISIBILITY void
1942create_directory_symlink(const path& __to, const path& __new) {
1943 __create_directory_symlink(__to, __new);
1944}
1945
1946inline _LIBCPP_INLINE_VISIBILITY void
1947create_directory_symlink(const path& __to, const path& __new,
1948 error_code& __ec) noexcept {
1949 __create_directory_symlink(__to, __new, &__ec);
1950}
1951
1952inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
1953 const path& __new) {
1954 __create_hard_link(__to, __new);
1955}
1956
1957inline _LIBCPP_INLINE_VISIBILITY void
1958create_hard_link(const path& __to, const path& __new,
1959 error_code& __ec) noexcept {
1960 __create_hard_link(__to, __new, &__ec);
1961}
1962
1963inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
1964 const path& __new) {
1965 __create_symlink(__to, __new);
1966}
1967
1968inline _LIBCPP_INLINE_VISIBILITY void
1969create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
1970 return __create_symlink(__to, __new, &__ec);
1971}
1972
1973inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
1974 return __s.type() != file_type::none;
1975}
1976
1977inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
1978 return status_known(__s) && __s.type() != file_type::not_found;
1979}
1980
1981inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
1982 return exists(__status(__p));
1983}
1984
1985inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
1986 error_code& __ec) noexcept {
1987 auto __s = __status(__p, &__ec);
1988 if (status_known(__s))
1989 __ec.clear();
1990 return exists(__s);
1991}
1992
1993inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
1994 const path& __p2) {
1995 return __equivalent(__p1, __p2);
1996}
1997
1998inline _LIBCPP_INLINE_VISIBILITY bool
1999equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
2000 return __equivalent(__p1, __p2, &__ec);
2001}
2002
2003inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
2004 return __file_size(__p);
2005}
2006
2007inline _LIBCPP_INLINE_VISIBILITY uintmax_t
2008file_size(const path& __p, error_code& __ec) noexcept {
2009 return __file_size(__p, &__ec);
2010}
2011
2012inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
2013 return __hard_link_count(__p);
2014}
2015
2016inline _LIBCPP_INLINE_VISIBILITY uintmax_t
2017hard_link_count(const path& __p, error_code& __ec) noexcept {
2018 return __hard_link_count(__p, &__ec);
2019}
2020
2021inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
2022 return __s.type() == file_type::block;
2023}
2024
2025inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
2026 return is_block_file(__status(__p));
2027}
2028
2029inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
2030 error_code& __ec) noexcept {
2031 return is_block_file(__status(__p, &__ec));
2032}
2033
2034inline _LIBCPP_INLINE_VISIBILITY bool
2035is_character_file(file_status __s) noexcept {
2036 return __s.type() == file_type::character;
2037}
2038
2039inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
2040 return is_character_file(__status(__p));
2041}
2042
2043inline _LIBCPP_INLINE_VISIBILITY bool
2044is_character_file(const path& __p, error_code& __ec) noexcept {
2045 return is_character_file(__status(__p, &__ec));
2046}
2047
2048inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
2049 return __s.type() == file_type::directory;
2050}
2051
2052inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
2053 return is_directory(__status(__p));
2054}
2055
2056inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
2057 error_code& __ec) noexcept {
2058 return is_directory(__status(__p, &__ec));
2059}
2060
2061inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
2062 return __fs_is_empty(__p);
2063}
2064
2065inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
2066 error_code& __ec) {
2067 return __fs_is_empty(__p, &__ec);
2068}
2069
2070inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
2071 return __s.type() == file_type::fifo;
2072}
2073inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
2074 return is_fifo(__status(__p));
2075}
2076
2077inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
2078 error_code& __ec) noexcept {
2079 return is_fifo(__status(__p, &__ec));
2080}
2081
2082inline _LIBCPP_INLINE_VISIBILITY bool
2083is_regular_file(file_status __s) noexcept {
2084 return __s.type() == file_type::regular;
2085}
2086
2087inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
2088 return is_regular_file(__status(__p));
2089}
2090
2091inline _LIBCPP_INLINE_VISIBILITY bool
2092is_regular_file(const path& __p, error_code& __ec) noexcept {
2093 return is_regular_file(__status(__p, &__ec));
2094}
2095
2096inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
2097 return __s.type() == file_type::socket;
2098}
2099
2100inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
2101 return is_socket(__status(__p));
2102}
2103
2104inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
2105 error_code& __ec) noexcept {
2106 return is_socket(__status(__p, &__ec));
2107}
2108
2109inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
2110 return __s.type() == file_type::symlink;
2111}
2112
2113inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
2114 return is_symlink(__symlink_status(__p));
2115}
2116
2117inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
2118 error_code& __ec) noexcept {
2119 return is_symlink(__symlink_status(__p, &__ec));
2120}
2121
2122inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
2123 return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
2124 !is_symlink(__s);
2125}
2126
2127inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
2128 return is_other(__status(__p));
2129}
2130
2131inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
2132 error_code& __ec) noexcept {
2133 return is_other(__status(__p, &__ec));
2134}
2135
2136inline _LIBCPP_INLINE_VISIBILITY file_time_type
2137last_write_time(const path& __p) {
2138 return __last_write_time(__p);
2139}
2140
2141inline _LIBCPP_INLINE_VISIBILITY file_time_type
2142last_write_time(const path& __p, error_code& __ec) noexcept {
2143 return __last_write_time(__p, &__ec);
2144}
2145
2146inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
2147 file_time_type __t) {
2148 __last_write_time(__p, __t);
2149}
2150
2151inline _LIBCPP_INLINE_VISIBILITY void
2152last_write_time(const path& __p, file_time_type __t,
2153 error_code& __ec) noexcept {
2154 __last_write_time(__p, __t, &__ec);
2155}
2156
2157inline _LIBCPP_INLINE_VISIBILITY void
2158permissions(const path& __p, perms __prms,
2159 perm_options __opts = perm_options::replace) {
2160 __permissions(__p, __prms, __opts);
2161}
2162
2163inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2164 error_code& __ec) noexcept {
2165 __permissions(__p, __prms, perm_options::replace, &__ec);
2166}
2167
2168inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2169 perm_options __opts,
2170 error_code& __ec) {
2171 __permissions(__p, __prms, __opts, &__ec);
2172}
2173
2174inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2175 const path& __base,
2176 error_code& __ec) {
2177 path __tmp = __weakly_canonical(__p, &__ec);
2178 if (__ec)
2179 return {};
2180 path __tmp_base = __weakly_canonical(__base, &__ec);
2181 if (__ec)
2182 return {};
2183 return __tmp.lexically_proximate(__tmp_base);
2184}
2185
2186inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2187 error_code& __ec) {
2188 return proximate(__p, current_path(), __ec);
2189}
2190
2191inline _LIBCPP_INLINE_VISIBILITY path
2192proximate(const path& __p, const path& __base = current_path()) {
2193 return __weakly_canonical(__p).lexically_proximate(
2194 __weakly_canonical(__base));
2195}
2196
2197inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
2198 return __read_symlink(__p);
2199}
2200
2201inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
2202 error_code& __ec) {
2203 return __read_symlink(__p, &__ec);
2204}
2205
2206inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2207 const path& __base,
2208 error_code& __ec) {
2209 path __tmp = __weakly_canonical(__p, &__ec);
2210 if (__ec)
2211 return path();
2212 path __tmpbase = __weakly_canonical(__base, &__ec);
2213 if (__ec)
2214 return path();
2215 return __tmp.lexically_relative(__tmpbase);
2216}
2217
2218inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2219 error_code& __ec) {
2220 return relative(__p, current_path(), __ec);
2221}
2222
2223inline _LIBCPP_INLINE_VISIBILITY path
2224relative(const path& __p, const path& __base = current_path()) {
2225 return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
2226}
2227
2228inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
2229 return __remove(__p);
2230}
2231
2232inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
2233 error_code& __ec) noexcept {
2234 return __remove(__p, &__ec);
2235}
2236
2237inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
2238 return __remove_all(__p);
2239}
2240
2241inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
2242 error_code& __ec) {
2243 return __remove_all(__p, &__ec);
2244}
2245
2246inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
2247 const path& __to) {
2248 return __rename(__from, __to);
2249}
2250
2251inline _LIBCPP_INLINE_VISIBILITY void
2252rename(const path& __from, const path& __to, error_code& __ec) noexcept {
2253 return __rename(__from, __to, &__ec);
2254}
2255
2256inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
2257 uintmax_t __ns) {
2258 return __resize_file(__p, __ns);
2259}
2260
2261inline _LIBCPP_INLINE_VISIBILITY void
2262resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
2263 return __resize_file(__p, __ns, &__ec);
2264}
2265
2266inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
2267 return __space(__p);
2268}
2269
2270inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
2271 error_code& __ec) noexcept {
2272 return __space(__p, &__ec);
2273}
2274
2275inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
2276 return __status(__p);
2277}
2278
2279inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
2280 error_code& __ec) noexcept {
2281 return __status(__p, &__ec);
2282}
2283
2284inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
2285 return __symlink_status(__p);
2286}
2287
2288inline _LIBCPP_INLINE_VISIBILITY file_status
2289symlink_status(const path& __p, error_code& __ec) noexcept {
2290 return __symlink_status(__p, &__ec);
2291}
2292
2293inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
2294 return __temp_directory_path();
2295}
2296
2297inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
2298 return __temp_directory_path(&__ec);
2299}
2300
2301inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
2302 return __weakly_canonical(__p);
2303}
2304
2305inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
2306 error_code& __ec) {
2307 return __weakly_canonical(__p, &__ec);
2308}
2309
2310class directory_iterator;
2311class recursive_directory_iterator;
Louis Dionne48ae8892019-03-19 17:47:53 +00002312class _LIBCPP_HIDDEN __dir_stream;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002313
2314class directory_entry {
2315 typedef _VSTD_FS::path _Path;
2316
2317public:
2318 // constructors and destructors
2319 directory_entry() noexcept = default;
2320 directory_entry(directory_entry const&) = default;
2321 directory_entry(directory_entry&&) noexcept = default;
2322
2323 _LIBCPP_INLINE_VISIBILITY
2324 explicit directory_entry(_Path const& __p) : __p_(__p) {
2325 error_code __ec;
2326 __refresh(&__ec);
2327 }
2328
2329 _LIBCPP_INLINE_VISIBILITY
2330 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
2331 __refresh(&__ec);
2332 }
2333
2334 ~directory_entry() {}
2335
2336 directory_entry& operator=(directory_entry const&) = default;
2337 directory_entry& operator=(directory_entry&&) noexcept = default;
2338
2339 _LIBCPP_INLINE_VISIBILITY
2340 void assign(_Path const& __p) {
2341 __p_ = __p;
2342 error_code __ec;
2343 __refresh(&__ec);
2344 }
2345
2346 _LIBCPP_INLINE_VISIBILITY
2347 void assign(_Path const& __p, error_code& __ec) {
2348 __p_ = __p;
2349 __refresh(&__ec);
2350 }
2351
2352 _LIBCPP_INLINE_VISIBILITY
2353 void replace_filename(_Path const& __p) {
2354 __p_.replace_filename(__p);
2355 error_code __ec;
2356 __refresh(&__ec);
2357 }
2358
2359 _LIBCPP_INLINE_VISIBILITY
2360 void replace_filename(_Path const& __p, error_code& __ec) {
2361 __p_ = __p_.parent_path() / __p;
2362 __refresh(&__ec);
2363 }
2364
2365 _LIBCPP_INLINE_VISIBILITY
2366 void refresh() { __refresh(); }
2367
2368 _LIBCPP_INLINE_VISIBILITY
2369 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
2370
2371 _LIBCPP_INLINE_VISIBILITY
2372 _Path const& path() const noexcept { return __p_; }
2373
2374 _LIBCPP_INLINE_VISIBILITY
2375 operator const _Path&() const noexcept { return __p_; }
2376
2377 _LIBCPP_INLINE_VISIBILITY
2378 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
2379
2380 _LIBCPP_INLINE_VISIBILITY
2381 bool exists(error_code& __ec) const noexcept {
2382 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
2383 }
2384
2385 _LIBCPP_INLINE_VISIBILITY
2386 bool is_block_file() const { return __get_ft() == file_type::block; }
2387
2388 _LIBCPP_INLINE_VISIBILITY
2389 bool is_block_file(error_code& __ec) const noexcept {
2390 return __get_ft(&__ec) == file_type::block;
2391 }
2392
2393 _LIBCPP_INLINE_VISIBILITY
2394 bool is_character_file() const { return __get_ft() == file_type::character; }
2395
2396 _LIBCPP_INLINE_VISIBILITY
2397 bool is_character_file(error_code& __ec) const noexcept {
2398 return __get_ft(&__ec) == file_type::character;
2399 }
2400
2401 _LIBCPP_INLINE_VISIBILITY
2402 bool is_directory() const { return __get_ft() == file_type::directory; }
2403
2404 _LIBCPP_INLINE_VISIBILITY
2405 bool is_directory(error_code& __ec) const noexcept {
2406 return __get_ft(&__ec) == file_type::directory;
2407 }
2408
2409 _LIBCPP_INLINE_VISIBILITY
2410 bool is_fifo() const { return __get_ft() == file_type::fifo; }
2411
2412 _LIBCPP_INLINE_VISIBILITY
2413 bool is_fifo(error_code& __ec) const noexcept {
2414 return __get_ft(&__ec) == file_type::fifo;
2415 }
2416
2417 _LIBCPP_INLINE_VISIBILITY
2418 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
2419
2420 _LIBCPP_INLINE_VISIBILITY
2421 bool is_other(error_code& __ec) const noexcept {
2422 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
2423 }
2424
2425 _LIBCPP_INLINE_VISIBILITY
2426 bool is_regular_file() const { return __get_ft() == file_type::regular; }
2427
2428 _LIBCPP_INLINE_VISIBILITY
2429 bool is_regular_file(error_code& __ec) const noexcept {
2430 return __get_ft(&__ec) == file_type::regular;
2431 }
2432
2433 _LIBCPP_INLINE_VISIBILITY
2434 bool is_socket() const { return __get_ft() == file_type::socket; }
2435
2436 _LIBCPP_INLINE_VISIBILITY
2437 bool is_socket(error_code& __ec) const noexcept {
2438 return __get_ft(&__ec) == file_type::socket;
2439 }
2440
2441 _LIBCPP_INLINE_VISIBILITY
2442 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
2443
2444 _LIBCPP_INLINE_VISIBILITY
2445 bool is_symlink(error_code& __ec) const noexcept {
2446 return __get_sym_ft(&__ec) == file_type::symlink;
2447 }
2448 _LIBCPP_INLINE_VISIBILITY
2449 uintmax_t file_size() const { return __get_size(); }
2450
2451 _LIBCPP_INLINE_VISIBILITY
2452 uintmax_t file_size(error_code& __ec) const noexcept {
2453 return __get_size(&__ec);
2454 }
2455
2456 _LIBCPP_INLINE_VISIBILITY
2457 uintmax_t hard_link_count() const { return __get_nlink(); }
2458
2459 _LIBCPP_INLINE_VISIBILITY
2460 uintmax_t hard_link_count(error_code& __ec) const noexcept {
2461 return __get_nlink(&__ec);
2462 }
2463
2464 _LIBCPP_INLINE_VISIBILITY
2465 file_time_type last_write_time() const { return __get_write_time(); }
2466
2467 _LIBCPP_INLINE_VISIBILITY
2468 file_time_type last_write_time(error_code& __ec) const noexcept {
2469 return __get_write_time(&__ec);
2470 }
2471
2472 _LIBCPP_INLINE_VISIBILITY
2473 file_status status() const { return __get_status(); }
2474
2475 _LIBCPP_INLINE_VISIBILITY
2476 file_status status(error_code& __ec) const noexcept {
2477 return __get_status(&__ec);
2478 }
2479
2480 _LIBCPP_INLINE_VISIBILITY
2481 file_status symlink_status() const { return __get_symlink_status(); }
2482
2483 _LIBCPP_INLINE_VISIBILITY
2484 file_status symlink_status(error_code& __ec) const noexcept {
2485 return __get_symlink_status(&__ec);
2486 }
2487
2488 _LIBCPP_INLINE_VISIBILITY
2489 bool operator<(directory_entry const& __rhs) const noexcept {
2490 return __p_ < __rhs.__p_;
2491 }
2492
2493 _LIBCPP_INLINE_VISIBILITY
2494 bool operator==(directory_entry const& __rhs) const noexcept {
2495 return __p_ == __rhs.__p_;
2496 }
2497
2498 _LIBCPP_INLINE_VISIBILITY
2499 bool operator!=(directory_entry const& __rhs) const noexcept {
2500 return __p_ != __rhs.__p_;
2501 }
2502
2503 _LIBCPP_INLINE_VISIBILITY
2504 bool operator<=(directory_entry const& __rhs) const noexcept {
2505 return __p_ <= __rhs.__p_;
2506 }
2507
2508 _LIBCPP_INLINE_VISIBILITY
2509 bool operator>(directory_entry const& __rhs) const noexcept {
2510 return __p_ > __rhs.__p_;
2511 }
2512
2513 _LIBCPP_INLINE_VISIBILITY
2514 bool operator>=(directory_entry const& __rhs) const noexcept {
2515 return __p_ >= __rhs.__p_;
2516 }
2517
2518private:
2519 friend class directory_iterator;
2520 friend class recursive_directory_iterator;
2521 friend class __dir_stream;
2522
2523 enum _CacheType : unsigned char {
2524 _Empty,
2525 _IterSymlink,
2526 _IterNonSymlink,
2527 _RefreshSymlink,
2528 _RefreshSymlinkUnresolved,
2529 _RefreshNonSymlink
2530 };
2531
2532 struct __cached_data {
2533 uintmax_t __size_;
2534 uintmax_t __nlink_;
2535 file_time_type __write_time_;
2536 perms __sym_perms_;
2537 perms __non_sym_perms_;
2538 file_type __type_;
2539 _CacheType __cache_type_;
2540
2541 _LIBCPP_INLINE_VISIBILITY
2542 __cached_data() noexcept { __reset(); }
2543
2544 _LIBCPP_INLINE_VISIBILITY
2545 void __reset() {
2546 __cache_type_ = _Empty;
2547 __type_ = file_type::none;
2548 __sym_perms_ = __non_sym_perms_ = perms::unknown;
2549 __size_ = __nlink_ = uintmax_t(-1);
2550 __write_time_ = file_time_type::min();
2551 }
2552 };
2553
2554 _LIBCPP_INLINE_VISIBILITY
2555 static __cached_data __create_iter_result(file_type __ft) {
2556 __cached_data __data;
2557 __data.__type_ = __ft;
2558 __data.__cache_type_ = [&]() {
2559 switch (__ft) {
2560 case file_type::none:
2561 return _Empty;
2562 case file_type::symlink:
2563 return _IterSymlink;
2564 default:
2565 return _IterNonSymlink;
2566 }
2567 }();
2568 return __data;
2569 }
2570
2571 _LIBCPP_INLINE_VISIBILITY
2572 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002573 __p_ = _VSTD::move(__p);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002574 __data_ = __dt;
2575 }
2576
2577 _LIBCPP_FUNC_VIS
2578 error_code __do_refresh() noexcept;
2579
2580 _LIBCPP_INLINE_VISIBILITY
2581 static bool __is_dne_error(error_code const& __ec) {
2582 if (!__ec)
2583 return true;
2584 switch (static_cast<errc>(__ec.value())) {
2585 case errc::no_such_file_or_directory:
2586 case errc::not_a_directory:
2587 return true;
2588 default:
2589 return false;
2590 }
2591 }
2592
2593 _LIBCPP_INLINE_VISIBILITY
2594 void __handle_error(const char* __msg, error_code* __dest_ec,
2595 error_code const& __ec, bool __allow_dne = false) const {
2596 if (__dest_ec) {
2597 *__dest_ec = __ec;
2598 return;
2599 }
2600 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
2601 __throw_filesystem_error(__msg, __p_, __ec);
2602 }
2603
2604 _LIBCPP_INLINE_VISIBILITY
2605 void __refresh(error_code* __ec = nullptr) {
2606 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
2607 /*allow_dne*/ true);
2608 }
2609
2610 _LIBCPP_INLINE_VISIBILITY
2611 file_type __get_sym_ft(error_code* __ec = nullptr) const {
2612 switch (__data_.__cache_type_) {
2613 case _Empty:
2614 return __symlink_status(__p_, __ec).type();
2615 case _IterSymlink:
2616 case _RefreshSymlink:
2617 case _RefreshSymlinkUnresolved:
2618 if (__ec)
2619 __ec->clear();
2620 return file_type::symlink;
2621 case _IterNonSymlink:
2622 case _RefreshNonSymlink:
2623 file_status __st(__data_.__type_);
2624 if (__ec && !_VSTD_FS::exists(__st))
2625 *__ec = make_error_code(errc::no_such_file_or_directory);
2626 else if (__ec)
2627 __ec->clear();
2628 return __data_.__type_;
2629 }
2630 _LIBCPP_UNREACHABLE();
2631 }
2632
2633 _LIBCPP_INLINE_VISIBILITY
2634 file_type __get_ft(error_code* __ec = nullptr) const {
2635 switch (__data_.__cache_type_) {
2636 case _Empty:
2637 case _IterSymlink:
2638 case _RefreshSymlinkUnresolved:
2639 return __status(__p_, __ec).type();
2640 case _IterNonSymlink:
2641 case _RefreshNonSymlink:
2642 case _RefreshSymlink: {
2643 file_status __st(__data_.__type_);
2644 if (__ec && !_VSTD_FS::exists(__st))
2645 *__ec = make_error_code(errc::no_such_file_or_directory);
2646 else if (__ec)
2647 __ec->clear();
2648 return __data_.__type_;
2649 }
2650 }
2651 _LIBCPP_UNREACHABLE();
2652 }
2653
2654 _LIBCPP_INLINE_VISIBILITY
2655 file_status __get_status(error_code* __ec = nullptr) const {
2656 switch (__data_.__cache_type_) {
2657 case _Empty:
2658 case _IterNonSymlink:
2659 case _IterSymlink:
2660 case _RefreshSymlinkUnresolved:
2661 return __status(__p_, __ec);
2662 case _RefreshNonSymlink:
2663 case _RefreshSymlink:
2664 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
2665 }
2666 _LIBCPP_UNREACHABLE();
2667 }
2668
2669 _LIBCPP_INLINE_VISIBILITY
2670 file_status __get_symlink_status(error_code* __ec = nullptr) const {
2671 switch (__data_.__cache_type_) {
2672 case _Empty:
2673 case _IterNonSymlink:
2674 case _IterSymlink:
2675 return __symlink_status(__p_, __ec);
2676 case _RefreshNonSymlink:
2677 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
2678 case _RefreshSymlink:
2679 case _RefreshSymlinkUnresolved:
2680 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
2681 }
2682 _LIBCPP_UNREACHABLE();
2683 }
2684
2685 _LIBCPP_INLINE_VISIBILITY
2686 uintmax_t __get_size(error_code* __ec = nullptr) const {
2687 switch (__data_.__cache_type_) {
2688 case _Empty:
2689 case _IterNonSymlink:
2690 case _IterSymlink:
2691 case _RefreshSymlinkUnresolved:
2692 return _VSTD_FS::__file_size(__p_, __ec);
2693 case _RefreshSymlink:
2694 case _RefreshNonSymlink: {
2695 error_code __m_ec;
2696 file_status __st(__get_ft(&__m_ec));
2697 __handle_error("in directory_entry::file_size", __ec, __m_ec);
2698 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
2699 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
2700 : errc::not_supported;
2701 __handle_error("in directory_entry::file_size", __ec,
2702 make_error_code(__err_kind));
2703 }
2704 return __data_.__size_;
2705 }
2706 }
2707 _LIBCPP_UNREACHABLE();
2708 }
2709
2710 _LIBCPP_INLINE_VISIBILITY
2711 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
2712 switch (__data_.__cache_type_) {
2713 case _Empty:
2714 case _IterNonSymlink:
2715 case _IterSymlink:
2716 case _RefreshSymlinkUnresolved:
2717 return _VSTD_FS::__hard_link_count(__p_, __ec);
2718 case _RefreshSymlink:
2719 case _RefreshNonSymlink: {
2720 error_code __m_ec;
2721 (void)__get_ft(&__m_ec);
2722 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
2723 return __data_.__nlink_;
2724 }
2725 }
2726 _LIBCPP_UNREACHABLE();
2727 }
2728
2729 _LIBCPP_INLINE_VISIBILITY
2730 file_time_type __get_write_time(error_code* __ec = nullptr) const {
2731 switch (__data_.__cache_type_) {
2732 case _Empty:
2733 case _IterNonSymlink:
2734 case _IterSymlink:
2735 case _RefreshSymlinkUnresolved:
2736 return _VSTD_FS::__last_write_time(__p_, __ec);
2737 case _RefreshSymlink:
2738 case _RefreshNonSymlink: {
2739 error_code __m_ec;
2740 file_status __st(__get_ft(&__m_ec));
2741 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
2742 if (_VSTD_FS::exists(__st) &&
2743 __data_.__write_time_ == file_time_type::min())
2744 __handle_error("in directory_entry::last_write_time", __ec,
2745 make_error_code(errc::value_too_large));
2746 return __data_.__write_time_;
2747 }
2748 }
2749 _LIBCPP_UNREACHABLE();
2750 }
2751
2752private:
2753 _Path __p_;
2754 __cached_data __data_;
2755};
2756
2757class __dir_element_proxy {
2758public:
2759 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
2760 return _VSTD::move(__elem_);
2761 }
2762
2763private:
2764 friend class directory_iterator;
2765 friend class recursive_directory_iterator;
2766 explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
2767 __dir_element_proxy(__dir_element_proxy&& __o)
2768 : __elem_(_VSTD::move(__o.__elem_)) {}
2769 directory_entry __elem_;
2770};
2771
2772class directory_iterator {
2773public:
2774 typedef directory_entry value_type;
2775 typedef ptrdiff_t difference_type;
2776 typedef value_type const* pointer;
2777 typedef value_type const& reference;
2778 typedef input_iterator_tag iterator_category;
2779
2780public:
2781 //ctor & dtor
2782 directory_iterator() noexcept {}
2783
2784 explicit directory_iterator(const path& __p)
2785 : directory_iterator(__p, nullptr) {}
2786
2787 directory_iterator(const path& __p, directory_options __opts)
2788 : directory_iterator(__p, nullptr, __opts) {}
2789
2790 directory_iterator(const path& __p, error_code& __ec)
2791 : directory_iterator(__p, &__ec) {}
2792
2793 directory_iterator(const path& __p, directory_options __opts,
2794 error_code& __ec)
2795 : directory_iterator(__p, &__ec, __opts) {}
2796
2797 directory_iterator(const directory_iterator&) = default;
2798 directory_iterator(directory_iterator&&) = default;
2799 directory_iterator& operator=(const directory_iterator&) = default;
2800
2801 directory_iterator& operator=(directory_iterator&& __o) noexcept {
2802 // non-default implementation provided to support self-move assign.
2803 if (this != &__o) {
2804 __imp_ = _VSTD::move(__o.__imp_);
2805 }
2806 return *this;
2807 }
2808
2809 ~directory_iterator() = default;
2810
2811 const directory_entry& operator*() const {
2812 _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
2813 return __dereference();
2814 }
2815
2816 const directory_entry* operator->() const { return &**this; }
2817
2818 directory_iterator& operator++() { return __increment(); }
2819
2820 __dir_element_proxy operator++(int) {
2821 __dir_element_proxy __p(**this);
2822 __increment();
2823 return __p;
2824 }
2825
2826 directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
2827
2828private:
2829 inline _LIBCPP_INLINE_VISIBILITY friend bool
2830 operator==(const directory_iterator& __lhs,
2831 const directory_iterator& __rhs) noexcept;
2832
2833 // construct the dir_stream
2834 _LIBCPP_FUNC_VIS
2835 directory_iterator(const path&, error_code*,
2836 directory_options = directory_options::none);
2837
2838 _LIBCPP_FUNC_VIS
2839 directory_iterator& __increment(error_code* __ec = nullptr);
2840
2841 _LIBCPP_FUNC_VIS
2842 const directory_entry& __dereference() const;
2843
2844private:
2845 shared_ptr<__dir_stream> __imp_;
2846};
2847
2848inline _LIBCPP_INLINE_VISIBILITY bool
2849operator==(const directory_iterator& __lhs,
2850 const directory_iterator& __rhs) noexcept {
2851 return __lhs.__imp_ == __rhs.__imp_;
2852}
2853
2854inline _LIBCPP_INLINE_VISIBILITY bool
2855operator!=(const directory_iterator& __lhs,
2856 const directory_iterator& __rhs) noexcept {
2857 return !(__lhs == __rhs);
2858}
2859
2860// enable directory_iterator range-based for statements
2861inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2862begin(directory_iterator __iter) noexcept {
2863 return __iter;
2864}
2865
2866inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2867end(const directory_iterator&) noexcept {
2868 return directory_iterator();
2869}
2870
2871class recursive_directory_iterator {
2872public:
2873 using value_type = directory_entry;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002874 using difference_type = ptrdiff_t;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002875 using pointer = directory_entry const*;
2876 using reference = directory_entry const&;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002877 using iterator_category = input_iterator_tag;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002878
2879public:
2880 // constructors and destructor
2881 _LIBCPP_INLINE_VISIBILITY
2882 recursive_directory_iterator() noexcept : __rec_(false) {}
2883
2884 _LIBCPP_INLINE_VISIBILITY
2885 explicit recursive_directory_iterator(
2886 const path& __p, directory_options __xoptions = directory_options::none)
2887 : recursive_directory_iterator(__p, __xoptions, nullptr) {}
2888
2889 _LIBCPP_INLINE_VISIBILITY
2890 recursive_directory_iterator(const path& __p, directory_options __xoptions,
2891 error_code& __ec)
2892 : recursive_directory_iterator(__p, __xoptions, &__ec) {}
2893
2894 _LIBCPP_INLINE_VISIBILITY
2895 recursive_directory_iterator(const path& __p, error_code& __ec)
2896 : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
2897
2898 recursive_directory_iterator(const recursive_directory_iterator&) = default;
2899 recursive_directory_iterator(recursive_directory_iterator&&) = default;
2900
2901 recursive_directory_iterator&
2902 operator=(const recursive_directory_iterator&) = default;
2903
2904 _LIBCPP_INLINE_VISIBILITY
2905 recursive_directory_iterator&
2906 operator=(recursive_directory_iterator&& __o) noexcept {
2907 // non-default implementation provided to support self-move assign.
2908 if (this != &__o) {
2909 __imp_ = _VSTD::move(__o.__imp_);
2910 __rec_ = __o.__rec_;
2911 }
2912 return *this;
2913 }
2914
2915 ~recursive_directory_iterator() = default;
2916
2917 _LIBCPP_INLINE_VISIBILITY
2918 const directory_entry& operator*() const { return __dereference(); }
2919
2920 _LIBCPP_INLINE_VISIBILITY
2921 const directory_entry* operator->() const { return &__dereference(); }
2922
2923 recursive_directory_iterator& operator++() { return __increment(); }
2924
2925 _LIBCPP_INLINE_VISIBILITY
2926 __dir_element_proxy operator++(int) {
2927 __dir_element_proxy __p(**this);
2928 __increment();
2929 return __p;
2930 }
2931
2932 _LIBCPP_INLINE_VISIBILITY
2933 recursive_directory_iterator& increment(error_code& __ec) {
2934 return __increment(&__ec);
2935 }
2936
2937 _LIBCPP_FUNC_VIS directory_options options() const;
2938 _LIBCPP_FUNC_VIS int depth() const;
2939
2940 _LIBCPP_INLINE_VISIBILITY
2941 void pop() { __pop(); }
2942
2943 _LIBCPP_INLINE_VISIBILITY
2944 void pop(error_code& __ec) { __pop(&__ec); }
2945
2946 _LIBCPP_INLINE_VISIBILITY
2947 bool recursion_pending() const { return __rec_; }
2948
2949 _LIBCPP_INLINE_VISIBILITY
2950 void disable_recursion_pending() { __rec_ = false; }
2951
2952private:
Louis Dionne0ba10dc2019-08-13 15:02:53 +00002953 _LIBCPP_FUNC_VIS
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002954 recursive_directory_iterator(const path& __p, directory_options __opt,
2955 error_code* __ec);
2956
2957 _LIBCPP_FUNC_VIS
2958 const directory_entry& __dereference() const;
2959
2960 _LIBCPP_FUNC_VIS
2961 bool __try_recursion(error_code* __ec);
2962
2963 _LIBCPP_FUNC_VIS
2964 void __advance(error_code* __ec = nullptr);
2965
2966 _LIBCPP_FUNC_VIS
2967 recursive_directory_iterator& __increment(error_code* __ec = nullptr);
2968
2969 _LIBCPP_FUNC_VIS
2970 void __pop(error_code* __ec = nullptr);
2971
2972 inline _LIBCPP_INLINE_VISIBILITY friend bool
2973 operator==(const recursive_directory_iterator&,
2974 const recursive_directory_iterator&) noexcept;
2975
Louis Dionne48ae8892019-03-19 17:47:53 +00002976 struct _LIBCPP_HIDDEN __shared_imp;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002977 shared_ptr<__shared_imp> __imp_;
2978 bool __rec_;
2979}; // class recursive_directory_iterator
2980
2981inline _LIBCPP_INLINE_VISIBILITY bool
2982operator==(const recursive_directory_iterator& __lhs,
2983 const recursive_directory_iterator& __rhs) noexcept {
2984 return __lhs.__imp_ == __rhs.__imp_;
2985}
2986
2987_LIBCPP_INLINE_VISIBILITY
2988inline bool operator!=(const recursive_directory_iterator& __lhs,
2989 const recursive_directory_iterator& __rhs) noexcept {
2990 return !(__lhs == __rhs);
2991}
2992// enable recursive_directory_iterator range-based for statements
2993inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2994begin(recursive_directory_iterator __iter) noexcept {
2995 return __iter;
2996}
2997
2998inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2999end(const recursive_directory_iterator&) noexcept {
3000 return recursive_directory_iterator();
3001}
3002
Louis Dionnef6bf76a2019-03-20 21:18:14 +00003003_LIBCPP_AVAILABILITY_FILESYSTEM_POP
3004
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003005_LIBCPP_END_NAMESPACE_FILESYSTEM
3006
3007#endif // !_LIBCPP_CXX03_LANG
3008
3009_LIBCPP_POP_MACROS
3010
3011#endif // _LIBCPP_FILESYSTEM