blob: c688ab765b13f80d9f8073feb739671ec9a76573 [file] [log] [blame]
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001// -*- C++ -*-
Louis Dionne9bd93882021-11-17 16:25:01 -05002//===----------------------------------------------------------------------===//
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003//
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
Joe Loser9d1c0d42021-10-14 11:53:43 -040014 namespace std::filesystem {
Eric Fiselier02cea5e2018-07-27 03:07:09 +000015
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;
Joe Loser9d1c0d42021-10-14 11:53:43 -040051 directory_iterator end(directory_iterator) noexcept;
Eric Fiselier02cea5e2018-07-27 03:07:09 +000052
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;
Joe Loser9d1c0d42021-10-14 11:53:43 -040057 recursive_directory_iterator end(recursive_directory_iterator) noexcept;
Eric Fiselier02cea5e2018-07-27 03:07:09 +000058
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
Joe Loser9d1c0d42021-10-14 11:53:43 -0400227} // namespace std::filesystem
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000228
Joe Loser9d1c0d42021-10-14 11:53:43 -0400229template <>
230inline constexpr bool std::ranges::enable_borrowed_range<std::filesystem::directory_iterator> = true;
231template <>
232inline constexpr bool std::ranges::enable_borrowed_range<std::filesystem::recursive_directory_iterator> = true;
233
234template <>
235inline constexpr bool std::ranges::enable_view<std::filesystem::directory_iterator> = true;
236template <>
237inline constexpr bool std::ranges::enable_view<std::filesystem::recursive_directory_iterator> = true;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000238
239*/
240
Louis Dionne73912b22020-11-04 15:01:25 -0500241#include <__availability>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400242#include <__config>
243#include <__debug>
Joe Loser9d1c0d42021-10-14 11:53:43 -0400244#include <__ranges/enable_borrowed_range.h>
245#include <__ranges/enable_view.h>
Christopher Di Bella41f26e82021-06-05 02:47:47 +0000246#include <__utility/forward.h>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000247#include <chrono>
Arthur O'Dwyer7deec122021-03-24 18:19:12 -0400248#include <compare>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400249#include <cstddef>
250#include <cstdlib>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000251#include <iosfwd>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400252#include <iterator>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000253#include <memory>
254#include <stack>
255#include <string>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400256#include <string_view>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000257#include <system_error>
258#include <utility>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000259#include <version>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000260
Louis Dionne8d053eb2020-10-09 15:31:05 -0400261#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
262# include <locale>
263# include <iomanip> // for quoted
264#endif
265
Louis Dionnedb84e122021-01-18 12:18:18 -0500266#if defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
Mark de Wever2d66e4b2021-07-28 08:11:52 +0200267# error "The Filesystem library is not supported since libc++ has been configured with LIBCXX_ENABLE_FILESYSTEM disabled"
Louis Dionnedb84e122021-01-18 12:18:18 -0500268#endif
269
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000270#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
271#pragma GCC system_header
272#endif
273
274_LIBCPP_PUSH_MACROS
275#include <__undef_macros>
276
277#ifndef _LIBCPP_CXX03_LANG
278
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000279_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
280
Louis Dionnef6bf76a2019-03-20 21:18:14 +0000281_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
282
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000283typedef chrono::time_point<_FilesystemClock> file_time_type;
284
285struct _LIBCPP_TYPE_VIS space_info {
286 uintmax_t capacity;
287 uintmax_t free;
288 uintmax_t available;
289};
290
Joe Loseraf491a22021-10-10 12:53:35 -0400291// On Windows, the library never identifies files as block, character, fifo
Martin Storsjöb2485452021-03-07 23:49:56 +0200292// or socket.
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000293enum class _LIBCPP_ENUM_VIS file_type : signed char {
294 none = 0,
295 not_found = -1,
296 regular = 1,
297 directory = 2,
298 symlink = 3,
299 block = 4,
300 character = 5,
301 fifo = 6,
302 socket = 7,
303 unknown = 8
304};
305
Martin Storsjöb2485452021-03-07 23:49:56 +0200306// On Windows, these permission bits map to one single readonly flag per
307// file, and the executable bit is always returned as set. When setting
308// permissions, as long as the write bit is set for either owner, group or
309// others, the readonly flag is cleared.
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000310enum class _LIBCPP_ENUM_VIS perms : unsigned {
311 none = 0,
312
313 owner_read = 0400,
314 owner_write = 0200,
315 owner_exec = 0100,
316 owner_all = 0700,
317
318 group_read = 040,
319 group_write = 020,
320 group_exec = 010,
321 group_all = 070,
322
323 others_read = 04,
324 others_write = 02,
325 others_exec = 01,
326 others_all = 07,
327
328 all = 0777,
329
330 set_uid = 04000,
331 set_gid = 02000,
332 sticky_bit = 01000,
333 mask = 07777,
334 unknown = 0xFFFF,
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, perms _RHS) {
345 return static_cast<perms>(static_cast<unsigned>(_LHS) |
346 static_cast<unsigned>(_RHS));
347}
348
349_LIBCPP_INLINE_VISIBILITY
350inline constexpr perms operator^(perms _LHS, perms _RHS) {
351 return static_cast<perms>(static_cast<unsigned>(_LHS) ^
352 static_cast<unsigned>(_RHS));
353}
354
355_LIBCPP_INLINE_VISIBILITY
356inline constexpr perms operator~(perms _LHS) {
357 return static_cast<perms>(~static_cast<unsigned>(_LHS));
358}
359
360_LIBCPP_INLINE_VISIBILITY
361inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
362
363_LIBCPP_INLINE_VISIBILITY
364inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
365
366_LIBCPP_INLINE_VISIBILITY
367inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
368
369enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
370 replace = 1,
371 add = 2,
372 remove = 4,
373 nofollow = 8
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, perm_options _RHS) {
384 return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
385 static_cast<unsigned>(_RHS));
386}
387
388_LIBCPP_INLINE_VISIBILITY
389inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) {
390 return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
391 static_cast<unsigned>(_RHS));
392}
393
394_LIBCPP_INLINE_VISIBILITY
395inline constexpr perm_options operator~(perm_options _LHS) {
396 return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
397}
398
399_LIBCPP_INLINE_VISIBILITY
400inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
401 return _LHS = _LHS & _RHS;
402}
403
404_LIBCPP_INLINE_VISIBILITY
405inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
406 return _LHS = _LHS | _RHS;
407}
408
409_LIBCPP_INLINE_VISIBILITY
410inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
411 return _LHS = _LHS ^ _RHS;
412}
413
414enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
415 none = 0,
416 skip_existing = 1,
417 overwrite_existing = 2,
418 update_existing = 4,
419 recursive = 8,
420 copy_symlinks = 16,
421 skip_symlinks = 32,
422 directories_only = 64,
423 create_symlinks = 128,
424 create_hard_links = 256,
425 __in_recursive_copy = 512,
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, copy_options _RHS) {
436 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
437 static_cast<unsigned short>(_RHS));
438}
439
440_LIBCPP_INLINE_VISIBILITY
441inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) {
442 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
443 static_cast<unsigned short>(_RHS));
444}
445
446_LIBCPP_INLINE_VISIBILITY
447inline constexpr copy_options operator~(copy_options _LHS) {
448 return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
449}
450
451_LIBCPP_INLINE_VISIBILITY
452inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
453 return _LHS = _LHS & _RHS;
454}
455
456_LIBCPP_INLINE_VISIBILITY
457inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
458 return _LHS = _LHS | _RHS;
459}
460
461_LIBCPP_INLINE_VISIBILITY
462inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
463 return _LHS = _LHS ^ _RHS;
464}
465
466enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
467 none = 0,
468 follow_directory_symlink = 1,
469 skip_permission_denied = 2
470};
471
472_LIBCPP_INLINE_VISIBILITY
473inline constexpr directory_options operator&(directory_options _LHS,
474 directory_options _RHS) {
475 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
476 static_cast<unsigned char>(_RHS));
477}
478
479_LIBCPP_INLINE_VISIBILITY
480inline constexpr directory_options operator|(directory_options _LHS,
481 directory_options _RHS) {
482 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
483 static_cast<unsigned char>(_RHS));
484}
485
486_LIBCPP_INLINE_VISIBILITY
487inline constexpr directory_options operator^(directory_options _LHS,
488 directory_options _RHS) {
489 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
490 static_cast<unsigned char>(_RHS));
491}
492
493_LIBCPP_INLINE_VISIBILITY
494inline constexpr directory_options operator~(directory_options _LHS) {
495 return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
496}
497
498_LIBCPP_INLINE_VISIBILITY
499inline directory_options& operator&=(directory_options& _LHS,
500 directory_options _RHS) {
501 return _LHS = _LHS & _RHS;
502}
503
504_LIBCPP_INLINE_VISIBILITY
505inline directory_options& operator|=(directory_options& _LHS,
506 directory_options _RHS) {
507 return _LHS = _LHS | _RHS;
508}
509
510_LIBCPP_INLINE_VISIBILITY
511inline directory_options& operator^=(directory_options& _LHS,
512 directory_options _RHS) {
513 return _LHS = _LHS ^ _RHS;
514}
515
516class _LIBCPP_TYPE_VIS file_status {
517public:
518 // constructors
519 _LIBCPP_INLINE_VISIBILITY
520 file_status() noexcept : file_status(file_type::none) {}
521 _LIBCPP_INLINE_VISIBILITY
522 explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
523 : __ft_(__ft),
524 __prms_(__prms) {}
525
526 file_status(const file_status&) noexcept = default;
527 file_status(file_status&&) noexcept = default;
528
529 _LIBCPP_INLINE_VISIBILITY
530 ~file_status() {}
531
532 file_status& operator=(const file_status&) noexcept = default;
533 file_status& operator=(file_status&&) noexcept = default;
534
535 // observers
536 _LIBCPP_INLINE_VISIBILITY
537 file_type type() const noexcept { return __ft_; }
538
539 _LIBCPP_INLINE_VISIBILITY
540 perms permissions() const noexcept { return __prms_; }
541
542 // modifiers
543 _LIBCPP_INLINE_VISIBILITY
544 void type(file_type __ft) noexcept { __ft_ = __ft; }
545
546 _LIBCPP_INLINE_VISIBILITY
547 void permissions(perms __p) noexcept { __prms_ = __p; }
548
549private:
550 file_type __ft_;
551 perms __prms_;
552};
553
554class _LIBCPP_TYPE_VIS directory_entry;
555
556template <class _Tp>
557struct __can_convert_char {
558 static const bool value = false;
559};
560template <class _Tp>
561struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
562template <>
563struct __can_convert_char<char> {
564 static const bool value = true;
565 using __char_type = char;
566};
567template <>
568struct __can_convert_char<wchar_t> {
569 static const bool value = true;
570 using __char_type = wchar_t;
571};
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400572#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +0200573template <>
574struct __can_convert_char<char8_t> {
575 static const bool value = true;
576 using __char_type = char8_t;
577};
578#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000579template <>
580struct __can_convert_char<char16_t> {
581 static const bool value = true;
582 using __char_type = char16_t;
583};
584template <>
585struct __can_convert_char<char32_t> {
586 static const bool value = true;
587 using __char_type = char32_t;
588};
589
590template <class _ECharT>
591typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
592__is_separator(_ECharT __e) {
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200593#if defined(_LIBCPP_WIN32API)
594 return __e == _ECharT('/') || __e == _ECharT('\\');
595#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000596 return __e == _ECharT('/');
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200597#endif
Eric Fiselierb41db9a2018-10-01 01:59:37 +0000598}
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000599
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400600#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200601typedef u8string __u8_string;
602#else
603typedef string __u8_string;
604#endif
605
Martin Storsjö2ae96532020-10-27 11:46:06 +0200606struct _NullSentinel {};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000607
608template <class _Tp>
609using _Void = void;
610
611template <class _Tp, class = void>
612struct __is_pathable_string : public false_type {};
613
614template <class _ECharT, class _Traits, class _Alloc>
615struct __is_pathable_string<
616 basic_string<_ECharT, _Traits, _Alloc>,
617 _Void<typename __can_convert_char<_ECharT>::__char_type> >
618 : public __can_convert_char<_ECharT> {
619 using _Str = basic_string<_ECharT, _Traits, _Alloc>;
620 using _Base = __can_convert_char<_ECharT>;
621 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
622 static _ECharT const* __range_end(_Str const& __s) {
623 return __s.data() + __s.length();
624 }
625 static _ECharT __first_or_null(_Str const& __s) {
626 return __s.empty() ? _ECharT{} : __s[0];
627 }
628};
629
630template <class _ECharT, class _Traits>
631struct __is_pathable_string<
632 basic_string_view<_ECharT, _Traits>,
633 _Void<typename __can_convert_char<_ECharT>::__char_type> >
634 : public __can_convert_char<_ECharT> {
635 using _Str = basic_string_view<_ECharT, _Traits>;
636 using _Base = __can_convert_char<_ECharT>;
637 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
638 static _ECharT const* __range_end(_Str const& __s) {
639 return __s.data() + __s.length();
640 }
641 static _ECharT __first_or_null(_Str const& __s) {
642 return __s.empty() ? _ECharT{} : __s[0];
643 }
644};
645
646template <class _Source, class _DS = typename decay<_Source>::type,
647 class _UnqualPtrType =
648 typename remove_const<typename remove_pointer<_DS>::type>::type,
649 bool _IsCharPtr = is_pointer<_DS>::value&&
650 __can_convert_char<_UnqualPtrType>::value>
651struct __is_pathable_char_array : false_type {};
652
653template <class _Source, class _ECharT, class _UPtr>
654struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
655 : __can_convert_char<typename remove_const<_ECharT>::type> {
656 using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
657
658 static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
659 static _ECharT const* __range_end(const _ECharT* __b) {
660 using _Iter = const _ECharT*;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200661 const _ECharT __sentinel = _ECharT{};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000662 _Iter __e = __b;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200663 for (; *__e != __sentinel; ++__e)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000664 ;
665 return __e;
666 }
667
668 static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
669};
670
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500671template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000672 class = void>
673struct __is_pathable_iter : false_type {};
674
675template <class _Iter>
676struct __is_pathable_iter<
677 _Iter, true,
678 _Void<typename __can_convert_char<
679 typename iterator_traits<_Iter>::value_type>::__char_type> >
680 : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
681 using _ECharT = typename iterator_traits<_Iter>::value_type;
682 using _Base = __can_convert_char<_ECharT>;
683
684 static _Iter __range_begin(_Iter __b) { return __b; }
Martin Storsjö2ae96532020-10-27 11:46:06 +0200685 static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000686
687 static _ECharT __first_or_null(_Iter __b) { return *__b; }
688};
689
690template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
691 bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
692 bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
693struct __is_pathable : false_type {
694 static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
695};
696
697template <class _Tp>
698struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
699
700template <class _Tp>
701struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
702};
703
704template <class _Tp>
705struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
706
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200707#if defined(_LIBCPP_WIN32API)
708typedef wstring __path_string;
709typedef wchar_t __path_value;
710#else
711typedef string __path_string;
712typedef char __path_value;
713#endif
714
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200715#if defined(_LIBCPP_WIN32API)
716_LIBCPP_FUNC_VIS
717size_t __wide_to_char(const wstring&, char*, size_t);
718_LIBCPP_FUNC_VIS
719size_t __char_to_wide(const string&, wchar_t*, size_t);
720#endif
721
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000722template <class _ECharT>
Louis Dionne8d053eb2020-10-09 15:31:05 -0400723struct _PathCVT;
724
725#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
726template <class _ECharT>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000727struct _PathCVT {
728 static_assert(__can_convert_char<_ECharT>::value,
729 "Char type not convertible");
730
731 typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200732#if defined(_LIBCPP_WIN32API)
733 typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
734#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000735
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200736 static void __append_range(__path_string& __dest, _ECharT const* __b,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000737 _ECharT const* __e) {
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200738#if defined(_LIBCPP_WIN32API)
739 string __utf8;
740 _Narrower()(back_inserter(__utf8), __b, __e);
741 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
742#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000743 _Narrower()(back_inserter(__dest), __b, __e);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200744#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000745 }
746
747 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200748 static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000749 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
750 if (__b == __e)
751 return;
752 basic_string<_ECharT> __tmp(__b, __e);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200753#if defined(_LIBCPP_WIN32API)
754 string __utf8;
755 _Narrower()(back_inserter(__utf8), __tmp.data(),
756 __tmp.data() + __tmp.length());
757 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
758#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000759 _Narrower()(back_inserter(__dest), __tmp.data(),
760 __tmp.data() + __tmp.length());
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200761#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000762 }
763
764 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200765 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000766 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
Martin Storsjö2ae96532020-10-27 11:46:06 +0200767 const _ECharT __sentinel = _ECharT{};
768 if (*__b == __sentinel)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000769 return;
770 basic_string<_ECharT> __tmp;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200771 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000772 __tmp.push_back(*__b);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200773#if defined(_LIBCPP_WIN32API)
774 string __utf8;
775 _Narrower()(back_inserter(__utf8), __tmp.data(),
776 __tmp.data() + __tmp.length());
777 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
778#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000779 _Narrower()(back_inserter(__dest), __tmp.data(),
780 __tmp.data() + __tmp.length());
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200781#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000782 }
783
784 template <class _Source>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200785 static void __append_source(__path_string& __dest, _Source const& __s) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000786 using _Traits = __is_pathable<_Source>;
787 __append_range(__dest, _Traits::__range_begin(__s),
788 _Traits::__range_end(__s));
789 }
790};
Louis Dionne8d053eb2020-10-09 15:31:05 -0400791#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000792
793template <>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200794struct _PathCVT<__path_value> {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000795
796 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500797 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200798 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000799 for (; __b != __e; ++__b)
800 __dest.push_back(*__b);
801 }
802
803 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500804 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200805 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Arthur O'Dwyer98ff31f2021-04-16 17:49:57 -0400806 __dest.append(__b, __e);
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000807 }
808
809 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200810 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
Martin Storsjö2ae96532020-10-27 11:46:06 +0200811 const char __sentinel = char{};
812 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000813 __dest.push_back(*__b);
814 }
815
816 template <class _Source>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200817 static void __append_source(__path_string& __dest, _Source const& __s) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000818 using _Traits = __is_pathable<_Source>;
819 __append_range(__dest, _Traits::__range_begin(__s),
820 _Traits::__range_end(__s));
821 }
822};
823
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200824#if defined(_LIBCPP_WIN32API)
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200825template <>
826struct _PathCVT<char> {
827
828 static void
829 __append_string(__path_string& __dest, const basic_string<char> &__str) {
830 size_t __size = __char_to_wide(__str, nullptr, 0);
831 size_t __pos = __dest.size();
832 __dest.resize(__pos + __size);
833 __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
834 }
835
836 template <class _Iter>
837 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
838 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
839 basic_string<char> __tmp(__b, __e);
840 __append_string(__dest, __tmp);
841 }
842
843 template <class _Iter>
844 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
845 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
846 basic_string<char> __tmp(__b, __e);
847 __append_string(__dest, __tmp);
848 }
849
850 template <class _Iter>
851 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
852 const char __sentinel = char{};
853 basic_string<char> __tmp;
854 for (; *__b != __sentinel; ++__b)
855 __tmp.push_back(*__b);
856 __append_string(__dest, __tmp);
857 }
858
859 template <class _Source>
860 static void __append_source(__path_string& __dest, _Source const& __s) {
861 using _Traits = __is_pathable<_Source>;
862 __append_range(__dest, _Traits::__range_begin(__s),
863 _Traits::__range_end(__s));
864 }
865};
866
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200867template <class _ECharT>
868struct _PathExport {
869 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
870 typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
871
872 template <class _Str>
873 static void __append(_Str& __dest, const __path_string& __src) {
874 string __utf8;
875 _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
876 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
877 }
878};
879
880template <>
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200881struct _PathExport<char> {
882 template <class _Str>
883 static void __append(_Str& __dest, const __path_string& __src) {
884 size_t __size = __wide_to_char(__src, nullptr, 0);
885 size_t __pos = __dest.size();
886 __dest.resize(__size);
887 __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
888 }
889};
890
891template <>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200892struct _PathExport<wchar_t> {
893 template <class _Str>
894 static void __append(_Str& __dest, const __path_string& __src) {
895 __dest.append(__src.begin(), __src.end());
896 }
897};
898
899template <>
900struct _PathExport<char16_t> {
901 template <class _Str>
902 static void __append(_Str& __dest, const __path_string& __src) {
903 __dest.append(__src.begin(), __src.end());
904 }
905};
906
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400907#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200908template <>
909struct _PathExport<char8_t> {
910 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
911
912 template <class _Str>
913 static void __append(_Str& __dest, const __path_string& __src) {
914 _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
915 }
916};
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400917#endif /* !_LIBCPP_HAS_NO_CHAR8_T */
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200918#endif /* _LIBCPP_WIN32API */
919
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000920class _LIBCPP_TYPE_VIS path {
921 template <class _SourceOrIter, class _Tp = path&>
922 using _EnableIfPathable =
923 typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
924
925 template <class _Tp>
926 using _SourceChar = typename __is_pathable<_Tp>::__char_type;
927
928 template <class _Tp>
929 using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
930
931public:
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200932#if defined(_LIBCPP_WIN32API)
933 typedef wchar_t value_type;
934 static constexpr value_type preferred_separator = L'\\';
935#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000936 typedef char value_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000937 static constexpr value_type preferred_separator = '/';
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200938#endif
939 typedef basic_string<value_type> string_type;
940 typedef basic_string_view<value_type> __string_view;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000941
Martin Storsjö560291c2020-11-06 11:57:47 +0200942 enum _LIBCPP_ENUM_VIS format : unsigned char {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000943 auto_format,
944 native_format,
945 generic_format
946 };
947
948 // constructors and destructor
949 _LIBCPP_INLINE_VISIBILITY path() noexcept {}
950 _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
951 _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
952 : __pn_(_VSTD::move(__p.__pn_)) {}
953
954 _LIBCPP_INLINE_VISIBILITY
955 path(string_type&& __s, format = format::auto_format) noexcept
956 : __pn_(_VSTD::move(__s)) {}
957
958 template <class _Source, class = _EnableIfPathable<_Source, void> >
959 path(const _Source& __src, format = format::auto_format) {
960 _SourceCVT<_Source>::__append_source(__pn_, __src);
961 }
962
963 template <class _InputIt>
964 path(_InputIt __first, _InputIt __last, format = format::auto_format) {
965 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
966 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
967 }
968
Muiez Ahmed07130662021-10-20 13:55:50 -0400969/*
Louis Dionne8d053eb2020-10-09 15:31:05 -0400970#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000971 // TODO Implement locale conversions.
972 template <class _Source, class = _EnableIfPathable<_Source, void> >
973 path(const _Source& __src, const locale& __loc, format = format::auto_format);
974 template <class _InputIt>
975 path(_InputIt __first, _InputIt _last, const locale& __loc,
976 format = format::auto_format);
Louis Dionne8d053eb2020-10-09 15:31:05 -0400977#endif
Muiez Ahmed07130662021-10-20 13:55:50 -0400978*/
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000979
980 _LIBCPP_INLINE_VISIBILITY
981 ~path() = default;
982
983 // assignments
984 _LIBCPP_INLINE_VISIBILITY
985 path& operator=(const path& __p) {
986 __pn_ = __p.__pn_;
987 return *this;
988 }
989
990 _LIBCPP_INLINE_VISIBILITY
991 path& operator=(path&& __p) noexcept {
992 __pn_ = _VSTD::move(__p.__pn_);
993 return *this;
994 }
995
Louis Dionne5da71d22021-02-03 16:40:41 -0500996 _LIBCPP_INLINE_VISIBILITY
997 path& operator=(string_type&& __s) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000998 __pn_ = _VSTD::move(__s);
999 return *this;
1000 }
1001
1002 _LIBCPP_INLINE_VISIBILITY
1003 path& assign(string_type&& __s) noexcept {
1004 __pn_ = _VSTD::move(__s);
1005 return *this;
1006 }
1007
1008 template <class _Source>
1009 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1010 operator=(const _Source& __src) {
1011 return this->assign(__src);
1012 }
1013
1014 template <class _Source>
1015 _EnableIfPathable<_Source> assign(const _Source& __src) {
1016 __pn_.clear();
1017 _SourceCVT<_Source>::__append_source(__pn_, __src);
1018 return *this;
1019 }
1020
1021 template <class _InputIt>
1022 path& assign(_InputIt __first, _InputIt __last) {
1023 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1024 __pn_.clear();
1025 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1026 return *this;
1027 }
1028
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001029public:
1030 // appends
Martin Storsjö98770152020-11-04 15:59:56 +02001031#if defined(_LIBCPP_WIN32API)
1032 path& operator/=(const path& __p) {
1033 auto __p_root_name = __p.__root_name();
1034 auto __p_root_name_size = __p_root_name.size();
1035 if (__p.is_absolute() ||
1036 (!__p_root_name.empty() && __p_root_name != root_name())) {
1037 __pn_ = __p.__pn_;
1038 return *this;
1039 }
1040 if (__p.has_root_directory()) {
1041 path __root_name_str = root_name();
1042 __pn_ = __root_name_str.native();
Martin Storsjöacb39e12021-03-11 13:06:08 +02001043 __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
Martin Storsjö98770152020-11-04 15:59:56 +02001044 return *this;
1045 }
1046 if (has_filename() || (!has_root_directory() && is_absolute()))
1047 __pn_ += preferred_separator;
Martin Storsjöacb39e12021-03-11 13:06:08 +02001048 __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
Martin Storsjö98770152020-11-04 15:59:56 +02001049 return *this;
1050 }
1051 template <class _Source>
1052 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1053 operator/=(const _Source& __src) {
1054 return operator/=(path(__src));
1055 }
1056
1057 template <class _Source>
1058 _EnableIfPathable<_Source> append(const _Source& __src) {
1059 return operator/=(path(__src));
1060 }
1061
1062 template <class _InputIt>
1063 path& append(_InputIt __first, _InputIt __last) {
1064 return operator/=(path(__first, __last));
1065 }
1066#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001067 path& operator/=(const path& __p) {
1068 if (__p.is_absolute()) {
1069 __pn_ = __p.__pn_;
1070 return *this;
1071 }
1072 if (has_filename())
1073 __pn_ += preferred_separator;
1074 __pn_ += __p.native();
1075 return *this;
1076 }
1077
1078 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
1079 // is known at compile time to be "/' since the user almost certainly intended
1080 // to append a separator instead of overwriting the path with "/"
1081 template <class _Source>
1082 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1083 operator/=(const _Source& __src) {
1084 return this->append(__src);
1085 }
1086
1087 template <class _Source>
1088 _EnableIfPathable<_Source> append(const _Source& __src) {
1089 using _Traits = __is_pathable<_Source>;
1090 using _CVT = _PathCVT<_SourceChar<_Source> >;
Martin Storsjö98770152020-11-04 15:59:56 +02001091 bool __source_is_absolute = __is_separator(_Traits::__first_or_null(__src));
1092 if (__source_is_absolute)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001093 __pn_.clear();
1094 else if (has_filename())
1095 __pn_ += preferred_separator;
1096 _CVT::__append_source(__pn_, __src);
1097 return *this;
1098 }
1099
1100 template <class _InputIt>
1101 path& append(_InputIt __first, _InputIt __last) {
1102 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1103 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
1104 using _CVT = _PathCVT<_ItVal>;
Martin Storsjö98770152020-11-04 15:59:56 +02001105 if (__first != __last && __is_separator(*__first))
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001106 __pn_.clear();
1107 else if (has_filename())
1108 __pn_ += preferred_separator;
1109 _CVT::__append_range(__pn_, __first, __last);
1110 return *this;
1111 }
Martin Storsjö98770152020-11-04 15:59:56 +02001112#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001113
1114 // concatenation
1115 _LIBCPP_INLINE_VISIBILITY
1116 path& operator+=(const path& __x) {
1117 __pn_ += __x.__pn_;
1118 return *this;
1119 }
1120
1121 _LIBCPP_INLINE_VISIBILITY
1122 path& operator+=(const string_type& __x) {
1123 __pn_ += __x;
1124 return *this;
1125 }
1126
1127 _LIBCPP_INLINE_VISIBILITY
1128 path& operator+=(__string_view __x) {
1129 __pn_ += __x;
1130 return *this;
1131 }
1132
1133 _LIBCPP_INLINE_VISIBILITY
1134 path& operator+=(const value_type* __x) {
1135 __pn_ += __x;
1136 return *this;
1137 }
1138
1139 _LIBCPP_INLINE_VISIBILITY
1140 path& operator+=(value_type __x) {
1141 __pn_ += __x;
1142 return *this;
1143 }
1144
1145 template <class _ECharT>
1146 typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
1147 operator+=(_ECharT __x) {
Marek Kurdej306a1b02020-12-07 20:07:25 +01001148 _PathCVT<_ECharT>::__append_source(__pn_,
1149 basic_string_view<_ECharT>(&__x, 1));
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001150 return *this;
1151 }
1152
1153 template <class _Source>
1154 _EnableIfPathable<_Source> operator+=(const _Source& __x) {
1155 return this->concat(__x);
1156 }
1157
1158 template <class _Source>
1159 _EnableIfPathable<_Source> concat(const _Source& __x) {
1160 _SourceCVT<_Source>::__append_source(__pn_, __x);
1161 return *this;
1162 }
1163
1164 template <class _InputIt>
1165 path& concat(_InputIt __first, _InputIt __last) {
1166 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1167 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1168 return *this;
1169 }
1170
1171 // modifiers
1172 _LIBCPP_INLINE_VISIBILITY
1173 void clear() noexcept { __pn_.clear(); }
1174
Martin Storsjöf543c7a2020-10-28 12:24:11 +02001175 path& make_preferred() {
1176#if defined(_LIBCPP_WIN32API)
1177 _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
1178#endif
1179 return *this;
1180 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001181
1182 _LIBCPP_INLINE_VISIBILITY
1183 path& remove_filename() {
1184 auto __fname = __filename();
1185 if (!__fname.empty())
1186 __pn_.erase(__fname.data() - __pn_.data());
1187 return *this;
1188 }
1189
1190 path& replace_filename(const path& __replacement) {
1191 remove_filename();
1192 return (*this /= __replacement);
1193 }
1194
1195 path& replace_extension(const path& __replacement = path());
1196
1197 _LIBCPP_INLINE_VISIBILITY
1198 void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
1199
1200 // private helper to allow reserving memory in the path
1201 _LIBCPP_INLINE_VISIBILITY
1202 void __reserve(size_t __s) { __pn_.reserve(__s); }
1203
1204 // native format observers
1205 _LIBCPP_INLINE_VISIBILITY
1206 const string_type& native() const noexcept { return __pn_; }
1207
1208 _LIBCPP_INLINE_VISIBILITY
1209 const value_type* c_str() const noexcept { return __pn_.c_str(); }
1210
1211 _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
1212
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001213#if defined(_LIBCPP_WIN32API)
1214 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; }
1215
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001216 _VSTD::wstring generic_wstring() const {
1217 _VSTD::wstring __s;
1218 __s.resize(__pn_.size());
1219 _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
1220 return __s;
1221 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001222
1223#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
1224 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1225 class _Allocator = allocator<_ECharT> >
1226 basic_string<_ECharT, _Traits, _Allocator>
1227 string(const _Allocator& __a = _Allocator()) const {
1228 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1229 _Str __s(__a);
1230 __s.reserve(__pn_.size());
1231 _PathExport<_ECharT>::__append(__s, __pn_);
1232 return __s;
1233 }
1234
1235 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const {
1236 return string<char>();
1237 }
1238 _LIBCPP_INLINE_VISIBILITY __u8_string u8string() const {
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001239 using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1240 __u8_string __s;
1241 __s.reserve(__pn_.size());
1242 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1243 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001244 }
1245
1246 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
1247 return string<char16_t>();
1248 }
1249 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
1250 return string<char32_t>();
1251 }
1252
1253 // generic format observers
1254 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1255 class _Allocator = allocator<_ECharT> >
1256 basic_string<_ECharT, _Traits, _Allocator>
1257 generic_string(const _Allocator& __a = _Allocator()) const {
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001258 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1259 _Str __s = string<_ECharT, _Traits, _Allocator>(__a);
1260 // Note: This (and generic_u8string below) is slightly suboptimal as
1261 // it iterates twice over the string; once to convert it to the right
1262 // character type, and once to replace path delimiters.
1263 _VSTD::replace(__s.begin(), __s.end(),
1264 static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
1265 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001266 }
1267
1268 _VSTD::string generic_string() const { return generic_string<char>(); }
1269 _VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); }
1270 _VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); }
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001271 __u8_string generic_u8string() const {
1272 __u8_string __s = u8string();
1273 _VSTD::replace(__s.begin(), __s.end(), '\\', '/');
1274 return __s;
1275 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001276#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1277#else /* _LIBCPP_WIN32API */
1278
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001279 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; }
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001280#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001281 _LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1282#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001283 _LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001284#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001285
1286#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001287 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1288 class _Allocator = allocator<_ECharT> >
1289 basic_string<_ECharT, _Traits, _Allocator>
1290 string(const _Allocator& __a = _Allocator()) const {
1291 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
1292 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1293 _Str __s(__a);
1294 __s.reserve(__pn_.size());
1295 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1296 return __s;
1297 }
1298
Louis Dionne89258142021-08-23 15:32:36 -04001299#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001300 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001301 return string<wchar_t>();
1302 }
Louis Dionne89258142021-08-23 15:32:36 -04001303#endif
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001304 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001305 return string<char16_t>();
1306 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001307 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001308 return string<char32_t>();
1309 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001310#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001311
1312 // generic format observers
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001313 _VSTD::string generic_string() const { return __pn_; }
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001314#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001315 _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1316#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001317 _VSTD::string generic_u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001318#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001319
1320#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001321 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1322 class _Allocator = allocator<_ECharT> >
1323 basic_string<_ECharT, _Traits, _Allocator>
1324 generic_string(const _Allocator& __a = _Allocator()) const {
1325 return string<_ECharT, _Traits, _Allocator>(__a);
1326 }
1327
Louis Dionne89258142021-08-23 15:32:36 -04001328#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001329 _VSTD::wstring generic_wstring() const { return string<wchar_t>(); }
Louis Dionne89258142021-08-23 15:32:36 -04001330#endif
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001331 _VSTD::u16string generic_u16string() const { return string<char16_t>(); }
1332 _VSTD::u32string generic_u32string() const { return string<char32_t>(); }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001333#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1334#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001335
1336private:
1337 int __compare(__string_view) const;
1338 __string_view __root_name() const;
1339 __string_view __root_directory() const;
1340 __string_view __root_path_raw() const;
1341 __string_view __relative_path() const;
1342 __string_view __parent_path() const;
1343 __string_view __filename() const;
1344 __string_view __stem() const;
1345 __string_view __extension() const;
1346
1347public:
1348 // compare
1349 _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
1350 return __compare(__p.__pn_);
1351 }
1352 _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
1353 return __compare(__s);
1354 }
1355 _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
1356 return __compare(__s);
1357 }
1358 _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
1359 return __compare(__s);
1360 }
1361
1362 // decomposition
1363 _LIBCPP_INLINE_VISIBILITY path root_name() const {
1364 return string_type(__root_name());
1365 }
1366 _LIBCPP_INLINE_VISIBILITY path root_directory() const {
1367 return string_type(__root_directory());
1368 }
1369 _LIBCPP_INLINE_VISIBILITY path root_path() const {
Martin Storsjö98770152020-11-04 15:59:56 +02001370#if defined(_LIBCPP_WIN32API)
1371 return string_type(__root_path_raw());
1372#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001373 return root_name().append(string_type(__root_directory()));
Martin Storsjö98770152020-11-04 15:59:56 +02001374#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001375 }
1376 _LIBCPP_INLINE_VISIBILITY path relative_path() const {
1377 return string_type(__relative_path());
1378 }
1379 _LIBCPP_INLINE_VISIBILITY path parent_path() const {
1380 return string_type(__parent_path());
1381 }
1382 _LIBCPP_INLINE_VISIBILITY path filename() const {
1383 return string_type(__filename());
1384 }
1385 _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
1386 _LIBCPP_INLINE_VISIBILITY path extension() const {
1387 return string_type(__extension());
1388 }
1389
1390 // query
1391 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
1392 empty() const noexcept {
1393 return __pn_.empty();
1394 }
1395
1396 _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
1397 return !__root_name().empty();
1398 }
1399 _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
1400 return !__root_directory().empty();
1401 }
1402 _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
1403 return !__root_path_raw().empty();
1404 }
1405 _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
1406 return !__relative_path().empty();
1407 }
1408 _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
1409 return !__parent_path().empty();
1410 }
1411 _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
1412 return !__filename().empty();
1413 }
1414 _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
1415 _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
1416 return !__extension().empty();
1417 }
1418
1419 _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
Martin Storsjöef6b7422020-11-01 23:39:03 +02001420#if defined(_LIBCPP_WIN32API)
1421 __string_view __root_name_str = __root_name();
1422 __string_view __root_dir = __root_directory();
1423 if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
1424 // A drive letter with no root directory is relative, e.g. x:example.
1425 return !__root_dir.empty();
1426 }
1427 // If no root name, it's relative, e.g. \example is relative to the current drive
1428 if (__root_name_str.empty())
1429 return false;
1430 if (__root_name_str.size() < 3)
1431 return false;
1432 // A server root name, like \\server, is always absolute
1433 if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
1434 return false;
1435 if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
1436 return false;
1437 // Seems to be a server root name
1438 return true;
1439#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001440 return has_root_directory();
Martin Storsjöef6b7422020-11-01 23:39:03 +02001441#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001442 }
1443 _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
1444
1445 // relative paths
1446 path lexically_normal() const;
1447 path lexically_relative(const path& __base) const;
1448
1449 _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
1450 path __result = this->lexically_relative(__base);
1451 if (__result.native().empty())
1452 return *this;
1453 return __result;
1454 }
1455
1456 // iterators
1457 class _LIBCPP_TYPE_VIS iterator;
1458 typedef iterator const_iterator;
1459
1460 iterator begin() const;
1461 iterator end() const;
1462
Louis Dionne8d053eb2020-10-09 15:31:05 -04001463#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001464 template <class _CharT, class _Traits>
1465 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001466 typename enable_if<is_same<_CharT, value_type>::value &&
1467 is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001468 basic_ostream<_CharT, _Traits>&>::type
1469 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001470 __os << _VSTD::__quoted(__p.native());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001471 return __os;
1472 }
1473
1474 template <class _CharT, class _Traits>
1475 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001476 typename enable_if<!is_same<_CharT, value_type>::value ||
1477 !is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001478 basic_ostream<_CharT, _Traits>&>::type
1479 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001480 __os << _VSTD::__quoted(__p.string<_CharT, _Traits>());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001481 return __os;
1482 }
1483
1484 template <class _CharT, class _Traits>
1485 _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
1486 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
1487 basic_string<_CharT, _Traits> __tmp;
1488 __is >> __quoted(__tmp);
1489 __p = __tmp;
1490 return __is;
1491 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001492#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001493
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001494 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
Joe Loser7c6947a2021-11-24 22:48:40 -05001495 return __lhs.__compare(__rhs.__pn_) == 0;
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001496 }
1497 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
Joe Loser7c6947a2021-11-24 22:48:40 -05001498 return __lhs.__compare(__rhs.__pn_) != 0;
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001499 }
1500 friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
Joe Loser7c6947a2021-11-24 22:48:40 -05001501 return __lhs.__compare(__rhs.__pn_) < 0;
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001502 }
1503 friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
Joe Loser7c6947a2021-11-24 22:48:40 -05001504 return __lhs.__compare(__rhs.__pn_) <= 0;
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001505 }
1506 friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
Joe Loser7c6947a2021-11-24 22:48:40 -05001507 return __lhs.__compare(__rhs.__pn_) > 0;
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001508 }
1509 friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
Joe Loser7c6947a2021-11-24 22:48:40 -05001510 return __lhs.__compare(__rhs.__pn_) >= 0;
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001511 }
1512
1513 friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
1514 const path& __rhs) {
1515 path __result(__lhs);
1516 __result /= __rhs;
1517 return __result;
1518 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001519private:
1520 inline _LIBCPP_INLINE_VISIBILITY path&
1521 __assign_view(__string_view const& __s) noexcept {
1522 __pn_ = string_type(__s);
1523 return *this;
1524 }
1525 string_type __pn_;
1526};
1527
1528inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
1529 __lhs.swap(__rhs);
1530}
1531
1532_LIBCPP_FUNC_VIS
1533size_t hash_value(const path& __p) noexcept;
1534
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001535template <class _InputIt>
Martin Storsjöe3a71972020-10-26 13:18:46 +02001536_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001537 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1538 u8path(_InputIt __f, _InputIt __l) {
1539 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001540#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001541 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1542#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001543 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
Martin Storsjöe3a71972020-10-26 13:18:46 +02001544 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
Martin Storsjö929dff92020-12-15 09:15:37 +02001545 " or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001546#if defined(_LIBCPP_WIN32API)
1547 string __tmp(__f, __l);
1548 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1549 _VSTD::wstring __w;
1550 __w.reserve(__tmp.size());
1551 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1552 return path(__w);
1553#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001554 return path(__f, __l);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001555#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001556}
1557
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001558#if defined(_LIBCPP_WIN32API)
1559template <class _InputIt>
1560_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1561 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1562 u8path(_InputIt __f, _NullSentinel) {
1563 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001564#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001565 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1566#endif
1567 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
1568 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
1569 " or 'char8_t'");
1570 string __tmp;
1571 const char __sentinel = char{};
1572 for (; *__f != __sentinel; ++__f)
1573 __tmp.push_back(*__f);
1574 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1575 _VSTD::wstring __w;
1576 __w.reserve(__tmp.size());
1577 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1578 return path(__w);
1579}
1580#endif /* _LIBCPP_WIN32API */
1581
Martin Storsjö367d7f02020-11-05 00:21:30 +02001582template <class _Source>
1583_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1584 typename enable_if<__is_pathable<_Source>::value, path>::type
1585 u8path(const _Source& __s) {
1586 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001587#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjö367d7f02020-11-05 00:21:30 +02001588 is_same<typename __is_pathable<_Source>::__char_type, char8_t>::value ||
1589#endif
1590 is_same<typename __is_pathable<_Source>::__char_type, char>::value,
1591 "u8path(Source const&) requires Source have a character type of type "
1592 "'char' or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001593#if defined(_LIBCPP_WIN32API)
1594 using _Traits = __is_pathable<_Source>;
Arthur O'Dwyer1ac9f092021-01-15 12:59:56 -05001595 return u8path(_VSTD::__unwrap_iter(_Traits::__range_begin(__s)), _VSTD::__unwrap_iter(_Traits::__range_end(__s)));
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001596#else
Martin Storsjö367d7f02020-11-05 00:21:30 +02001597 return path(__s);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001598#endif
Martin Storsjö367d7f02020-11-05 00:21:30 +02001599}
1600
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001601class _LIBCPP_TYPE_VIS path::iterator {
1602public:
1603 enum _ParserState : unsigned char {
1604 _Singular,
1605 _BeforeBegin,
1606 _InRootName,
1607 _InRootDir,
1608 _InFilenames,
1609 _InTrailingSep,
1610 _AtEnd
1611 };
1612
1613public:
1614 typedef bidirectional_iterator_tag iterator_category;
1615
1616 typedef path value_type;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001617 typedef ptrdiff_t difference_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001618 typedef const path* pointer;
1619 typedef const path& reference;
1620
1621 typedef void
1622 __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
1623
1624public:
1625 _LIBCPP_INLINE_VISIBILITY
1626 iterator()
1627 : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
1628 __state_(_Singular) {}
1629
1630 iterator(const iterator&) = default;
1631 ~iterator() = default;
1632
1633 iterator& operator=(const iterator&) = default;
1634
1635 _LIBCPP_INLINE_VISIBILITY
1636 reference operator*() const { return __stashed_elem_; }
1637
1638 _LIBCPP_INLINE_VISIBILITY
1639 pointer operator->() const { return &__stashed_elem_; }
1640
1641 _LIBCPP_INLINE_VISIBILITY
1642 iterator& operator++() {
1643 _LIBCPP_ASSERT(__state_ != _Singular,
1644 "attempting to increment a singular iterator");
1645 _LIBCPP_ASSERT(__state_ != _AtEnd,
1646 "attempting to increment the end iterator");
1647 return __increment();
1648 }
1649
1650 _LIBCPP_INLINE_VISIBILITY
1651 iterator operator++(int) {
1652 iterator __it(*this);
1653 this->operator++();
1654 return __it;
1655 }
1656
1657 _LIBCPP_INLINE_VISIBILITY
1658 iterator& operator--() {
1659 _LIBCPP_ASSERT(__state_ != _Singular,
1660 "attempting to decrement a singular iterator");
1661 _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
1662 "attempting to decrement the begin iterator");
1663 return __decrement();
1664 }
1665
1666 _LIBCPP_INLINE_VISIBILITY
1667 iterator operator--(int) {
1668 iterator __it(*this);
1669 this->operator--();
1670 return __it;
1671 }
1672
1673private:
1674 friend class path;
1675
1676 inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
1677 const iterator&);
1678
1679 iterator& __increment();
1680 iterator& __decrement();
1681
1682 path __stashed_elem_;
1683 const path* __path_ptr_;
1684 path::__string_view __entry_;
1685 _ParserState __state_;
1686};
1687
1688inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
1689 const path::iterator& __rhs) {
1690 return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
1691 __lhs.__entry_.data() == __rhs.__entry_.data();
1692}
1693
1694inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
1695 const path::iterator& __rhs) {
1696 return !(__lhs == __rhs);
1697}
1698
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001699// TODO(ldionne): We need to pop the pragma and push it again after
1700// filesystem_error to work around PR41078.
1701_LIBCPP_AVAILABILITY_FILESYSTEM_POP
1702
1703class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001704public:
1705 _LIBCPP_INLINE_VISIBILITY
1706 filesystem_error(const string& __what, error_code __ec)
1707 : system_error(__ec, __what),
1708 __storage_(make_shared<_Storage>(path(), path())) {
1709 __create_what(0);
1710 }
1711
1712 _LIBCPP_INLINE_VISIBILITY
1713 filesystem_error(const string& __what, const path& __p1, error_code __ec)
1714 : system_error(__ec, __what),
1715 __storage_(make_shared<_Storage>(__p1, path())) {
1716 __create_what(1);
1717 }
1718
1719 _LIBCPP_INLINE_VISIBILITY
1720 filesystem_error(const string& __what, const path& __p1, const path& __p2,
1721 error_code __ec)
1722 : system_error(__ec, __what),
1723 __storage_(make_shared<_Storage>(__p1, __p2)) {
1724 __create_what(2);
1725 }
1726
1727 _LIBCPP_INLINE_VISIBILITY
1728 const path& path1() const noexcept { return __storage_->__p1_; }
1729
1730 _LIBCPP_INLINE_VISIBILITY
1731 const path& path2() const noexcept { return __storage_->__p2_; }
1732
Dimitry Andric47269ce2020-03-13 19:36:26 +01001733 filesystem_error(const filesystem_error&) = default;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001734 ~filesystem_error() override; // key function
1735
1736 _LIBCPP_INLINE_VISIBILITY
1737 const char* what() const noexcept override {
1738 return __storage_->__what_.c_str();
1739 }
1740
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001741 void __create_what(int __num_paths);
1742
1743private:
Louis Dionne48ae8892019-03-19 17:47:53 +00001744 struct _LIBCPP_HIDDEN _Storage {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001745 _LIBCPP_INLINE_VISIBILITY
1746 _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
1747
1748 path __p1_;
1749 path __p2_;
1750 string __what_;
1751 };
1752 shared_ptr<_Storage> __storage_;
1753};
1754
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001755_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
1756
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001757template <class... _Args>
1758_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
1759#ifndef _LIBCPP_NO_EXCEPTIONS
Louis Dionne6251ef02019-02-05 15:46:52 +00001760void __throw_filesystem_error(_Args&&... __args) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001761 throw filesystem_error(_VSTD::forward<_Args>(__args)...);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001762}
1763#else
Louis Dionne6251ef02019-02-05 15:46:52 +00001764void __throw_filesystem_error(_Args&&...) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001765 _VSTD::abort();
1766}
1767#endif
1768
1769// operational functions
1770
1771_LIBCPP_FUNC_VIS
1772path __absolute(const path&, error_code* __ec = nullptr);
1773_LIBCPP_FUNC_VIS
1774path __canonical(const path&, error_code* __ec = nullptr);
1775_LIBCPP_FUNC_VIS
1776void __copy(const path& __from, const path& __to, copy_options __opt,
1777 error_code* __ec = nullptr);
1778_LIBCPP_FUNC_VIS
1779bool __copy_file(const path& __from, const path& __to, copy_options __opt,
1780 error_code* __ec = nullptr);
1781_LIBCPP_FUNC_VIS
1782void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
1783 error_code* __ec = nullptr);
1784_LIBCPP_FUNC_VIS
1785bool __create_directories(const path& p, error_code* ec = nullptr);
1786_LIBCPP_FUNC_VIS
1787bool __create_directory(const path& p, error_code* ec = nullptr);
1788_LIBCPP_FUNC_VIS
1789bool __create_directory(const path& p, const path& attributes,
1790 error_code* ec = nullptr);
1791_LIBCPP_FUNC_VIS
1792void __create_directory_symlink(const path& __to, const path& __new_symlink,
1793 error_code* __ec = nullptr);
1794_LIBCPP_FUNC_VIS
1795void __create_hard_link(const path& __to, const path& __new_hard_link,
1796 error_code* __ec = nullptr);
1797_LIBCPP_FUNC_VIS
1798void __create_symlink(const path& __to, const path& __new_symlink,
1799 error_code* __ec = nullptr);
1800_LIBCPP_FUNC_VIS
1801path __current_path(error_code* __ec = nullptr);
1802_LIBCPP_FUNC_VIS
1803void __current_path(const path&, error_code* __ec = nullptr);
1804_LIBCPP_FUNC_VIS
1805bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
1806_LIBCPP_FUNC_VIS
1807uintmax_t __file_size(const path&, error_code* __ec = nullptr);
1808_LIBCPP_FUNC_VIS
1809uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
1810_LIBCPP_FUNC_VIS
1811bool __fs_is_empty(const path& p, error_code* ec = nullptr);
1812_LIBCPP_FUNC_VIS
1813file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
1814_LIBCPP_FUNC_VIS
1815void __last_write_time(const path& p, file_time_type new_time,
1816 error_code* ec = nullptr);
1817_LIBCPP_FUNC_VIS
1818void __permissions(const path&, perms, perm_options, error_code* = nullptr);
1819_LIBCPP_FUNC_VIS
1820path __read_symlink(const path& p, error_code* ec = nullptr);
1821_LIBCPP_FUNC_VIS
1822bool __remove(const path& p, error_code* ec = nullptr);
1823_LIBCPP_FUNC_VIS
1824uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
1825_LIBCPP_FUNC_VIS
1826void __rename(const path& from, const path& to, error_code* ec = nullptr);
1827_LIBCPP_FUNC_VIS
1828void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
1829_LIBCPP_FUNC_VIS
1830space_info __space(const path&, error_code* __ec = nullptr);
1831_LIBCPP_FUNC_VIS
1832file_status __status(const path&, error_code* __ec = nullptr);
1833_LIBCPP_FUNC_VIS
1834file_status __symlink_status(const path&, error_code* __ec = nullptr);
1835_LIBCPP_FUNC_VIS
1836path __system_complete(const path&, error_code* __ec = nullptr);
1837_LIBCPP_FUNC_VIS
1838path __temp_directory_path(error_code* __ec = nullptr);
1839_LIBCPP_FUNC_VIS
1840path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
1841
1842inline _LIBCPP_INLINE_VISIBILITY path current_path() {
1843 return __current_path();
1844}
1845
1846inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
1847 return __current_path(&__ec);
1848}
1849
1850inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
1851 __current_path(__p);
1852}
1853
1854inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
1855 error_code& __ec) noexcept {
1856 __current_path(__p, &__ec);
1857}
1858
1859inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
1860 return __absolute(__p);
1861}
1862
1863inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
1864 error_code& __ec) {
1865 return __absolute(__p, &__ec);
1866}
1867
1868inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
1869 return __canonical(__p);
1870}
1871
1872inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
1873 error_code& __ec) {
1874 return __canonical(__p, &__ec);
1875}
1876
1877inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
1878 const path& __to) {
1879 __copy(__from, __to, copy_options::none);
1880}
1881
1882inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1883 error_code& __ec) {
1884 __copy(__from, __to, copy_options::none, &__ec);
1885}
1886
1887inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1888 copy_options __opt) {
1889 __copy(__from, __to, __opt);
1890}
1891
1892inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1893 copy_options __opt,
1894 error_code& __ec) {
1895 __copy(__from, __to, __opt, &__ec);
1896}
1897
1898inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1899 const path& __to) {
1900 return __copy_file(__from, __to, copy_options::none);
1901}
1902
1903inline _LIBCPP_INLINE_VISIBILITY bool
1904copy_file(const path& __from, const path& __to, error_code& __ec) {
1905 return __copy_file(__from, __to, copy_options::none, &__ec);
1906}
1907
1908inline _LIBCPP_INLINE_VISIBILITY bool
1909copy_file(const path& __from, const path& __to, copy_options __opt) {
1910 return __copy_file(__from, __to, __opt);
1911}
1912
1913inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1914 const path& __to,
1915 copy_options __opt,
1916 error_code& __ec) {
1917 return __copy_file(__from, __to, __opt, &__ec);
1918}
1919
1920inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
1921 const path& __new) {
1922 __copy_symlink(__existing, __new);
1923}
1924
1925inline _LIBCPP_INLINE_VISIBILITY void
1926copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
1927 __copy_symlink(__ext, __new, &__ec);
1928}
1929
1930inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
1931 return __create_directories(__p);
1932}
1933
1934inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
1935 error_code& __ec) {
1936 return __create_directories(__p, &__ec);
1937}
1938
1939inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
1940 return __create_directory(__p);
1941}
1942
1943inline _LIBCPP_INLINE_VISIBILITY bool
1944create_directory(const path& __p, error_code& __ec) noexcept {
1945 return __create_directory(__p, &__ec);
1946}
1947
1948inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
1949 const path& __attrs) {
1950 return __create_directory(__p, __attrs);
1951}
1952
1953inline _LIBCPP_INLINE_VISIBILITY bool
1954create_directory(const path& __p, const path& __attrs,
1955 error_code& __ec) noexcept {
1956 return __create_directory(__p, __attrs, &__ec);
1957}
1958
1959inline _LIBCPP_INLINE_VISIBILITY void
1960create_directory_symlink(const path& __to, const path& __new) {
1961 __create_directory_symlink(__to, __new);
1962}
1963
1964inline _LIBCPP_INLINE_VISIBILITY void
1965create_directory_symlink(const path& __to, const path& __new,
1966 error_code& __ec) noexcept {
1967 __create_directory_symlink(__to, __new, &__ec);
1968}
1969
1970inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
1971 const path& __new) {
1972 __create_hard_link(__to, __new);
1973}
1974
1975inline _LIBCPP_INLINE_VISIBILITY void
1976create_hard_link(const path& __to, const path& __new,
1977 error_code& __ec) noexcept {
1978 __create_hard_link(__to, __new, &__ec);
1979}
1980
1981inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
1982 const path& __new) {
1983 __create_symlink(__to, __new);
1984}
1985
1986inline _LIBCPP_INLINE_VISIBILITY void
1987create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
1988 return __create_symlink(__to, __new, &__ec);
1989}
1990
1991inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
1992 return __s.type() != file_type::none;
1993}
1994
1995inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
1996 return status_known(__s) && __s.type() != file_type::not_found;
1997}
1998
1999inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
2000 return exists(__status(__p));
2001}
2002
2003inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
2004 error_code& __ec) noexcept {
2005 auto __s = __status(__p, &__ec);
2006 if (status_known(__s))
2007 __ec.clear();
2008 return exists(__s);
2009}
2010
2011inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
2012 const path& __p2) {
2013 return __equivalent(__p1, __p2);
2014}
2015
2016inline _LIBCPP_INLINE_VISIBILITY bool
2017equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
2018 return __equivalent(__p1, __p2, &__ec);
2019}
2020
2021inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
2022 return __file_size(__p);
2023}
2024
2025inline _LIBCPP_INLINE_VISIBILITY uintmax_t
2026file_size(const path& __p, error_code& __ec) noexcept {
2027 return __file_size(__p, &__ec);
2028}
2029
2030inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
2031 return __hard_link_count(__p);
2032}
2033
2034inline _LIBCPP_INLINE_VISIBILITY uintmax_t
2035hard_link_count(const path& __p, error_code& __ec) noexcept {
2036 return __hard_link_count(__p, &__ec);
2037}
2038
2039inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
2040 return __s.type() == file_type::block;
2041}
2042
2043inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
2044 return is_block_file(__status(__p));
2045}
2046
2047inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
2048 error_code& __ec) noexcept {
2049 return is_block_file(__status(__p, &__ec));
2050}
2051
2052inline _LIBCPP_INLINE_VISIBILITY bool
2053is_character_file(file_status __s) noexcept {
2054 return __s.type() == file_type::character;
2055}
2056
2057inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
2058 return is_character_file(__status(__p));
2059}
2060
2061inline _LIBCPP_INLINE_VISIBILITY bool
2062is_character_file(const path& __p, error_code& __ec) noexcept {
2063 return is_character_file(__status(__p, &__ec));
2064}
2065
2066inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
2067 return __s.type() == file_type::directory;
2068}
2069
2070inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
2071 return is_directory(__status(__p));
2072}
2073
2074inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
2075 error_code& __ec) noexcept {
2076 return is_directory(__status(__p, &__ec));
2077}
2078
2079inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
2080 return __fs_is_empty(__p);
2081}
2082
2083inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
2084 error_code& __ec) {
2085 return __fs_is_empty(__p, &__ec);
2086}
2087
2088inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
2089 return __s.type() == file_type::fifo;
2090}
2091inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
2092 return is_fifo(__status(__p));
2093}
2094
2095inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
2096 error_code& __ec) noexcept {
2097 return is_fifo(__status(__p, &__ec));
2098}
2099
2100inline _LIBCPP_INLINE_VISIBILITY bool
2101is_regular_file(file_status __s) noexcept {
2102 return __s.type() == file_type::regular;
2103}
2104
2105inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
2106 return is_regular_file(__status(__p));
2107}
2108
2109inline _LIBCPP_INLINE_VISIBILITY bool
2110is_regular_file(const path& __p, error_code& __ec) noexcept {
2111 return is_regular_file(__status(__p, &__ec));
2112}
2113
2114inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
2115 return __s.type() == file_type::socket;
2116}
2117
2118inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
2119 return is_socket(__status(__p));
2120}
2121
2122inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
2123 error_code& __ec) noexcept {
2124 return is_socket(__status(__p, &__ec));
2125}
2126
2127inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
2128 return __s.type() == file_type::symlink;
2129}
2130
2131inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
2132 return is_symlink(__symlink_status(__p));
2133}
2134
2135inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
2136 error_code& __ec) noexcept {
2137 return is_symlink(__symlink_status(__p, &__ec));
2138}
2139
2140inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
2141 return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
2142 !is_symlink(__s);
2143}
2144
2145inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
2146 return is_other(__status(__p));
2147}
2148
2149inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
2150 error_code& __ec) noexcept {
2151 return is_other(__status(__p, &__ec));
2152}
2153
2154inline _LIBCPP_INLINE_VISIBILITY file_time_type
2155last_write_time(const path& __p) {
2156 return __last_write_time(__p);
2157}
2158
2159inline _LIBCPP_INLINE_VISIBILITY file_time_type
2160last_write_time(const path& __p, error_code& __ec) noexcept {
2161 return __last_write_time(__p, &__ec);
2162}
2163
2164inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
2165 file_time_type __t) {
2166 __last_write_time(__p, __t);
2167}
2168
2169inline _LIBCPP_INLINE_VISIBILITY void
2170last_write_time(const path& __p, file_time_type __t,
2171 error_code& __ec) noexcept {
2172 __last_write_time(__p, __t, &__ec);
2173}
2174
2175inline _LIBCPP_INLINE_VISIBILITY void
2176permissions(const path& __p, perms __prms,
2177 perm_options __opts = perm_options::replace) {
2178 __permissions(__p, __prms, __opts);
2179}
2180
2181inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2182 error_code& __ec) noexcept {
2183 __permissions(__p, __prms, perm_options::replace, &__ec);
2184}
2185
2186inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2187 perm_options __opts,
2188 error_code& __ec) {
2189 __permissions(__p, __prms, __opts, &__ec);
2190}
2191
2192inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2193 const path& __base,
2194 error_code& __ec) {
2195 path __tmp = __weakly_canonical(__p, &__ec);
2196 if (__ec)
2197 return {};
2198 path __tmp_base = __weakly_canonical(__base, &__ec);
2199 if (__ec)
2200 return {};
2201 return __tmp.lexically_proximate(__tmp_base);
2202}
2203
2204inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2205 error_code& __ec) {
2206 return proximate(__p, current_path(), __ec);
2207}
2208
2209inline _LIBCPP_INLINE_VISIBILITY path
2210proximate(const path& __p, const path& __base = current_path()) {
2211 return __weakly_canonical(__p).lexically_proximate(
2212 __weakly_canonical(__base));
2213}
2214
2215inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
2216 return __read_symlink(__p);
2217}
2218
2219inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
2220 error_code& __ec) {
2221 return __read_symlink(__p, &__ec);
2222}
2223
2224inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2225 const path& __base,
2226 error_code& __ec) {
2227 path __tmp = __weakly_canonical(__p, &__ec);
2228 if (__ec)
2229 return path();
2230 path __tmpbase = __weakly_canonical(__base, &__ec);
2231 if (__ec)
2232 return path();
2233 return __tmp.lexically_relative(__tmpbase);
2234}
2235
2236inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2237 error_code& __ec) {
2238 return relative(__p, current_path(), __ec);
2239}
2240
2241inline _LIBCPP_INLINE_VISIBILITY path
2242relative(const path& __p, const path& __base = current_path()) {
2243 return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
2244}
2245
2246inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
2247 return __remove(__p);
2248}
2249
2250inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
2251 error_code& __ec) noexcept {
2252 return __remove(__p, &__ec);
2253}
2254
2255inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
2256 return __remove_all(__p);
2257}
2258
2259inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
2260 error_code& __ec) {
2261 return __remove_all(__p, &__ec);
2262}
2263
2264inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
2265 const path& __to) {
2266 return __rename(__from, __to);
2267}
2268
2269inline _LIBCPP_INLINE_VISIBILITY void
2270rename(const path& __from, const path& __to, error_code& __ec) noexcept {
2271 return __rename(__from, __to, &__ec);
2272}
2273
2274inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
2275 uintmax_t __ns) {
2276 return __resize_file(__p, __ns);
2277}
2278
2279inline _LIBCPP_INLINE_VISIBILITY void
2280resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
2281 return __resize_file(__p, __ns, &__ec);
2282}
2283
2284inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
2285 return __space(__p);
2286}
2287
2288inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
2289 error_code& __ec) noexcept {
2290 return __space(__p, &__ec);
2291}
2292
2293inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
2294 return __status(__p);
2295}
2296
2297inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
2298 error_code& __ec) noexcept {
2299 return __status(__p, &__ec);
2300}
2301
2302inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
2303 return __symlink_status(__p);
2304}
2305
2306inline _LIBCPP_INLINE_VISIBILITY file_status
2307symlink_status(const path& __p, error_code& __ec) noexcept {
2308 return __symlink_status(__p, &__ec);
2309}
2310
2311inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
2312 return __temp_directory_path();
2313}
2314
2315inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
2316 return __temp_directory_path(&__ec);
2317}
2318
2319inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
2320 return __weakly_canonical(__p);
2321}
2322
2323inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
2324 error_code& __ec) {
2325 return __weakly_canonical(__p, &__ec);
2326}
2327
2328class directory_iterator;
2329class recursive_directory_iterator;
Louis Dionne48ae8892019-03-19 17:47:53 +00002330class _LIBCPP_HIDDEN __dir_stream;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002331
2332class directory_entry {
2333 typedef _VSTD_FS::path _Path;
2334
2335public:
2336 // constructors and destructors
2337 directory_entry() noexcept = default;
2338 directory_entry(directory_entry const&) = default;
2339 directory_entry(directory_entry&&) noexcept = default;
2340
2341 _LIBCPP_INLINE_VISIBILITY
2342 explicit directory_entry(_Path const& __p) : __p_(__p) {
2343 error_code __ec;
2344 __refresh(&__ec);
2345 }
2346
2347 _LIBCPP_INLINE_VISIBILITY
2348 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
2349 __refresh(&__ec);
2350 }
2351
2352 ~directory_entry() {}
2353
2354 directory_entry& operator=(directory_entry const&) = default;
2355 directory_entry& operator=(directory_entry&&) noexcept = default;
2356
2357 _LIBCPP_INLINE_VISIBILITY
2358 void assign(_Path const& __p) {
2359 __p_ = __p;
2360 error_code __ec;
2361 __refresh(&__ec);
2362 }
2363
2364 _LIBCPP_INLINE_VISIBILITY
2365 void assign(_Path const& __p, error_code& __ec) {
2366 __p_ = __p;
2367 __refresh(&__ec);
2368 }
2369
2370 _LIBCPP_INLINE_VISIBILITY
2371 void replace_filename(_Path const& __p) {
2372 __p_.replace_filename(__p);
2373 error_code __ec;
2374 __refresh(&__ec);
2375 }
2376
2377 _LIBCPP_INLINE_VISIBILITY
2378 void replace_filename(_Path const& __p, error_code& __ec) {
2379 __p_ = __p_.parent_path() / __p;
2380 __refresh(&__ec);
2381 }
2382
2383 _LIBCPP_INLINE_VISIBILITY
2384 void refresh() { __refresh(); }
2385
2386 _LIBCPP_INLINE_VISIBILITY
2387 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
2388
2389 _LIBCPP_INLINE_VISIBILITY
2390 _Path const& path() const noexcept { return __p_; }
2391
2392 _LIBCPP_INLINE_VISIBILITY
2393 operator const _Path&() const noexcept { return __p_; }
2394
2395 _LIBCPP_INLINE_VISIBILITY
2396 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
2397
2398 _LIBCPP_INLINE_VISIBILITY
2399 bool exists(error_code& __ec) const noexcept {
2400 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
2401 }
2402
2403 _LIBCPP_INLINE_VISIBILITY
2404 bool is_block_file() const { return __get_ft() == file_type::block; }
2405
2406 _LIBCPP_INLINE_VISIBILITY
2407 bool is_block_file(error_code& __ec) const noexcept {
2408 return __get_ft(&__ec) == file_type::block;
2409 }
2410
2411 _LIBCPP_INLINE_VISIBILITY
2412 bool is_character_file() const { return __get_ft() == file_type::character; }
2413
2414 _LIBCPP_INLINE_VISIBILITY
2415 bool is_character_file(error_code& __ec) const noexcept {
2416 return __get_ft(&__ec) == file_type::character;
2417 }
2418
2419 _LIBCPP_INLINE_VISIBILITY
2420 bool is_directory() const { return __get_ft() == file_type::directory; }
2421
2422 _LIBCPP_INLINE_VISIBILITY
2423 bool is_directory(error_code& __ec) const noexcept {
2424 return __get_ft(&__ec) == file_type::directory;
2425 }
2426
2427 _LIBCPP_INLINE_VISIBILITY
2428 bool is_fifo() const { return __get_ft() == file_type::fifo; }
2429
2430 _LIBCPP_INLINE_VISIBILITY
2431 bool is_fifo(error_code& __ec) const noexcept {
2432 return __get_ft(&__ec) == file_type::fifo;
2433 }
2434
2435 _LIBCPP_INLINE_VISIBILITY
2436 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
2437
2438 _LIBCPP_INLINE_VISIBILITY
2439 bool is_other(error_code& __ec) const noexcept {
2440 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
2441 }
2442
2443 _LIBCPP_INLINE_VISIBILITY
2444 bool is_regular_file() const { return __get_ft() == file_type::regular; }
2445
2446 _LIBCPP_INLINE_VISIBILITY
2447 bool is_regular_file(error_code& __ec) const noexcept {
2448 return __get_ft(&__ec) == file_type::regular;
2449 }
2450
2451 _LIBCPP_INLINE_VISIBILITY
2452 bool is_socket() const { return __get_ft() == file_type::socket; }
2453
2454 _LIBCPP_INLINE_VISIBILITY
2455 bool is_socket(error_code& __ec) const noexcept {
2456 return __get_ft(&__ec) == file_type::socket;
2457 }
2458
2459 _LIBCPP_INLINE_VISIBILITY
2460 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
2461
2462 _LIBCPP_INLINE_VISIBILITY
2463 bool is_symlink(error_code& __ec) const noexcept {
2464 return __get_sym_ft(&__ec) == file_type::symlink;
2465 }
2466 _LIBCPP_INLINE_VISIBILITY
2467 uintmax_t file_size() const { return __get_size(); }
2468
2469 _LIBCPP_INLINE_VISIBILITY
2470 uintmax_t file_size(error_code& __ec) const noexcept {
2471 return __get_size(&__ec);
2472 }
2473
2474 _LIBCPP_INLINE_VISIBILITY
2475 uintmax_t hard_link_count() const { return __get_nlink(); }
2476
2477 _LIBCPP_INLINE_VISIBILITY
2478 uintmax_t hard_link_count(error_code& __ec) const noexcept {
2479 return __get_nlink(&__ec);
2480 }
2481
2482 _LIBCPP_INLINE_VISIBILITY
2483 file_time_type last_write_time() const { return __get_write_time(); }
2484
2485 _LIBCPP_INLINE_VISIBILITY
2486 file_time_type last_write_time(error_code& __ec) const noexcept {
2487 return __get_write_time(&__ec);
2488 }
2489
2490 _LIBCPP_INLINE_VISIBILITY
2491 file_status status() const { return __get_status(); }
2492
2493 _LIBCPP_INLINE_VISIBILITY
2494 file_status status(error_code& __ec) const noexcept {
2495 return __get_status(&__ec);
2496 }
2497
2498 _LIBCPP_INLINE_VISIBILITY
2499 file_status symlink_status() const { return __get_symlink_status(); }
2500
2501 _LIBCPP_INLINE_VISIBILITY
2502 file_status symlink_status(error_code& __ec) const noexcept {
2503 return __get_symlink_status(&__ec);
2504 }
2505
2506 _LIBCPP_INLINE_VISIBILITY
2507 bool operator<(directory_entry const& __rhs) const noexcept {
2508 return __p_ < __rhs.__p_;
2509 }
2510
2511 _LIBCPP_INLINE_VISIBILITY
2512 bool operator==(directory_entry const& __rhs) const noexcept {
2513 return __p_ == __rhs.__p_;
2514 }
2515
2516 _LIBCPP_INLINE_VISIBILITY
2517 bool operator!=(directory_entry const& __rhs) const noexcept {
2518 return __p_ != __rhs.__p_;
2519 }
2520
2521 _LIBCPP_INLINE_VISIBILITY
2522 bool operator<=(directory_entry const& __rhs) const noexcept {
2523 return __p_ <= __rhs.__p_;
2524 }
2525
2526 _LIBCPP_INLINE_VISIBILITY
2527 bool operator>(directory_entry const& __rhs) const noexcept {
2528 return __p_ > __rhs.__p_;
2529 }
2530
2531 _LIBCPP_INLINE_VISIBILITY
2532 bool operator>=(directory_entry const& __rhs) const noexcept {
2533 return __p_ >= __rhs.__p_;
2534 }
2535
2536private:
2537 friend class directory_iterator;
2538 friend class recursive_directory_iterator;
2539 friend class __dir_stream;
2540
2541 enum _CacheType : unsigned char {
2542 _Empty,
2543 _IterSymlink,
2544 _IterNonSymlink,
2545 _RefreshSymlink,
2546 _RefreshSymlinkUnresolved,
2547 _RefreshNonSymlink
2548 };
2549
2550 struct __cached_data {
2551 uintmax_t __size_;
2552 uintmax_t __nlink_;
2553 file_time_type __write_time_;
2554 perms __sym_perms_;
2555 perms __non_sym_perms_;
2556 file_type __type_;
2557 _CacheType __cache_type_;
2558
2559 _LIBCPP_INLINE_VISIBILITY
2560 __cached_data() noexcept { __reset(); }
2561
2562 _LIBCPP_INLINE_VISIBILITY
2563 void __reset() {
2564 __cache_type_ = _Empty;
2565 __type_ = file_type::none;
2566 __sym_perms_ = __non_sym_perms_ = perms::unknown;
2567 __size_ = __nlink_ = uintmax_t(-1);
2568 __write_time_ = file_time_type::min();
2569 }
2570 };
2571
2572 _LIBCPP_INLINE_VISIBILITY
2573 static __cached_data __create_iter_result(file_type __ft) {
2574 __cached_data __data;
2575 __data.__type_ = __ft;
2576 __data.__cache_type_ = [&]() {
2577 switch (__ft) {
2578 case file_type::none:
2579 return _Empty;
2580 case file_type::symlink:
2581 return _IterSymlink;
2582 default:
2583 return _IterNonSymlink;
2584 }
2585 }();
2586 return __data;
2587 }
2588
2589 _LIBCPP_INLINE_VISIBILITY
2590 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002591 __p_ = _VSTD::move(__p);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002592 __data_ = __dt;
2593 }
2594
2595 _LIBCPP_FUNC_VIS
2596 error_code __do_refresh() noexcept;
2597
2598 _LIBCPP_INLINE_VISIBILITY
2599 static bool __is_dne_error(error_code const& __ec) {
2600 if (!__ec)
2601 return true;
2602 switch (static_cast<errc>(__ec.value())) {
2603 case errc::no_such_file_or_directory:
2604 case errc::not_a_directory:
2605 return true;
2606 default:
2607 return false;
2608 }
2609 }
2610
2611 _LIBCPP_INLINE_VISIBILITY
2612 void __handle_error(const char* __msg, error_code* __dest_ec,
2613 error_code const& __ec, bool __allow_dne = false) const {
2614 if (__dest_ec) {
2615 *__dest_ec = __ec;
2616 return;
2617 }
2618 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
2619 __throw_filesystem_error(__msg, __p_, __ec);
2620 }
2621
2622 _LIBCPP_INLINE_VISIBILITY
2623 void __refresh(error_code* __ec = nullptr) {
2624 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
2625 /*allow_dne*/ true);
2626 }
2627
2628 _LIBCPP_INLINE_VISIBILITY
2629 file_type __get_sym_ft(error_code* __ec = nullptr) const {
2630 switch (__data_.__cache_type_) {
2631 case _Empty:
2632 return __symlink_status(__p_, __ec).type();
2633 case _IterSymlink:
2634 case _RefreshSymlink:
2635 case _RefreshSymlinkUnresolved:
2636 if (__ec)
2637 __ec->clear();
2638 return file_type::symlink;
2639 case _IterNonSymlink:
2640 case _RefreshNonSymlink:
2641 file_status __st(__data_.__type_);
2642 if (__ec && !_VSTD_FS::exists(__st))
2643 *__ec = make_error_code(errc::no_such_file_or_directory);
2644 else if (__ec)
2645 __ec->clear();
2646 return __data_.__type_;
2647 }
2648 _LIBCPP_UNREACHABLE();
2649 }
2650
2651 _LIBCPP_INLINE_VISIBILITY
2652 file_type __get_ft(error_code* __ec = nullptr) const {
2653 switch (__data_.__cache_type_) {
2654 case _Empty:
2655 case _IterSymlink:
2656 case _RefreshSymlinkUnresolved:
2657 return __status(__p_, __ec).type();
2658 case _IterNonSymlink:
2659 case _RefreshNonSymlink:
2660 case _RefreshSymlink: {
2661 file_status __st(__data_.__type_);
2662 if (__ec && !_VSTD_FS::exists(__st))
2663 *__ec = make_error_code(errc::no_such_file_or_directory);
2664 else if (__ec)
2665 __ec->clear();
2666 return __data_.__type_;
2667 }
2668 }
2669 _LIBCPP_UNREACHABLE();
2670 }
2671
2672 _LIBCPP_INLINE_VISIBILITY
2673 file_status __get_status(error_code* __ec = nullptr) const {
2674 switch (__data_.__cache_type_) {
2675 case _Empty:
2676 case _IterNonSymlink:
2677 case _IterSymlink:
2678 case _RefreshSymlinkUnresolved:
2679 return __status(__p_, __ec);
2680 case _RefreshNonSymlink:
2681 case _RefreshSymlink:
2682 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
2683 }
2684 _LIBCPP_UNREACHABLE();
2685 }
2686
2687 _LIBCPP_INLINE_VISIBILITY
2688 file_status __get_symlink_status(error_code* __ec = nullptr) const {
2689 switch (__data_.__cache_type_) {
2690 case _Empty:
2691 case _IterNonSymlink:
2692 case _IterSymlink:
2693 return __symlink_status(__p_, __ec);
2694 case _RefreshNonSymlink:
2695 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
2696 case _RefreshSymlink:
2697 case _RefreshSymlinkUnresolved:
2698 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
2699 }
2700 _LIBCPP_UNREACHABLE();
2701 }
2702
2703 _LIBCPP_INLINE_VISIBILITY
2704 uintmax_t __get_size(error_code* __ec = nullptr) const {
2705 switch (__data_.__cache_type_) {
2706 case _Empty:
2707 case _IterNonSymlink:
2708 case _IterSymlink:
2709 case _RefreshSymlinkUnresolved:
2710 return _VSTD_FS::__file_size(__p_, __ec);
2711 case _RefreshSymlink:
2712 case _RefreshNonSymlink: {
2713 error_code __m_ec;
2714 file_status __st(__get_ft(&__m_ec));
2715 __handle_error("in directory_entry::file_size", __ec, __m_ec);
2716 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
2717 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
2718 : errc::not_supported;
2719 __handle_error("in directory_entry::file_size", __ec,
2720 make_error_code(__err_kind));
2721 }
2722 return __data_.__size_;
2723 }
2724 }
2725 _LIBCPP_UNREACHABLE();
2726 }
2727
2728 _LIBCPP_INLINE_VISIBILITY
2729 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
2730 switch (__data_.__cache_type_) {
2731 case _Empty:
2732 case _IterNonSymlink:
2733 case _IterSymlink:
2734 case _RefreshSymlinkUnresolved:
2735 return _VSTD_FS::__hard_link_count(__p_, __ec);
2736 case _RefreshSymlink:
2737 case _RefreshNonSymlink: {
2738 error_code __m_ec;
2739 (void)__get_ft(&__m_ec);
2740 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
2741 return __data_.__nlink_;
2742 }
2743 }
2744 _LIBCPP_UNREACHABLE();
2745 }
2746
2747 _LIBCPP_INLINE_VISIBILITY
2748 file_time_type __get_write_time(error_code* __ec = nullptr) const {
2749 switch (__data_.__cache_type_) {
2750 case _Empty:
2751 case _IterNonSymlink:
2752 case _IterSymlink:
2753 case _RefreshSymlinkUnresolved:
2754 return _VSTD_FS::__last_write_time(__p_, __ec);
2755 case _RefreshSymlink:
2756 case _RefreshNonSymlink: {
2757 error_code __m_ec;
2758 file_status __st(__get_ft(&__m_ec));
2759 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
2760 if (_VSTD_FS::exists(__st) &&
2761 __data_.__write_time_ == file_time_type::min())
2762 __handle_error("in directory_entry::last_write_time", __ec,
2763 make_error_code(errc::value_too_large));
2764 return __data_.__write_time_;
2765 }
2766 }
2767 _LIBCPP_UNREACHABLE();
2768 }
2769
2770private:
2771 _Path __p_;
2772 __cached_data __data_;
2773};
2774
2775class __dir_element_proxy {
2776public:
2777 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
2778 return _VSTD::move(__elem_);
2779 }
2780
2781private:
2782 friend class directory_iterator;
2783 friend class recursive_directory_iterator;
2784 explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
2785 __dir_element_proxy(__dir_element_proxy&& __o)
2786 : __elem_(_VSTD::move(__o.__elem_)) {}
2787 directory_entry __elem_;
2788};
2789
2790class directory_iterator {
2791public:
2792 typedef directory_entry value_type;
2793 typedef ptrdiff_t difference_type;
2794 typedef value_type const* pointer;
2795 typedef value_type const& reference;
2796 typedef input_iterator_tag iterator_category;
2797
2798public:
2799 //ctor & dtor
2800 directory_iterator() noexcept {}
2801
2802 explicit directory_iterator(const path& __p)
2803 : directory_iterator(__p, nullptr) {}
2804
2805 directory_iterator(const path& __p, directory_options __opts)
2806 : directory_iterator(__p, nullptr, __opts) {}
2807
2808 directory_iterator(const path& __p, error_code& __ec)
2809 : directory_iterator(__p, &__ec) {}
2810
2811 directory_iterator(const path& __p, directory_options __opts,
2812 error_code& __ec)
2813 : directory_iterator(__p, &__ec, __opts) {}
2814
2815 directory_iterator(const directory_iterator&) = default;
2816 directory_iterator(directory_iterator&&) = default;
2817 directory_iterator& operator=(const directory_iterator&) = default;
2818
2819 directory_iterator& operator=(directory_iterator&& __o) noexcept {
2820 // non-default implementation provided to support self-move assign.
2821 if (this != &__o) {
2822 __imp_ = _VSTD::move(__o.__imp_);
2823 }
2824 return *this;
2825 }
2826
2827 ~directory_iterator() = default;
2828
2829 const directory_entry& operator*() const {
2830 _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
2831 return __dereference();
2832 }
2833
2834 const directory_entry* operator->() const { return &**this; }
2835
2836 directory_iterator& operator++() { return __increment(); }
2837
2838 __dir_element_proxy operator++(int) {
2839 __dir_element_proxy __p(**this);
2840 __increment();
2841 return __p;
2842 }
2843
2844 directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
2845
2846private:
2847 inline _LIBCPP_INLINE_VISIBILITY friend bool
2848 operator==(const directory_iterator& __lhs,
2849 const directory_iterator& __rhs) noexcept;
2850
2851 // construct the dir_stream
2852 _LIBCPP_FUNC_VIS
2853 directory_iterator(const path&, error_code*,
2854 directory_options = directory_options::none);
2855
2856 _LIBCPP_FUNC_VIS
2857 directory_iterator& __increment(error_code* __ec = nullptr);
2858
2859 _LIBCPP_FUNC_VIS
2860 const directory_entry& __dereference() const;
2861
2862private:
2863 shared_ptr<__dir_stream> __imp_;
2864};
2865
2866inline _LIBCPP_INLINE_VISIBILITY bool
2867operator==(const directory_iterator& __lhs,
2868 const directory_iterator& __rhs) noexcept {
2869 return __lhs.__imp_ == __rhs.__imp_;
2870}
2871
2872inline _LIBCPP_INLINE_VISIBILITY bool
2873operator!=(const directory_iterator& __lhs,
2874 const directory_iterator& __rhs) noexcept {
2875 return !(__lhs == __rhs);
2876}
2877
2878// enable directory_iterator range-based for statements
2879inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2880begin(directory_iterator __iter) noexcept {
2881 return __iter;
2882}
2883
2884inline _LIBCPP_INLINE_VISIBILITY directory_iterator
Joe Loser9d1c0d42021-10-14 11:53:43 -04002885end(directory_iterator) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002886 return directory_iterator();
2887}
2888
2889class recursive_directory_iterator {
2890public:
2891 using value_type = directory_entry;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002892 using difference_type = ptrdiff_t;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002893 using pointer = directory_entry const*;
2894 using reference = directory_entry const&;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002895 using iterator_category = input_iterator_tag;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002896
2897public:
2898 // constructors and destructor
2899 _LIBCPP_INLINE_VISIBILITY
2900 recursive_directory_iterator() noexcept : __rec_(false) {}
2901
2902 _LIBCPP_INLINE_VISIBILITY
2903 explicit recursive_directory_iterator(
2904 const path& __p, directory_options __xoptions = directory_options::none)
2905 : recursive_directory_iterator(__p, __xoptions, nullptr) {}
2906
2907 _LIBCPP_INLINE_VISIBILITY
2908 recursive_directory_iterator(const path& __p, directory_options __xoptions,
2909 error_code& __ec)
2910 : recursive_directory_iterator(__p, __xoptions, &__ec) {}
2911
2912 _LIBCPP_INLINE_VISIBILITY
2913 recursive_directory_iterator(const path& __p, error_code& __ec)
2914 : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
2915
2916 recursive_directory_iterator(const recursive_directory_iterator&) = default;
2917 recursive_directory_iterator(recursive_directory_iterator&&) = default;
2918
2919 recursive_directory_iterator&
2920 operator=(const recursive_directory_iterator&) = default;
2921
2922 _LIBCPP_INLINE_VISIBILITY
2923 recursive_directory_iterator&
2924 operator=(recursive_directory_iterator&& __o) noexcept {
2925 // non-default implementation provided to support self-move assign.
2926 if (this != &__o) {
2927 __imp_ = _VSTD::move(__o.__imp_);
2928 __rec_ = __o.__rec_;
2929 }
2930 return *this;
2931 }
2932
2933 ~recursive_directory_iterator() = default;
2934
2935 _LIBCPP_INLINE_VISIBILITY
2936 const directory_entry& operator*() const { return __dereference(); }
2937
2938 _LIBCPP_INLINE_VISIBILITY
2939 const directory_entry* operator->() const { return &__dereference(); }
2940
2941 recursive_directory_iterator& operator++() { return __increment(); }
2942
2943 _LIBCPP_INLINE_VISIBILITY
2944 __dir_element_proxy operator++(int) {
2945 __dir_element_proxy __p(**this);
2946 __increment();
2947 return __p;
2948 }
2949
2950 _LIBCPP_INLINE_VISIBILITY
2951 recursive_directory_iterator& increment(error_code& __ec) {
2952 return __increment(&__ec);
2953 }
2954
2955 _LIBCPP_FUNC_VIS directory_options options() const;
2956 _LIBCPP_FUNC_VIS int depth() const;
2957
2958 _LIBCPP_INLINE_VISIBILITY
2959 void pop() { __pop(); }
2960
2961 _LIBCPP_INLINE_VISIBILITY
2962 void pop(error_code& __ec) { __pop(&__ec); }
2963
2964 _LIBCPP_INLINE_VISIBILITY
2965 bool recursion_pending() const { return __rec_; }
2966
2967 _LIBCPP_INLINE_VISIBILITY
2968 void disable_recursion_pending() { __rec_ = false; }
2969
2970private:
Louis Dionne0ba10dc2019-08-13 15:02:53 +00002971 _LIBCPP_FUNC_VIS
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002972 recursive_directory_iterator(const path& __p, directory_options __opt,
2973 error_code* __ec);
2974
2975 _LIBCPP_FUNC_VIS
2976 const directory_entry& __dereference() const;
2977
2978 _LIBCPP_FUNC_VIS
2979 bool __try_recursion(error_code* __ec);
2980
2981 _LIBCPP_FUNC_VIS
2982 void __advance(error_code* __ec = nullptr);
2983
2984 _LIBCPP_FUNC_VIS
2985 recursive_directory_iterator& __increment(error_code* __ec = nullptr);
2986
2987 _LIBCPP_FUNC_VIS
2988 void __pop(error_code* __ec = nullptr);
2989
2990 inline _LIBCPP_INLINE_VISIBILITY friend bool
2991 operator==(const recursive_directory_iterator&,
2992 const recursive_directory_iterator&) noexcept;
2993
Louis Dionne48ae8892019-03-19 17:47:53 +00002994 struct _LIBCPP_HIDDEN __shared_imp;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002995 shared_ptr<__shared_imp> __imp_;
2996 bool __rec_;
2997}; // class recursive_directory_iterator
2998
2999inline _LIBCPP_INLINE_VISIBILITY bool
3000operator==(const recursive_directory_iterator& __lhs,
3001 const recursive_directory_iterator& __rhs) noexcept {
3002 return __lhs.__imp_ == __rhs.__imp_;
3003}
3004
3005_LIBCPP_INLINE_VISIBILITY
3006inline bool operator!=(const recursive_directory_iterator& __lhs,
3007 const recursive_directory_iterator& __rhs) noexcept {
3008 return !(__lhs == __rhs);
3009}
3010// enable recursive_directory_iterator range-based for statements
3011inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
3012begin(recursive_directory_iterator __iter) noexcept {
3013 return __iter;
3014}
3015
3016inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
Joe Loser9d1c0d42021-10-14 11:53:43 -04003017end(recursive_directory_iterator) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003018 return recursive_directory_iterator();
3019}
3020
Louis Dionnef6bf76a2019-03-20 21:18:14 +00003021_LIBCPP_AVAILABILITY_FILESYSTEM_POP
3022
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003023_LIBCPP_END_NAMESPACE_FILESYSTEM
3024
Joe Loser9d1c0d42021-10-14 11:53:43 -04003025#if !defined(_LIBCPP_HAS_NO_RANGES)
3026template <>
Louis Dionne6efb7892021-11-23 12:26:53 -05003027_LIBCPP_AVAILABILITY_FILESYSTEM
Joe Loser9d1c0d42021-10-14 11:53:43 -04003028inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::directory_iterator> = true;
3029template <>
Louis Dionne6efb7892021-11-23 12:26:53 -05003030_LIBCPP_AVAILABILITY_FILESYSTEM
Joe Loser9d1c0d42021-10-14 11:53:43 -04003031inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::recursive_directory_iterator> = true;
3032
3033template <>
Louis Dionne6efb7892021-11-23 12:26:53 -05003034_LIBCPP_AVAILABILITY_FILESYSTEM
Joe Loser9d1c0d42021-10-14 11:53:43 -04003035inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::directory_iterator> = true;
3036template <>
Louis Dionne6efb7892021-11-23 12:26:53 -05003037_LIBCPP_AVAILABILITY_FILESYSTEM
Joe Loser9d1c0d42021-10-14 11:53:43 -04003038inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::recursive_directory_iterator> = true;
3039#endif
3040
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003041#endif // !_LIBCPP_CXX03_LANG
3042
3043_LIBCPP_POP_MACROS
3044
3045#endif // _LIBCPP_FILESYSTEM