blob: a11d2a4888f40291472c8ee0e1ee62523f9bfd09 [file] [log] [blame]
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001// -*- C++ -*-
2//===--------------------------- filesystem -------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier02cea5e2018-07-27 03:07:09 +00007//
8//===----------------------------------------------------------------------===//
9#ifndef _LIBCPP_FILESYSTEM
10#define _LIBCPP_FILESYSTEM
11/*
12 filesystem synopsis
13
14 namespace std { namespace filesystem {
15
16 class path;
17
18 void swap(path& lhs, path& rhs) noexcept;
19 size_t hash_value(const path& p) noexcept;
20
21 bool operator==(const path& lhs, const path& rhs) noexcept;
22 bool operator!=(const path& lhs, const path& rhs) noexcept;
23 bool operator< (const path& lhs, const path& rhs) noexcept;
24 bool operator<=(const path& lhs, const path& rhs) noexcept;
25 bool operator> (const path& lhs, const path& rhs) noexcept;
26 bool operator>=(const path& lhs, const path& rhs) noexcept;
27
28 path operator/ (const path& lhs, const path& rhs);
29
30 // fs.path.io operators are friends of path.
31 template <class charT, class traits>
32 friend basic_ostream<charT, traits>&
33 operator<<(basic_ostream<charT, traits>& os, const path& p);
34
35 template <class charT, class traits>
36 friend basic_istream<charT, traits>&
37 operator>>(basic_istream<charT, traits>& is, path& p);
38
39 template <class Source>
40 path u8path(const Source& source);
41 template <class InputIterator>
42 path u8path(InputIterator first, InputIterator last);
43
44 class filesystem_error;
45 class directory_entry;
46
47 class directory_iterator;
48
49 // enable directory_iterator range-based for statements
50 directory_iterator begin(directory_iterator iter) noexcept;
51 directory_iterator end(const directory_iterator&) noexcept;
52
53 class recursive_directory_iterator;
54
55 // enable recursive_directory_iterator range-based for statements
56 recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
57 recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
58
59 class file_status;
60
61 struct space_info
62 {
63 uintmax_t capacity;
64 uintmax_t free;
65 uintmax_t available;
66 };
67
68 enum class file_type;
69 enum class perms;
70 enum class perm_options;
71 enum class copy_options;
72 enum class directory_options;
73
74 typedef chrono::time_point<trivial-clock> file_time_type;
75
76 // operational functions
77
78 path absolute(const path& p);
79 path absolute(const path& p, error_code &ec);
80
81 path canonical(const path& p);
82 path canonical(const path& p, error_code& ec);
83
84 void copy(const path& from, const path& to);
85 void copy(const path& from, const path& to, error_code& ec);
86 void copy(const path& from, const path& to, copy_options options);
87 void copy(const path& from, const path& to, copy_options options,
88 error_code& ec);
89
90 bool copy_file(const path& from, const path& to);
91 bool copy_file(const path& from, const path& to, error_code& ec);
92 bool copy_file(const path& from, const path& to, copy_options option);
93 bool copy_file(const path& from, const path& to, copy_options option,
94 error_code& ec);
95
96 void copy_symlink(const path& existing_symlink, const path& new_symlink);
97 void copy_symlink(const path& existing_symlink, const path& new_symlink,
98 error_code& ec) noexcept;
99
100 bool create_directories(const path& p);
101 bool create_directories(const path& p, error_code& ec);
102
103 bool create_directory(const path& p);
104 bool create_directory(const path& p, error_code& ec) noexcept;
105
106 bool create_directory(const path& p, const path& attributes);
107 bool create_directory(const path& p, const path& attributes,
108 error_code& ec) noexcept;
109
110 void create_directory_symlink(const path& to, const path& new_symlink);
111 void create_directory_symlink(const path& to, const path& new_symlink,
112 error_code& ec) noexcept;
113
114 void create_hard_link(const path& to, const path& new_hard_link);
115 void create_hard_link(const path& to, const path& new_hard_link,
116 error_code& ec) noexcept;
117
118 void create_symlink(const path& to, const path& new_symlink);
119 void create_symlink(const path& to, const path& new_symlink,
120 error_code& ec) noexcept;
121
122 path current_path();
123 path current_path(error_code& ec);
124 void current_path(const path& p);
125 void current_path(const path& p, error_code& ec) noexcept;
126
127 bool exists(file_status s) noexcept;
128 bool exists(const path& p);
129 bool exists(const path& p, error_code& ec) noexcept;
130
131 bool equivalent(const path& p1, const path& p2);
132 bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
133
134 uintmax_t file_size(const path& p);
135 uintmax_t file_size(const path& p, error_code& ec) noexcept;
136
137 uintmax_t hard_link_count(const path& p);
138 uintmax_t hard_link_count(const path& p, error_code& ec) noexcept;
139
140 bool is_block_file(file_status s) noexcept;
141 bool is_block_file(const path& p);
142 bool is_block_file(const path& p, error_code& ec) noexcept;
143
144 bool is_character_file(file_status s) noexcept;
145 bool is_character_file(const path& p);
146 bool is_character_file(const path& p, error_code& ec) noexcept;
147
148 bool is_directory(file_status s) noexcept;
149 bool is_directory(const path& p);
150 bool is_directory(const path& p, error_code& ec) noexcept;
151
152 bool is_empty(const path& p);
153 bool is_empty(const path& p, error_code& ec) noexcept;
154
155 bool is_fifo(file_status s) noexcept;
156 bool is_fifo(const path& p);
157 bool is_fifo(const path& p, error_code& ec) noexcept;
158
159 bool is_other(file_status s) noexcept;
160 bool is_other(const path& p);
161 bool is_other(const path& p, error_code& ec) noexcept;
162
163 bool is_regular_file(file_status s) noexcept;
164 bool is_regular_file(const path& p);
165 bool is_regular_file(const path& p, error_code& ec) noexcept;
166
167 bool is_socket(file_status s) noexcept;
168 bool is_socket(const path& p);
169 bool is_socket(const path& p, error_code& ec) noexcept;
170
171 bool is_symlink(file_status s) noexcept;
172 bool is_symlink(const path& p);
173 bool is_symlink(const path& p, error_code& ec) noexcept;
174
175 file_time_type last_write_time(const path& p);
176 file_time_type last_write_time(const path& p, error_code& ec) noexcept;
177 void last_write_time(const path& p, file_time_type new_time);
178 void last_write_time(const path& p, file_time_type new_time,
179 error_code& ec) noexcept;
180
181 void permissions(const path& p, perms prms,
182 perm_options opts=perm_options::replace);
183 void permissions(const path& p, perms prms, error_code& ec) noexcept;
184 void permissions(const path& p, perms prms, perm_options opts,
185 error_code& ec);
186
187 path proximate(const path& p, error_code& ec);
188 path proximate(const path& p, const path& base = current_path());
189 path proximate(const path& p, const path& base, error_code &ec);
190
191 path read_symlink(const path& p);
192 path read_symlink(const path& p, error_code& ec);
193
194 path relative(const path& p, error_code& ec);
195 path relative(const path& p, const path& base=current_path());
196 path relative(const path& p, const path& base, error_code& ec);
197
198 bool remove(const path& p);
199 bool remove(const path& p, error_code& ec) noexcept;
200
201 uintmax_t remove_all(const path& p);
202 uintmax_t remove_all(const path& p, error_code& ec);
203
204 void rename(const path& from, const path& to);
205 void rename(const path& from, const path& to, error_code& ec) noexcept;
206
207 void resize_file(const path& p, uintmax_t size);
208 void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept;
209
210 space_info space(const path& p);
211 space_info space(const path& p, error_code& ec) noexcept;
212
213 file_status status(const path& p);
214 file_status status(const path& p, error_code& ec) noexcept;
215
216 bool status_known(file_status s) noexcept;
217
218 file_status symlink_status(const path& p);
219 file_status symlink_status(const path& p, error_code& ec) noexcept;
220
221 path temp_directory_path();
222 path temp_directory_path(error_code& ec);
223
224 path weakly_canonical(path const& p);
225 path weakly_canonical(path const& p, error_code& ec);
226
227
228} } // namespaces std::filesystem
229
230*/
231
Louis Dionne73912b22020-11-04 15:01:25 -0500232#include <__availability>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400233#include <__config>
234#include <__debug>
Christopher Di Bella41f26e82021-06-05 02:47:47 +0000235#include <__utility/forward.h>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000236#include <chrono>
Arthur O'Dwyer7deec122021-03-24 18:19:12 -0400237#include <compare>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400238#include <cstddef>
239#include <cstdlib>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000240#include <iosfwd>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400241#include <iterator>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000242#include <memory>
243#include <stack>
244#include <string>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400245#include <string_view>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000246#include <system_error>
247#include <utility>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000248#include <version>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000249
Louis Dionne8d053eb2020-10-09 15:31:05 -0400250#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
251# include <locale>
252# include <iomanip> // for quoted
253#endif
254
Louis Dionnedb84e122021-01-18 12:18:18 -0500255#if defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
Mark de Wever2d66e4b2021-07-28 08:11:52 +0200256# error "The Filesystem library is not supported since libc++ has been configured with LIBCXX_ENABLE_FILESYSTEM disabled"
Louis Dionnedb84e122021-01-18 12:18:18 -0500257#endif
258
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000259#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
260#pragma GCC system_header
261#endif
262
263_LIBCPP_PUSH_MACROS
264#include <__undef_macros>
265
266#ifndef _LIBCPP_CXX03_LANG
267
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000268_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
269
Louis Dionnef6bf76a2019-03-20 21:18:14 +0000270_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
271
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000272typedef chrono::time_point<_FilesystemClock> file_time_type;
273
274struct _LIBCPP_TYPE_VIS space_info {
275 uintmax_t capacity;
276 uintmax_t free;
277 uintmax_t available;
278};
279
Joe Loseraf491a22021-10-10 12:53:35 -0400280// On Windows, the library never identifies files as block, character, fifo
Martin Storsjöb2485452021-03-07 23:49:56 +0200281// or socket.
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000282enum class _LIBCPP_ENUM_VIS file_type : signed char {
283 none = 0,
284 not_found = -1,
285 regular = 1,
286 directory = 2,
287 symlink = 3,
288 block = 4,
289 character = 5,
290 fifo = 6,
291 socket = 7,
292 unknown = 8
293};
294
Martin Storsjöb2485452021-03-07 23:49:56 +0200295// On Windows, these permission bits map to one single readonly flag per
296// file, and the executable bit is always returned as set. When setting
297// permissions, as long as the write bit is set for either owner, group or
298// others, the readonly flag is cleared.
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000299enum class _LIBCPP_ENUM_VIS perms : unsigned {
300 none = 0,
301
302 owner_read = 0400,
303 owner_write = 0200,
304 owner_exec = 0100,
305 owner_all = 0700,
306
307 group_read = 040,
308 group_write = 020,
309 group_exec = 010,
310 group_all = 070,
311
312 others_read = 04,
313 others_write = 02,
314 others_exec = 01,
315 others_all = 07,
316
317 all = 0777,
318
319 set_uid = 04000,
320 set_gid = 02000,
321 sticky_bit = 01000,
322 mask = 07777,
323 unknown = 0xFFFF,
324};
325
326_LIBCPP_INLINE_VISIBILITY
327inline constexpr perms operator&(perms _LHS, perms _RHS) {
328 return static_cast<perms>(static_cast<unsigned>(_LHS) &
329 static_cast<unsigned>(_RHS));
330}
331
332_LIBCPP_INLINE_VISIBILITY
333inline constexpr perms operator|(perms _LHS, perms _RHS) {
334 return static_cast<perms>(static_cast<unsigned>(_LHS) |
335 static_cast<unsigned>(_RHS));
336}
337
338_LIBCPP_INLINE_VISIBILITY
339inline constexpr perms operator^(perms _LHS, perms _RHS) {
340 return static_cast<perms>(static_cast<unsigned>(_LHS) ^
341 static_cast<unsigned>(_RHS));
342}
343
344_LIBCPP_INLINE_VISIBILITY
345inline constexpr perms operator~(perms _LHS) {
346 return static_cast<perms>(~static_cast<unsigned>(_LHS));
347}
348
349_LIBCPP_INLINE_VISIBILITY
350inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
351
352_LIBCPP_INLINE_VISIBILITY
353inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
354
355_LIBCPP_INLINE_VISIBILITY
356inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
357
358enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
359 replace = 1,
360 add = 2,
361 remove = 4,
362 nofollow = 8
363};
364
365_LIBCPP_INLINE_VISIBILITY
366inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) {
367 return static_cast<perm_options>(static_cast<unsigned>(_LHS) &
368 static_cast<unsigned>(_RHS));
369}
370
371_LIBCPP_INLINE_VISIBILITY
372inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) {
373 return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
374 static_cast<unsigned>(_RHS));
375}
376
377_LIBCPP_INLINE_VISIBILITY
378inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) {
379 return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
380 static_cast<unsigned>(_RHS));
381}
382
383_LIBCPP_INLINE_VISIBILITY
384inline constexpr perm_options operator~(perm_options _LHS) {
385 return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
386}
387
388_LIBCPP_INLINE_VISIBILITY
389inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
390 return _LHS = _LHS & _RHS;
391}
392
393_LIBCPP_INLINE_VISIBILITY
394inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
395 return _LHS = _LHS | _RHS;
396}
397
398_LIBCPP_INLINE_VISIBILITY
399inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
400 return _LHS = _LHS ^ _RHS;
401}
402
403enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
404 none = 0,
405 skip_existing = 1,
406 overwrite_existing = 2,
407 update_existing = 4,
408 recursive = 8,
409 copy_symlinks = 16,
410 skip_symlinks = 32,
411 directories_only = 64,
412 create_symlinks = 128,
413 create_hard_links = 256,
414 __in_recursive_copy = 512,
415};
416
417_LIBCPP_INLINE_VISIBILITY
418inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) {
419 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) &
420 static_cast<unsigned short>(_RHS));
421}
422
423_LIBCPP_INLINE_VISIBILITY
424inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) {
425 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
426 static_cast<unsigned short>(_RHS));
427}
428
429_LIBCPP_INLINE_VISIBILITY
430inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) {
431 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
432 static_cast<unsigned short>(_RHS));
433}
434
435_LIBCPP_INLINE_VISIBILITY
436inline constexpr copy_options operator~(copy_options _LHS) {
437 return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
438}
439
440_LIBCPP_INLINE_VISIBILITY
441inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
442 return _LHS = _LHS & _RHS;
443}
444
445_LIBCPP_INLINE_VISIBILITY
446inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
447 return _LHS = _LHS | _RHS;
448}
449
450_LIBCPP_INLINE_VISIBILITY
451inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
452 return _LHS = _LHS ^ _RHS;
453}
454
455enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
456 none = 0,
457 follow_directory_symlink = 1,
458 skip_permission_denied = 2
459};
460
461_LIBCPP_INLINE_VISIBILITY
462inline constexpr directory_options operator&(directory_options _LHS,
463 directory_options _RHS) {
464 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
465 static_cast<unsigned char>(_RHS));
466}
467
468_LIBCPP_INLINE_VISIBILITY
469inline constexpr directory_options operator|(directory_options _LHS,
470 directory_options _RHS) {
471 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
472 static_cast<unsigned char>(_RHS));
473}
474
475_LIBCPP_INLINE_VISIBILITY
476inline constexpr directory_options operator^(directory_options _LHS,
477 directory_options _RHS) {
478 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
479 static_cast<unsigned char>(_RHS));
480}
481
482_LIBCPP_INLINE_VISIBILITY
483inline constexpr directory_options operator~(directory_options _LHS) {
484 return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
485}
486
487_LIBCPP_INLINE_VISIBILITY
488inline directory_options& operator&=(directory_options& _LHS,
489 directory_options _RHS) {
490 return _LHS = _LHS & _RHS;
491}
492
493_LIBCPP_INLINE_VISIBILITY
494inline directory_options& operator|=(directory_options& _LHS,
495 directory_options _RHS) {
496 return _LHS = _LHS | _RHS;
497}
498
499_LIBCPP_INLINE_VISIBILITY
500inline directory_options& operator^=(directory_options& _LHS,
501 directory_options _RHS) {
502 return _LHS = _LHS ^ _RHS;
503}
504
505class _LIBCPP_TYPE_VIS file_status {
506public:
507 // constructors
508 _LIBCPP_INLINE_VISIBILITY
509 file_status() noexcept : file_status(file_type::none) {}
510 _LIBCPP_INLINE_VISIBILITY
511 explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
512 : __ft_(__ft),
513 __prms_(__prms) {}
514
515 file_status(const file_status&) noexcept = default;
516 file_status(file_status&&) noexcept = default;
517
518 _LIBCPP_INLINE_VISIBILITY
519 ~file_status() {}
520
521 file_status& operator=(const file_status&) noexcept = default;
522 file_status& operator=(file_status&&) noexcept = default;
523
524 // observers
525 _LIBCPP_INLINE_VISIBILITY
526 file_type type() const noexcept { return __ft_; }
527
528 _LIBCPP_INLINE_VISIBILITY
529 perms permissions() const noexcept { return __prms_; }
530
531 // modifiers
532 _LIBCPP_INLINE_VISIBILITY
533 void type(file_type __ft) noexcept { __ft_ = __ft; }
534
535 _LIBCPP_INLINE_VISIBILITY
536 void permissions(perms __p) noexcept { __prms_ = __p; }
537
538private:
539 file_type __ft_;
540 perms __prms_;
541};
542
543class _LIBCPP_TYPE_VIS directory_entry;
544
545template <class _Tp>
546struct __can_convert_char {
547 static const bool value = false;
548};
549template <class _Tp>
550struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
551template <>
552struct __can_convert_char<char> {
553 static const bool value = true;
554 using __char_type = char;
555};
556template <>
557struct __can_convert_char<wchar_t> {
558 static const bool value = true;
559 using __char_type = wchar_t;
560};
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400561#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +0200562template <>
563struct __can_convert_char<char8_t> {
564 static const bool value = true;
565 using __char_type = char8_t;
566};
567#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000568template <>
569struct __can_convert_char<char16_t> {
570 static const bool value = true;
571 using __char_type = char16_t;
572};
573template <>
574struct __can_convert_char<char32_t> {
575 static const bool value = true;
576 using __char_type = char32_t;
577};
578
579template <class _ECharT>
580typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
581__is_separator(_ECharT __e) {
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200582#if defined(_LIBCPP_WIN32API)
583 return __e == _ECharT('/') || __e == _ECharT('\\');
584#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000585 return __e == _ECharT('/');
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200586#endif
Eric Fiselierb41db9a2018-10-01 01:59:37 +0000587}
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000588
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400589#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200590typedef u8string __u8_string;
591#else
592typedef string __u8_string;
593#endif
594
Martin Storsjö2ae96532020-10-27 11:46:06 +0200595struct _NullSentinel {};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000596
597template <class _Tp>
598using _Void = void;
599
600template <class _Tp, class = void>
601struct __is_pathable_string : public false_type {};
602
603template <class _ECharT, class _Traits, class _Alloc>
604struct __is_pathable_string<
605 basic_string<_ECharT, _Traits, _Alloc>,
606 _Void<typename __can_convert_char<_ECharT>::__char_type> >
607 : public __can_convert_char<_ECharT> {
608 using _Str = basic_string<_ECharT, _Traits, _Alloc>;
609 using _Base = __can_convert_char<_ECharT>;
610 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
611 static _ECharT const* __range_end(_Str const& __s) {
612 return __s.data() + __s.length();
613 }
614 static _ECharT __first_or_null(_Str const& __s) {
615 return __s.empty() ? _ECharT{} : __s[0];
616 }
617};
618
619template <class _ECharT, class _Traits>
620struct __is_pathable_string<
621 basic_string_view<_ECharT, _Traits>,
622 _Void<typename __can_convert_char<_ECharT>::__char_type> >
623 : public __can_convert_char<_ECharT> {
624 using _Str = basic_string_view<_ECharT, _Traits>;
625 using _Base = __can_convert_char<_ECharT>;
626 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
627 static _ECharT const* __range_end(_Str const& __s) {
628 return __s.data() + __s.length();
629 }
630 static _ECharT __first_or_null(_Str const& __s) {
631 return __s.empty() ? _ECharT{} : __s[0];
632 }
633};
634
635template <class _Source, class _DS = typename decay<_Source>::type,
636 class _UnqualPtrType =
637 typename remove_const<typename remove_pointer<_DS>::type>::type,
638 bool _IsCharPtr = is_pointer<_DS>::value&&
639 __can_convert_char<_UnqualPtrType>::value>
640struct __is_pathable_char_array : false_type {};
641
642template <class _Source, class _ECharT, class _UPtr>
643struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
644 : __can_convert_char<typename remove_const<_ECharT>::type> {
645 using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
646
647 static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
648 static _ECharT const* __range_end(const _ECharT* __b) {
649 using _Iter = const _ECharT*;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200650 const _ECharT __sentinel = _ECharT{};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000651 _Iter __e = __b;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200652 for (; *__e != __sentinel; ++__e)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000653 ;
654 return __e;
655 }
656
657 static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
658};
659
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500660template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000661 class = void>
662struct __is_pathable_iter : false_type {};
663
664template <class _Iter>
665struct __is_pathable_iter<
666 _Iter, true,
667 _Void<typename __can_convert_char<
668 typename iterator_traits<_Iter>::value_type>::__char_type> >
669 : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
670 using _ECharT = typename iterator_traits<_Iter>::value_type;
671 using _Base = __can_convert_char<_ECharT>;
672
673 static _Iter __range_begin(_Iter __b) { return __b; }
Martin Storsjö2ae96532020-10-27 11:46:06 +0200674 static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000675
676 static _ECharT __first_or_null(_Iter __b) { return *__b; }
677};
678
679template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
680 bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
681 bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
682struct __is_pathable : false_type {
683 static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
684};
685
686template <class _Tp>
687struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
688
689template <class _Tp>
690struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
691};
692
693template <class _Tp>
694struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
695
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200696#if defined(_LIBCPP_WIN32API)
697typedef wstring __path_string;
698typedef wchar_t __path_value;
699#else
700typedef string __path_string;
701typedef char __path_value;
702#endif
703
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200704#if defined(_LIBCPP_WIN32API)
705_LIBCPP_FUNC_VIS
706size_t __wide_to_char(const wstring&, char*, size_t);
707_LIBCPP_FUNC_VIS
708size_t __char_to_wide(const string&, wchar_t*, size_t);
709#endif
710
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000711template <class _ECharT>
Louis Dionne8d053eb2020-10-09 15:31:05 -0400712struct _PathCVT;
713
714#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
715template <class _ECharT>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000716struct _PathCVT {
717 static_assert(__can_convert_char<_ECharT>::value,
718 "Char type not convertible");
719
720 typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200721#if defined(_LIBCPP_WIN32API)
722 typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
723#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000724
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200725 static void __append_range(__path_string& __dest, _ECharT const* __b,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000726 _ECharT const* __e) {
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200727#if defined(_LIBCPP_WIN32API)
728 string __utf8;
729 _Narrower()(back_inserter(__utf8), __b, __e);
730 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
731#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000732 _Narrower()(back_inserter(__dest), __b, __e);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200733#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000734 }
735
736 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200737 static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000738 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
739 if (__b == __e)
740 return;
741 basic_string<_ECharT> __tmp(__b, __e);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200742#if defined(_LIBCPP_WIN32API)
743 string __utf8;
744 _Narrower()(back_inserter(__utf8), __tmp.data(),
745 __tmp.data() + __tmp.length());
746 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
747#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000748 _Narrower()(back_inserter(__dest), __tmp.data(),
749 __tmp.data() + __tmp.length());
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200750#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000751 }
752
753 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200754 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000755 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
Martin Storsjö2ae96532020-10-27 11:46:06 +0200756 const _ECharT __sentinel = _ECharT{};
757 if (*__b == __sentinel)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000758 return;
759 basic_string<_ECharT> __tmp;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200760 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000761 __tmp.push_back(*__b);
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200762#if defined(_LIBCPP_WIN32API)
763 string __utf8;
764 _Narrower()(back_inserter(__utf8), __tmp.data(),
765 __tmp.data() + __tmp.length());
766 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
767#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000768 _Narrower()(back_inserter(__dest), __tmp.data(),
769 __tmp.data() + __tmp.length());
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200770#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000771 }
772
773 template <class _Source>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200774 static void __append_source(__path_string& __dest, _Source const& __s) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000775 using _Traits = __is_pathable<_Source>;
776 __append_range(__dest, _Traits::__range_begin(__s),
777 _Traits::__range_end(__s));
778 }
779};
Louis Dionne8d053eb2020-10-09 15:31:05 -0400780#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000781
782template <>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200783struct _PathCVT<__path_value> {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000784
785 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500786 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200787 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000788 for (; __b != __e; ++__b)
789 __dest.push_back(*__b);
790 }
791
792 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500793 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200794 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
Arthur O'Dwyer98ff31f2021-04-16 17:49:57 -0400795 __dest.append(__b, __e);
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000796 }
797
798 template <class _Iter>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200799 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
Martin Storsjö2ae96532020-10-27 11:46:06 +0200800 const char __sentinel = char{};
801 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000802 __dest.push_back(*__b);
803 }
804
805 template <class _Source>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200806 static void __append_source(__path_string& __dest, _Source const& __s) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000807 using _Traits = __is_pathable<_Source>;
808 __append_range(__dest, _Traits::__range_begin(__s),
809 _Traits::__range_end(__s));
810 }
811};
812
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200813#if defined(_LIBCPP_WIN32API)
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200814template <>
815struct _PathCVT<char> {
816
817 static void
818 __append_string(__path_string& __dest, const basic_string<char> &__str) {
819 size_t __size = __char_to_wide(__str, nullptr, 0);
820 size_t __pos = __dest.size();
821 __dest.resize(__pos + __size);
822 __char_to_wide(__str, const_cast<__path_value*>(__dest.data()) + __pos, __size);
823 }
824
825 template <class _Iter>
826 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
827 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
828 basic_string<char> __tmp(__b, __e);
829 __append_string(__dest, __tmp);
830 }
831
832 template <class _Iter>
833 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
834 __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
835 basic_string<char> __tmp(__b, __e);
836 __append_string(__dest, __tmp);
837 }
838
839 template <class _Iter>
840 static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
841 const char __sentinel = char{};
842 basic_string<char> __tmp;
843 for (; *__b != __sentinel; ++__b)
844 __tmp.push_back(*__b);
845 __append_string(__dest, __tmp);
846 }
847
848 template <class _Source>
849 static void __append_source(__path_string& __dest, _Source const& __s) {
850 using _Traits = __is_pathable<_Source>;
851 __append_range(__dest, _Traits::__range_begin(__s),
852 _Traits::__range_end(__s));
853 }
854};
855
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200856template <class _ECharT>
857struct _PathExport {
858 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
859 typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
860
861 template <class _Str>
862 static void __append(_Str& __dest, const __path_string& __src) {
863 string __utf8;
864 _Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
865 _Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
866 }
867};
868
869template <>
Martin Storsjöfc25e3a2020-10-27 13:30:34 +0200870struct _PathExport<char> {
871 template <class _Str>
872 static void __append(_Str& __dest, const __path_string& __src) {
873 size_t __size = __wide_to_char(__src, nullptr, 0);
874 size_t __pos = __dest.size();
875 __dest.resize(__size);
876 __wide_to_char(__src, const_cast<char*>(__dest.data()) + __pos, __size);
877 }
878};
879
880template <>
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200881struct _PathExport<wchar_t> {
882 template <class _Str>
883 static void __append(_Str& __dest, const __path_string& __src) {
884 __dest.append(__src.begin(), __src.end());
885 }
886};
887
888template <>
889struct _PathExport<char16_t> {
890 template <class _Str>
891 static void __append(_Str& __dest, const __path_string& __src) {
892 __dest.append(__src.begin(), __src.end());
893 }
894};
895
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400896#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200897template <>
898struct _PathExport<char8_t> {
899 typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
900
901 template <class _Str>
902 static void __append(_Str& __dest, const __path_string& __src) {
903 _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
904 }
905};
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400906#endif /* !_LIBCPP_HAS_NO_CHAR8_T */
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200907#endif /* _LIBCPP_WIN32API */
908
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000909class _LIBCPP_TYPE_VIS path {
910 template <class _SourceOrIter, class _Tp = path&>
911 using _EnableIfPathable =
912 typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
913
914 template <class _Tp>
915 using _SourceChar = typename __is_pathable<_Tp>::__char_type;
916
917 template <class _Tp>
918 using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
919
920public:
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200921#if defined(_LIBCPP_WIN32API)
922 typedef wchar_t value_type;
923 static constexpr value_type preferred_separator = L'\\';
924#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000925 typedef char value_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000926 static constexpr value_type preferred_separator = '/';
Martin Storsjöe482f4b2020-10-27 13:09:08 +0200927#endif
928 typedef basic_string<value_type> string_type;
929 typedef basic_string_view<value_type> __string_view;
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000930
Martin Storsjö560291c2020-11-06 11:57:47 +0200931 enum _LIBCPP_ENUM_VIS format : unsigned char {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000932 auto_format,
933 native_format,
934 generic_format
935 };
936
937 // constructors and destructor
938 _LIBCPP_INLINE_VISIBILITY path() noexcept {}
939 _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
940 _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
941 : __pn_(_VSTD::move(__p.__pn_)) {}
942
943 _LIBCPP_INLINE_VISIBILITY
944 path(string_type&& __s, format = format::auto_format) noexcept
945 : __pn_(_VSTD::move(__s)) {}
946
947 template <class _Source, class = _EnableIfPathable<_Source, void> >
948 path(const _Source& __src, format = format::auto_format) {
949 _SourceCVT<_Source>::__append_source(__pn_, __src);
950 }
951
952 template <class _InputIt>
953 path(_InputIt __first, _InputIt __last, format = format::auto_format) {
954 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
955 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
956 }
957
Louis Dionne8d053eb2020-10-09 15:31:05 -0400958#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000959 // TODO Implement locale conversions.
960 template <class _Source, class = _EnableIfPathable<_Source, void> >
961 path(const _Source& __src, const locale& __loc, format = format::auto_format);
962 template <class _InputIt>
963 path(_InputIt __first, _InputIt _last, const locale& __loc,
964 format = format::auto_format);
Louis Dionne8d053eb2020-10-09 15:31:05 -0400965#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000966
967 _LIBCPP_INLINE_VISIBILITY
968 ~path() = default;
969
970 // assignments
971 _LIBCPP_INLINE_VISIBILITY
972 path& operator=(const path& __p) {
973 __pn_ = __p.__pn_;
974 return *this;
975 }
976
977 _LIBCPP_INLINE_VISIBILITY
978 path& operator=(path&& __p) noexcept {
979 __pn_ = _VSTD::move(__p.__pn_);
980 return *this;
981 }
982
Louis Dionne5da71d22021-02-03 16:40:41 -0500983 _LIBCPP_INLINE_VISIBILITY
984 path& operator=(string_type&& __s) noexcept {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000985 __pn_ = _VSTD::move(__s);
986 return *this;
987 }
988
989 _LIBCPP_INLINE_VISIBILITY
990 path& assign(string_type&& __s) noexcept {
991 __pn_ = _VSTD::move(__s);
992 return *this;
993 }
994
995 template <class _Source>
996 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
997 operator=(const _Source& __src) {
998 return this->assign(__src);
999 }
1000
1001 template <class _Source>
1002 _EnableIfPathable<_Source> assign(const _Source& __src) {
1003 __pn_.clear();
1004 _SourceCVT<_Source>::__append_source(__pn_, __src);
1005 return *this;
1006 }
1007
1008 template <class _InputIt>
1009 path& assign(_InputIt __first, _InputIt __last) {
1010 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1011 __pn_.clear();
1012 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1013 return *this;
1014 }
1015
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001016public:
1017 // appends
Martin Storsjö98770152020-11-04 15:59:56 +02001018#if defined(_LIBCPP_WIN32API)
1019 path& operator/=(const path& __p) {
1020 auto __p_root_name = __p.__root_name();
1021 auto __p_root_name_size = __p_root_name.size();
1022 if (__p.is_absolute() ||
1023 (!__p_root_name.empty() && __p_root_name != root_name())) {
1024 __pn_ = __p.__pn_;
1025 return *this;
1026 }
1027 if (__p.has_root_directory()) {
1028 path __root_name_str = root_name();
1029 __pn_ = __root_name_str.native();
Martin Storsjöacb39e12021-03-11 13:06:08 +02001030 __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
Martin Storsjö98770152020-11-04 15:59:56 +02001031 return *this;
1032 }
1033 if (has_filename() || (!has_root_directory() && is_absolute()))
1034 __pn_ += preferred_separator;
Martin Storsjöacb39e12021-03-11 13:06:08 +02001035 __pn_ += __string_view(__p.__pn_).substr(__p_root_name_size);
Martin Storsjö98770152020-11-04 15:59:56 +02001036 return *this;
1037 }
1038 template <class _Source>
1039 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1040 operator/=(const _Source& __src) {
1041 return operator/=(path(__src));
1042 }
1043
1044 template <class _Source>
1045 _EnableIfPathable<_Source> append(const _Source& __src) {
1046 return operator/=(path(__src));
1047 }
1048
1049 template <class _InputIt>
1050 path& append(_InputIt __first, _InputIt __last) {
1051 return operator/=(path(__first, __last));
1052 }
1053#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001054 path& operator/=(const path& __p) {
1055 if (__p.is_absolute()) {
1056 __pn_ = __p.__pn_;
1057 return *this;
1058 }
1059 if (has_filename())
1060 __pn_ += preferred_separator;
1061 __pn_ += __p.native();
1062 return *this;
1063 }
1064
1065 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
1066 // is known at compile time to be "/' since the user almost certainly intended
1067 // to append a separator instead of overwriting the path with "/"
1068 template <class _Source>
1069 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
1070 operator/=(const _Source& __src) {
1071 return this->append(__src);
1072 }
1073
1074 template <class _Source>
1075 _EnableIfPathable<_Source> append(const _Source& __src) {
1076 using _Traits = __is_pathable<_Source>;
1077 using _CVT = _PathCVT<_SourceChar<_Source> >;
Martin Storsjö98770152020-11-04 15:59:56 +02001078 bool __source_is_absolute = __is_separator(_Traits::__first_or_null(__src));
1079 if (__source_is_absolute)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001080 __pn_.clear();
1081 else if (has_filename())
1082 __pn_ += preferred_separator;
1083 _CVT::__append_source(__pn_, __src);
1084 return *this;
1085 }
1086
1087 template <class _InputIt>
1088 path& append(_InputIt __first, _InputIt __last) {
1089 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1090 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
1091 using _CVT = _PathCVT<_ItVal>;
Martin Storsjö98770152020-11-04 15:59:56 +02001092 if (__first != __last && __is_separator(*__first))
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001093 __pn_.clear();
1094 else if (has_filename())
1095 __pn_ += preferred_separator;
1096 _CVT::__append_range(__pn_, __first, __last);
1097 return *this;
1098 }
Martin Storsjö98770152020-11-04 15:59:56 +02001099#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001100
1101 // concatenation
1102 _LIBCPP_INLINE_VISIBILITY
1103 path& operator+=(const path& __x) {
1104 __pn_ += __x.__pn_;
1105 return *this;
1106 }
1107
1108 _LIBCPP_INLINE_VISIBILITY
1109 path& operator+=(const string_type& __x) {
1110 __pn_ += __x;
1111 return *this;
1112 }
1113
1114 _LIBCPP_INLINE_VISIBILITY
1115 path& operator+=(__string_view __x) {
1116 __pn_ += __x;
1117 return *this;
1118 }
1119
1120 _LIBCPP_INLINE_VISIBILITY
1121 path& operator+=(const value_type* __x) {
1122 __pn_ += __x;
1123 return *this;
1124 }
1125
1126 _LIBCPP_INLINE_VISIBILITY
1127 path& operator+=(value_type __x) {
1128 __pn_ += __x;
1129 return *this;
1130 }
1131
1132 template <class _ECharT>
1133 typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
1134 operator+=(_ECharT __x) {
Marek Kurdej306a1b02020-12-07 20:07:25 +01001135 _PathCVT<_ECharT>::__append_source(__pn_,
1136 basic_string_view<_ECharT>(&__x, 1));
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001137 return *this;
1138 }
1139
1140 template <class _Source>
1141 _EnableIfPathable<_Source> operator+=(const _Source& __x) {
1142 return this->concat(__x);
1143 }
1144
1145 template <class _Source>
1146 _EnableIfPathable<_Source> concat(const _Source& __x) {
1147 _SourceCVT<_Source>::__append_source(__pn_, __x);
1148 return *this;
1149 }
1150
1151 template <class _InputIt>
1152 path& concat(_InputIt __first, _InputIt __last) {
1153 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
1154 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
1155 return *this;
1156 }
1157
1158 // modifiers
1159 _LIBCPP_INLINE_VISIBILITY
1160 void clear() noexcept { __pn_.clear(); }
1161
Martin Storsjöf543c7a2020-10-28 12:24:11 +02001162 path& make_preferred() {
1163#if defined(_LIBCPP_WIN32API)
1164 _VSTD::replace(__pn_.begin(), __pn_.end(), L'/', L'\\');
1165#endif
1166 return *this;
1167 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001168
1169 _LIBCPP_INLINE_VISIBILITY
1170 path& remove_filename() {
1171 auto __fname = __filename();
1172 if (!__fname.empty())
1173 __pn_.erase(__fname.data() - __pn_.data());
1174 return *this;
1175 }
1176
1177 path& replace_filename(const path& __replacement) {
1178 remove_filename();
1179 return (*this /= __replacement);
1180 }
1181
1182 path& replace_extension(const path& __replacement = path());
1183
1184 _LIBCPP_INLINE_VISIBILITY
1185 void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
1186
1187 // private helper to allow reserving memory in the path
1188 _LIBCPP_INLINE_VISIBILITY
1189 void __reserve(size_t __s) { __pn_.reserve(__s); }
1190
1191 // native format observers
1192 _LIBCPP_INLINE_VISIBILITY
1193 const string_type& native() const noexcept { return __pn_; }
1194
1195 _LIBCPP_INLINE_VISIBILITY
1196 const value_type* c_str() const noexcept { return __pn_.c_str(); }
1197
1198 _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
1199
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001200#if defined(_LIBCPP_WIN32API)
1201 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; }
1202
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001203 _VSTD::wstring generic_wstring() const {
1204 _VSTD::wstring __s;
1205 __s.resize(__pn_.size());
1206 _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/');
1207 return __s;
1208 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001209
1210#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
1211 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1212 class _Allocator = allocator<_ECharT> >
1213 basic_string<_ECharT, _Traits, _Allocator>
1214 string(const _Allocator& __a = _Allocator()) const {
1215 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1216 _Str __s(__a);
1217 __s.reserve(__pn_.size());
1218 _PathExport<_ECharT>::__append(__s, __pn_);
1219 return __s;
1220 }
1221
1222 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const {
1223 return string<char>();
1224 }
1225 _LIBCPP_INLINE_VISIBILITY __u8_string u8string() const {
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001226 using _CVT = __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1227 __u8_string __s;
1228 __s.reserve(__pn_.size());
1229 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1230 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001231 }
1232
1233 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
1234 return string<char16_t>();
1235 }
1236 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
1237 return string<char32_t>();
1238 }
1239
1240 // generic format observers
1241 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1242 class _Allocator = allocator<_ECharT> >
1243 basic_string<_ECharT, _Traits, _Allocator>
1244 generic_string(const _Allocator& __a = _Allocator()) const {
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001245 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1246 _Str __s = string<_ECharT, _Traits, _Allocator>(__a);
1247 // Note: This (and generic_u8string below) is slightly suboptimal as
1248 // it iterates twice over the string; once to convert it to the right
1249 // character type, and once to replace path delimiters.
1250 _VSTD::replace(__s.begin(), __s.end(),
1251 static_cast<_ECharT>('\\'), static_cast<_ECharT>('/'));
1252 return __s;
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001253 }
1254
1255 _VSTD::string generic_string() const { return generic_string<char>(); }
1256 _VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); }
1257 _VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); }
Martin Storsjö15cd83a2020-11-09 11:45:13 +02001258 __u8_string generic_u8string() const {
1259 __u8_string __s = u8string();
1260 _VSTD::replace(__s.begin(), __s.end(), '\\', '/');
1261 return __s;
1262 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001263#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1264#else /* _LIBCPP_WIN32API */
1265
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001266 _LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; }
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001267#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001268 _LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1269#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001270 _LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001271#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001272
1273#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001274 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1275 class _Allocator = allocator<_ECharT> >
1276 basic_string<_ECharT, _Traits, _Allocator>
1277 string(const _Allocator& __a = _Allocator()) const {
1278 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
1279 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1280 _Str __s(__a);
1281 __s.reserve(__pn_.size());
1282 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1283 return __s;
1284 }
1285
Louis Dionne89258142021-08-23 15:32:36 -04001286#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001287 _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001288 return string<wchar_t>();
1289 }
Louis Dionne89258142021-08-23 15:32:36 -04001290#endif
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001291 _LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001292 return string<char16_t>();
1293 }
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001294 _LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001295 return string<char32_t>();
1296 }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001297#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001298
1299 // generic format observers
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001300 _VSTD::string generic_string() const { return __pn_; }
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001301#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001302 _VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
1303#else
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001304 _VSTD::string generic_u8string() const { return __pn_; }
Martin Storsjöe3a71972020-10-26 13:18:46 +02001305#endif
Louis Dionne8d053eb2020-10-09 15:31:05 -04001306
1307#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001308 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1309 class _Allocator = allocator<_ECharT> >
1310 basic_string<_ECharT, _Traits, _Allocator>
1311 generic_string(const _Allocator& __a = _Allocator()) const {
1312 return string<_ECharT, _Traits, _Allocator>(__a);
1313 }
1314
Louis Dionne89258142021-08-23 15:32:36 -04001315#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001316 _VSTD::wstring generic_wstring() const { return string<wchar_t>(); }
Louis Dionne89258142021-08-23 15:32:36 -04001317#endif
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001318 _VSTD::u16string generic_u16string() const { return string<char16_t>(); }
1319 _VSTD::u32string generic_u32string() const { return string<char32_t>(); }
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001320#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1321#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001322
1323private:
1324 int __compare(__string_view) const;
1325 __string_view __root_name() const;
1326 __string_view __root_directory() const;
1327 __string_view __root_path_raw() const;
1328 __string_view __relative_path() const;
1329 __string_view __parent_path() const;
1330 __string_view __filename() const;
1331 __string_view __stem() const;
1332 __string_view __extension() const;
1333
1334public:
1335 // compare
1336 _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
1337 return __compare(__p.__pn_);
1338 }
1339 _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
1340 return __compare(__s);
1341 }
1342 _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
1343 return __compare(__s);
1344 }
1345 _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
1346 return __compare(__s);
1347 }
1348
1349 // decomposition
1350 _LIBCPP_INLINE_VISIBILITY path root_name() const {
1351 return string_type(__root_name());
1352 }
1353 _LIBCPP_INLINE_VISIBILITY path root_directory() const {
1354 return string_type(__root_directory());
1355 }
1356 _LIBCPP_INLINE_VISIBILITY path root_path() const {
Martin Storsjö98770152020-11-04 15:59:56 +02001357#if defined(_LIBCPP_WIN32API)
1358 return string_type(__root_path_raw());
1359#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001360 return root_name().append(string_type(__root_directory()));
Martin Storsjö98770152020-11-04 15:59:56 +02001361#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001362 }
1363 _LIBCPP_INLINE_VISIBILITY path relative_path() const {
1364 return string_type(__relative_path());
1365 }
1366 _LIBCPP_INLINE_VISIBILITY path parent_path() const {
1367 return string_type(__parent_path());
1368 }
1369 _LIBCPP_INLINE_VISIBILITY path filename() const {
1370 return string_type(__filename());
1371 }
1372 _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
1373 _LIBCPP_INLINE_VISIBILITY path extension() const {
1374 return string_type(__extension());
1375 }
1376
1377 // query
1378 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
1379 empty() const noexcept {
1380 return __pn_.empty();
1381 }
1382
1383 _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
1384 return !__root_name().empty();
1385 }
1386 _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
1387 return !__root_directory().empty();
1388 }
1389 _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
1390 return !__root_path_raw().empty();
1391 }
1392 _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
1393 return !__relative_path().empty();
1394 }
1395 _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
1396 return !__parent_path().empty();
1397 }
1398 _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
1399 return !__filename().empty();
1400 }
1401 _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
1402 _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
1403 return !__extension().empty();
1404 }
1405
1406 _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
Martin Storsjöef6b7422020-11-01 23:39:03 +02001407#if defined(_LIBCPP_WIN32API)
1408 __string_view __root_name_str = __root_name();
1409 __string_view __root_dir = __root_directory();
1410 if (__root_name_str.size() == 2 && __root_name_str[1] == ':') {
1411 // A drive letter with no root directory is relative, e.g. x:example.
1412 return !__root_dir.empty();
1413 }
1414 // If no root name, it's relative, e.g. \example is relative to the current drive
1415 if (__root_name_str.empty())
1416 return false;
1417 if (__root_name_str.size() < 3)
1418 return false;
1419 // A server root name, like \\server, is always absolute
1420 if (__root_name_str[0] != '/' && __root_name_str[0] != '\\')
1421 return false;
1422 if (__root_name_str[1] != '/' && __root_name_str[1] != '\\')
1423 return false;
1424 // Seems to be a server root name
1425 return true;
1426#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001427 return has_root_directory();
Martin Storsjöef6b7422020-11-01 23:39:03 +02001428#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001429 }
1430 _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
1431
1432 // relative paths
1433 path lexically_normal() const;
1434 path lexically_relative(const path& __base) const;
1435
1436 _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
1437 path __result = this->lexically_relative(__base);
1438 if (__result.native().empty())
1439 return *this;
1440 return __result;
1441 }
1442
1443 // iterators
1444 class _LIBCPP_TYPE_VIS iterator;
1445 typedef iterator const_iterator;
1446
1447 iterator begin() const;
1448 iterator end() const;
1449
Louis Dionne8d053eb2020-10-09 15:31:05 -04001450#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001451 template <class _CharT, class _Traits>
1452 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001453 typename enable_if<is_same<_CharT, value_type>::value &&
1454 is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001455 basic_ostream<_CharT, _Traits>&>::type
1456 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001457 __os << _VSTD::__quoted(__p.native());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001458 return __os;
1459 }
1460
1461 template <class _CharT, class _Traits>
1462 _LIBCPP_INLINE_VISIBILITY friend
Martin Storsjöe482f4b2020-10-27 13:09:08 +02001463 typename enable_if<!is_same<_CharT, value_type>::value ||
1464 !is_same<_Traits, char_traits<value_type> >::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001465 basic_ostream<_CharT, _Traits>&>::type
1466 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001467 __os << _VSTD::__quoted(__p.string<_CharT, _Traits>());
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001468 return __os;
1469 }
1470
1471 template <class _CharT, class _Traits>
1472 _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
1473 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
1474 basic_string<_CharT, _Traits> __tmp;
1475 __is >> __quoted(__tmp);
1476 __p = __tmp;
1477 return __is;
1478 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001479#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001480
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001481 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
1482 return __lhs.compare(__rhs) == 0;
1483 }
1484 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
1485 return __lhs.compare(__rhs) != 0;
1486 }
1487 friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
1488 return __lhs.compare(__rhs) < 0;
1489 }
1490 friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
1491 return __lhs.compare(__rhs) <= 0;
1492 }
1493 friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
1494 return __lhs.compare(__rhs) > 0;
1495 }
1496 friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
1497 return __lhs.compare(__rhs) >= 0;
1498 }
1499
1500 friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
1501 const path& __rhs) {
1502 path __result(__lhs);
1503 __result /= __rhs;
1504 return __result;
1505 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001506private:
1507 inline _LIBCPP_INLINE_VISIBILITY path&
1508 __assign_view(__string_view const& __s) noexcept {
1509 __pn_ = string_type(__s);
1510 return *this;
1511 }
1512 string_type __pn_;
1513};
1514
1515inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
1516 __lhs.swap(__rhs);
1517}
1518
1519_LIBCPP_FUNC_VIS
1520size_t hash_value(const path& __p) noexcept;
1521
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001522template <class _InputIt>
Martin Storsjöe3a71972020-10-26 13:18:46 +02001523_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001524 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1525 u8path(_InputIt __f, _InputIt __l) {
1526 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001527#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöe3a71972020-10-26 13:18:46 +02001528 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1529#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001530 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
Martin Storsjöe3a71972020-10-26 13:18:46 +02001531 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
Martin Storsjö929dff92020-12-15 09:15:37 +02001532 " or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001533#if defined(_LIBCPP_WIN32API)
1534 string __tmp(__f, __l);
1535 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1536 _VSTD::wstring __w;
1537 __w.reserve(__tmp.size());
1538 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1539 return path(__w);
1540#else
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001541 return path(__f, __l);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001542#endif /* !_LIBCPP_WIN32API */
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001543}
1544
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001545#if defined(_LIBCPP_WIN32API)
1546template <class _InputIt>
1547_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1548 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1549 u8path(_InputIt __f, _NullSentinel) {
1550 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001551#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001552 is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
1553#endif
1554 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
1555 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
1556 " or 'char8_t'");
1557 string __tmp;
1558 const char __sentinel = char{};
1559 for (; *__f != __sentinel; ++__f)
1560 __tmp.push_back(*__f);
1561 using _CVT = __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__>;
1562 _VSTD::wstring __w;
1563 __w.reserve(__tmp.size());
1564 _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size());
1565 return path(__w);
1566}
1567#endif /* _LIBCPP_WIN32API */
1568
Martin Storsjö367d7f02020-11-05 00:21:30 +02001569template <class _Source>
1570_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T
1571 typename enable_if<__is_pathable<_Source>::value, path>::type
1572 u8path(const _Source& __s) {
1573 static_assert(
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04001574#ifndef _LIBCPP_HAS_NO_CHAR8_T
Martin Storsjö367d7f02020-11-05 00:21:30 +02001575 is_same<typename __is_pathable<_Source>::__char_type, char8_t>::value ||
1576#endif
1577 is_same<typename __is_pathable<_Source>::__char_type, char>::value,
1578 "u8path(Source const&) requires Source have a character type of type "
1579 "'char' or 'char8_t'");
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001580#if defined(_LIBCPP_WIN32API)
1581 using _Traits = __is_pathable<_Source>;
Arthur O'Dwyer1ac9f092021-01-15 12:59:56 -05001582 return u8path(_VSTD::__unwrap_iter(_Traits::__range_begin(__s)), _VSTD::__unwrap_iter(_Traits::__range_end(__s)));
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001583#else
Martin Storsjö367d7f02020-11-05 00:21:30 +02001584 return path(__s);
Martin Storsjöfc25e3a2020-10-27 13:30:34 +02001585#endif
Martin Storsjö367d7f02020-11-05 00:21:30 +02001586}
1587
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001588class _LIBCPP_TYPE_VIS path::iterator {
1589public:
1590 enum _ParserState : unsigned char {
1591 _Singular,
1592 _BeforeBegin,
1593 _InRootName,
1594 _InRootDir,
1595 _InFilenames,
1596 _InTrailingSep,
1597 _AtEnd
1598 };
1599
1600public:
1601 typedef bidirectional_iterator_tag iterator_category;
1602
1603 typedef path value_type;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001604 typedef ptrdiff_t difference_type;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001605 typedef const path* pointer;
1606 typedef const path& reference;
1607
1608 typedef void
1609 __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
1610
1611public:
1612 _LIBCPP_INLINE_VISIBILITY
1613 iterator()
1614 : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
1615 __state_(_Singular) {}
1616
1617 iterator(const iterator&) = default;
1618 ~iterator() = default;
1619
1620 iterator& operator=(const iterator&) = default;
1621
1622 _LIBCPP_INLINE_VISIBILITY
1623 reference operator*() const { return __stashed_elem_; }
1624
1625 _LIBCPP_INLINE_VISIBILITY
1626 pointer operator->() const { return &__stashed_elem_; }
1627
1628 _LIBCPP_INLINE_VISIBILITY
1629 iterator& operator++() {
1630 _LIBCPP_ASSERT(__state_ != _Singular,
1631 "attempting to increment a singular iterator");
1632 _LIBCPP_ASSERT(__state_ != _AtEnd,
1633 "attempting to increment the end iterator");
1634 return __increment();
1635 }
1636
1637 _LIBCPP_INLINE_VISIBILITY
1638 iterator operator++(int) {
1639 iterator __it(*this);
1640 this->operator++();
1641 return __it;
1642 }
1643
1644 _LIBCPP_INLINE_VISIBILITY
1645 iterator& operator--() {
1646 _LIBCPP_ASSERT(__state_ != _Singular,
1647 "attempting to decrement a singular iterator");
1648 _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
1649 "attempting to decrement the begin iterator");
1650 return __decrement();
1651 }
1652
1653 _LIBCPP_INLINE_VISIBILITY
1654 iterator operator--(int) {
1655 iterator __it(*this);
1656 this->operator--();
1657 return __it;
1658 }
1659
1660private:
1661 friend class path;
1662
1663 inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
1664 const iterator&);
1665
1666 iterator& __increment();
1667 iterator& __decrement();
1668
1669 path __stashed_elem_;
1670 const path* __path_ptr_;
1671 path::__string_view __entry_;
1672 _ParserState __state_;
1673};
1674
1675inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
1676 const path::iterator& __rhs) {
1677 return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
1678 __lhs.__entry_.data() == __rhs.__entry_.data();
1679}
1680
1681inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
1682 const path::iterator& __rhs) {
1683 return !(__lhs == __rhs);
1684}
1685
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001686// TODO(ldionne): We need to pop the pragma and push it again after
1687// filesystem_error to work around PR41078.
1688_LIBCPP_AVAILABILITY_FILESYSTEM_POP
1689
1690class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001691public:
1692 _LIBCPP_INLINE_VISIBILITY
1693 filesystem_error(const string& __what, error_code __ec)
1694 : system_error(__ec, __what),
1695 __storage_(make_shared<_Storage>(path(), path())) {
1696 __create_what(0);
1697 }
1698
1699 _LIBCPP_INLINE_VISIBILITY
1700 filesystem_error(const string& __what, const path& __p1, error_code __ec)
1701 : system_error(__ec, __what),
1702 __storage_(make_shared<_Storage>(__p1, path())) {
1703 __create_what(1);
1704 }
1705
1706 _LIBCPP_INLINE_VISIBILITY
1707 filesystem_error(const string& __what, const path& __p1, const path& __p2,
1708 error_code __ec)
1709 : system_error(__ec, __what),
1710 __storage_(make_shared<_Storage>(__p1, __p2)) {
1711 __create_what(2);
1712 }
1713
1714 _LIBCPP_INLINE_VISIBILITY
1715 const path& path1() const noexcept { return __storage_->__p1_; }
1716
1717 _LIBCPP_INLINE_VISIBILITY
1718 const path& path2() const noexcept { return __storage_->__p2_; }
1719
Dimitry Andric47269ce2020-03-13 19:36:26 +01001720 filesystem_error(const filesystem_error&) = default;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001721 ~filesystem_error() override; // key function
1722
1723 _LIBCPP_INLINE_VISIBILITY
1724 const char* what() const noexcept override {
1725 return __storage_->__what_.c_str();
1726 }
1727
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001728 void __create_what(int __num_paths);
1729
1730private:
Louis Dionne48ae8892019-03-19 17:47:53 +00001731 struct _LIBCPP_HIDDEN _Storage {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001732 _LIBCPP_INLINE_VISIBILITY
1733 _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
1734
1735 path __p1_;
1736 path __p2_;
1737 string __what_;
1738 };
1739 shared_ptr<_Storage> __storage_;
1740};
1741
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001742_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
1743
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001744template <class... _Args>
1745_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
1746#ifndef _LIBCPP_NO_EXCEPTIONS
Louis Dionne6251ef02019-02-05 15:46:52 +00001747void __throw_filesystem_error(_Args&&... __args) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05001748 throw filesystem_error(_VSTD::forward<_Args>(__args)...);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001749}
1750#else
Louis Dionne6251ef02019-02-05 15:46:52 +00001751void __throw_filesystem_error(_Args&&...) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001752 _VSTD::abort();
1753}
1754#endif
1755
1756// operational functions
1757
1758_LIBCPP_FUNC_VIS
1759path __absolute(const path&, error_code* __ec = nullptr);
1760_LIBCPP_FUNC_VIS
1761path __canonical(const path&, error_code* __ec = nullptr);
1762_LIBCPP_FUNC_VIS
1763void __copy(const path& __from, const path& __to, copy_options __opt,
1764 error_code* __ec = nullptr);
1765_LIBCPP_FUNC_VIS
1766bool __copy_file(const path& __from, const path& __to, copy_options __opt,
1767 error_code* __ec = nullptr);
1768_LIBCPP_FUNC_VIS
1769void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
1770 error_code* __ec = nullptr);
1771_LIBCPP_FUNC_VIS
1772bool __create_directories(const path& p, error_code* ec = nullptr);
1773_LIBCPP_FUNC_VIS
1774bool __create_directory(const path& p, error_code* ec = nullptr);
1775_LIBCPP_FUNC_VIS
1776bool __create_directory(const path& p, const path& attributes,
1777 error_code* ec = nullptr);
1778_LIBCPP_FUNC_VIS
1779void __create_directory_symlink(const path& __to, const path& __new_symlink,
1780 error_code* __ec = nullptr);
1781_LIBCPP_FUNC_VIS
1782void __create_hard_link(const path& __to, const path& __new_hard_link,
1783 error_code* __ec = nullptr);
1784_LIBCPP_FUNC_VIS
1785void __create_symlink(const path& __to, const path& __new_symlink,
1786 error_code* __ec = nullptr);
1787_LIBCPP_FUNC_VIS
1788path __current_path(error_code* __ec = nullptr);
1789_LIBCPP_FUNC_VIS
1790void __current_path(const path&, error_code* __ec = nullptr);
1791_LIBCPP_FUNC_VIS
1792bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
1793_LIBCPP_FUNC_VIS
1794uintmax_t __file_size(const path&, error_code* __ec = nullptr);
1795_LIBCPP_FUNC_VIS
1796uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
1797_LIBCPP_FUNC_VIS
1798bool __fs_is_empty(const path& p, error_code* ec = nullptr);
1799_LIBCPP_FUNC_VIS
1800file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
1801_LIBCPP_FUNC_VIS
1802void __last_write_time(const path& p, file_time_type new_time,
1803 error_code* ec = nullptr);
1804_LIBCPP_FUNC_VIS
1805void __permissions(const path&, perms, perm_options, error_code* = nullptr);
1806_LIBCPP_FUNC_VIS
1807path __read_symlink(const path& p, error_code* ec = nullptr);
1808_LIBCPP_FUNC_VIS
1809bool __remove(const path& p, error_code* ec = nullptr);
1810_LIBCPP_FUNC_VIS
1811uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
1812_LIBCPP_FUNC_VIS
1813void __rename(const path& from, const path& to, error_code* ec = nullptr);
1814_LIBCPP_FUNC_VIS
1815void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
1816_LIBCPP_FUNC_VIS
1817space_info __space(const path&, error_code* __ec = nullptr);
1818_LIBCPP_FUNC_VIS
1819file_status __status(const path&, error_code* __ec = nullptr);
1820_LIBCPP_FUNC_VIS
1821file_status __symlink_status(const path&, error_code* __ec = nullptr);
1822_LIBCPP_FUNC_VIS
1823path __system_complete(const path&, error_code* __ec = nullptr);
1824_LIBCPP_FUNC_VIS
1825path __temp_directory_path(error_code* __ec = nullptr);
1826_LIBCPP_FUNC_VIS
1827path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
1828
1829inline _LIBCPP_INLINE_VISIBILITY path current_path() {
1830 return __current_path();
1831}
1832
1833inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
1834 return __current_path(&__ec);
1835}
1836
1837inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
1838 __current_path(__p);
1839}
1840
1841inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
1842 error_code& __ec) noexcept {
1843 __current_path(__p, &__ec);
1844}
1845
1846inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
1847 return __absolute(__p);
1848}
1849
1850inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
1851 error_code& __ec) {
1852 return __absolute(__p, &__ec);
1853}
1854
1855inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
1856 return __canonical(__p);
1857}
1858
1859inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
1860 error_code& __ec) {
1861 return __canonical(__p, &__ec);
1862}
1863
1864inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
1865 const path& __to) {
1866 __copy(__from, __to, copy_options::none);
1867}
1868
1869inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1870 error_code& __ec) {
1871 __copy(__from, __to, copy_options::none, &__ec);
1872}
1873
1874inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1875 copy_options __opt) {
1876 __copy(__from, __to, __opt);
1877}
1878
1879inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1880 copy_options __opt,
1881 error_code& __ec) {
1882 __copy(__from, __to, __opt, &__ec);
1883}
1884
1885inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1886 const path& __to) {
1887 return __copy_file(__from, __to, copy_options::none);
1888}
1889
1890inline _LIBCPP_INLINE_VISIBILITY bool
1891copy_file(const path& __from, const path& __to, error_code& __ec) {
1892 return __copy_file(__from, __to, copy_options::none, &__ec);
1893}
1894
1895inline _LIBCPP_INLINE_VISIBILITY bool
1896copy_file(const path& __from, const path& __to, copy_options __opt) {
1897 return __copy_file(__from, __to, __opt);
1898}
1899
1900inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1901 const path& __to,
1902 copy_options __opt,
1903 error_code& __ec) {
1904 return __copy_file(__from, __to, __opt, &__ec);
1905}
1906
1907inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
1908 const path& __new) {
1909 __copy_symlink(__existing, __new);
1910}
1911
1912inline _LIBCPP_INLINE_VISIBILITY void
1913copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
1914 __copy_symlink(__ext, __new, &__ec);
1915}
1916
1917inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
1918 return __create_directories(__p);
1919}
1920
1921inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
1922 error_code& __ec) {
1923 return __create_directories(__p, &__ec);
1924}
1925
1926inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
1927 return __create_directory(__p);
1928}
1929
1930inline _LIBCPP_INLINE_VISIBILITY bool
1931create_directory(const path& __p, error_code& __ec) noexcept {
1932 return __create_directory(__p, &__ec);
1933}
1934
1935inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
1936 const path& __attrs) {
1937 return __create_directory(__p, __attrs);
1938}
1939
1940inline _LIBCPP_INLINE_VISIBILITY bool
1941create_directory(const path& __p, const path& __attrs,
1942 error_code& __ec) noexcept {
1943 return __create_directory(__p, __attrs, &__ec);
1944}
1945
1946inline _LIBCPP_INLINE_VISIBILITY void
1947create_directory_symlink(const path& __to, const path& __new) {
1948 __create_directory_symlink(__to, __new);
1949}
1950
1951inline _LIBCPP_INLINE_VISIBILITY void
1952create_directory_symlink(const path& __to, const path& __new,
1953 error_code& __ec) noexcept {
1954 __create_directory_symlink(__to, __new, &__ec);
1955}
1956
1957inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
1958 const path& __new) {
1959 __create_hard_link(__to, __new);
1960}
1961
1962inline _LIBCPP_INLINE_VISIBILITY void
1963create_hard_link(const path& __to, const path& __new,
1964 error_code& __ec) noexcept {
1965 __create_hard_link(__to, __new, &__ec);
1966}
1967
1968inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
1969 const path& __new) {
1970 __create_symlink(__to, __new);
1971}
1972
1973inline _LIBCPP_INLINE_VISIBILITY void
1974create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
1975 return __create_symlink(__to, __new, &__ec);
1976}
1977
1978inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
1979 return __s.type() != file_type::none;
1980}
1981
1982inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
1983 return status_known(__s) && __s.type() != file_type::not_found;
1984}
1985
1986inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
1987 return exists(__status(__p));
1988}
1989
1990inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
1991 error_code& __ec) noexcept {
1992 auto __s = __status(__p, &__ec);
1993 if (status_known(__s))
1994 __ec.clear();
1995 return exists(__s);
1996}
1997
1998inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
1999 const path& __p2) {
2000 return __equivalent(__p1, __p2);
2001}
2002
2003inline _LIBCPP_INLINE_VISIBILITY bool
2004equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
2005 return __equivalent(__p1, __p2, &__ec);
2006}
2007
2008inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
2009 return __file_size(__p);
2010}
2011
2012inline _LIBCPP_INLINE_VISIBILITY uintmax_t
2013file_size(const path& __p, error_code& __ec) noexcept {
2014 return __file_size(__p, &__ec);
2015}
2016
2017inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
2018 return __hard_link_count(__p);
2019}
2020
2021inline _LIBCPP_INLINE_VISIBILITY uintmax_t
2022hard_link_count(const path& __p, error_code& __ec) noexcept {
2023 return __hard_link_count(__p, &__ec);
2024}
2025
2026inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
2027 return __s.type() == file_type::block;
2028}
2029
2030inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
2031 return is_block_file(__status(__p));
2032}
2033
2034inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
2035 error_code& __ec) noexcept {
2036 return is_block_file(__status(__p, &__ec));
2037}
2038
2039inline _LIBCPP_INLINE_VISIBILITY bool
2040is_character_file(file_status __s) noexcept {
2041 return __s.type() == file_type::character;
2042}
2043
2044inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
2045 return is_character_file(__status(__p));
2046}
2047
2048inline _LIBCPP_INLINE_VISIBILITY bool
2049is_character_file(const path& __p, error_code& __ec) noexcept {
2050 return is_character_file(__status(__p, &__ec));
2051}
2052
2053inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
2054 return __s.type() == file_type::directory;
2055}
2056
2057inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
2058 return is_directory(__status(__p));
2059}
2060
2061inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
2062 error_code& __ec) noexcept {
2063 return is_directory(__status(__p, &__ec));
2064}
2065
2066inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
2067 return __fs_is_empty(__p);
2068}
2069
2070inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
2071 error_code& __ec) {
2072 return __fs_is_empty(__p, &__ec);
2073}
2074
2075inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
2076 return __s.type() == file_type::fifo;
2077}
2078inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
2079 return is_fifo(__status(__p));
2080}
2081
2082inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
2083 error_code& __ec) noexcept {
2084 return is_fifo(__status(__p, &__ec));
2085}
2086
2087inline _LIBCPP_INLINE_VISIBILITY bool
2088is_regular_file(file_status __s) noexcept {
2089 return __s.type() == file_type::regular;
2090}
2091
2092inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
2093 return is_regular_file(__status(__p));
2094}
2095
2096inline _LIBCPP_INLINE_VISIBILITY bool
2097is_regular_file(const path& __p, error_code& __ec) noexcept {
2098 return is_regular_file(__status(__p, &__ec));
2099}
2100
2101inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
2102 return __s.type() == file_type::socket;
2103}
2104
2105inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
2106 return is_socket(__status(__p));
2107}
2108
2109inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
2110 error_code& __ec) noexcept {
2111 return is_socket(__status(__p, &__ec));
2112}
2113
2114inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
2115 return __s.type() == file_type::symlink;
2116}
2117
2118inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
2119 return is_symlink(__symlink_status(__p));
2120}
2121
2122inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
2123 error_code& __ec) noexcept {
2124 return is_symlink(__symlink_status(__p, &__ec));
2125}
2126
2127inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
2128 return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
2129 !is_symlink(__s);
2130}
2131
2132inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
2133 return is_other(__status(__p));
2134}
2135
2136inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
2137 error_code& __ec) noexcept {
2138 return is_other(__status(__p, &__ec));
2139}
2140
2141inline _LIBCPP_INLINE_VISIBILITY file_time_type
2142last_write_time(const path& __p) {
2143 return __last_write_time(__p);
2144}
2145
2146inline _LIBCPP_INLINE_VISIBILITY file_time_type
2147last_write_time(const path& __p, error_code& __ec) noexcept {
2148 return __last_write_time(__p, &__ec);
2149}
2150
2151inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
2152 file_time_type __t) {
2153 __last_write_time(__p, __t);
2154}
2155
2156inline _LIBCPP_INLINE_VISIBILITY void
2157last_write_time(const path& __p, file_time_type __t,
2158 error_code& __ec) noexcept {
2159 __last_write_time(__p, __t, &__ec);
2160}
2161
2162inline _LIBCPP_INLINE_VISIBILITY void
2163permissions(const path& __p, perms __prms,
2164 perm_options __opts = perm_options::replace) {
2165 __permissions(__p, __prms, __opts);
2166}
2167
2168inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2169 error_code& __ec) noexcept {
2170 __permissions(__p, __prms, perm_options::replace, &__ec);
2171}
2172
2173inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
2174 perm_options __opts,
2175 error_code& __ec) {
2176 __permissions(__p, __prms, __opts, &__ec);
2177}
2178
2179inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2180 const path& __base,
2181 error_code& __ec) {
2182 path __tmp = __weakly_canonical(__p, &__ec);
2183 if (__ec)
2184 return {};
2185 path __tmp_base = __weakly_canonical(__base, &__ec);
2186 if (__ec)
2187 return {};
2188 return __tmp.lexically_proximate(__tmp_base);
2189}
2190
2191inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
2192 error_code& __ec) {
2193 return proximate(__p, current_path(), __ec);
2194}
2195
2196inline _LIBCPP_INLINE_VISIBILITY path
2197proximate(const path& __p, const path& __base = current_path()) {
2198 return __weakly_canonical(__p).lexically_proximate(
2199 __weakly_canonical(__base));
2200}
2201
2202inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
2203 return __read_symlink(__p);
2204}
2205
2206inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
2207 error_code& __ec) {
2208 return __read_symlink(__p, &__ec);
2209}
2210
2211inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2212 const path& __base,
2213 error_code& __ec) {
2214 path __tmp = __weakly_canonical(__p, &__ec);
2215 if (__ec)
2216 return path();
2217 path __tmpbase = __weakly_canonical(__base, &__ec);
2218 if (__ec)
2219 return path();
2220 return __tmp.lexically_relative(__tmpbase);
2221}
2222
2223inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
2224 error_code& __ec) {
2225 return relative(__p, current_path(), __ec);
2226}
2227
2228inline _LIBCPP_INLINE_VISIBILITY path
2229relative(const path& __p, const path& __base = current_path()) {
2230 return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
2231}
2232
2233inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
2234 return __remove(__p);
2235}
2236
2237inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
2238 error_code& __ec) noexcept {
2239 return __remove(__p, &__ec);
2240}
2241
2242inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
2243 return __remove_all(__p);
2244}
2245
2246inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
2247 error_code& __ec) {
2248 return __remove_all(__p, &__ec);
2249}
2250
2251inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
2252 const path& __to) {
2253 return __rename(__from, __to);
2254}
2255
2256inline _LIBCPP_INLINE_VISIBILITY void
2257rename(const path& __from, const path& __to, error_code& __ec) noexcept {
2258 return __rename(__from, __to, &__ec);
2259}
2260
2261inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
2262 uintmax_t __ns) {
2263 return __resize_file(__p, __ns);
2264}
2265
2266inline _LIBCPP_INLINE_VISIBILITY void
2267resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
2268 return __resize_file(__p, __ns, &__ec);
2269}
2270
2271inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
2272 return __space(__p);
2273}
2274
2275inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
2276 error_code& __ec) noexcept {
2277 return __space(__p, &__ec);
2278}
2279
2280inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
2281 return __status(__p);
2282}
2283
2284inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
2285 error_code& __ec) noexcept {
2286 return __status(__p, &__ec);
2287}
2288
2289inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
2290 return __symlink_status(__p);
2291}
2292
2293inline _LIBCPP_INLINE_VISIBILITY file_status
2294symlink_status(const path& __p, error_code& __ec) noexcept {
2295 return __symlink_status(__p, &__ec);
2296}
2297
2298inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
2299 return __temp_directory_path();
2300}
2301
2302inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
2303 return __temp_directory_path(&__ec);
2304}
2305
2306inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
2307 return __weakly_canonical(__p);
2308}
2309
2310inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
2311 error_code& __ec) {
2312 return __weakly_canonical(__p, &__ec);
2313}
2314
2315class directory_iterator;
2316class recursive_directory_iterator;
Louis Dionne48ae8892019-03-19 17:47:53 +00002317class _LIBCPP_HIDDEN __dir_stream;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002318
2319class directory_entry {
2320 typedef _VSTD_FS::path _Path;
2321
2322public:
2323 // constructors and destructors
2324 directory_entry() noexcept = default;
2325 directory_entry(directory_entry const&) = default;
2326 directory_entry(directory_entry&&) noexcept = default;
2327
2328 _LIBCPP_INLINE_VISIBILITY
2329 explicit directory_entry(_Path const& __p) : __p_(__p) {
2330 error_code __ec;
2331 __refresh(&__ec);
2332 }
2333
2334 _LIBCPP_INLINE_VISIBILITY
2335 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
2336 __refresh(&__ec);
2337 }
2338
2339 ~directory_entry() {}
2340
2341 directory_entry& operator=(directory_entry const&) = default;
2342 directory_entry& operator=(directory_entry&&) noexcept = default;
2343
2344 _LIBCPP_INLINE_VISIBILITY
2345 void assign(_Path const& __p) {
2346 __p_ = __p;
2347 error_code __ec;
2348 __refresh(&__ec);
2349 }
2350
2351 _LIBCPP_INLINE_VISIBILITY
2352 void assign(_Path const& __p, error_code& __ec) {
2353 __p_ = __p;
2354 __refresh(&__ec);
2355 }
2356
2357 _LIBCPP_INLINE_VISIBILITY
2358 void replace_filename(_Path const& __p) {
2359 __p_.replace_filename(__p);
2360 error_code __ec;
2361 __refresh(&__ec);
2362 }
2363
2364 _LIBCPP_INLINE_VISIBILITY
2365 void replace_filename(_Path const& __p, error_code& __ec) {
2366 __p_ = __p_.parent_path() / __p;
2367 __refresh(&__ec);
2368 }
2369
2370 _LIBCPP_INLINE_VISIBILITY
2371 void refresh() { __refresh(); }
2372
2373 _LIBCPP_INLINE_VISIBILITY
2374 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
2375
2376 _LIBCPP_INLINE_VISIBILITY
2377 _Path const& path() const noexcept { return __p_; }
2378
2379 _LIBCPP_INLINE_VISIBILITY
2380 operator const _Path&() const noexcept { return __p_; }
2381
2382 _LIBCPP_INLINE_VISIBILITY
2383 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
2384
2385 _LIBCPP_INLINE_VISIBILITY
2386 bool exists(error_code& __ec) const noexcept {
2387 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
2388 }
2389
2390 _LIBCPP_INLINE_VISIBILITY
2391 bool is_block_file() const { return __get_ft() == file_type::block; }
2392
2393 _LIBCPP_INLINE_VISIBILITY
2394 bool is_block_file(error_code& __ec) const noexcept {
2395 return __get_ft(&__ec) == file_type::block;
2396 }
2397
2398 _LIBCPP_INLINE_VISIBILITY
2399 bool is_character_file() const { return __get_ft() == file_type::character; }
2400
2401 _LIBCPP_INLINE_VISIBILITY
2402 bool is_character_file(error_code& __ec) const noexcept {
2403 return __get_ft(&__ec) == file_type::character;
2404 }
2405
2406 _LIBCPP_INLINE_VISIBILITY
2407 bool is_directory() const { return __get_ft() == file_type::directory; }
2408
2409 _LIBCPP_INLINE_VISIBILITY
2410 bool is_directory(error_code& __ec) const noexcept {
2411 return __get_ft(&__ec) == file_type::directory;
2412 }
2413
2414 _LIBCPP_INLINE_VISIBILITY
2415 bool is_fifo() const { return __get_ft() == file_type::fifo; }
2416
2417 _LIBCPP_INLINE_VISIBILITY
2418 bool is_fifo(error_code& __ec) const noexcept {
2419 return __get_ft(&__ec) == file_type::fifo;
2420 }
2421
2422 _LIBCPP_INLINE_VISIBILITY
2423 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
2424
2425 _LIBCPP_INLINE_VISIBILITY
2426 bool is_other(error_code& __ec) const noexcept {
2427 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
2428 }
2429
2430 _LIBCPP_INLINE_VISIBILITY
2431 bool is_regular_file() const { return __get_ft() == file_type::regular; }
2432
2433 _LIBCPP_INLINE_VISIBILITY
2434 bool is_regular_file(error_code& __ec) const noexcept {
2435 return __get_ft(&__ec) == file_type::regular;
2436 }
2437
2438 _LIBCPP_INLINE_VISIBILITY
2439 bool is_socket() const { return __get_ft() == file_type::socket; }
2440
2441 _LIBCPP_INLINE_VISIBILITY
2442 bool is_socket(error_code& __ec) const noexcept {
2443 return __get_ft(&__ec) == file_type::socket;
2444 }
2445
2446 _LIBCPP_INLINE_VISIBILITY
2447 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
2448
2449 _LIBCPP_INLINE_VISIBILITY
2450 bool is_symlink(error_code& __ec) const noexcept {
2451 return __get_sym_ft(&__ec) == file_type::symlink;
2452 }
2453 _LIBCPP_INLINE_VISIBILITY
2454 uintmax_t file_size() const { return __get_size(); }
2455
2456 _LIBCPP_INLINE_VISIBILITY
2457 uintmax_t file_size(error_code& __ec) const noexcept {
2458 return __get_size(&__ec);
2459 }
2460
2461 _LIBCPP_INLINE_VISIBILITY
2462 uintmax_t hard_link_count() const { return __get_nlink(); }
2463
2464 _LIBCPP_INLINE_VISIBILITY
2465 uintmax_t hard_link_count(error_code& __ec) const noexcept {
2466 return __get_nlink(&__ec);
2467 }
2468
2469 _LIBCPP_INLINE_VISIBILITY
2470 file_time_type last_write_time() const { return __get_write_time(); }
2471
2472 _LIBCPP_INLINE_VISIBILITY
2473 file_time_type last_write_time(error_code& __ec) const noexcept {
2474 return __get_write_time(&__ec);
2475 }
2476
2477 _LIBCPP_INLINE_VISIBILITY
2478 file_status status() const { return __get_status(); }
2479
2480 _LIBCPP_INLINE_VISIBILITY
2481 file_status status(error_code& __ec) const noexcept {
2482 return __get_status(&__ec);
2483 }
2484
2485 _LIBCPP_INLINE_VISIBILITY
2486 file_status symlink_status() const { return __get_symlink_status(); }
2487
2488 _LIBCPP_INLINE_VISIBILITY
2489 file_status symlink_status(error_code& __ec) const noexcept {
2490 return __get_symlink_status(&__ec);
2491 }
2492
2493 _LIBCPP_INLINE_VISIBILITY
2494 bool operator<(directory_entry const& __rhs) const noexcept {
2495 return __p_ < __rhs.__p_;
2496 }
2497
2498 _LIBCPP_INLINE_VISIBILITY
2499 bool operator==(directory_entry const& __rhs) const noexcept {
2500 return __p_ == __rhs.__p_;
2501 }
2502
2503 _LIBCPP_INLINE_VISIBILITY
2504 bool operator!=(directory_entry const& __rhs) const noexcept {
2505 return __p_ != __rhs.__p_;
2506 }
2507
2508 _LIBCPP_INLINE_VISIBILITY
2509 bool operator<=(directory_entry const& __rhs) const noexcept {
2510 return __p_ <= __rhs.__p_;
2511 }
2512
2513 _LIBCPP_INLINE_VISIBILITY
2514 bool operator>(directory_entry const& __rhs) const noexcept {
2515 return __p_ > __rhs.__p_;
2516 }
2517
2518 _LIBCPP_INLINE_VISIBILITY
2519 bool operator>=(directory_entry const& __rhs) const noexcept {
2520 return __p_ >= __rhs.__p_;
2521 }
2522
2523private:
2524 friend class directory_iterator;
2525 friend class recursive_directory_iterator;
2526 friend class __dir_stream;
2527
2528 enum _CacheType : unsigned char {
2529 _Empty,
2530 _IterSymlink,
2531 _IterNonSymlink,
2532 _RefreshSymlink,
2533 _RefreshSymlinkUnresolved,
2534 _RefreshNonSymlink
2535 };
2536
2537 struct __cached_data {
2538 uintmax_t __size_;
2539 uintmax_t __nlink_;
2540 file_time_type __write_time_;
2541 perms __sym_perms_;
2542 perms __non_sym_perms_;
2543 file_type __type_;
2544 _CacheType __cache_type_;
2545
2546 _LIBCPP_INLINE_VISIBILITY
2547 __cached_data() noexcept { __reset(); }
2548
2549 _LIBCPP_INLINE_VISIBILITY
2550 void __reset() {
2551 __cache_type_ = _Empty;
2552 __type_ = file_type::none;
2553 __sym_perms_ = __non_sym_perms_ = perms::unknown;
2554 __size_ = __nlink_ = uintmax_t(-1);
2555 __write_time_ = file_time_type::min();
2556 }
2557 };
2558
2559 _LIBCPP_INLINE_VISIBILITY
2560 static __cached_data __create_iter_result(file_type __ft) {
2561 __cached_data __data;
2562 __data.__type_ = __ft;
2563 __data.__cache_type_ = [&]() {
2564 switch (__ft) {
2565 case file_type::none:
2566 return _Empty;
2567 case file_type::symlink:
2568 return _IterSymlink;
2569 default:
2570 return _IterNonSymlink;
2571 }
2572 }();
2573 return __data;
2574 }
2575
2576 _LIBCPP_INLINE_VISIBILITY
2577 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002578 __p_ = _VSTD::move(__p);
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002579 __data_ = __dt;
2580 }
2581
2582 _LIBCPP_FUNC_VIS
2583 error_code __do_refresh() noexcept;
2584
2585 _LIBCPP_INLINE_VISIBILITY
2586 static bool __is_dne_error(error_code const& __ec) {
2587 if (!__ec)
2588 return true;
2589 switch (static_cast<errc>(__ec.value())) {
2590 case errc::no_such_file_or_directory:
2591 case errc::not_a_directory:
2592 return true;
2593 default:
2594 return false;
2595 }
2596 }
2597
2598 _LIBCPP_INLINE_VISIBILITY
2599 void __handle_error(const char* __msg, error_code* __dest_ec,
2600 error_code const& __ec, bool __allow_dne = false) const {
2601 if (__dest_ec) {
2602 *__dest_ec = __ec;
2603 return;
2604 }
2605 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
2606 __throw_filesystem_error(__msg, __p_, __ec);
2607 }
2608
2609 _LIBCPP_INLINE_VISIBILITY
2610 void __refresh(error_code* __ec = nullptr) {
2611 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
2612 /*allow_dne*/ true);
2613 }
2614
2615 _LIBCPP_INLINE_VISIBILITY
2616 file_type __get_sym_ft(error_code* __ec = nullptr) const {
2617 switch (__data_.__cache_type_) {
2618 case _Empty:
2619 return __symlink_status(__p_, __ec).type();
2620 case _IterSymlink:
2621 case _RefreshSymlink:
2622 case _RefreshSymlinkUnresolved:
2623 if (__ec)
2624 __ec->clear();
2625 return file_type::symlink;
2626 case _IterNonSymlink:
2627 case _RefreshNonSymlink:
2628 file_status __st(__data_.__type_);
2629 if (__ec && !_VSTD_FS::exists(__st))
2630 *__ec = make_error_code(errc::no_such_file_or_directory);
2631 else if (__ec)
2632 __ec->clear();
2633 return __data_.__type_;
2634 }
2635 _LIBCPP_UNREACHABLE();
2636 }
2637
2638 _LIBCPP_INLINE_VISIBILITY
2639 file_type __get_ft(error_code* __ec = nullptr) const {
2640 switch (__data_.__cache_type_) {
2641 case _Empty:
2642 case _IterSymlink:
2643 case _RefreshSymlinkUnresolved:
2644 return __status(__p_, __ec).type();
2645 case _IterNonSymlink:
2646 case _RefreshNonSymlink:
2647 case _RefreshSymlink: {
2648 file_status __st(__data_.__type_);
2649 if (__ec && !_VSTD_FS::exists(__st))
2650 *__ec = make_error_code(errc::no_such_file_or_directory);
2651 else if (__ec)
2652 __ec->clear();
2653 return __data_.__type_;
2654 }
2655 }
2656 _LIBCPP_UNREACHABLE();
2657 }
2658
2659 _LIBCPP_INLINE_VISIBILITY
2660 file_status __get_status(error_code* __ec = nullptr) const {
2661 switch (__data_.__cache_type_) {
2662 case _Empty:
2663 case _IterNonSymlink:
2664 case _IterSymlink:
2665 case _RefreshSymlinkUnresolved:
2666 return __status(__p_, __ec);
2667 case _RefreshNonSymlink:
2668 case _RefreshSymlink:
2669 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
2670 }
2671 _LIBCPP_UNREACHABLE();
2672 }
2673
2674 _LIBCPP_INLINE_VISIBILITY
2675 file_status __get_symlink_status(error_code* __ec = nullptr) const {
2676 switch (__data_.__cache_type_) {
2677 case _Empty:
2678 case _IterNonSymlink:
2679 case _IterSymlink:
2680 return __symlink_status(__p_, __ec);
2681 case _RefreshNonSymlink:
2682 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
2683 case _RefreshSymlink:
2684 case _RefreshSymlinkUnresolved:
2685 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
2686 }
2687 _LIBCPP_UNREACHABLE();
2688 }
2689
2690 _LIBCPP_INLINE_VISIBILITY
2691 uintmax_t __get_size(error_code* __ec = nullptr) const {
2692 switch (__data_.__cache_type_) {
2693 case _Empty:
2694 case _IterNonSymlink:
2695 case _IterSymlink:
2696 case _RefreshSymlinkUnresolved:
2697 return _VSTD_FS::__file_size(__p_, __ec);
2698 case _RefreshSymlink:
2699 case _RefreshNonSymlink: {
2700 error_code __m_ec;
2701 file_status __st(__get_ft(&__m_ec));
2702 __handle_error("in directory_entry::file_size", __ec, __m_ec);
2703 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
2704 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
2705 : errc::not_supported;
2706 __handle_error("in directory_entry::file_size", __ec,
2707 make_error_code(__err_kind));
2708 }
2709 return __data_.__size_;
2710 }
2711 }
2712 _LIBCPP_UNREACHABLE();
2713 }
2714
2715 _LIBCPP_INLINE_VISIBILITY
2716 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
2717 switch (__data_.__cache_type_) {
2718 case _Empty:
2719 case _IterNonSymlink:
2720 case _IterSymlink:
2721 case _RefreshSymlinkUnresolved:
2722 return _VSTD_FS::__hard_link_count(__p_, __ec);
2723 case _RefreshSymlink:
2724 case _RefreshNonSymlink: {
2725 error_code __m_ec;
2726 (void)__get_ft(&__m_ec);
2727 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
2728 return __data_.__nlink_;
2729 }
2730 }
2731 _LIBCPP_UNREACHABLE();
2732 }
2733
2734 _LIBCPP_INLINE_VISIBILITY
2735 file_time_type __get_write_time(error_code* __ec = nullptr) const {
2736 switch (__data_.__cache_type_) {
2737 case _Empty:
2738 case _IterNonSymlink:
2739 case _IterSymlink:
2740 case _RefreshSymlinkUnresolved:
2741 return _VSTD_FS::__last_write_time(__p_, __ec);
2742 case _RefreshSymlink:
2743 case _RefreshNonSymlink: {
2744 error_code __m_ec;
2745 file_status __st(__get_ft(&__m_ec));
2746 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
2747 if (_VSTD_FS::exists(__st) &&
2748 __data_.__write_time_ == file_time_type::min())
2749 __handle_error("in directory_entry::last_write_time", __ec,
2750 make_error_code(errc::value_too_large));
2751 return __data_.__write_time_;
2752 }
2753 }
2754 _LIBCPP_UNREACHABLE();
2755 }
2756
2757private:
2758 _Path __p_;
2759 __cached_data __data_;
2760};
2761
2762class __dir_element_proxy {
2763public:
2764 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
2765 return _VSTD::move(__elem_);
2766 }
2767
2768private:
2769 friend class directory_iterator;
2770 friend class recursive_directory_iterator;
2771 explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
2772 __dir_element_proxy(__dir_element_proxy&& __o)
2773 : __elem_(_VSTD::move(__o.__elem_)) {}
2774 directory_entry __elem_;
2775};
2776
2777class directory_iterator {
2778public:
2779 typedef directory_entry value_type;
2780 typedef ptrdiff_t difference_type;
2781 typedef value_type const* pointer;
2782 typedef value_type const& reference;
2783 typedef input_iterator_tag iterator_category;
2784
2785public:
2786 //ctor & dtor
2787 directory_iterator() noexcept {}
2788
2789 explicit directory_iterator(const path& __p)
2790 : directory_iterator(__p, nullptr) {}
2791
2792 directory_iterator(const path& __p, directory_options __opts)
2793 : directory_iterator(__p, nullptr, __opts) {}
2794
2795 directory_iterator(const path& __p, error_code& __ec)
2796 : directory_iterator(__p, &__ec) {}
2797
2798 directory_iterator(const path& __p, directory_options __opts,
2799 error_code& __ec)
2800 : directory_iterator(__p, &__ec, __opts) {}
2801
2802 directory_iterator(const directory_iterator&) = default;
2803 directory_iterator(directory_iterator&&) = default;
2804 directory_iterator& operator=(const directory_iterator&) = default;
2805
2806 directory_iterator& operator=(directory_iterator&& __o) noexcept {
2807 // non-default implementation provided to support self-move assign.
2808 if (this != &__o) {
2809 __imp_ = _VSTD::move(__o.__imp_);
2810 }
2811 return *this;
2812 }
2813
2814 ~directory_iterator() = default;
2815
2816 const directory_entry& operator*() const {
2817 _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
2818 return __dereference();
2819 }
2820
2821 const directory_entry* operator->() const { return &**this; }
2822
2823 directory_iterator& operator++() { return __increment(); }
2824
2825 __dir_element_proxy operator++(int) {
2826 __dir_element_proxy __p(**this);
2827 __increment();
2828 return __p;
2829 }
2830
2831 directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
2832
2833private:
2834 inline _LIBCPP_INLINE_VISIBILITY friend bool
2835 operator==(const directory_iterator& __lhs,
2836 const directory_iterator& __rhs) noexcept;
2837
2838 // construct the dir_stream
2839 _LIBCPP_FUNC_VIS
2840 directory_iterator(const path&, error_code*,
2841 directory_options = directory_options::none);
2842
2843 _LIBCPP_FUNC_VIS
2844 directory_iterator& __increment(error_code* __ec = nullptr);
2845
2846 _LIBCPP_FUNC_VIS
2847 const directory_entry& __dereference() const;
2848
2849private:
2850 shared_ptr<__dir_stream> __imp_;
2851};
2852
2853inline _LIBCPP_INLINE_VISIBILITY bool
2854operator==(const directory_iterator& __lhs,
2855 const directory_iterator& __rhs) noexcept {
2856 return __lhs.__imp_ == __rhs.__imp_;
2857}
2858
2859inline _LIBCPP_INLINE_VISIBILITY bool
2860operator!=(const directory_iterator& __lhs,
2861 const directory_iterator& __rhs) noexcept {
2862 return !(__lhs == __rhs);
2863}
2864
2865// enable directory_iterator range-based for statements
2866inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2867begin(directory_iterator __iter) noexcept {
2868 return __iter;
2869}
2870
2871inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2872end(const directory_iterator&) noexcept {
2873 return directory_iterator();
2874}
2875
2876class recursive_directory_iterator {
2877public:
2878 using value_type = directory_entry;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002879 using difference_type = ptrdiff_t;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002880 using pointer = directory_entry const*;
2881 using reference = directory_entry const&;
Arthur O'Dwyer07b22492020-11-27 11:02:06 -05002882 using iterator_category = input_iterator_tag;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002883
2884public:
2885 // constructors and destructor
2886 _LIBCPP_INLINE_VISIBILITY
2887 recursive_directory_iterator() noexcept : __rec_(false) {}
2888
2889 _LIBCPP_INLINE_VISIBILITY
2890 explicit recursive_directory_iterator(
2891 const path& __p, directory_options __xoptions = directory_options::none)
2892 : recursive_directory_iterator(__p, __xoptions, nullptr) {}
2893
2894 _LIBCPP_INLINE_VISIBILITY
2895 recursive_directory_iterator(const path& __p, directory_options __xoptions,
2896 error_code& __ec)
2897 : recursive_directory_iterator(__p, __xoptions, &__ec) {}
2898
2899 _LIBCPP_INLINE_VISIBILITY
2900 recursive_directory_iterator(const path& __p, error_code& __ec)
2901 : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
2902
2903 recursive_directory_iterator(const recursive_directory_iterator&) = default;
2904 recursive_directory_iterator(recursive_directory_iterator&&) = default;
2905
2906 recursive_directory_iterator&
2907 operator=(const recursive_directory_iterator&) = default;
2908
2909 _LIBCPP_INLINE_VISIBILITY
2910 recursive_directory_iterator&
2911 operator=(recursive_directory_iterator&& __o) noexcept {
2912 // non-default implementation provided to support self-move assign.
2913 if (this != &__o) {
2914 __imp_ = _VSTD::move(__o.__imp_);
2915 __rec_ = __o.__rec_;
2916 }
2917 return *this;
2918 }
2919
2920 ~recursive_directory_iterator() = default;
2921
2922 _LIBCPP_INLINE_VISIBILITY
2923 const directory_entry& operator*() const { return __dereference(); }
2924
2925 _LIBCPP_INLINE_VISIBILITY
2926 const directory_entry* operator->() const { return &__dereference(); }
2927
2928 recursive_directory_iterator& operator++() { return __increment(); }
2929
2930 _LIBCPP_INLINE_VISIBILITY
2931 __dir_element_proxy operator++(int) {
2932 __dir_element_proxy __p(**this);
2933 __increment();
2934 return __p;
2935 }
2936
2937 _LIBCPP_INLINE_VISIBILITY
2938 recursive_directory_iterator& increment(error_code& __ec) {
2939 return __increment(&__ec);
2940 }
2941
2942 _LIBCPP_FUNC_VIS directory_options options() const;
2943 _LIBCPP_FUNC_VIS int depth() const;
2944
2945 _LIBCPP_INLINE_VISIBILITY
2946 void pop() { __pop(); }
2947
2948 _LIBCPP_INLINE_VISIBILITY
2949 void pop(error_code& __ec) { __pop(&__ec); }
2950
2951 _LIBCPP_INLINE_VISIBILITY
2952 bool recursion_pending() const { return __rec_; }
2953
2954 _LIBCPP_INLINE_VISIBILITY
2955 void disable_recursion_pending() { __rec_ = false; }
2956
2957private:
Louis Dionne0ba10dc2019-08-13 15:02:53 +00002958 _LIBCPP_FUNC_VIS
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002959 recursive_directory_iterator(const path& __p, directory_options __opt,
2960 error_code* __ec);
2961
2962 _LIBCPP_FUNC_VIS
2963 const directory_entry& __dereference() const;
2964
2965 _LIBCPP_FUNC_VIS
2966 bool __try_recursion(error_code* __ec);
2967
2968 _LIBCPP_FUNC_VIS
2969 void __advance(error_code* __ec = nullptr);
2970
2971 _LIBCPP_FUNC_VIS
2972 recursive_directory_iterator& __increment(error_code* __ec = nullptr);
2973
2974 _LIBCPP_FUNC_VIS
2975 void __pop(error_code* __ec = nullptr);
2976
2977 inline _LIBCPP_INLINE_VISIBILITY friend bool
2978 operator==(const recursive_directory_iterator&,
2979 const recursive_directory_iterator&) noexcept;
2980
Louis Dionne48ae8892019-03-19 17:47:53 +00002981 struct _LIBCPP_HIDDEN __shared_imp;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002982 shared_ptr<__shared_imp> __imp_;
2983 bool __rec_;
2984}; // class recursive_directory_iterator
2985
2986inline _LIBCPP_INLINE_VISIBILITY bool
2987operator==(const recursive_directory_iterator& __lhs,
2988 const recursive_directory_iterator& __rhs) noexcept {
2989 return __lhs.__imp_ == __rhs.__imp_;
2990}
2991
2992_LIBCPP_INLINE_VISIBILITY
2993inline bool operator!=(const recursive_directory_iterator& __lhs,
2994 const recursive_directory_iterator& __rhs) noexcept {
2995 return !(__lhs == __rhs);
2996}
2997// enable recursive_directory_iterator range-based for statements
2998inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2999begin(recursive_directory_iterator __iter) noexcept {
3000 return __iter;
3001}
3002
3003inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
3004end(const recursive_directory_iterator&) noexcept {
3005 return recursive_directory_iterator();
3006}
3007
Louis Dionnef6bf76a2019-03-20 21:18:14 +00003008_LIBCPP_AVAILABILITY_FILESYSTEM_POP
3009
Eric Fiselier02cea5e2018-07-27 03:07:09 +00003010_LIBCPP_END_NAMESPACE_FILESYSTEM
3011
3012#endif // !_LIBCPP_CXX03_LANG
3013
3014_LIBCPP_POP_MACROS
3015
3016#endif // _LIBCPP_FILESYSTEM