blob: 1fd77af99cc41efb0c3a11c23ed40bbde786e9d5 [file] [log] [blame]
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001// -*- C++ -*-
2//===--------------------------- filesystem -------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier02cea5e2018-07-27 03:07:09 +00007//
8//===----------------------------------------------------------------------===//
9#ifndef _LIBCPP_FILESYSTEM
10#define _LIBCPP_FILESYSTEM
11/*
12 filesystem synopsis
13
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
Louis Dionne8d053eb2020-10-09 15:31:05 -0400969#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000970 // TODO Implement locale conversions.
971 template <class _Source, class = _EnableIfPathable<_Source, void> >
972 path(const _Source& __src, const locale& __loc, format = format::auto_format);
973 template <class _InputIt>
974 path(_InputIt __first, _InputIt _last, const locale& __loc,
975 format = format::auto_format);
Louis Dionne8d053eb2020-10-09 15:31:05 -0400976#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000977
978 _LIBCPP_INLINE_VISIBILITY
979 ~path() = default;
980
981 // assignments
982 _LIBCPP_INLINE_VISIBILITY
983 path& operator=(const path& __p) {
984 __pn_ = __p.__pn_;
985 return *this;
986 }
987
988 _LIBCPP_INLINE_VISIBILITY
989 path& operator=(path&& __p) noexcept {
990 __pn_ = _VSTD::move(__p.__pn_);
991 return *this;
992 }
993
Louis Dionne5da71d22021-02-03 16:40:41 -0500994 _LIBCPP_INLINE_VISIBILITY
995 path& operator=(string_type&& __s) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000996 __pn_ = _VSTD::move(__s);
997 return *this;
998 }
999
1000 _LIBCPP_INLINE_VISIBILITY
1001 path& assign(string_type&& __s) noexcept {
1002 __pn_ = _VSTD::move(__s);
1003 return *this;
1004 }
1005
1006 template <class _Source>
1007 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1008 operator=(const _Source& __src) {
1009 return this->assign(__src);
1010 }
1011
1012 template <class _Source>
1013 _EnableIfPathable<_Source> assign(const _Source& __src) {
1014 __pn_.clear();
1015 _SourceCVT<_Source>::__append_source(__pn_, __src);
1016 return *this;
1017 }
1018
1019 template <class _InputIt>
1020 path& assign(_InputIt __first, _InputIt __last) {
1021 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1022 __pn_.clear();
1023 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1024 return *this;
1025 }
1026
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001027public:
1028 // appends
Martin Storsjö98770152020-11-04 15:59:56 +02001029#if defined(_LIBCPP_WIN32API)
1030 path& operator/=(const path& __p) {
1031 auto __p_root_name = __p.__root_name();
1032 auto __p_root_name_size = __p_root_name.size();
1033 if (__p.is_absolute() ||
1034 (!__p_root_name.empty() && __p_root_name != root_name())) {
1035 __pn_ = __p.__pn_;
1036 return *this;
1037 }
1038 if (__p.has_root_directory()) {
1039 path __root_name_str = root_name();
1040 __pn_ = __root_name_str.native();
Martin Storsjöacb39e12021-03-11 13:06:08 +02001041 __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
Martin Storsjö98770152020-11-04 15:59:56 +02001042 return *this;
1043 }
1044 if (has_filename() || (!has_root_directory() && is_absolute()))
1045 __pn_ += preferred_separator;
Martin Storsjöacb39e12021-03-11 13:06:08 +02001046 __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
Martin Storsjö98770152020-11-04 15:59:56 +02001047 return *this;
1048 }
1049 template <class _Source>
1050 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1051 operator/=(const _Source& __src) {
1052 return operator/=(path(__src));
1053 }
1054
1055 template <class _Source>
1056 _EnableIfPathable<_Source> append(const _Source& __src) {
1057 return operator/=(path(__src));
1058 }
1059
1060 template <class _InputIt>
1061 path& append(_InputIt __first, _InputIt __last) {
1062 return operator/=(path(__first, __last));
1063 }
1064#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001065 path& operator/=(const path& __p) {
1066 if (__p.is_absolute()) {
1067 __pn_ = __p.__pn_;
1068 return *this;
1069 }
1070 if (has_filename())
1071 __pn_ += preferred_separator;
1072 __pn_ += __p.native();
1073 return *this;
1074 }
1075
1076 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
1077 // is known at compile time to be "/' since the user almost certainly intended
1078 // to append a separator instead of overwriting the path with "/"
1079 template <class _Source>
1080 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1081 operator/=(const _Source& __src) {
1082 return this->append(__src);
1083 }
1084
1085 template <class _Source>
1086 _EnableIfPathable<_Source> append(const _Source& __src) {
1087 using _Traits = __is_pathable<_Source>;
1088 using _CVT = _PathCVT<_SourceChar<_Source> >;
Martin Storsjö98770152020-11-04 15:59:56 +02001089 bool __source_is_absolute = __is_separator(_Traits::__first_or_null(__src));
1090 if (__source_is_absolute)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001091 __pn_.clear();
1092 else if (has_filename())
1093 __pn_ += preferred_separator;
1094 _CVT::__append_source(__pn_, __src);
1095 return *this;
1096 }
1097
1098 template <class _InputIt>
1099 path& append(_InputIt __first, _InputIt __last) {
1100 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1101 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
1102 using _CVT = _PathCVT<_ItVal>;
Martin Storsjö98770152020-11-04 15:59:56 +02001103 if (__first != __last && __is_separator(*__first))
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001104 __pn_.clear();
1105 else if (has_filename())
1106 __pn_ += preferred_separator;
1107 _CVT::__append_range(__pn_, __first, __last);
1108 return *this;
1109 }
Martin Storsjö98770152020-11-04 15:59:56 +02001110#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001111
1112 // concatenation
1113 _LIBCPP_INLINE_VISIBILITY
1114 path& operator+=(const path& __x) {
1115 __pn_ += __x.__pn_;
1116 return *this;
1117 }
1118
1119 _LIBCPP_INLINE_VISIBILITY
1120 path& operator+=(const string_type& __x) {
1121 __pn_ += __x;
1122 return *this;
1123 }
1124
1125 _LIBCPP_INLINE_VISIBILITY
1126 path& operator+=(__string_view __x) {
1127 __pn_ += __x;
1128 return *this;
1129 }
1130
1131 _LIBCPP_INLINE_VISIBILITY
1132 path& operator+=(const value_type* __x) {
1133 __pn_ += __x;
1134 return *this;
1135 }
1136
1137 _LIBCPP_INLINE_VISIBILITY
1138 path& operator+=(value_type __x) {
1139 __pn_ += __x;
1140 return *this;
1141 }
1142
1143 template <class _ECharT>
1144 typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
1145 operator+=(_ECharT __x) {
Marek Kurdej306a1b02020-12-07 20:07:25 +01001146 _PathCVT<_ECharT>::__append_source(__pn_,
1147 basic_string_view<_ECharT>(&__x, 1));
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001148 return *this;
1149 }
1150
1151 template <class _Source>
1152 _EnableIfPathable<_Source> operator+=(const _Source& __x) {
1153 return this->concat(__x);
1154 }
1155
1156 template <class _Source>
1157 _EnableIfPathable<_Source> concat(const _Source& __x) {
1158 _SourceCVT<_Source>::__append_source(__pn_, __x);
1159 return *this;
1160 }
1161
1162 template <class _InputIt>
1163 path& concat(_InputIt __first, _InputIt __last) {
1164 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1165 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1166 return *this;
1167 }
1168
1169 // modifiers
1170 _LIBCPP_INLINE_VISIBILITY
1171 void clear() noexcept { __pn_.clear(); }
1172
Martin Storsjöf543c7a2020-10-28 12:24:11 +02001173 path& make_preferred() {
1174#if defined(_LIBCPP_WIN32API)
1175 _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
1176#endif
1177 return *this;
1178 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001179
1180 _LIBCPP_INLINE_VISIBILITY
1181 path& remove_filename() {
1182 auto __fname = __filename();
1183 if (!__fname.empty())
1184 __pn_.erase(__fname.data() - __pn_.data());
1185 return *this;
1186 }
1187
1188 path& replace_filename(const path& __replacement) {
1189 remove_filename();
1190 return (*this /= __replacement);
1191 }
1192
1193 path& replace_extension(const path& __replacement = path());
1194
1195 _LIBCPP_INLINE_VISIBILITY
1196 void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
1197
1198 // private helper to allow reserving memory in the path
1199 _LIBCPP_INLINE_VISIBILITY
1200 void __reserve(size_t __s) { __pn_.reserve(__s); }
1201
1202 // native format observers
1203 _LIBCPP_INLINE_VISIBILITY
1204 const string_type& native() const noexcept { return __pn_; }
1205
1206 _LIBCPP_INLINE_VISIBILITY
1207 const value_type* c_str() const noexcept { return __pn_.c_str(); }
1208
1209 _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
1210
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001211#if defined(_LIBCPP_WIN32API)
1212 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; }
1213
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001214 _VSTD::wstring generic_wstring() const {
1215 _VSTD::wstring __s;
1216 __s.resize(__pn_.size());
1217 _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
1218 return __s;
1219 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001220
1221#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
1222 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1223 class _Allocator = allocator<_ECharT> >
1224 basic_string<_ECharT, _Traits, _Allocator>
1225 string(const _Allocator& __a = _Allocator()) const {
1226 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1227 _Str __s(__a);
1228 __s.reserve(__pn_.size());
1229 _PathExport<_ECharT>::__append(__s, __pn_);
1230 return __s;
1231 }
1232
1233 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const {
1234 return string<char>();
1235 }
1236 _LIBCPP_INLINE_VISIBILITY __u8_string u8string() const {
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001237 using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1238 __u8_string __s;
1239 __s.reserve(__pn_.size());
1240 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1241 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001242 }
1243
1244 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
1245 return string<char16_t>();
1246 }
1247 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
1248 return string<char32_t>();
1249 }
1250
1251 // generic format observers
1252 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1253 class _Allocator = allocator<_ECharT> >
1254 basic_string<_ECharT, _Traits, _Allocator>
1255 generic_string(const _Allocator& __a = _Allocator()) const {
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001256 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1257 _Str __s = string<_ECharT, _Traits, _Allocator>(__a);
1258 // Note: This (and generic_u8string below) is slightly suboptimal as
1259 // it iterates twice over the string; once to convert it to the right
1260 // character type, and once to replace path delimiters.
1261 _VSTD::replace(__s.begin(), __s.end(),
1262 static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
1263 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001264 }
1265
1266 _VSTD::string generic_string() const { return generic_string<char>(); }
1267 _VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); }
1268 _VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); }
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001269 __u8_string generic_u8string() const {
1270 __u8_string __s = u8string();
1271 _VSTD::replace(__s.begin(), __s.end(), '\\', '/');
1272 return __s;
1273 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001274#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1275#else /* _LIBCPP_WIN32API */
1276
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001277 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; }
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001278#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001279 _LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1280#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001281 _LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001282#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001283
1284#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001285 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1286 class _Allocator = allocator<_ECharT> >
1287 basic_string<_ECharT, _Traits, _Allocator>
1288 string(const _Allocator& __a = _Allocator()) const {
1289 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
1290 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1291 _Str __s(__a);
1292 __s.reserve(__pn_.size());
1293 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1294 return __s;
1295 }
1296
Louis Dionne89258142021-08-23 15:32:36 -04001297#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001298 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001299 return string<wchar_t>();
1300 }
Louis Dionne89258142021-08-23 15:32:36 -04001301#endif
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001302 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001303 return string<char16_t>();
1304 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001305 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001306 return string<char32_t>();
1307 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001308#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001309
1310 // generic format observers
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001311 _VSTD::string generic_string() const { return __pn_; }
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001312#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001313 _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1314#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001315 _VSTD::string generic_u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001316#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001317
1318#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001319 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1320 class _Allocator = allocator<_ECharT> >
1321 basic_string<_ECharT, _Traits, _Allocator>
1322 generic_string(const _Allocator& __a = _Allocator()) const {
1323 return string<_ECharT, _Traits, _Allocator>(__a);
1324 }
1325
Louis Dionne89258142021-08-23 15:32:36 -04001326#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001327 _VSTD::wstring generic_wstring() const { return string<wchar_t>(); }
Louis Dionne89258142021-08-23 15:32:36 -04001328#endif
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001329 _VSTD::u16string generic_u16string() const { return string<char16_t>(); }
1330 _VSTD::u32string generic_u32string() const { return string<char32_t>(); }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001331#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1332#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001333
1334private:
1335 int __compare(__string_view) const;
1336 __string_view __root_name() const;
1337 __string_view __root_directory() const;
1338 __string_view __root_path_raw() const;
1339 __string_view __relative_path() const;
1340 __string_view __parent_path() const;
1341 __string_view __filename() const;
1342 __string_view __stem() const;
1343 __string_view __extension() const;
1344
1345public:
1346 // compare
1347 _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
1348 return __compare(__p.__pn_);
1349 }
1350 _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
1351 return __compare(__s);
1352 }
1353 _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
1354 return __compare(__s);
1355 }
1356 _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
1357 return __compare(__s);
1358 }
1359
1360 // decomposition
1361 _LIBCPP_INLINE_VISIBILITY path root_name() const {
1362 return string_type(__root_name());
1363 }
1364 _LIBCPP_INLINE_VISIBILITY path root_directory() const {
1365 return string_type(__root_directory());
1366 }
1367 _LIBCPP_INLINE_VISIBILITY path root_path() const {
Martin Storsjö98770152020-11-04 15:59:56 +02001368#if defined(_LIBCPP_WIN32API)
1369 return string_type(__root_path_raw());
1370#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001371 return root_name().append(string_type(__root_directory()));
Martin Storsjö98770152020-11-04 15:59:56 +02001372#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001373 }
1374 _LIBCPP_INLINE_VISIBILITY path relative_path() const {
1375 return string_type(__relative_path());
1376 }
1377 _LIBCPP_INLINE_VISIBILITY path parent_path() const {
1378 return string_type(__parent_path());
1379 }
1380 _LIBCPP_INLINE_VISIBILITY path filename() const {
1381 return string_type(__filename());
1382 }
1383 _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
1384 _LIBCPP_INLINE_VISIBILITY path extension() const {
1385 return string_type(__extension());
1386 }
1387
1388 // query
1389 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
1390 empty() const noexcept {
1391 return __pn_.empty();
1392 }
1393
1394 _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
1395 return !__root_name().empty();
1396 }
1397 _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
1398 return !__root_directory().empty();
1399 }
1400 _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
1401 return !__root_path_raw().empty();
1402 }
1403 _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
1404 return !__relative_path().empty();
1405 }
1406 _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
1407 return !__parent_path().empty();
1408 }
1409 _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
1410 return !__filename().empty();
1411 }
1412 _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
1413 _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
1414 return !__extension().empty();
1415 }
1416
1417 _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
Martin Storsjöef6b7422020-11-01 23:39:03 +02001418#if defined(_LIBCPP_WIN32API)
1419 __string_view __root_name_str = __root_name();
1420 __string_view __root_dir = __root_directory();
1421 if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
1422 // A drive letter with no root directory is relative, e.g. x:example.
1423 return !__root_dir.empty();
1424 }
1425 // If no root name, it's relative, e.g. \example is relative to the current drive
1426 if (__root_name_str.empty())
1427 return false;
1428 if (__root_name_str.size() < 3)
1429 return false;
1430 // A server root name, like \\server, is always absolute
1431 if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
1432 return false;
1433 if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
1434 return false;
1435 // Seems to be a server root name
1436 return true;
1437#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001438 return has_root_directory();
Martin Storsjöef6b7422020-11-01 23:39:03 +02001439#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001440 }
1441 _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
1442
1443 // relative paths
1444 path lexically_normal() const;
1445 path lexically_relative(const path& __base) const;
1446
1447 _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
1448 path __result = this->lexically_relative(__base);
1449 if (__result.native().empty())
1450 return *this;
1451 return __result;
1452 }
1453
1454 // iterators
1455 class _LIBCPP_TYPE_VIS iterator;
1456 typedef iterator const_iterator;
1457
1458 iterator begin() const;
1459 iterator end() const;
1460
Louis Dionne8d053eb2020-10-09 15:31:05 -04001461#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001462 template <class _CharT, class _Traits>
1463 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001464 typename enable_if<is_same<_CharT, value_type>::value &&
1465 is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001466 basic_ostream<_CharT, _Traits>&>::type
1467 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001468 __os << _VSTD::__quoted(__p.native());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001469 return __os;
1470 }
1471
1472 template <class _CharT, class _Traits>
1473 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001474 typename enable_if<!is_same<_CharT, value_type>::value ||
1475 !is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001476 basic_ostream<_CharT, _Traits>&>::type
1477 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001478 __os << _VSTD::__quoted(__p.string<_CharT, _Traits>());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001479 return __os;
1480 }
1481
1482 template <class _CharT, class _Traits>
1483 _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
1484 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
1485 basic_string<_CharT, _Traits> __tmp;
1486 __is >> __quoted(__tmp);
1487 __p = __tmp;
1488 return __is;
1489 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001490#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001491
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001492 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
1493 return __lhs.compare(__rhs) == 0;
1494 }
1495 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
1496 return __lhs.compare(__rhs) != 0;
1497 }
1498 friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
1499 return __lhs.compare(__rhs) < 0;
1500 }
1501 friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
1502 return __lhs.compare(__rhs) <= 0;
1503 }
1504 friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
1505 return __lhs.compare(__rhs) > 0;
1506 }
1507 friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
1508 return __lhs.compare(__rhs) >= 0;
1509 }
1510
1511 friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
1512 const path& __rhs) {
1513 path __result(__lhs);
1514 __result /= __rhs;
1515 return __result;
1516 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001517private:
1518 inline _LIBCPP_INLINE_VISIBILITY path&
1519 __assign_view(__string_view const& __s) noexcept {
1520 __pn_ = string_type(__s);
1521 return *this;
1522 }
1523 string_type __pn_;
1524};
1525
1526inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
1527 __lhs.swap(__rhs);
1528}
1529
1530_LIBCPP_FUNC_VIS
1531size_t hash_value(const path& __p) noexcept;
1532
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001533template <class _InputIt>
Martin Storsjöe3a71972020-10-26 13:18:46 +02001534_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001535 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1536 u8path(_InputIt __f, _InputIt __l) {
1537 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001538#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001539 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1540#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001541 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
Martin Storsjöe3a71972020-10-26 13:18:46 +02001542 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
Martin Storsjö929dff92020-12-15 09:15:37 +02001543 " or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001544#if defined(_LIBCPP_WIN32API)
1545 string __tmp(__f, __l);
1546 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1547 _VSTD::wstring __w;
1548 __w.reserve(__tmp.size());
1549 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1550 return path(__w);
1551#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001552 return path(__f, __l);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001553#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001554}
1555
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001556#if defined(_LIBCPP_WIN32API)
1557template <class _InputIt>
1558_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1559 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1560 u8path(_InputIt __f, _NullSentinel) {
1561 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001562#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001563 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1564#endif
1565 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
1566 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
1567 " or 'char8_t'");
1568 string __tmp;
1569 const char __sentinel = char{};
1570 for (; *__f != __sentinel; ++__f)
1571 __tmp.push_back(*__f);
1572 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1573 _VSTD::wstring __w;
1574 __w.reserve(__tmp.size());
1575 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1576 return path(__w);
1577}
1578#endif /* _LIBCPP_WIN32API */
1579
Martin Storsjö367d7f02020-11-05 00:21:30 +02001580template <class _Source>
1581_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1582 typename enable_if<__is_pathable<_Source>::value, path>::type
1583 u8path(const _Source& __s) {
1584 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001585#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjö367d7f02020-11-05 00:21:30 +02001586 is_same<typename __is_pathable<_Source>::__char_type, char8_t>::value ||
1587#endif
1588 is_same<typename __is_pathable<_Source>::__char_type, char>::value,
1589 "u8path(Source const&) requires Source have a character type of type "
1590 "'char' or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001591#if defined(_LIBCPP_WIN32API)
1592 using _Traits = __is_pathable<_Source>;
Arthur O'Dwyer1ac9f092021-01-15 12:59:56 -05001593 return u8path(_VSTD::__unwrap_iter(_Traits::__range_begin(__s)), _VSTD::__unwrap_iter(_Traits::__range_end(__s)));
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001594#else
Martin Storsjö367d7f02020-11-05 00:21:30 +02001595 return path(__s);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001596#endif
Martin Storsjö367d7f02020-11-05 00:21:30 +02001597}
1598
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001599class _LIBCPP_TYPE_VIS path::iterator {
1600public:
1601 enum _ParserState : unsigned char {
1602 _Singular,
1603 _BeforeBegin,
1604 _InRootName,
1605 _InRootDir,
1606 _InFilenames,
1607 _InTrailingSep,
1608 _AtEnd
1609 };
1610
1611public:
1612 typedef bidirectional_iterator_tag iterator_category;
1613
1614 typedef path value_type;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001615 typedef ptrdiff_t difference_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001616 typedef const path* pointer;
1617 typedef const path& reference;
1618
1619 typedef void
1620 __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
1621
1622public:
1623 _LIBCPP_INLINE_VISIBILITY
1624 iterator()
1625 : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
1626 __state_(_Singular) {}
1627
1628 iterator(const iterator&) = default;
1629 ~iterator() = default;
1630
1631 iterator& operator=(const iterator&) = default;
1632
1633 _LIBCPP_INLINE_VISIBILITY
1634 reference operator*() const { return __stashed_elem_; }
1635
1636 _LIBCPP_INLINE_VISIBILITY
1637 pointer operator->() const { return &__stashed_elem_; }
1638
1639 _LIBCPP_INLINE_VISIBILITY
1640 iterator& operator++() {
1641 _LIBCPP_ASSERT(__state_ != _Singular,
1642 "attempting to increment a singular iterator");
1643 _LIBCPP_ASSERT(__state_ != _AtEnd,
1644 "attempting to increment the end iterator");
1645 return __increment();
1646 }
1647
1648 _LIBCPP_INLINE_VISIBILITY
1649 iterator operator++(int) {
1650 iterator __it(*this);
1651 this->operator++();
1652 return __it;
1653 }
1654
1655 _LIBCPP_INLINE_VISIBILITY
1656 iterator& operator--() {
1657 _LIBCPP_ASSERT(__state_ != _Singular,
1658 "attempting to decrement a singular iterator");
1659 _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
1660 "attempting to decrement the begin iterator");
1661 return __decrement();
1662 }
1663
1664 _LIBCPP_INLINE_VISIBILITY
1665 iterator operator--(int) {
1666 iterator __it(*this);
1667 this->operator--();
1668 return __it;
1669 }
1670
1671private:
1672 friend class path;
1673
1674 inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
1675 const iterator&);
1676
1677 iterator& __increment();
1678 iterator& __decrement();
1679
1680 path __stashed_elem_;
1681 const path* __path_ptr_;
1682 path::__string_view __entry_;
1683 _ParserState __state_;
1684};
1685
1686inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
1687 const path::iterator& __rhs) {
1688 return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
1689 __lhs.__entry_.data() == __rhs.__entry_.data();
1690}
1691
1692inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
1693 const path::iterator& __rhs) {
1694 return !(__lhs == __rhs);
1695}
1696
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001697// TODO(ldionne): We need to pop the pragma and push it again after
1698// filesystem_error to work around PR41078.
1699_LIBCPP_AVAILABILITY_FILESYSTEM_POP
1700
1701class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001702public:
1703 _LIBCPP_INLINE_VISIBILITY
1704 filesystem_error(const string& __what, error_code __ec)
1705 : system_error(__ec, __what),
1706 __storage_(make_shared<_Storage>(path(), path())) {
1707 __create_what(0);
1708 }
1709
1710 _LIBCPP_INLINE_VISIBILITY
1711 filesystem_error(const string& __what, const path& __p1, error_code __ec)
1712 : system_error(__ec, __what),
1713 __storage_(make_shared<_Storage>(__p1, path())) {
1714 __create_what(1);
1715 }
1716
1717 _LIBCPP_INLINE_VISIBILITY
1718 filesystem_error(const string& __what, const path& __p1, const path& __p2,
1719 error_code __ec)
1720 : system_error(__ec, __what),
1721 __storage_(make_shared<_Storage>(__p1, __p2)) {
1722 __create_what(2);
1723 }
1724
1725 _LIBCPP_INLINE_VISIBILITY
1726 const path& path1() const noexcept { return __storage_->__p1_; }
1727
1728 _LIBCPP_INLINE_VISIBILITY
1729 const path& path2() const noexcept { return __storage_->__p2_; }
1730
Dimitry Andric47269ce2020-03-13 19:36:26 +01001731 filesystem_error(const filesystem_error&) = default;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001732 ~filesystem_error() override; // key function
1733
1734 _LIBCPP_INLINE_VISIBILITY
1735 const char* what() const noexcept override {
1736 return __storage_->__what_.c_str();
1737 }
1738
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001739 void __create_what(int __num_paths);
1740
1741private:
Louis Dionne48ae8892019-03-19 17:47:53 +00001742 struct _LIBCPP_HIDDEN _Storage {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001743 _LIBCPP_INLINE_VISIBILITY
1744 _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
1745
1746 path __p1_;
1747 path __p2_;
1748 string __what_;
1749 };
1750 shared_ptr<_Storage> __storage_;
1751};
1752
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001753_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
1754
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001755template <class... _Args>
1756_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
1757#ifndef _LIBCPP_NO_EXCEPTIONS
Louis Dionne6251ef02019-02-05 15:46:52 +00001758void __throw_filesystem_error(_Args&&... __args) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001759 throw filesystem_error(_VSTD::forward<_Args>(__args)...);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001760}
1761#else
Louis Dionne6251ef02019-02-05 15:46:52 +00001762void __throw_filesystem_error(_Args&&...) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001763 _VSTD::abort();
1764}
1765#endif
1766
1767// operational functions
1768
1769_LIBCPP_FUNC_VIS
1770path __absolute(const path&, error_code* __ec = nullptr);
1771_LIBCPP_FUNC_VIS
1772path __canonical(const path&, error_code* __ec = nullptr);
1773_LIBCPP_FUNC_VIS
1774void __copy(const path& __from, const path& __to, copy_options __opt,
1775 error_code* __ec = nullptr);
1776_LIBCPP_FUNC_VIS
1777bool __copy_file(const path& __from, const path& __to, copy_options __opt,
1778 error_code* __ec = nullptr);
1779_LIBCPP_FUNC_VIS
1780void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
1781 error_code* __ec = nullptr);
1782_LIBCPP_FUNC_VIS
1783bool __create_directories(const path& p, error_code* ec = nullptr);
1784_LIBCPP_FUNC_VIS
1785bool __create_directory(const path& p, error_code* ec = nullptr);
1786_LIBCPP_FUNC_VIS
1787bool __create_directory(const path& p, const path& attributes,
1788 error_code* ec = nullptr);
1789_LIBCPP_FUNC_VIS
1790void __create_directory_symlink(const path& __to, const path& __new_symlink,
1791 error_code* __ec = nullptr);
1792_LIBCPP_FUNC_VIS
1793void __create_hard_link(const path& __to, const path& __new_hard_link,
1794 error_code* __ec = nullptr);
1795_LIBCPP_FUNC_VIS
1796void __create_symlink(const path& __to, const path& __new_symlink,
1797 error_code* __ec = nullptr);
1798_LIBCPP_FUNC_VIS
1799path __current_path(error_code* __ec = nullptr);
1800_LIBCPP_FUNC_VIS
1801void __current_path(const path&, error_code* __ec = nullptr);
1802_LIBCPP_FUNC_VIS
1803bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
1804_LIBCPP_FUNC_VIS
1805uintmax_t __file_size(const path&, error_code* __ec = nullptr);
1806_LIBCPP_FUNC_VIS
1807uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
1808_LIBCPP_FUNC_VIS
1809bool __fs_is_empty(const path& p, error_code* ec = nullptr);
1810_LIBCPP_FUNC_VIS
1811file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
1812_LIBCPP_FUNC_VIS
1813void __last_write_time(const path& p, file_time_type new_time,
1814 error_code* ec = nullptr);
1815_LIBCPP_FUNC_VIS
1816void __permissions(const path&, perms, perm_options, error_code* = nullptr);
1817_LIBCPP_FUNC_VIS
1818path __read_symlink(const path& p, error_code* ec = nullptr);
1819_LIBCPP_FUNC_VIS
1820bool __remove(const path& p, error_code* ec = nullptr);
1821_LIBCPP_FUNC_VIS
1822uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
1823_LIBCPP_FUNC_VIS
1824void __rename(const path& from, const path& to, error_code* ec = nullptr);
1825_LIBCPP_FUNC_VIS
1826void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
1827_LIBCPP_FUNC_VIS
1828space_info __space(const path&, error_code* __ec = nullptr);
1829_LIBCPP_FUNC_VIS
1830file_status __status(const path&, error_code* __ec = nullptr);
1831_LIBCPP_FUNC_VIS
1832file_status __symlink_status(const path&, error_code* __ec = nullptr);
1833_LIBCPP_FUNC_VIS
1834path __system_complete(const path&, error_code* __ec = nullptr);
1835_LIBCPP_FUNC_VIS
1836path __temp_directory_path(error_code* __ec = nullptr);
1837_LIBCPP_FUNC_VIS
1838path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
1839
1840inline _LIBCPP_INLINE_VISIBILITY path current_path() {
1841 return __current_path();
1842}
1843
1844inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
1845 return __current_path(&__ec);
1846}
1847
1848inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
1849 __current_path(__p);
1850}
1851
1852inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
1853 error_code& __ec) noexcept {
1854 __current_path(__p, &__ec);
1855}
1856
1857inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
1858 return __absolute(__p);
1859}
1860
1861inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
1862 error_code& __ec) {
1863 return __absolute(__p, &__ec);
1864}
1865
1866inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
1867 return __canonical(__p);
1868}
1869
1870inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
1871 error_code& __ec) {
1872 return __canonical(__p, &__ec);
1873}
1874
1875inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
1876 const path& __to) {
1877 __copy(__from, __to, copy_options::none);
1878}
1879
1880inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1881 error_code& __ec) {
1882 __copy(__from, __to, copy_options::none, &__ec);
1883}
1884
1885inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1886 copy_options __opt) {
1887 __copy(__from, __to, __opt);
1888}
1889
1890inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1891 copy_options __opt,
1892 error_code& __ec) {
1893 __copy(__from, __to, __opt, &__ec);
1894}
1895
1896inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1897 const path& __to) {
1898 return __copy_file(__from, __to, copy_options::none);
1899}
1900
1901inline _LIBCPP_INLINE_VISIBILITY bool
1902copy_file(const path& __from, const path& __to, error_code& __ec) {
1903 return __copy_file(__from, __to, copy_options::none, &__ec);
1904}
1905
1906inline _LIBCPP_INLINE_VISIBILITY bool
1907copy_file(const path& __from, const path& __to, copy_options __opt) {
1908 return __copy_file(__from, __to, __opt);
1909}
1910
1911inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1912 const path& __to,
1913 copy_options __opt,
1914 error_code& __ec) {
1915 return __copy_file(__from, __to, __opt, &__ec);
1916}
1917
1918inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
1919 const path& __new) {
1920 __copy_symlink(__existing, __new);
1921}
1922
1923inline _LIBCPP_INLINE_VISIBILITY void
1924copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
1925 __copy_symlink(__ext, __new, &__ec);
1926}
1927
1928inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
1929 return __create_directories(__p);
1930}
1931
1932inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
1933 error_code& __ec) {
1934 return __create_directories(__p, &__ec);
1935}
1936
1937inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
1938 return __create_directory(__p);
1939}
1940
1941inline _LIBCPP_INLINE_VISIBILITY bool
1942create_directory(const path& __p, error_code& __ec) noexcept {
1943 return __create_directory(__p, &__ec);
1944}
1945
1946inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
1947 const path& __attrs) {
1948 return __create_directory(__p, __attrs);
1949}
1950
1951inline _LIBCPP_INLINE_VISIBILITY bool
1952create_directory(const path& __p, const path& __attrs,
1953 error_code& __ec) noexcept {
1954 return __create_directory(__p, __attrs, &__ec);
1955}
1956
1957inline _LIBCPP_INLINE_VISIBILITY void
1958create_directory_symlink(const path& __to, const path& __new) {
1959 __create_directory_symlink(__to, __new);
1960}
1961
1962inline _LIBCPP_INLINE_VISIBILITY void
1963create_directory_symlink(const path& __to, const path& __new,
1964 error_code& __ec) noexcept {
1965 __create_directory_symlink(__to, __new, &__ec);
1966}
1967
1968inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
1969 const path& __new) {
1970 __create_hard_link(__to, __new);
1971}
1972
1973inline _LIBCPP_INLINE_VISIBILITY void
1974create_hard_link(const path& __to, const path& __new,
1975 error_code& __ec) noexcept {
1976 __create_hard_link(__to, __new, &__ec);
1977}
1978
1979inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
1980 const path& __new) {
1981 __create_symlink(__to, __new);
1982}
1983
1984inline _LIBCPP_INLINE_VISIBILITY void
1985create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
1986 return __create_symlink(__to, __new, &__ec);
1987}
1988
1989inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
1990 return __s.type() != file_type::none;
1991}
1992
1993inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
1994 return status_known(__s) && __s.type() != file_type::not_found;
1995}
1996
1997inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
1998 return exists(__status(__p));
1999}
2000
2001inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
2002 error_code& __ec) noexcept {
2003 auto __s = __status(__p, &__ec);
2004 if (status_known(__s))
2005 __ec.clear();
2006 return exists(__s);
2007}
2008
2009inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
2010 const path& __p2) {
2011 return __equivalent(__p1, __p2);
2012}
2013
2014inline _LIBCPP_INLINE_VISIBILITY bool
2015equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
2016 return __equivalent(__p1, __p2, &__ec);
2017}
2018
2019inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
2020 return __file_size(__p);
2021}
2022
2023inline _LIBCPP_INLINE_VISIBILITY uintmax_t
2024file_size(const path& __p, error_code& __ec) noexcept {
2025 return __file_size(__p, &__ec);
2026}
2027
2028inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
2029 return __hard_link_count(__p);
2030}
2031
2032inline _LIBCPP_INLINE_VISIBILITY uintmax_t
2033hard_link_count(const path& __p, error_code& __ec) noexcept {
2034 return __hard_link_count(__p, &__ec);
2035}
2036
2037inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
2038 return __s.type() == file_type::block;
2039}
2040
2041inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
2042 return is_block_file(__status(__p));
2043}
2044
2045inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
2046 error_code& __ec) noexcept {
2047 return is_block_file(__status(__p, &__ec));
2048}
2049
2050inline _LIBCPP_INLINE_VISIBILITY bool
2051is_character_file(file_status __s) noexcept {
2052 return __s.type() == file_type::character;
2053}
2054
2055inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
2056 return is_character_file(__status(__p));
2057}
2058
2059inline _LIBCPP_INLINE_VISIBILITY bool
2060is_character_file(const path& __p, error_code& __ec) noexcept {
2061 return is_character_file(__status(__p, &__ec));
2062}
2063
2064inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
2065 return __s.type() == file_type::directory;
2066}
2067
2068inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
2069 return is_directory(__status(__p));
2070}
2071
2072inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
2073 error_code& __ec) noexcept {
2074 return is_directory(__status(__p, &__ec));
2075}
2076
2077inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
2078 return __fs_is_empty(__p);
2079}
2080
2081inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
2082 error_code& __ec) {
2083 return __fs_is_empty(__p, &__ec);
2084}
2085
2086inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
2087 return __s.type() == file_type::fifo;
2088}
2089inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
2090 return is_fifo(__status(__p));
2091}
2092
2093inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
2094 error_code& __ec) noexcept {
2095 return is_fifo(__status(__p, &__ec));
2096}
2097
2098inline _LIBCPP_INLINE_VISIBILITY bool
2099is_regular_file(file_status __s) noexcept {
2100 return __s.type() == file_type::regular;
2101}
2102
2103inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
2104 return is_regular_file(__status(__p));
2105}
2106
2107inline _LIBCPP_INLINE_VISIBILITY bool
2108is_regular_file(const path& __p, error_code& __ec) noexcept {
2109 return is_regular_file(__status(__p, &__ec));
2110}
2111
2112inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
2113 return __s.type() == file_type::socket;
2114}
2115
2116inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
2117 return is_socket(__status(__p));
2118}
2119
2120inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
2121 error_code& __ec) noexcept {
2122 return is_socket(__status(__p, &__ec));
2123}
2124
2125inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
2126 return __s.type() == file_type::symlink;
2127}
2128
2129inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
2130 return is_symlink(__symlink_status(__p));
2131}
2132
2133inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
2134 error_code& __ec) noexcept {
2135 return is_symlink(__symlink_status(__p, &__ec));
2136}
2137
2138inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
2139 return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
2140 !is_symlink(__s);
2141}
2142
2143inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
2144 return is_other(__status(__p));
2145}
2146
2147inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
2148 error_code& __ec) noexcept {
2149 return is_other(__status(__p, &__ec));
2150}
2151
2152inline _LIBCPP_INLINE_VISIBILITY file_time_type
2153last_write_time(const path& __p) {
2154 return __last_write_time(__p);
2155}
2156
2157inline _LIBCPP_INLINE_VISIBILITY file_time_type
2158last_write_time(const path& __p, error_code& __ec) noexcept {
2159 return __last_write_time(__p, &__ec);
2160}
2161
2162inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
2163 file_time_type __t) {
2164 __last_write_time(__p, __t);
2165}
2166
2167inline _LIBCPP_INLINE_VISIBILITY void
2168last_write_time(const path& __p, file_time_type __t,
2169 error_code& __ec) noexcept {
2170 __last_write_time(__p, __t, &__ec);
2171}
2172
2173inline _LIBCPP_INLINE_VISIBILITY void
2174permissions(const path& __p, perms __prms,
2175 perm_options __opts = perm_options::replace) {
2176 __permissions(__p, __prms, __opts);
2177}
2178
2179inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2180 error_code& __ec) noexcept {
2181 __permissions(__p, __prms, perm_options::replace, &__ec);
2182}
2183
2184inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2185 perm_options __opts,
2186 error_code& __ec) {
2187 __permissions(__p, __prms, __opts, &__ec);
2188}
2189
2190inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2191 const path& __base,
2192 error_code& __ec) {
2193 path __tmp = __weakly_canonical(__p, &__ec);
2194 if (__ec)
2195 return {};
2196 path __tmp_base = __weakly_canonical(__base, &__ec);
2197 if (__ec)
2198 return {};
2199 return __tmp.lexically_proximate(__tmp_base);
2200}
2201
2202inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2203 error_code& __ec) {
2204 return proximate(__p, current_path(), __ec);
2205}
2206
2207inline _LIBCPP_INLINE_VISIBILITY path
2208proximate(const path& __p, const path& __base = current_path()) {
2209 return __weakly_canonical(__p).lexically_proximate(
2210 __weakly_canonical(__base));
2211}
2212
2213inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
2214 return __read_symlink(__p);
2215}
2216
2217inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
2218 error_code& __ec) {
2219 return __read_symlink(__p, &__ec);
2220}
2221
2222inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2223 const path& __base,
2224 error_code& __ec) {
2225 path __tmp = __weakly_canonical(__p, &__ec);
2226 if (__ec)
2227 return path();
2228 path __tmpbase = __weakly_canonical(__base, &__ec);
2229 if (__ec)
2230 return path();
2231 return __tmp.lexically_relative(__tmpbase);
2232}
2233
2234inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2235 error_code& __ec) {
2236 return relative(__p, current_path(), __ec);
2237}
2238
2239inline _LIBCPP_INLINE_VISIBILITY path
2240relative(const path& __p, const path& __base = current_path()) {
2241 return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
2242}
2243
2244inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
2245 return __remove(__p);
2246}
2247
2248inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
2249 error_code& __ec) noexcept {
2250 return __remove(__p, &__ec);
2251}
2252
2253inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
2254 return __remove_all(__p);
2255}
2256
2257inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
2258 error_code& __ec) {
2259 return __remove_all(__p, &__ec);
2260}
2261
2262inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
2263 const path& __to) {
2264 return __rename(__from, __to);
2265}
2266
2267inline _LIBCPP_INLINE_VISIBILITY void
2268rename(const path& __from, const path& __to, error_code& __ec) noexcept {
2269 return __rename(__from, __to, &__ec);
2270}
2271
2272inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
2273 uintmax_t __ns) {
2274 return __resize_file(__p, __ns);
2275}
2276
2277inline _LIBCPP_INLINE_VISIBILITY void
2278resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
2279 return __resize_file(__p, __ns, &__ec);
2280}
2281
2282inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
2283 return __space(__p);
2284}
2285
2286inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
2287 error_code& __ec) noexcept {
2288 return __space(__p, &__ec);
2289}
2290
2291inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
2292 return __status(__p);
2293}
2294
2295inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
2296 error_code& __ec) noexcept {
2297 return __status(__p, &__ec);
2298}
2299
2300inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
2301 return __symlink_status(__p);
2302}
2303
2304inline _LIBCPP_INLINE_VISIBILITY file_status
2305symlink_status(const path& __p, error_code& __ec) noexcept {
2306 return __symlink_status(__p, &__ec);
2307}
2308
2309inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
2310 return __temp_directory_path();
2311}
2312
2313inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
2314 return __temp_directory_path(&__ec);
2315}
2316
2317inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
2318 return __weakly_canonical(__p);
2319}
2320
2321inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
2322 error_code& __ec) {
2323 return __weakly_canonical(__p, &__ec);
2324}
2325
2326class directory_iterator;
2327class recursive_directory_iterator;
Louis Dionne48ae8892019-03-19 17:47:53 +00002328class _LIBCPP_HIDDEN __dir_stream;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002329
2330class directory_entry {
2331 typedef _VSTD_FS::path _Path;
2332
2333public:
2334 // constructors and destructors
2335 directory_entry() noexcept = default;
2336 directory_entry(directory_entry const&) = default;
2337 directory_entry(directory_entry&&) noexcept = default;
2338
2339 _LIBCPP_INLINE_VISIBILITY
2340 explicit directory_entry(_Path const& __p) : __p_(__p) {
2341 error_code __ec;
2342 __refresh(&__ec);
2343 }
2344
2345 _LIBCPP_INLINE_VISIBILITY
2346 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
2347 __refresh(&__ec);
2348 }
2349
2350 ~directory_entry() {}
2351
2352 directory_entry& operator=(directory_entry const&) = default;
2353 directory_entry& operator=(directory_entry&&) noexcept = default;
2354
2355 _LIBCPP_INLINE_VISIBILITY
2356 void assign(_Path const& __p) {
2357 __p_ = __p;
2358 error_code __ec;
2359 __refresh(&__ec);
2360 }
2361
2362 _LIBCPP_INLINE_VISIBILITY
2363 void assign(_Path const& __p, error_code& __ec) {
2364 __p_ = __p;
2365 __refresh(&__ec);
2366 }
2367
2368 _LIBCPP_INLINE_VISIBILITY
2369 void replace_filename(_Path const& __p) {
2370 __p_.replace_filename(__p);
2371 error_code __ec;
2372 __refresh(&__ec);
2373 }
2374
2375 _LIBCPP_INLINE_VISIBILITY
2376 void replace_filename(_Path const& __p, error_code& __ec) {
2377 __p_ = __p_.parent_path() / __p;
2378 __refresh(&__ec);
2379 }
2380
2381 _LIBCPP_INLINE_VISIBILITY
2382 void refresh() { __refresh(); }
2383
2384 _LIBCPP_INLINE_VISIBILITY
2385 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
2386
2387 _LIBCPP_INLINE_VISIBILITY
2388 _Path const& path() const noexcept { return __p_; }
2389
2390 _LIBCPP_INLINE_VISIBILITY
2391 operator const _Path&() const noexcept { return __p_; }
2392
2393 _LIBCPP_INLINE_VISIBILITY
2394 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
2395
2396 _LIBCPP_INLINE_VISIBILITY
2397 bool exists(error_code& __ec) const noexcept {
2398 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
2399 }
2400
2401 _LIBCPP_INLINE_VISIBILITY
2402 bool is_block_file() const { return __get_ft() == file_type::block; }
2403
2404 _LIBCPP_INLINE_VISIBILITY
2405 bool is_block_file(error_code& __ec) const noexcept {
2406 return __get_ft(&__ec) == file_type::block;
2407 }
2408
2409 _LIBCPP_INLINE_VISIBILITY
2410 bool is_character_file() const { return __get_ft() == file_type::character; }
2411
2412 _LIBCPP_INLINE_VISIBILITY
2413 bool is_character_file(error_code& __ec) const noexcept {
2414 return __get_ft(&__ec) == file_type::character;
2415 }
2416
2417 _LIBCPP_INLINE_VISIBILITY
2418 bool is_directory() const { return __get_ft() == file_type::directory; }
2419
2420 _LIBCPP_INLINE_VISIBILITY
2421 bool is_directory(error_code& __ec) const noexcept {
2422 return __get_ft(&__ec) == file_type::directory;
2423 }
2424
2425 _LIBCPP_INLINE_VISIBILITY
2426 bool is_fifo() const { return __get_ft() == file_type::fifo; }
2427
2428 _LIBCPP_INLINE_VISIBILITY
2429 bool is_fifo(error_code& __ec) const noexcept {
2430 return __get_ft(&__ec) == file_type::fifo;
2431 }
2432
2433 _LIBCPP_INLINE_VISIBILITY
2434 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
2435
2436 _LIBCPP_INLINE_VISIBILITY
2437 bool is_other(error_code& __ec) const noexcept {
2438 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
2439 }
2440
2441 _LIBCPP_INLINE_VISIBILITY
2442 bool is_regular_file() const { return __get_ft() == file_type::regular; }
2443
2444 _LIBCPP_INLINE_VISIBILITY
2445 bool is_regular_file(error_code& __ec) const noexcept {
2446 return __get_ft(&__ec) == file_type::regular;
2447 }
2448
2449 _LIBCPP_INLINE_VISIBILITY
2450 bool is_socket() const { return __get_ft() == file_type::socket; }
2451
2452 _LIBCPP_INLINE_VISIBILITY
2453 bool is_socket(error_code& __ec) const noexcept {
2454 return __get_ft(&__ec) == file_type::socket;
2455 }
2456
2457 _LIBCPP_INLINE_VISIBILITY
2458 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
2459
2460 _LIBCPP_INLINE_VISIBILITY
2461 bool is_symlink(error_code& __ec) const noexcept {
2462 return __get_sym_ft(&__ec) == file_type::symlink;
2463 }
2464 _LIBCPP_INLINE_VISIBILITY
2465 uintmax_t file_size() const { return __get_size(); }
2466
2467 _LIBCPP_INLINE_VISIBILITY
2468 uintmax_t file_size(error_code& __ec) const noexcept {
2469 return __get_size(&__ec);
2470 }
2471
2472 _LIBCPP_INLINE_VISIBILITY
2473 uintmax_t hard_link_count() const { return __get_nlink(); }
2474
2475 _LIBCPP_INLINE_VISIBILITY
2476 uintmax_t hard_link_count(error_code& __ec) const noexcept {
2477 return __get_nlink(&__ec);
2478 }
2479
2480 _LIBCPP_INLINE_VISIBILITY
2481 file_time_type last_write_time() const { return __get_write_time(); }
2482
2483 _LIBCPP_INLINE_VISIBILITY
2484 file_time_type last_write_time(error_code& __ec) const noexcept {
2485 return __get_write_time(&__ec);
2486 }
2487
2488 _LIBCPP_INLINE_VISIBILITY
2489 file_status status() const { return __get_status(); }
2490
2491 _LIBCPP_INLINE_VISIBILITY
2492 file_status status(error_code& __ec) const noexcept {
2493 return __get_status(&__ec);
2494 }
2495
2496 _LIBCPP_INLINE_VISIBILITY
2497 file_status symlink_status() const { return __get_symlink_status(); }
2498
2499 _LIBCPP_INLINE_VISIBILITY
2500 file_status symlink_status(error_code& __ec) const noexcept {
2501 return __get_symlink_status(&__ec);
2502 }
2503
2504 _LIBCPP_INLINE_VISIBILITY
2505 bool operator<(directory_entry const& __rhs) const noexcept {
2506 return __p_ < __rhs.__p_;
2507 }
2508
2509 _LIBCPP_INLINE_VISIBILITY
2510 bool operator==(directory_entry const& __rhs) const noexcept {
2511 return __p_ == __rhs.__p_;
2512 }
2513
2514 _LIBCPP_INLINE_VISIBILITY
2515 bool operator!=(directory_entry const& __rhs) const noexcept {
2516 return __p_ != __rhs.__p_;
2517 }
2518
2519 _LIBCPP_INLINE_VISIBILITY
2520 bool operator<=(directory_entry const& __rhs) const noexcept {
2521 return __p_ <= __rhs.__p_;
2522 }
2523
2524 _LIBCPP_INLINE_VISIBILITY
2525 bool operator>(directory_entry const& __rhs) const noexcept {
2526 return __p_ > __rhs.__p_;
2527 }
2528
2529 _LIBCPP_INLINE_VISIBILITY
2530 bool operator>=(directory_entry const& __rhs) const noexcept {
2531 return __p_ >= __rhs.__p_;
2532 }
2533
2534private:
2535 friend class directory_iterator;
2536 friend class recursive_directory_iterator;
2537 friend class __dir_stream;
2538
2539 enum _CacheType : unsigned char {
2540 _Empty,
2541 _IterSymlink,
2542 _IterNonSymlink,
2543 _RefreshSymlink,
2544 _RefreshSymlinkUnresolved,
2545 _RefreshNonSymlink
2546 };
2547
2548 struct __cached_data {
2549 uintmax_t __size_;
2550 uintmax_t __nlink_;
2551 file_time_type __write_time_;
2552 perms __sym_perms_;
2553 perms __non_sym_perms_;
2554 file_type __type_;
2555 _CacheType __cache_type_;
2556
2557 _LIBCPP_INLINE_VISIBILITY
2558 __cached_data() noexcept { __reset(); }
2559
2560 _LIBCPP_INLINE_VISIBILITY
2561 void __reset() {
2562 __cache_type_ = _Empty;
2563 __type_ = file_type::none;
2564 __sym_perms_ = __non_sym_perms_ = perms::unknown;
2565 __size_ = __nlink_ = uintmax_t(-1);
2566 __write_time_ = file_time_type::min();
2567 }
2568 };
2569
2570 _LIBCPP_INLINE_VISIBILITY
2571 static __cached_data __create_iter_result(file_type __ft) {
2572 __cached_data __data;
2573 __data.__type_ = __ft;
2574 __data.__cache_type_ = [&]() {
2575 switch (__ft) {
2576 case file_type::none:
2577 return _Empty;
2578 case file_type::symlink:
2579 return _IterSymlink;
2580 default:
2581 return _IterNonSymlink;
2582 }
2583 }();
2584 return __data;
2585 }
2586
2587 _LIBCPP_INLINE_VISIBILITY
2588 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002589 __p_ = _VSTD::move(__p);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002590 __data_ = __dt;
2591 }
2592
2593 _LIBCPP_FUNC_VIS
2594 error_code __do_refresh() noexcept;
2595
2596 _LIBCPP_INLINE_VISIBILITY
2597 static bool __is_dne_error(error_code const& __ec) {
2598 if (!__ec)
2599 return true;
2600 switch (static_cast<errc>(__ec.value())) {
2601 case errc::no_such_file_or_directory:
2602 case errc::not_a_directory:
2603 return true;
2604 default:
2605 return false;
2606 }
2607 }
2608
2609 _LIBCPP_INLINE_VISIBILITY
2610 void __handle_error(const char* __msg, error_code* __dest_ec,
2611 error_code const& __ec, bool __allow_dne = false) const {
2612 if (__dest_ec) {
2613 *__dest_ec = __ec;
2614 return;
2615 }
2616 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
2617 __throw_filesystem_error(__msg, __p_, __ec);
2618 }
2619
2620 _LIBCPP_INLINE_VISIBILITY
2621 void __refresh(error_code* __ec = nullptr) {
2622 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
2623 /*allow_dne*/ true);
2624 }
2625
2626 _LIBCPP_INLINE_VISIBILITY
2627 file_type __get_sym_ft(error_code* __ec = nullptr) const {
2628 switch (__data_.__cache_type_) {
2629 case _Empty:
2630 return __symlink_status(__p_, __ec).type();
2631 case _IterSymlink:
2632 case _RefreshSymlink:
2633 case _RefreshSymlinkUnresolved:
2634 if (__ec)
2635 __ec->clear();
2636 return file_type::symlink;
2637 case _IterNonSymlink:
2638 case _RefreshNonSymlink:
2639 file_status __st(__data_.__type_);
2640 if (__ec && !_VSTD_FS::exists(__st))
2641 *__ec = make_error_code(errc::no_such_file_or_directory);
2642 else if (__ec)
2643 __ec->clear();
2644 return __data_.__type_;
2645 }
2646 _LIBCPP_UNREACHABLE();
2647 }
2648
2649 _LIBCPP_INLINE_VISIBILITY
2650 file_type __get_ft(error_code* __ec = nullptr) const {
2651 switch (__data_.__cache_type_) {
2652 case _Empty:
2653 case _IterSymlink:
2654 case _RefreshSymlinkUnresolved:
2655 return __status(__p_, __ec).type();
2656 case _IterNonSymlink:
2657 case _RefreshNonSymlink:
2658 case _RefreshSymlink: {
2659 file_status __st(__data_.__type_);
2660 if (__ec && !_VSTD_FS::exists(__st))
2661 *__ec = make_error_code(errc::no_such_file_or_directory);
2662 else if (__ec)
2663 __ec->clear();
2664 return __data_.__type_;
2665 }
2666 }
2667 _LIBCPP_UNREACHABLE();
2668 }
2669
2670 _LIBCPP_INLINE_VISIBILITY
2671 file_status __get_status(error_code* __ec = nullptr) const {
2672 switch (__data_.__cache_type_) {
2673 case _Empty:
2674 case _IterNonSymlink:
2675 case _IterSymlink:
2676 case _RefreshSymlinkUnresolved:
2677 return __status(__p_, __ec);
2678 case _RefreshNonSymlink:
2679 case _RefreshSymlink:
2680 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
2681 }
2682 _LIBCPP_UNREACHABLE();
2683 }
2684
2685 _LIBCPP_INLINE_VISIBILITY
2686 file_status __get_symlink_status(error_code* __ec = nullptr) const {
2687 switch (__data_.__cache_type_) {
2688 case _Empty:
2689 case _IterNonSymlink:
2690 case _IterSymlink:
2691 return __symlink_status(__p_, __ec);
2692 case _RefreshNonSymlink:
2693 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
2694 case _RefreshSymlink:
2695 case _RefreshSymlinkUnresolved:
2696 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
2697 }
2698 _LIBCPP_UNREACHABLE();
2699 }
2700
2701 _LIBCPP_INLINE_VISIBILITY
2702 uintmax_t __get_size(error_code* __ec = nullptr) const {
2703 switch (__data_.__cache_type_) {
2704 case _Empty:
2705 case _IterNonSymlink:
2706 case _IterSymlink:
2707 case _RefreshSymlinkUnresolved:
2708 return _VSTD_FS::__file_size(__p_, __ec);
2709 case _RefreshSymlink:
2710 case _RefreshNonSymlink: {
2711 error_code __m_ec;
2712 file_status __st(__get_ft(&__m_ec));
2713 __handle_error("in directory_entry::file_size", __ec, __m_ec);
2714 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
2715 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
2716 : errc::not_supported;
2717 __handle_error("in directory_entry::file_size", __ec,
2718 make_error_code(__err_kind));
2719 }
2720 return __data_.__size_;
2721 }
2722 }
2723 _LIBCPP_UNREACHABLE();
2724 }
2725
2726 _LIBCPP_INLINE_VISIBILITY
2727 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
2728 switch (__data_.__cache_type_) {
2729 case _Empty:
2730 case _IterNonSymlink:
2731 case _IterSymlink:
2732 case _RefreshSymlinkUnresolved:
2733 return _VSTD_FS::__hard_link_count(__p_, __ec);
2734 case _RefreshSymlink:
2735 case _RefreshNonSymlink: {
2736 error_code __m_ec;
2737 (void)__get_ft(&__m_ec);
2738 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
2739 return __data_.__nlink_;
2740 }
2741 }
2742 _LIBCPP_UNREACHABLE();
2743 }
2744
2745 _LIBCPP_INLINE_VISIBILITY
2746 file_time_type __get_write_time(error_code* __ec = nullptr) const {
2747 switch (__data_.__cache_type_) {
2748 case _Empty:
2749 case _IterNonSymlink:
2750 case _IterSymlink:
2751 case _RefreshSymlinkUnresolved:
2752 return _VSTD_FS::__last_write_time(__p_, __ec);
2753 case _RefreshSymlink:
2754 case _RefreshNonSymlink: {
2755 error_code __m_ec;
2756 file_status __st(__get_ft(&__m_ec));
2757 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
2758 if (_VSTD_FS::exists(__st) &&
2759 __data_.__write_time_ == file_time_type::min())
2760 __handle_error("in directory_entry::last_write_time", __ec,
2761 make_error_code(errc::value_too_large));
2762 return __data_.__write_time_;
2763 }
2764 }
2765 _LIBCPP_UNREACHABLE();
2766 }
2767
2768private:
2769 _Path __p_;
2770 __cached_data __data_;
2771};
2772
2773class __dir_element_proxy {
2774public:
2775 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
2776 return _VSTD::move(__elem_);
2777 }
2778
2779private:
2780 friend class directory_iterator;
2781 friend class recursive_directory_iterator;
2782 explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
2783 __dir_element_proxy(__dir_element_proxy&& __o)
2784 : __elem_(_VSTD::move(__o.__elem_)) {}
2785 directory_entry __elem_;
2786};
2787
2788class directory_iterator {
2789public:
2790 typedef directory_entry value_type;
2791 typedef ptrdiff_t difference_type;
2792 typedef value_type const* pointer;
2793 typedef value_type const& reference;
2794 typedef input_iterator_tag iterator_category;
2795
2796public:
2797 //ctor & dtor
2798 directory_iterator() noexcept {}
2799
2800 explicit directory_iterator(const path& __p)
2801 : directory_iterator(__p, nullptr) {}
2802
2803 directory_iterator(const path& __p, directory_options __opts)
2804 : directory_iterator(__p, nullptr, __opts) {}
2805
2806 directory_iterator(const path& __p, error_code& __ec)
2807 : directory_iterator(__p, &__ec) {}
2808
2809 directory_iterator(const path& __p, directory_options __opts,
2810 error_code& __ec)
2811 : directory_iterator(__p, &__ec, __opts) {}
2812
2813 directory_iterator(const directory_iterator&) = default;
2814 directory_iterator(directory_iterator&&) = default;
2815 directory_iterator& operator=(const directory_iterator&) = default;
2816
2817 directory_iterator& operator=(directory_iterator&& __o) noexcept {
2818 // non-default implementation provided to support self-move assign.
2819 if (this != &__o) {
2820 __imp_ = _VSTD::move(__o.__imp_);
2821 }
2822 return *this;
2823 }
2824
2825 ~directory_iterator() = default;
2826
2827 const directory_entry& operator*() const {
2828 _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
2829 return __dereference();
2830 }
2831
2832 const directory_entry* operator->() const { return &**this; }
2833
2834 directory_iterator& operator++() { return __increment(); }
2835
2836 __dir_element_proxy operator++(int) {
2837 __dir_element_proxy __p(**this);
2838 __increment();
2839 return __p;
2840 }
2841
2842 directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
2843
2844private:
2845 inline _LIBCPP_INLINE_VISIBILITY friend bool
2846 operator==(const directory_iterator& __lhs,
2847 const directory_iterator& __rhs) noexcept;
2848
2849 // construct the dir_stream
2850 _LIBCPP_FUNC_VIS
2851 directory_iterator(const path&, error_code*,
2852 directory_options = directory_options::none);
2853
2854 _LIBCPP_FUNC_VIS
2855 directory_iterator& __increment(error_code* __ec = nullptr);
2856
2857 _LIBCPP_FUNC_VIS
2858 const directory_entry& __dereference() const;
2859
2860private:
2861 shared_ptr<__dir_stream> __imp_;
2862};
2863
2864inline _LIBCPP_INLINE_VISIBILITY bool
2865operator==(const directory_iterator& __lhs,
2866 const directory_iterator& __rhs) noexcept {
2867 return __lhs.__imp_ == __rhs.__imp_;
2868}
2869
2870inline _LIBCPP_INLINE_VISIBILITY bool
2871operator!=(const directory_iterator& __lhs,
2872 const directory_iterator& __rhs) noexcept {
2873 return !(__lhs == __rhs);
2874}
2875
2876// enable directory_iterator range-based for statements
2877inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2878begin(directory_iterator __iter) noexcept {
2879 return __iter;
2880}
2881
2882inline _LIBCPP_INLINE_VISIBILITY directory_iterator
Joe Loser9d1c0d42021-10-14 11:53:43 -04002883end(directory_iterator) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002884 return directory_iterator();
2885}
2886
2887class recursive_directory_iterator {
2888public:
2889 using value_type = directory_entry;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002890 using difference_type = ptrdiff_t;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002891 using pointer = directory_entry const*;
2892 using reference = directory_entry const&;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002893 using iterator_category = input_iterator_tag;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002894
2895public:
2896 // constructors and destructor
2897 _LIBCPP_INLINE_VISIBILITY
2898 recursive_directory_iterator() noexcept : __rec_(false) {}
2899
2900 _LIBCPP_INLINE_VISIBILITY
2901 explicit recursive_directory_iterator(
2902 const path& __p, directory_options __xoptions = directory_options::none)
2903 : recursive_directory_iterator(__p, __xoptions, nullptr) {}
2904
2905 _LIBCPP_INLINE_VISIBILITY
2906 recursive_directory_iterator(const path& __p, directory_options __xoptions,
2907 error_code& __ec)
2908 : recursive_directory_iterator(__p, __xoptions, &__ec) {}
2909
2910 _LIBCPP_INLINE_VISIBILITY
2911 recursive_directory_iterator(const path& __p, error_code& __ec)
2912 : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
2913
2914 recursive_directory_iterator(const recursive_directory_iterator&) = default;
2915 recursive_directory_iterator(recursive_directory_iterator&&) = default;
2916
2917 recursive_directory_iterator&
2918 operator=(const recursive_directory_iterator&) = default;
2919
2920 _LIBCPP_INLINE_VISIBILITY
2921 recursive_directory_iterator&
2922 operator=(recursive_directory_iterator&& __o) noexcept {
2923 // non-default implementation provided to support self-move assign.
2924 if (this != &__o) {
2925 __imp_ = _VSTD::move(__o.__imp_);
2926 __rec_ = __o.__rec_;
2927 }
2928 return *this;
2929 }
2930
2931 ~recursive_directory_iterator() = default;
2932
2933 _LIBCPP_INLINE_VISIBILITY
2934 const directory_entry& operator*() const { return __dereference(); }
2935
2936 _LIBCPP_INLINE_VISIBILITY
2937 const directory_entry* operator->() const { return &__dereference(); }
2938
2939 recursive_directory_iterator& operator++() { return __increment(); }
2940
2941 _LIBCPP_INLINE_VISIBILITY
2942 __dir_element_proxy operator++(int) {
2943 __dir_element_proxy __p(**this);
2944 __increment();
2945 return __p;
2946 }
2947
2948 _LIBCPP_INLINE_VISIBILITY
2949 recursive_directory_iterator& increment(error_code& __ec) {
2950 return __increment(&__ec);
2951 }
2952
2953 _LIBCPP_FUNC_VIS directory_options options() const;
2954 _LIBCPP_FUNC_VIS int depth() const;
2955
2956 _LIBCPP_INLINE_VISIBILITY
2957 void pop() { __pop(); }
2958
2959 _LIBCPP_INLINE_VISIBILITY
2960 void pop(error_code& __ec) { __pop(&__ec); }
2961
2962 _LIBCPP_INLINE_VISIBILITY
2963 bool recursion_pending() const { return __rec_; }
2964
2965 _LIBCPP_INLINE_VISIBILITY
2966 void disable_recursion_pending() { __rec_ = false; }
2967
2968private:
Louis Dionne0ba10dc2019-08-13 15:02:53 +00002969 _LIBCPP_FUNC_VIS
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002970 recursive_directory_iterator(const path& __p, directory_options __opt,
2971 error_code* __ec);
2972
2973 _LIBCPP_FUNC_VIS
2974 const directory_entry& __dereference() const;
2975
2976 _LIBCPP_FUNC_VIS
2977 bool __try_recursion(error_code* __ec);
2978
2979 _LIBCPP_FUNC_VIS
2980 void __advance(error_code* __ec = nullptr);
2981
2982 _LIBCPP_FUNC_VIS
2983 recursive_directory_iterator& __increment(error_code* __ec = nullptr);
2984
2985 _LIBCPP_FUNC_VIS
2986 void __pop(error_code* __ec = nullptr);
2987
2988 inline _LIBCPP_INLINE_VISIBILITY friend bool
2989 operator==(const recursive_directory_iterator&,
2990 const recursive_directory_iterator&) noexcept;
2991
Louis Dionne48ae8892019-03-19 17:47:53 +00002992 struct _LIBCPP_HIDDEN __shared_imp;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002993 shared_ptr<__shared_imp> __imp_;
2994 bool __rec_;
2995}; // class recursive_directory_iterator
2996
2997inline _LIBCPP_INLINE_VISIBILITY bool
2998operator==(const recursive_directory_iterator& __lhs,
2999 const recursive_directory_iterator& __rhs) noexcept {
3000 return __lhs.__imp_ == __rhs.__imp_;
3001}
3002
3003_LIBCPP_INLINE_VISIBILITY
3004inline bool operator!=(const recursive_directory_iterator& __lhs,
3005 const recursive_directory_iterator& __rhs) noexcept {
3006 return !(__lhs == __rhs);
3007}
3008// enable recursive_directory_iterator range-based for statements
3009inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
3010begin(recursive_directory_iterator __iter) noexcept {
3011 return __iter;
3012}
3013
3014inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
Joe Loser9d1c0d42021-10-14 11:53:43 -04003015end(recursive_directory_iterator) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003016 return recursive_directory_iterator();
3017}
3018
Louis Dionnef6bf76a2019-03-20 21:18:14 +00003019_LIBCPP_AVAILABILITY_FILESYSTEM_POP
3020
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003021_LIBCPP_END_NAMESPACE_FILESYSTEM
3022
Joe Loser9d1c0d42021-10-14 11:53:43 -04003023#if !defined(_LIBCPP_HAS_NO_RANGES)
3024template <>
3025inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::directory_iterator> = true;
3026template <>
3027inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::recursive_directory_iterator> = true;
3028
3029template <>
3030inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::directory_iterator> = true;
3031template <>
3032inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::recursive_directory_iterator> = true;
3033#endif
3034
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003035#endif // !_LIBCPP_CXX03_LANG
3036
3037_LIBCPP_POP_MACROS
3038
3039#endif // _LIBCPP_FILESYSTEM