blob: 5783ed3560ba6f42c02150e1c0d781360a530022 [file] [log] [blame]
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001// -*- C++ -*-
2//===--------------------------- filesystem -------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier02cea5e2018-07-27 03:07:09 +00007//
8//===----------------------------------------------------------------------===//
9#ifndef _LIBCPP_FILESYSTEM
10#define _LIBCPP_FILESYSTEM
11/*
12 filesystem synopsis
13
14 namespace std { namespace filesystem {
15
16 class path;
17
18 void swap(path& lhs, path& rhs) noexcept;
19 size_t hash_value(const path& p) noexcept;
20
21 bool operator==(const path& lhs, const path& rhs) noexcept;
22 bool operator!=(const path& lhs, const path& rhs) noexcept;
23 bool operator< (const path& lhs, const path& rhs) noexcept;
24 bool operator<=(const path& lhs, const path& rhs) noexcept;
25 bool operator> (const path& lhs, const path& rhs) noexcept;
26 bool operator>=(const path& lhs, const path& rhs) noexcept;
27
28 path operator/ (const path& lhs, const path& rhs);
29
30 // fs.path.io operators are friends of path.
31 template <class charT, class traits>
32 friend basic_ostream<charT, traits>&
33 operator<<(basic_ostream<charT, traits>& os, const path& p);
34
35 template <class charT, class traits>
36 friend basic_istream<charT, traits>&
37 operator>>(basic_istream<charT, traits>& is, path& p);
38
39 template <class Source>
40 path u8path(const Source& source);
41 template <class InputIterator>
42 path u8path(InputIterator first, InputIterator last);
43
44 class filesystem_error;
45 class directory_entry;
46
47 class directory_iterator;
48
49 // enable directory_iterator range-based for statements
50 directory_iterator begin(directory_iterator iter) noexcept;
51 directory_iterator end(const directory_iterator&) noexcept;
52
53 class recursive_directory_iterator;
54
55 // enable recursive_directory_iterator range-based for statements
56 recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
57 recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
58
59 class file_status;
60
61 struct space_info
62 {
63 uintmax_t capacity;
64 uintmax_t free;
65 uintmax_t available;
66 };
67
68 enum class file_type;
69 enum class perms;
70 enum class perm_options;
71 enum class copy_options;
72 enum class directory_options;
73
74 typedef chrono::time_point<trivial-clock> file_time_type;
75
76 // operational functions
77
78 path absolute(const path& p);
79 path absolute(const path& p, error_code &ec);
80
81 path canonical(const path& p);
82 path canonical(const path& p, error_code& ec);
83
84 void copy(const path& from, const path& to);
85 void copy(const path& from, const path& to, error_code& ec);
86 void copy(const path& from, const path& to, copy_options options);
87 void copy(const path& from, const path& to, copy_options options,
88 error_code& ec);
89
90 bool copy_file(const path& from, const path& to);
91 bool copy_file(const path& from, const path& to, error_code& ec);
92 bool copy_file(const path& from, const path& to, copy_options option);
93 bool copy_file(const path& from, const path& to, copy_options option,
94 error_code& ec);
95
96 void copy_symlink(const path& existing_symlink, const path& new_symlink);
97 void copy_symlink(const path& existing_symlink, const path& new_symlink,
98 error_code& ec) noexcept;
99
100 bool create_directories(const path& p);
101 bool create_directories(const path& p, error_code& ec);
102
103 bool create_directory(const path& p);
104 bool create_directory(const path& p, error_code& ec) noexcept;
105
106 bool create_directory(const path& p, const path& attributes);
107 bool create_directory(const path& p, const path& attributes,
108 error_code& ec) noexcept;
109
110 void create_directory_symlink(const path& to, const path& new_symlink);
111 void create_directory_symlink(const path& to, const path& new_symlink,
112 error_code& ec) noexcept;
113
114 void create_hard_link(const path& to, const path& new_hard_link);
115 void create_hard_link(const path& to, const path& new_hard_link,
116 error_code& ec) noexcept;
117
118 void create_symlink(const path& to, const path& new_symlink);
119 void create_symlink(const path& to, const path& new_symlink,
120 error_code& ec) noexcept;
121
122 path current_path();
123 path current_path(error_code& ec);
124 void current_path(const path& p);
125 void current_path(const path& p, error_code& ec) noexcept;
126
127 bool exists(file_status s) noexcept;
128 bool exists(const path& p);
129 bool exists(const path& p, error_code& ec) noexcept;
130
131 bool equivalent(const path& p1, const path& p2);
132 bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
133
134 uintmax_t file_size(const path& p);
135 uintmax_t file_size(const path& p, error_code& ec) noexcept;
136
137 uintmax_t hard_link_count(const path& p);
138 uintmax_t hard_link_count(const path& p, error_code& ec) noexcept;
139
140 bool is_block_file(file_status s) noexcept;
141 bool is_block_file(const path& p);
142 bool is_block_file(const path& p, error_code& ec) noexcept;
143
144 bool is_character_file(file_status s) noexcept;
145 bool is_character_file(const path& p);
146 bool is_character_file(const path& p, error_code& ec) noexcept;
147
148 bool is_directory(file_status s) noexcept;
149 bool is_directory(const path& p);
150 bool is_directory(const path& p, error_code& ec) noexcept;
151
152 bool is_empty(const path& p);
153 bool is_empty(const path& p, error_code& ec) noexcept;
154
155 bool is_fifo(file_status s) noexcept;
156 bool is_fifo(const path& p);
157 bool is_fifo(const path& p, error_code& ec) noexcept;
158
159 bool is_other(file_status s) noexcept;
160 bool is_other(const path& p);
161 bool is_other(const path& p, error_code& ec) noexcept;
162
163 bool is_regular_file(file_status s) noexcept;
164 bool is_regular_file(const path& p);
165 bool is_regular_file(const path& p, error_code& ec) noexcept;
166
167 bool is_socket(file_status s) noexcept;
168 bool is_socket(const path& p);
169 bool is_socket(const path& p, error_code& ec) noexcept;
170
171 bool is_symlink(file_status s) noexcept;
172 bool is_symlink(const path& p);
173 bool is_symlink(const path& p, error_code& ec) noexcept;
174
175 file_time_type last_write_time(const path& p);
176 file_time_type last_write_time(const path& p, error_code& ec) noexcept;
177 void last_write_time(const path& p, file_time_type new_time);
178 void last_write_time(const path& p, file_time_type new_time,
179 error_code& ec) noexcept;
180
181 void permissions(const path& p, perms prms,
182 perm_options opts=perm_options::replace);
183 void permissions(const path& p, perms prms, error_code& ec) noexcept;
184 void permissions(const path& p, perms prms, perm_options opts,
185 error_code& ec);
186
187 path proximate(const path& p, error_code& ec);
188 path proximate(const path& p, const path& base = current_path());
189 path proximate(const path& p, const path& base, error_code &ec);
190
191 path read_symlink(const path& p);
192 path read_symlink(const path& p, error_code& ec);
193
194 path relative(const path& p, error_code& ec);
195 path relative(const path& p, const path& base=current_path());
196 path relative(const path& p, const path& base, error_code& ec);
197
198 bool remove(const path& p);
199 bool remove(const path& p, error_code& ec) noexcept;
200
201 uintmax_t remove_all(const path& p);
202 uintmax_t remove_all(const path& p, error_code& ec);
203
204 void rename(const path& from, const path& to);
205 void rename(const path& from, const path& to, error_code& ec) noexcept;
206
207 void resize_file(const path& p, uintmax_t size);
208 void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept;
209
210 space_info space(const path& p);
211 space_info space(const path& p, error_code& ec) noexcept;
212
213 file_status status(const path& p);
214 file_status status(const path& p, error_code& ec) noexcept;
215
216 bool status_known(file_status s) noexcept;
217
218 file_status symlink_status(const path& p);
219 file_status symlink_status(const path& p, error_code& ec) noexcept;
220
221 path temp_directory_path();
222 path temp_directory_path(error_code& ec);
223
224 path weakly_canonical(path const& p);
225 path weakly_canonical(path const& p, error_code& ec);
226
227
228} } // namespaces std::filesystem
229
230*/
231
232#include <__config>
233#include <cstddef>
234#include <cstdlib>
235#include <chrono>
236#include <iterator>
237#include <iosfwd>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000238#include <memory>
239#include <stack>
240#include <string>
241#include <system_error>
242#include <utility>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000243#include <string_view>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000244#include <version>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000245
Louis Dionne8d053eb2020-10-09 15:31:05 -0400246#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
247# include <locale>
248# include <iomanip> // for quoted
249#endif
250
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000251#include <__debug>
252
253#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
254#pragma GCC system_header
255#endif
256
257_LIBCPP_PUSH_MACROS
258#include <__undef_macros>
259
260#ifndef _LIBCPP_CXX03_LANG
261
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000262_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
263
Louis Dionnef6bf76a2019-03-20 21:18:14 +0000264_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
265
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000266typedef chrono::time_point<_FilesystemClock> file_time_type;
267
268struct _LIBCPP_TYPE_VIS space_info {
269 uintmax_t capacity;
270 uintmax_t free;
271 uintmax_t available;
272};
273
274enum class _LIBCPP_ENUM_VIS file_type : signed char {
275 none = 0,
276 not_found = -1,
277 regular = 1,
278 directory = 2,
279 symlink = 3,
280 block = 4,
281 character = 5,
282 fifo = 6,
283 socket = 7,
284 unknown = 8
285};
286
287enum class _LIBCPP_ENUM_VIS perms : unsigned {
288 none = 0,
289
290 owner_read = 0400,
291 owner_write = 0200,
292 owner_exec = 0100,
293 owner_all = 0700,
294
295 group_read = 040,
296 group_write = 020,
297 group_exec = 010,
298 group_all = 070,
299
300 others_read = 04,
301 others_write = 02,
302 others_exec = 01,
303 others_all = 07,
304
305 all = 0777,
306
307 set_uid = 04000,
308 set_gid = 02000,
309 sticky_bit = 01000,
310 mask = 07777,
311 unknown = 0xFFFF,
312};
313
314_LIBCPP_INLINE_VISIBILITY
315inline constexpr perms operator&(perms _LHS, perms _RHS) {
316 return static_cast<perms>(static_cast<unsigned>(_LHS) &
317 static_cast<unsigned>(_RHS));
318}
319
320_LIBCPP_INLINE_VISIBILITY
321inline constexpr perms operator|(perms _LHS, perms _RHS) {
322 return static_cast<perms>(static_cast<unsigned>(_LHS) |
323 static_cast<unsigned>(_RHS));
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) {
334 return static_cast<perms>(~static_cast<unsigned>(_LHS));
335}
336
337_LIBCPP_INLINE_VISIBILITY
338inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
339
340_LIBCPP_INLINE_VISIBILITY
341inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
342
343_LIBCPP_INLINE_VISIBILITY
344inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
345
346enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
347 replace = 1,
348 add = 2,
349 remove = 4,
350 nofollow = 8
351};
352
353_LIBCPP_INLINE_VISIBILITY
354inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) {
355 return static_cast<perm_options>(static_cast<unsigned>(_LHS) &
356 static_cast<unsigned>(_RHS));
357}
358
359_LIBCPP_INLINE_VISIBILITY
360inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) {
361 return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
362 static_cast<unsigned>(_RHS));
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) {
373 return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
374}
375
376_LIBCPP_INLINE_VISIBILITY
377inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
378 return _LHS = _LHS & _RHS;
379}
380
381_LIBCPP_INLINE_VISIBILITY
382inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
383 return _LHS = _LHS | _RHS;
384}
385
386_LIBCPP_INLINE_VISIBILITY
387inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
388 return _LHS = _LHS ^ _RHS;
389}
390
391enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
392 none = 0,
393 skip_existing = 1,
394 overwrite_existing = 2,
395 update_existing = 4,
396 recursive = 8,
397 copy_symlinks = 16,
398 skip_symlinks = 32,
399 directories_only = 64,
400 create_symlinks = 128,
401 create_hard_links = 256,
402 __in_recursive_copy = 512,
403};
404
405_LIBCPP_INLINE_VISIBILITY
406inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) {
407 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) &
408 static_cast<unsigned short>(_RHS));
409}
410
411_LIBCPP_INLINE_VISIBILITY
412inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) {
413 return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
414 static_cast<unsigned short>(_RHS));
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) {
425 return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
426}
427
428_LIBCPP_INLINE_VISIBILITY
429inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
430 return _LHS = _LHS & _RHS;
431}
432
433_LIBCPP_INLINE_VISIBILITY
434inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
435 return _LHS = _LHS | _RHS;
436}
437
438_LIBCPP_INLINE_VISIBILITY
439inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
440 return _LHS = _LHS ^ _RHS;
441}
442
443enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
444 none = 0,
445 follow_directory_symlink = 1,
446 skip_permission_denied = 2
447};
448
449_LIBCPP_INLINE_VISIBILITY
450inline constexpr directory_options operator&(directory_options _LHS,
451 directory_options _RHS) {
452 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
453 static_cast<unsigned char>(_RHS));
454}
455
456_LIBCPP_INLINE_VISIBILITY
457inline constexpr directory_options operator|(directory_options _LHS,
458 directory_options _RHS) {
459 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
460 static_cast<unsigned char>(_RHS));
461}
462
463_LIBCPP_INLINE_VISIBILITY
464inline constexpr directory_options operator^(directory_options _LHS,
465 directory_options _RHS) {
466 return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
467 static_cast<unsigned char>(_RHS));
468}
469
470_LIBCPP_INLINE_VISIBILITY
471inline constexpr directory_options operator~(directory_options _LHS) {
472 return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
473}
474
475_LIBCPP_INLINE_VISIBILITY
476inline directory_options& operator&=(directory_options& _LHS,
477 directory_options _RHS) {
478 return _LHS = _LHS & _RHS;
479}
480
481_LIBCPP_INLINE_VISIBILITY
482inline directory_options& operator|=(directory_options& _LHS,
483 directory_options _RHS) {
484 return _LHS = _LHS | _RHS;
485}
486
487_LIBCPP_INLINE_VISIBILITY
488inline directory_options& operator^=(directory_options& _LHS,
489 directory_options _RHS) {
490 return _LHS = _LHS ^ _RHS;
491}
492
493class _LIBCPP_TYPE_VIS file_status {
494public:
495 // constructors
496 _LIBCPP_INLINE_VISIBILITY
497 file_status() noexcept : file_status(file_type::none) {}
498 _LIBCPP_INLINE_VISIBILITY
499 explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
500 : __ft_(__ft),
501 __prms_(__prms) {}
502
503 file_status(const file_status&) noexcept = default;
504 file_status(file_status&&) noexcept = default;
505
506 _LIBCPP_INLINE_VISIBILITY
507 ~file_status() {}
508
509 file_status& operator=(const file_status&) noexcept = default;
510 file_status& operator=(file_status&&) noexcept = default;
511
512 // observers
513 _LIBCPP_INLINE_VISIBILITY
514 file_type type() const noexcept { return __ft_; }
515
516 _LIBCPP_INLINE_VISIBILITY
517 perms permissions() const noexcept { return __prms_; }
518
519 // modifiers
520 _LIBCPP_INLINE_VISIBILITY
521 void type(file_type __ft) noexcept { __ft_ = __ft; }
522
523 _LIBCPP_INLINE_VISIBILITY
524 void permissions(perms __p) noexcept { __prms_ = __p; }
525
526private:
527 file_type __ft_;
528 perms __prms_;
529};
530
531class _LIBCPP_TYPE_VIS directory_entry;
532
533template <class _Tp>
534struct __can_convert_char {
535 static const bool value = false;
536};
537template <class _Tp>
538struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
539template <>
540struct __can_convert_char<char> {
541 static const bool value = true;
542 using __char_type = char;
543};
544template <>
545struct __can_convert_char<wchar_t> {
546 static const bool value = true;
547 using __char_type = wchar_t;
548};
549template <>
550struct __can_convert_char<char16_t> {
551 static const bool value = true;
552 using __char_type = char16_t;
553};
554template <>
555struct __can_convert_char<char32_t> {
556 static const bool value = true;
557 using __char_type = char32_t;
558};
559
560template <class _ECharT>
561typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
562__is_separator(_ECharT __e) {
563 return __e == _ECharT('/');
Eric Fiselierb41db9a2018-10-01 01:59:37 +0000564}
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000565
Martin Storsjö2ae96532020-10-27 11:46:06 +0200566struct _NullSentinel {};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000567
568template <class _Tp>
569using _Void = void;
570
571template <class _Tp, class = void>
572struct __is_pathable_string : public false_type {};
573
574template <class _ECharT, class _Traits, class _Alloc>
575struct __is_pathable_string<
576 basic_string<_ECharT, _Traits, _Alloc>,
577 _Void<typename __can_convert_char<_ECharT>::__char_type> >
578 : public __can_convert_char<_ECharT> {
579 using _Str = basic_string<_ECharT, _Traits, _Alloc>;
580 using _Base = __can_convert_char<_ECharT>;
581 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
582 static _ECharT const* __range_end(_Str const& __s) {
583 return __s.data() + __s.length();
584 }
585 static _ECharT __first_or_null(_Str const& __s) {
586 return __s.empty() ? _ECharT{} : __s[0];
587 }
588};
589
590template <class _ECharT, class _Traits>
591struct __is_pathable_string<
592 basic_string_view<_ECharT, _Traits>,
593 _Void<typename __can_convert_char<_ECharT>::__char_type> >
594 : public __can_convert_char<_ECharT> {
595 using _Str = basic_string_view<_ECharT, _Traits>;
596 using _Base = __can_convert_char<_ECharT>;
597 static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
598 static _ECharT const* __range_end(_Str const& __s) {
599 return __s.data() + __s.length();
600 }
601 static _ECharT __first_or_null(_Str const& __s) {
602 return __s.empty() ? _ECharT{} : __s[0];
603 }
604};
605
606template <class _Source, class _DS = typename decay<_Source>::type,
607 class _UnqualPtrType =
608 typename remove_const<typename remove_pointer<_DS>::type>::type,
609 bool _IsCharPtr = is_pointer<_DS>::value&&
610 __can_convert_char<_UnqualPtrType>::value>
611struct __is_pathable_char_array : false_type {};
612
613template <class _Source, class _ECharT, class _UPtr>
614struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
615 : __can_convert_char<typename remove_const<_ECharT>::type> {
616 using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
617
618 static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
619 static _ECharT const* __range_end(const _ECharT* __b) {
620 using _Iter = const _ECharT*;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200621 const _ECharT __sentinel = _ECharT{};
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000622 _Iter __e = __b;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200623 for (; *__e != __sentinel; ++__e)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000624 ;
625 return __e;
626 }
627
628 static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
629};
630
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500631template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value,
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000632 class = void>
633struct __is_pathable_iter : false_type {};
634
635template <class _Iter>
636struct __is_pathable_iter<
637 _Iter, true,
638 _Void<typename __can_convert_char<
639 typename iterator_traits<_Iter>::value_type>::__char_type> >
640 : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
641 using _ECharT = typename iterator_traits<_Iter>::value_type;
642 using _Base = __can_convert_char<_ECharT>;
643
644 static _Iter __range_begin(_Iter __b) { return __b; }
Martin Storsjö2ae96532020-10-27 11:46:06 +0200645 static _NullSentinel __range_end(_Iter) { return _NullSentinel{}; }
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000646
647 static _ECharT __first_or_null(_Iter __b) { return *__b; }
648};
649
650template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
651 bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
652 bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
653struct __is_pathable : false_type {
654 static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
655};
656
657template <class _Tp>
658struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
659
660template <class _Tp>
661struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
662};
663
664template <class _Tp>
665struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
666
667template <class _ECharT>
Louis Dionne8d053eb2020-10-09 15:31:05 -0400668struct _PathCVT;
669
670#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
671template <class _ECharT>
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000672struct _PathCVT {
673 static_assert(__can_convert_char<_ECharT>::value,
674 "Char type not convertible");
675
676 typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
677
678 static void __append_range(string& __dest, _ECharT const* __b,
679 _ECharT const* __e) {
680 _Narrower()(back_inserter(__dest), __b, __e);
681 }
682
683 template <class _Iter>
684 static void __append_range(string& __dest, _Iter __b, _Iter __e) {
685 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
686 if (__b == __e)
687 return;
688 basic_string<_ECharT> __tmp(__b, __e);
689 _Narrower()(back_inserter(__dest), __tmp.data(),
690 __tmp.data() + __tmp.length());
691 }
692
693 template <class _Iter>
Martin Storsjö2ae96532020-10-27 11:46:06 +0200694 static void __append_range(string& __dest, _Iter __b, _NullSentinel) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000695 static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
Martin Storsjö2ae96532020-10-27 11:46:06 +0200696 const _ECharT __sentinel = _ECharT{};
697 if (*__b == __sentinel)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000698 return;
699 basic_string<_ECharT> __tmp;
Martin Storsjö2ae96532020-10-27 11:46:06 +0200700 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000701 __tmp.push_back(*__b);
702 _Narrower()(back_inserter(__dest), __tmp.data(),
703 __tmp.data() + __tmp.length());
704 }
705
706 template <class _Source>
707 static void __append_source(string& __dest, _Source const& __s) {
708 using _Traits = __is_pathable<_Source>;
709 __append_range(__dest, _Traits::__range_begin(__s),
710 _Traits::__range_end(__s));
711 }
712};
Louis Dionne8d053eb2020-10-09 15:31:05 -0400713#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000714
715template <>
716struct _PathCVT<char> {
717
718 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500719 static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000720 __append_range(string& __dest, _Iter __b, _Iter __e) {
721 for (; __b != __e; ++__b)
722 __dest.push_back(*__b);
723 }
724
725 template <class _Iter>
Eric Fiseliercd5a6772019-11-18 01:46:58 -0500726 static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000727 __append_range(string& __dest, _Iter __b, _Iter __e) {
728 __dest.__append_forward_unsafe(__b, __e);
729 }
730
731 template <class _Iter>
Martin Storsjö2ae96532020-10-27 11:46:06 +0200732 static void __append_range(string& __dest, _Iter __b, _NullSentinel) {
733 const char __sentinel = char{};
734 for (; *__b != __sentinel; ++__b)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000735 __dest.push_back(*__b);
736 }
737
738 template <class _Source>
739 static void __append_source(string& __dest, _Source const& __s) {
740 using _Traits = __is_pathable<_Source>;
741 __append_range(__dest, _Traits::__range_begin(__s),
742 _Traits::__range_end(__s));
743 }
744};
745
746class _LIBCPP_TYPE_VIS path {
747 template <class _SourceOrIter, class _Tp = path&>
748 using _EnableIfPathable =
749 typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
750
751 template <class _Tp>
752 using _SourceChar = typename __is_pathable<_Tp>::__char_type;
753
754 template <class _Tp>
755 using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
756
757public:
758 typedef char value_type;
759 typedef basic_string<value_type> string_type;
760 typedef _VSTD::string_view __string_view;
761 static constexpr value_type preferred_separator = '/';
762
763 enum class _LIBCPP_ENUM_VIS format : unsigned char {
764 auto_format,
765 native_format,
766 generic_format
767 };
768
769 // constructors and destructor
770 _LIBCPP_INLINE_VISIBILITY path() noexcept {}
771 _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
772 _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
773 : __pn_(_VSTD::move(__p.__pn_)) {}
774
775 _LIBCPP_INLINE_VISIBILITY
776 path(string_type&& __s, format = format::auto_format) noexcept
777 : __pn_(_VSTD::move(__s)) {}
778
779 template <class _Source, class = _EnableIfPathable<_Source, void> >
780 path(const _Source& __src, format = format::auto_format) {
781 _SourceCVT<_Source>::__append_source(__pn_, __src);
782 }
783
784 template <class _InputIt>
785 path(_InputIt __first, _InputIt __last, format = format::auto_format) {
786 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
787 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
788 }
789
Louis Dionne8d053eb2020-10-09 15:31:05 -0400790#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000791 // TODO Implement locale conversions.
792 template <class _Source, class = _EnableIfPathable<_Source, void> >
793 path(const _Source& __src, const locale& __loc, format = format::auto_format);
794 template <class _InputIt>
795 path(_InputIt __first, _InputIt _last, const locale& __loc,
796 format = format::auto_format);
Louis Dionne8d053eb2020-10-09 15:31:05 -0400797#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +0000798
799 _LIBCPP_INLINE_VISIBILITY
800 ~path() = default;
801
802 // assignments
803 _LIBCPP_INLINE_VISIBILITY
804 path& operator=(const path& __p) {
805 __pn_ = __p.__pn_;
806 return *this;
807 }
808
809 _LIBCPP_INLINE_VISIBILITY
810 path& operator=(path&& __p) noexcept {
811 __pn_ = _VSTD::move(__p.__pn_);
812 return *this;
813 }
814
815 template <class = void>
816 _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept {
817 __pn_ = _VSTD::move(__s);
818 return *this;
819 }
820
821 _LIBCPP_INLINE_VISIBILITY
822 path& assign(string_type&& __s) noexcept {
823 __pn_ = _VSTD::move(__s);
824 return *this;
825 }
826
827 template <class _Source>
828 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
829 operator=(const _Source& __src) {
830 return this->assign(__src);
831 }
832
833 template <class _Source>
834 _EnableIfPathable<_Source> assign(const _Source& __src) {
835 __pn_.clear();
836 _SourceCVT<_Source>::__append_source(__pn_, __src);
837 return *this;
838 }
839
840 template <class _InputIt>
841 path& assign(_InputIt __first, _InputIt __last) {
842 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
843 __pn_.clear();
844 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
845 return *this;
846 }
847
848private:
849 template <class _ECharT>
850 static bool __source_is_absolute(_ECharT __first_or_null) {
851 return __is_separator(__first_or_null);
852 }
853
854public:
855 // appends
856 path& operator/=(const path& __p) {
857 if (__p.is_absolute()) {
858 __pn_ = __p.__pn_;
859 return *this;
860 }
861 if (has_filename())
862 __pn_ += preferred_separator;
863 __pn_ += __p.native();
864 return *this;
865 }
866
867 // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src
868 // is known at compile time to be "/' since the user almost certainly intended
869 // to append a separator instead of overwriting the path with "/"
870 template <class _Source>
871 _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
872 operator/=(const _Source& __src) {
873 return this->append(__src);
874 }
875
876 template <class _Source>
877 _EnableIfPathable<_Source> append(const _Source& __src) {
878 using _Traits = __is_pathable<_Source>;
879 using _CVT = _PathCVT<_SourceChar<_Source> >;
880 if (__source_is_absolute(_Traits::__first_or_null(__src)))
881 __pn_.clear();
882 else if (has_filename())
883 __pn_ += preferred_separator;
884 _CVT::__append_source(__pn_, __src);
885 return *this;
886 }
887
888 template <class _InputIt>
889 path& append(_InputIt __first, _InputIt __last) {
890 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
891 static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
892 using _CVT = _PathCVT<_ItVal>;
893 if (__first != __last && __source_is_absolute(*__first))
894 __pn_.clear();
895 else if (has_filename())
896 __pn_ += preferred_separator;
897 _CVT::__append_range(__pn_, __first, __last);
898 return *this;
899 }
900
901 // concatenation
902 _LIBCPP_INLINE_VISIBILITY
903 path& operator+=(const path& __x) {
904 __pn_ += __x.__pn_;
905 return *this;
906 }
907
908 _LIBCPP_INLINE_VISIBILITY
909 path& operator+=(const string_type& __x) {
910 __pn_ += __x;
911 return *this;
912 }
913
914 _LIBCPP_INLINE_VISIBILITY
915 path& operator+=(__string_view __x) {
916 __pn_ += __x;
917 return *this;
918 }
919
920 _LIBCPP_INLINE_VISIBILITY
921 path& operator+=(const value_type* __x) {
922 __pn_ += __x;
923 return *this;
924 }
925
926 _LIBCPP_INLINE_VISIBILITY
927 path& operator+=(value_type __x) {
928 __pn_ += __x;
929 return *this;
930 }
931
932 template <class _ECharT>
933 typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
934 operator+=(_ECharT __x) {
935 basic_string<_ECharT> __tmp;
936 __tmp += __x;
937 _PathCVT<_ECharT>::__append_source(__pn_, __tmp);
938 return *this;
939 }
940
941 template <class _Source>
942 _EnableIfPathable<_Source> operator+=(const _Source& __x) {
943 return this->concat(__x);
944 }
945
946 template <class _Source>
947 _EnableIfPathable<_Source> concat(const _Source& __x) {
948 _SourceCVT<_Source>::__append_source(__pn_, __x);
949 return *this;
950 }
951
952 template <class _InputIt>
953 path& concat(_InputIt __first, _InputIt __last) {
954 typedef typename iterator_traits<_InputIt>::value_type _ItVal;
955 _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
956 return *this;
957 }
958
959 // modifiers
960 _LIBCPP_INLINE_VISIBILITY
961 void clear() noexcept { __pn_.clear(); }
962
963 path& make_preferred() { return *this; }
964
965 _LIBCPP_INLINE_VISIBILITY
966 path& remove_filename() {
967 auto __fname = __filename();
968 if (!__fname.empty())
969 __pn_.erase(__fname.data() - __pn_.data());
970 return *this;
971 }
972
973 path& replace_filename(const path& __replacement) {
974 remove_filename();
975 return (*this /= __replacement);
976 }
977
978 path& replace_extension(const path& __replacement = path());
979
980 _LIBCPP_INLINE_VISIBILITY
981 void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); }
982
983 // private helper to allow reserving memory in the path
984 _LIBCPP_INLINE_VISIBILITY
985 void __reserve(size_t __s) { __pn_.reserve(__s); }
986
987 // native format observers
988 _LIBCPP_INLINE_VISIBILITY
989 const string_type& native() const noexcept { return __pn_; }
990
991 _LIBCPP_INLINE_VISIBILITY
992 const value_type* c_str() const noexcept { return __pn_.c_str(); }
993
994 _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
995
Louis Dionne8d053eb2020-10-09 15:31:05 -0400996 _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; }
997 _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; }
998
999#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001000 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1001 class _Allocator = allocator<_ECharT> >
1002 basic_string<_ECharT, _Traits, _Allocator>
1003 string(const _Allocator& __a = _Allocator()) const {
1004 using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
1005 using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1006 _Str __s(__a);
1007 __s.reserve(__pn_.size());
1008 _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
1009 return __s;
1010 }
1011
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001012 _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const {
1013 return string<wchar_t>();
1014 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001015 _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const {
1016 return string<char16_t>();
1017 }
1018 _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const {
1019 return string<char32_t>();
1020 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001021#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001022
1023 // generic format observers
Louis Dionne8d053eb2020-10-09 15:31:05 -04001024 std::string generic_string() const { return __pn_; }
1025 std::string generic_u8string() const { return __pn_; }
1026
1027#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001028 template <class _ECharT, class _Traits = char_traits<_ECharT>,
1029 class _Allocator = allocator<_ECharT> >
1030 basic_string<_ECharT, _Traits, _Allocator>
1031 generic_string(const _Allocator& __a = _Allocator()) const {
1032 return string<_ECharT, _Traits, _Allocator>(__a);
1033 }
1034
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001035 std::wstring generic_wstring() const { return string<wchar_t>(); }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001036 std::u16string generic_u16string() const { return string<char16_t>(); }
1037 std::u32string generic_u32string() const { return string<char32_t>(); }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001038#endif
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001039
1040private:
1041 int __compare(__string_view) const;
1042 __string_view __root_name() const;
1043 __string_view __root_directory() const;
1044 __string_view __root_path_raw() const;
1045 __string_view __relative_path() const;
1046 __string_view __parent_path() const;
1047 __string_view __filename() const;
1048 __string_view __stem() const;
1049 __string_view __extension() const;
1050
1051public:
1052 // compare
1053 _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
1054 return __compare(__p.__pn_);
1055 }
1056 _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
1057 return __compare(__s);
1058 }
1059 _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
1060 return __compare(__s);
1061 }
1062 _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
1063 return __compare(__s);
1064 }
1065
1066 // decomposition
1067 _LIBCPP_INLINE_VISIBILITY path root_name() const {
1068 return string_type(__root_name());
1069 }
1070 _LIBCPP_INLINE_VISIBILITY path root_directory() const {
1071 return string_type(__root_directory());
1072 }
1073 _LIBCPP_INLINE_VISIBILITY path root_path() const {
1074 return root_name().append(string_type(__root_directory()));
1075 }
1076 _LIBCPP_INLINE_VISIBILITY path relative_path() const {
1077 return string_type(__relative_path());
1078 }
1079 _LIBCPP_INLINE_VISIBILITY path parent_path() const {
1080 return string_type(__parent_path());
1081 }
1082 _LIBCPP_INLINE_VISIBILITY path filename() const {
1083 return string_type(__filename());
1084 }
1085 _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
1086 _LIBCPP_INLINE_VISIBILITY path extension() const {
1087 return string_type(__extension());
1088 }
1089
1090 // query
1091 _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
1092 empty() const noexcept {
1093 return __pn_.empty();
1094 }
1095
1096 _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
1097 return !__root_name().empty();
1098 }
1099 _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
1100 return !__root_directory().empty();
1101 }
1102 _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
1103 return !__root_path_raw().empty();
1104 }
1105 _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
1106 return !__relative_path().empty();
1107 }
1108 _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
1109 return !__parent_path().empty();
1110 }
1111 _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
1112 return !__filename().empty();
1113 }
1114 _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
1115 _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
1116 return !__extension().empty();
1117 }
1118
1119 _LIBCPP_INLINE_VISIBILITY bool is_absolute() const {
1120 return has_root_directory();
1121 }
1122 _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); }
1123
1124 // relative paths
1125 path lexically_normal() const;
1126 path lexically_relative(const path& __base) const;
1127
1128 _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const {
1129 path __result = this->lexically_relative(__base);
1130 if (__result.native().empty())
1131 return *this;
1132 return __result;
1133 }
1134
1135 // iterators
1136 class _LIBCPP_TYPE_VIS iterator;
1137 typedef iterator const_iterator;
1138
1139 iterator begin() const;
1140 iterator end() const;
1141
Louis Dionne8d053eb2020-10-09 15:31:05 -04001142#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001143 template <class _CharT, class _Traits>
1144 _LIBCPP_INLINE_VISIBILITY friend
1145 typename enable_if<is_same<_CharT, char>::value &&
1146 is_same<_Traits, char_traits<char> >::value,
1147 basic_ostream<_CharT, _Traits>&>::type
1148 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
1149 __os << std::__quoted(__p.native());
1150 return __os;
1151 }
1152
1153 template <class _CharT, class _Traits>
1154 _LIBCPP_INLINE_VISIBILITY friend
1155 typename enable_if<!is_same<_CharT, char>::value ||
1156 !is_same<_Traits, char_traits<char> >::value,
1157 basic_ostream<_CharT, _Traits>&>::type
1158 operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
1159 __os << std::__quoted(__p.string<_CharT, _Traits>());
1160 return __os;
1161 }
1162
1163 template <class _CharT, class _Traits>
1164 _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
1165 operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
1166 basic_string<_CharT, _Traits> __tmp;
1167 __is >> __quoted(__tmp);
1168 __p = __tmp;
1169 return __is;
1170 }
Louis Dionne8d053eb2020-10-09 15:31:05 -04001171#endif // !_LIBCPP_HAS_NO_LOCALIZATION
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001172
Eric Fiselierab3f9d62018-12-21 04:09:01 +00001173 friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept {
1174 return __lhs.compare(__rhs) == 0;
1175 }
1176 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept {
1177 return __lhs.compare(__rhs) != 0;
1178 }
1179 friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept {
1180 return __lhs.compare(__rhs) < 0;
1181 }
1182 friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept {
1183 return __lhs.compare(__rhs) <= 0;
1184 }
1185 friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept {
1186 return __lhs.compare(__rhs) > 0;
1187 }
1188 friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept {
1189 return __lhs.compare(__rhs) >= 0;
1190 }
1191
1192 friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
1193 const path& __rhs) {
1194 path __result(__lhs);
1195 __result /= __rhs;
1196 return __result;
1197 }
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001198private:
1199 inline _LIBCPP_INLINE_VISIBILITY path&
1200 __assign_view(__string_view const& __s) noexcept {
1201 __pn_ = string_type(__s);
1202 return *this;
1203 }
1204 string_type __pn_;
1205};
1206
1207inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
1208 __lhs.swap(__rhs);
1209}
1210
1211_LIBCPP_FUNC_VIS
1212size_t hash_value(const path& __p) noexcept;
1213
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001214template <class _Source>
1215_LIBCPP_INLINE_VISIBILITY
1216 typename enable_if<__is_pathable<_Source>::value, path>::type
1217 u8path(const _Source& __s) {
1218 static_assert(
1219 is_same<typename __is_pathable<_Source>::__char_type, char>::value,
1220 "u8path(Source const&) requires Source have a character type of type "
1221 "'char'");
1222 return path(__s);
1223}
1224
1225template <class _InputIt>
1226_LIBCPP_INLINE_VISIBILITY
1227 typename enable_if<__is_pathable<_InputIt>::value, path>::type
1228 u8path(_InputIt __f, _InputIt __l) {
1229 static_assert(
1230 is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
1231 "u8path(Iter, Iter) requires Iter have a value_type of type 'char'");
1232 return path(__f, __l);
1233}
1234
1235class _LIBCPP_TYPE_VIS path::iterator {
1236public:
1237 enum _ParserState : unsigned char {
1238 _Singular,
1239 _BeforeBegin,
1240 _InRootName,
1241 _InRootDir,
1242 _InFilenames,
1243 _InTrailingSep,
1244 _AtEnd
1245 };
1246
1247public:
1248 typedef bidirectional_iterator_tag iterator_category;
1249
1250 typedef path value_type;
1251 typedef std::ptrdiff_t difference_type;
1252 typedef const path* pointer;
1253 typedef const path& reference;
1254
1255 typedef void
1256 __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
1257
1258public:
1259 _LIBCPP_INLINE_VISIBILITY
1260 iterator()
1261 : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
1262 __state_(_Singular) {}
1263
1264 iterator(const iterator&) = default;
1265 ~iterator() = default;
1266
1267 iterator& operator=(const iterator&) = default;
1268
1269 _LIBCPP_INLINE_VISIBILITY
1270 reference operator*() const { return __stashed_elem_; }
1271
1272 _LIBCPP_INLINE_VISIBILITY
1273 pointer operator->() const { return &__stashed_elem_; }
1274
1275 _LIBCPP_INLINE_VISIBILITY
1276 iterator& operator++() {
1277 _LIBCPP_ASSERT(__state_ != _Singular,
1278 "attempting to increment a singular iterator");
1279 _LIBCPP_ASSERT(__state_ != _AtEnd,
1280 "attempting to increment the end iterator");
1281 return __increment();
1282 }
1283
1284 _LIBCPP_INLINE_VISIBILITY
1285 iterator operator++(int) {
1286 iterator __it(*this);
1287 this->operator++();
1288 return __it;
1289 }
1290
1291 _LIBCPP_INLINE_VISIBILITY
1292 iterator& operator--() {
1293 _LIBCPP_ASSERT(__state_ != _Singular,
1294 "attempting to decrement a singular iterator");
1295 _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
1296 "attempting to decrement the begin iterator");
1297 return __decrement();
1298 }
1299
1300 _LIBCPP_INLINE_VISIBILITY
1301 iterator operator--(int) {
1302 iterator __it(*this);
1303 this->operator--();
1304 return __it;
1305 }
1306
1307private:
1308 friend class path;
1309
1310 inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
1311 const iterator&);
1312
1313 iterator& __increment();
1314 iterator& __decrement();
1315
1316 path __stashed_elem_;
1317 const path* __path_ptr_;
1318 path::__string_view __entry_;
1319 _ParserState __state_;
1320};
1321
1322inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
1323 const path::iterator& __rhs) {
1324 return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
1325 __lhs.__entry_.data() == __rhs.__entry_.data();
1326}
1327
1328inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
1329 const path::iterator& __rhs) {
1330 return !(__lhs == __rhs);
1331}
1332
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001333// TODO(ldionne): We need to pop the pragma and push it again after
1334// filesystem_error to work around PR41078.
1335_LIBCPP_AVAILABILITY_FILESYSTEM_POP
1336
1337class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001338public:
1339 _LIBCPP_INLINE_VISIBILITY
1340 filesystem_error(const string& __what, error_code __ec)
1341 : system_error(__ec, __what),
1342 __storage_(make_shared<_Storage>(path(), path())) {
1343 __create_what(0);
1344 }
1345
1346 _LIBCPP_INLINE_VISIBILITY
1347 filesystem_error(const string& __what, const path& __p1, error_code __ec)
1348 : system_error(__ec, __what),
1349 __storage_(make_shared<_Storage>(__p1, path())) {
1350 __create_what(1);
1351 }
1352
1353 _LIBCPP_INLINE_VISIBILITY
1354 filesystem_error(const string& __what, const path& __p1, const path& __p2,
1355 error_code __ec)
1356 : system_error(__ec, __what),
1357 __storage_(make_shared<_Storage>(__p1, __p2)) {
1358 __create_what(2);
1359 }
1360
1361 _LIBCPP_INLINE_VISIBILITY
1362 const path& path1() const noexcept { return __storage_->__p1_; }
1363
1364 _LIBCPP_INLINE_VISIBILITY
1365 const path& path2() const noexcept { return __storage_->__p2_; }
1366
Dimitry Andric47269ce2020-03-13 19:36:26 +01001367 filesystem_error(const filesystem_error&) = default;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001368 ~filesystem_error() override; // key function
1369
1370 _LIBCPP_INLINE_VISIBILITY
1371 const char* what() const noexcept override {
1372 return __storage_->__what_.c_str();
1373 }
1374
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001375 void __create_what(int __num_paths);
1376
1377private:
Louis Dionne48ae8892019-03-19 17:47:53 +00001378 struct _LIBCPP_HIDDEN _Storage {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001379 _LIBCPP_INLINE_VISIBILITY
1380 _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
1381
1382 path __p1_;
1383 path __p2_;
1384 string __what_;
1385 };
1386 shared_ptr<_Storage> __storage_;
1387};
1388
Louis Dionnef6bf76a2019-03-20 21:18:14 +00001389_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
1390
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001391template <class... _Args>
1392_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
1393#ifndef _LIBCPP_NO_EXCEPTIONS
Louis Dionne6251ef02019-02-05 15:46:52 +00001394void __throw_filesystem_error(_Args&&... __args) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001395 throw filesystem_error(std::forward<_Args>(__args)...);
1396}
1397#else
Louis Dionne6251ef02019-02-05 15:46:52 +00001398void __throw_filesystem_error(_Args&&...) {
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001399 _VSTD::abort();
1400}
1401#endif
1402
1403// operational functions
1404
1405_LIBCPP_FUNC_VIS
1406path __absolute(const path&, error_code* __ec = nullptr);
1407_LIBCPP_FUNC_VIS
1408path __canonical(const path&, error_code* __ec = nullptr);
1409_LIBCPP_FUNC_VIS
1410void __copy(const path& __from, const path& __to, copy_options __opt,
1411 error_code* __ec = nullptr);
1412_LIBCPP_FUNC_VIS
1413bool __copy_file(const path& __from, const path& __to, copy_options __opt,
1414 error_code* __ec = nullptr);
1415_LIBCPP_FUNC_VIS
1416void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
1417 error_code* __ec = nullptr);
1418_LIBCPP_FUNC_VIS
1419bool __create_directories(const path& p, error_code* ec = nullptr);
1420_LIBCPP_FUNC_VIS
1421bool __create_directory(const path& p, error_code* ec = nullptr);
1422_LIBCPP_FUNC_VIS
1423bool __create_directory(const path& p, const path& attributes,
1424 error_code* ec = nullptr);
1425_LIBCPP_FUNC_VIS
1426void __create_directory_symlink(const path& __to, const path& __new_symlink,
1427 error_code* __ec = nullptr);
1428_LIBCPP_FUNC_VIS
1429void __create_hard_link(const path& __to, const path& __new_hard_link,
1430 error_code* __ec = nullptr);
1431_LIBCPP_FUNC_VIS
1432void __create_symlink(const path& __to, const path& __new_symlink,
1433 error_code* __ec = nullptr);
1434_LIBCPP_FUNC_VIS
1435path __current_path(error_code* __ec = nullptr);
1436_LIBCPP_FUNC_VIS
1437void __current_path(const path&, error_code* __ec = nullptr);
1438_LIBCPP_FUNC_VIS
1439bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
1440_LIBCPP_FUNC_VIS
1441uintmax_t __file_size(const path&, error_code* __ec = nullptr);
1442_LIBCPP_FUNC_VIS
1443uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
1444_LIBCPP_FUNC_VIS
1445bool __fs_is_empty(const path& p, error_code* ec = nullptr);
1446_LIBCPP_FUNC_VIS
1447file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
1448_LIBCPP_FUNC_VIS
1449void __last_write_time(const path& p, file_time_type new_time,
1450 error_code* ec = nullptr);
1451_LIBCPP_FUNC_VIS
1452void __permissions(const path&, perms, perm_options, error_code* = nullptr);
1453_LIBCPP_FUNC_VIS
1454path __read_symlink(const path& p, error_code* ec = nullptr);
1455_LIBCPP_FUNC_VIS
1456bool __remove(const path& p, error_code* ec = nullptr);
1457_LIBCPP_FUNC_VIS
1458uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
1459_LIBCPP_FUNC_VIS
1460void __rename(const path& from, const path& to, error_code* ec = nullptr);
1461_LIBCPP_FUNC_VIS
1462void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
1463_LIBCPP_FUNC_VIS
1464space_info __space(const path&, error_code* __ec = nullptr);
1465_LIBCPP_FUNC_VIS
1466file_status __status(const path&, error_code* __ec = nullptr);
1467_LIBCPP_FUNC_VIS
1468file_status __symlink_status(const path&, error_code* __ec = nullptr);
1469_LIBCPP_FUNC_VIS
1470path __system_complete(const path&, error_code* __ec = nullptr);
1471_LIBCPP_FUNC_VIS
1472path __temp_directory_path(error_code* __ec = nullptr);
1473_LIBCPP_FUNC_VIS
1474path __weakly_canonical(path const& __p, error_code* __ec = nullptr);
1475
1476inline _LIBCPP_INLINE_VISIBILITY path current_path() {
1477 return __current_path();
1478}
1479
1480inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
1481 return __current_path(&__ec);
1482}
1483
1484inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
1485 __current_path(__p);
1486}
1487
1488inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
1489 error_code& __ec) noexcept {
1490 __current_path(__p, &__ec);
1491}
1492
1493inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
1494 return __absolute(__p);
1495}
1496
1497inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
1498 error_code& __ec) {
1499 return __absolute(__p, &__ec);
1500}
1501
1502inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
1503 return __canonical(__p);
1504}
1505
1506inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
1507 error_code& __ec) {
1508 return __canonical(__p, &__ec);
1509}
1510
1511inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
1512 const path& __to) {
1513 __copy(__from, __to, copy_options::none);
1514}
1515
1516inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1517 error_code& __ec) {
1518 __copy(__from, __to, copy_options::none, &__ec);
1519}
1520
1521inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1522 copy_options __opt) {
1523 __copy(__from, __to, __opt);
1524}
1525
1526inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
1527 copy_options __opt,
1528 error_code& __ec) {
1529 __copy(__from, __to, __opt, &__ec);
1530}
1531
1532inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1533 const path& __to) {
1534 return __copy_file(__from, __to, copy_options::none);
1535}
1536
1537inline _LIBCPP_INLINE_VISIBILITY bool
1538copy_file(const path& __from, const path& __to, error_code& __ec) {
1539 return __copy_file(__from, __to, copy_options::none, &__ec);
1540}
1541
1542inline _LIBCPP_INLINE_VISIBILITY bool
1543copy_file(const path& __from, const path& __to, copy_options __opt) {
1544 return __copy_file(__from, __to, __opt);
1545}
1546
1547inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
1548 const path& __to,
1549 copy_options __opt,
1550 error_code& __ec) {
1551 return __copy_file(__from, __to, __opt, &__ec);
1552}
1553
1554inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
1555 const path& __new) {
1556 __copy_symlink(__existing, __new);
1557}
1558
1559inline _LIBCPP_INLINE_VISIBILITY void
1560copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
1561 __copy_symlink(__ext, __new, &__ec);
1562}
1563
1564inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
1565 return __create_directories(__p);
1566}
1567
1568inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
1569 error_code& __ec) {
1570 return __create_directories(__p, &__ec);
1571}
1572
1573inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
1574 return __create_directory(__p);
1575}
1576
1577inline _LIBCPP_INLINE_VISIBILITY bool
1578create_directory(const path& __p, error_code& __ec) noexcept {
1579 return __create_directory(__p, &__ec);
1580}
1581
1582inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
1583 const path& __attrs) {
1584 return __create_directory(__p, __attrs);
1585}
1586
1587inline _LIBCPP_INLINE_VISIBILITY bool
1588create_directory(const path& __p, const path& __attrs,
1589 error_code& __ec) noexcept {
1590 return __create_directory(__p, __attrs, &__ec);
1591}
1592
1593inline _LIBCPP_INLINE_VISIBILITY void
1594create_directory_symlink(const path& __to, const path& __new) {
1595 __create_directory_symlink(__to, __new);
1596}
1597
1598inline _LIBCPP_INLINE_VISIBILITY void
1599create_directory_symlink(const path& __to, const path& __new,
1600 error_code& __ec) noexcept {
1601 __create_directory_symlink(__to, __new, &__ec);
1602}
1603
1604inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
1605 const path& __new) {
1606 __create_hard_link(__to, __new);
1607}
1608
1609inline _LIBCPP_INLINE_VISIBILITY void
1610create_hard_link(const path& __to, const path& __new,
1611 error_code& __ec) noexcept {
1612 __create_hard_link(__to, __new, &__ec);
1613}
1614
1615inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
1616 const path& __new) {
1617 __create_symlink(__to, __new);
1618}
1619
1620inline _LIBCPP_INLINE_VISIBILITY void
1621create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
1622 return __create_symlink(__to, __new, &__ec);
1623}
1624
1625inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
1626 return __s.type() != file_type::none;
1627}
1628
1629inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
1630 return status_known(__s) && __s.type() != file_type::not_found;
1631}
1632
1633inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
1634 return exists(__status(__p));
1635}
1636
1637inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
1638 error_code& __ec) noexcept {
1639 auto __s = __status(__p, &__ec);
1640 if (status_known(__s))
1641 __ec.clear();
1642 return exists(__s);
1643}
1644
1645inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
1646 const path& __p2) {
1647 return __equivalent(__p1, __p2);
1648}
1649
1650inline _LIBCPP_INLINE_VISIBILITY bool
1651equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
1652 return __equivalent(__p1, __p2, &__ec);
1653}
1654
1655inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
1656 return __file_size(__p);
1657}
1658
1659inline _LIBCPP_INLINE_VISIBILITY uintmax_t
1660file_size(const path& __p, error_code& __ec) noexcept {
1661 return __file_size(__p, &__ec);
1662}
1663
1664inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
1665 return __hard_link_count(__p);
1666}
1667
1668inline _LIBCPP_INLINE_VISIBILITY uintmax_t
1669hard_link_count(const path& __p, error_code& __ec) noexcept {
1670 return __hard_link_count(__p, &__ec);
1671}
1672
1673inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
1674 return __s.type() == file_type::block;
1675}
1676
1677inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
1678 return is_block_file(__status(__p));
1679}
1680
1681inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
1682 error_code& __ec) noexcept {
1683 return is_block_file(__status(__p, &__ec));
1684}
1685
1686inline _LIBCPP_INLINE_VISIBILITY bool
1687is_character_file(file_status __s) noexcept {
1688 return __s.type() == file_type::character;
1689}
1690
1691inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
1692 return is_character_file(__status(__p));
1693}
1694
1695inline _LIBCPP_INLINE_VISIBILITY bool
1696is_character_file(const path& __p, error_code& __ec) noexcept {
1697 return is_character_file(__status(__p, &__ec));
1698}
1699
1700inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
1701 return __s.type() == file_type::directory;
1702}
1703
1704inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
1705 return is_directory(__status(__p));
1706}
1707
1708inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
1709 error_code& __ec) noexcept {
1710 return is_directory(__status(__p, &__ec));
1711}
1712
1713inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
1714 return __fs_is_empty(__p);
1715}
1716
1717inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
1718 error_code& __ec) {
1719 return __fs_is_empty(__p, &__ec);
1720}
1721
1722inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
1723 return __s.type() == file_type::fifo;
1724}
1725inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
1726 return is_fifo(__status(__p));
1727}
1728
1729inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
1730 error_code& __ec) noexcept {
1731 return is_fifo(__status(__p, &__ec));
1732}
1733
1734inline _LIBCPP_INLINE_VISIBILITY bool
1735is_regular_file(file_status __s) noexcept {
1736 return __s.type() == file_type::regular;
1737}
1738
1739inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
1740 return is_regular_file(__status(__p));
1741}
1742
1743inline _LIBCPP_INLINE_VISIBILITY bool
1744is_regular_file(const path& __p, error_code& __ec) noexcept {
1745 return is_regular_file(__status(__p, &__ec));
1746}
1747
1748inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
1749 return __s.type() == file_type::socket;
1750}
1751
1752inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
1753 return is_socket(__status(__p));
1754}
1755
1756inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
1757 error_code& __ec) noexcept {
1758 return is_socket(__status(__p, &__ec));
1759}
1760
1761inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
1762 return __s.type() == file_type::symlink;
1763}
1764
1765inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
1766 return is_symlink(__symlink_status(__p));
1767}
1768
1769inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
1770 error_code& __ec) noexcept {
1771 return is_symlink(__symlink_status(__p, &__ec));
1772}
1773
1774inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
1775 return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
1776 !is_symlink(__s);
1777}
1778
1779inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
1780 return is_other(__status(__p));
1781}
1782
1783inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
1784 error_code& __ec) noexcept {
1785 return is_other(__status(__p, &__ec));
1786}
1787
1788inline _LIBCPP_INLINE_VISIBILITY file_time_type
1789last_write_time(const path& __p) {
1790 return __last_write_time(__p);
1791}
1792
1793inline _LIBCPP_INLINE_VISIBILITY file_time_type
1794last_write_time(const path& __p, error_code& __ec) noexcept {
1795 return __last_write_time(__p, &__ec);
1796}
1797
1798inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
1799 file_time_type __t) {
1800 __last_write_time(__p, __t);
1801}
1802
1803inline _LIBCPP_INLINE_VISIBILITY void
1804last_write_time(const path& __p, file_time_type __t,
1805 error_code& __ec) noexcept {
1806 __last_write_time(__p, __t, &__ec);
1807}
1808
1809inline _LIBCPP_INLINE_VISIBILITY void
1810permissions(const path& __p, perms __prms,
1811 perm_options __opts = perm_options::replace) {
1812 __permissions(__p, __prms, __opts);
1813}
1814
1815inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
1816 error_code& __ec) noexcept {
1817 __permissions(__p, __prms, perm_options::replace, &__ec);
1818}
1819
1820inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
1821 perm_options __opts,
1822 error_code& __ec) {
1823 __permissions(__p, __prms, __opts, &__ec);
1824}
1825
1826inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
1827 const path& __base,
1828 error_code& __ec) {
1829 path __tmp = __weakly_canonical(__p, &__ec);
1830 if (__ec)
1831 return {};
1832 path __tmp_base = __weakly_canonical(__base, &__ec);
1833 if (__ec)
1834 return {};
1835 return __tmp.lexically_proximate(__tmp_base);
1836}
1837
1838inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p,
1839 error_code& __ec) {
1840 return proximate(__p, current_path(), __ec);
1841}
1842
1843inline _LIBCPP_INLINE_VISIBILITY path
1844proximate(const path& __p, const path& __base = current_path()) {
1845 return __weakly_canonical(__p).lexically_proximate(
1846 __weakly_canonical(__base));
1847}
1848
1849inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) {
1850 return __read_symlink(__p);
1851}
1852
1853inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p,
1854 error_code& __ec) {
1855 return __read_symlink(__p, &__ec);
1856}
1857
1858inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
1859 const path& __base,
1860 error_code& __ec) {
1861 path __tmp = __weakly_canonical(__p, &__ec);
1862 if (__ec)
1863 return path();
1864 path __tmpbase = __weakly_canonical(__base, &__ec);
1865 if (__ec)
1866 return path();
1867 return __tmp.lexically_relative(__tmpbase);
1868}
1869
1870inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p,
1871 error_code& __ec) {
1872 return relative(__p, current_path(), __ec);
1873}
1874
1875inline _LIBCPP_INLINE_VISIBILITY path
1876relative(const path& __p, const path& __base = current_path()) {
1877 return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base));
1878}
1879
1880inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) {
1881 return __remove(__p);
1882}
1883
1884inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
1885 error_code& __ec) noexcept {
1886 return __remove(__p, &__ec);
1887}
1888
1889inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
1890 return __remove_all(__p);
1891}
1892
1893inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
1894 error_code& __ec) {
1895 return __remove_all(__p, &__ec);
1896}
1897
1898inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
1899 const path& __to) {
1900 return __rename(__from, __to);
1901}
1902
1903inline _LIBCPP_INLINE_VISIBILITY void
1904rename(const path& __from, const path& __to, error_code& __ec) noexcept {
1905 return __rename(__from, __to, &__ec);
1906}
1907
1908inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
1909 uintmax_t __ns) {
1910 return __resize_file(__p, __ns);
1911}
1912
1913inline _LIBCPP_INLINE_VISIBILITY void
1914resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
1915 return __resize_file(__p, __ns, &__ec);
1916}
1917
1918inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
1919 return __space(__p);
1920}
1921
1922inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
1923 error_code& __ec) noexcept {
1924 return __space(__p, &__ec);
1925}
1926
1927inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
1928 return __status(__p);
1929}
1930
1931inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
1932 error_code& __ec) noexcept {
1933 return __status(__p, &__ec);
1934}
1935
1936inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
1937 return __symlink_status(__p);
1938}
1939
1940inline _LIBCPP_INLINE_VISIBILITY file_status
1941symlink_status(const path& __p, error_code& __ec) noexcept {
1942 return __symlink_status(__p, &__ec);
1943}
1944
1945inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
1946 return __temp_directory_path();
1947}
1948
1949inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
1950 return __temp_directory_path(&__ec);
1951}
1952
1953inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
1954 return __weakly_canonical(__p);
1955}
1956
1957inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
1958 error_code& __ec) {
1959 return __weakly_canonical(__p, &__ec);
1960}
1961
1962class directory_iterator;
1963class recursive_directory_iterator;
Louis Dionne48ae8892019-03-19 17:47:53 +00001964class _LIBCPP_HIDDEN __dir_stream;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00001965
1966class directory_entry {
1967 typedef _VSTD_FS::path _Path;
1968
1969public:
1970 // constructors and destructors
1971 directory_entry() noexcept = default;
1972 directory_entry(directory_entry const&) = default;
1973 directory_entry(directory_entry&&) noexcept = default;
1974
1975 _LIBCPP_INLINE_VISIBILITY
1976 explicit directory_entry(_Path const& __p) : __p_(__p) {
1977 error_code __ec;
1978 __refresh(&__ec);
1979 }
1980
1981 _LIBCPP_INLINE_VISIBILITY
1982 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
1983 __refresh(&__ec);
1984 }
1985
1986 ~directory_entry() {}
1987
1988 directory_entry& operator=(directory_entry const&) = default;
1989 directory_entry& operator=(directory_entry&&) noexcept = default;
1990
1991 _LIBCPP_INLINE_VISIBILITY
1992 void assign(_Path const& __p) {
1993 __p_ = __p;
1994 error_code __ec;
1995 __refresh(&__ec);
1996 }
1997
1998 _LIBCPP_INLINE_VISIBILITY
1999 void assign(_Path const& __p, error_code& __ec) {
2000 __p_ = __p;
2001 __refresh(&__ec);
2002 }
2003
2004 _LIBCPP_INLINE_VISIBILITY
2005 void replace_filename(_Path const& __p) {
2006 __p_.replace_filename(__p);
2007 error_code __ec;
2008 __refresh(&__ec);
2009 }
2010
2011 _LIBCPP_INLINE_VISIBILITY
2012 void replace_filename(_Path const& __p, error_code& __ec) {
2013 __p_ = __p_.parent_path() / __p;
2014 __refresh(&__ec);
2015 }
2016
2017 _LIBCPP_INLINE_VISIBILITY
2018 void refresh() { __refresh(); }
2019
2020 _LIBCPP_INLINE_VISIBILITY
2021 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
2022
2023 _LIBCPP_INLINE_VISIBILITY
2024 _Path const& path() const noexcept { return __p_; }
2025
2026 _LIBCPP_INLINE_VISIBILITY
2027 operator const _Path&() const noexcept { return __p_; }
2028
2029 _LIBCPP_INLINE_VISIBILITY
2030 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
2031
2032 _LIBCPP_INLINE_VISIBILITY
2033 bool exists(error_code& __ec) const noexcept {
2034 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
2035 }
2036
2037 _LIBCPP_INLINE_VISIBILITY
2038 bool is_block_file() const { return __get_ft() == file_type::block; }
2039
2040 _LIBCPP_INLINE_VISIBILITY
2041 bool is_block_file(error_code& __ec) const noexcept {
2042 return __get_ft(&__ec) == file_type::block;
2043 }
2044
2045 _LIBCPP_INLINE_VISIBILITY
2046 bool is_character_file() const { return __get_ft() == file_type::character; }
2047
2048 _LIBCPP_INLINE_VISIBILITY
2049 bool is_character_file(error_code& __ec) const noexcept {
2050 return __get_ft(&__ec) == file_type::character;
2051 }
2052
2053 _LIBCPP_INLINE_VISIBILITY
2054 bool is_directory() const { return __get_ft() == file_type::directory; }
2055
2056 _LIBCPP_INLINE_VISIBILITY
2057 bool is_directory(error_code& __ec) const noexcept {
2058 return __get_ft(&__ec) == file_type::directory;
2059 }
2060
2061 _LIBCPP_INLINE_VISIBILITY
2062 bool is_fifo() const { return __get_ft() == file_type::fifo; }
2063
2064 _LIBCPP_INLINE_VISIBILITY
2065 bool is_fifo(error_code& __ec) const noexcept {
2066 return __get_ft(&__ec) == file_type::fifo;
2067 }
2068
2069 _LIBCPP_INLINE_VISIBILITY
2070 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
2071
2072 _LIBCPP_INLINE_VISIBILITY
2073 bool is_other(error_code& __ec) const noexcept {
2074 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
2075 }
2076
2077 _LIBCPP_INLINE_VISIBILITY
2078 bool is_regular_file() const { return __get_ft() == file_type::regular; }
2079
2080 _LIBCPP_INLINE_VISIBILITY
2081 bool is_regular_file(error_code& __ec) const noexcept {
2082 return __get_ft(&__ec) == file_type::regular;
2083 }
2084
2085 _LIBCPP_INLINE_VISIBILITY
2086 bool is_socket() const { return __get_ft() == file_type::socket; }
2087
2088 _LIBCPP_INLINE_VISIBILITY
2089 bool is_socket(error_code& __ec) const noexcept {
2090 return __get_ft(&__ec) == file_type::socket;
2091 }
2092
2093 _LIBCPP_INLINE_VISIBILITY
2094 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
2095
2096 _LIBCPP_INLINE_VISIBILITY
2097 bool is_symlink(error_code& __ec) const noexcept {
2098 return __get_sym_ft(&__ec) == file_type::symlink;
2099 }
2100 _LIBCPP_INLINE_VISIBILITY
2101 uintmax_t file_size() const { return __get_size(); }
2102
2103 _LIBCPP_INLINE_VISIBILITY
2104 uintmax_t file_size(error_code& __ec) const noexcept {
2105 return __get_size(&__ec);
2106 }
2107
2108 _LIBCPP_INLINE_VISIBILITY
2109 uintmax_t hard_link_count() const { return __get_nlink(); }
2110
2111 _LIBCPP_INLINE_VISIBILITY
2112 uintmax_t hard_link_count(error_code& __ec) const noexcept {
2113 return __get_nlink(&__ec);
2114 }
2115
2116 _LIBCPP_INLINE_VISIBILITY
2117 file_time_type last_write_time() const { return __get_write_time(); }
2118
2119 _LIBCPP_INLINE_VISIBILITY
2120 file_time_type last_write_time(error_code& __ec) const noexcept {
2121 return __get_write_time(&__ec);
2122 }
2123
2124 _LIBCPP_INLINE_VISIBILITY
2125 file_status status() const { return __get_status(); }
2126
2127 _LIBCPP_INLINE_VISIBILITY
2128 file_status status(error_code& __ec) const noexcept {
2129 return __get_status(&__ec);
2130 }
2131
2132 _LIBCPP_INLINE_VISIBILITY
2133 file_status symlink_status() const { return __get_symlink_status(); }
2134
2135 _LIBCPP_INLINE_VISIBILITY
2136 file_status symlink_status(error_code& __ec) const noexcept {
2137 return __get_symlink_status(&__ec);
2138 }
2139
2140 _LIBCPP_INLINE_VISIBILITY
2141 bool operator<(directory_entry const& __rhs) const noexcept {
2142 return __p_ < __rhs.__p_;
2143 }
2144
2145 _LIBCPP_INLINE_VISIBILITY
2146 bool operator==(directory_entry const& __rhs) const noexcept {
2147 return __p_ == __rhs.__p_;
2148 }
2149
2150 _LIBCPP_INLINE_VISIBILITY
2151 bool operator!=(directory_entry const& __rhs) const noexcept {
2152 return __p_ != __rhs.__p_;
2153 }
2154
2155 _LIBCPP_INLINE_VISIBILITY
2156 bool operator<=(directory_entry const& __rhs) const noexcept {
2157 return __p_ <= __rhs.__p_;
2158 }
2159
2160 _LIBCPP_INLINE_VISIBILITY
2161 bool operator>(directory_entry const& __rhs) const noexcept {
2162 return __p_ > __rhs.__p_;
2163 }
2164
2165 _LIBCPP_INLINE_VISIBILITY
2166 bool operator>=(directory_entry const& __rhs) const noexcept {
2167 return __p_ >= __rhs.__p_;
2168 }
2169
2170private:
2171 friend class directory_iterator;
2172 friend class recursive_directory_iterator;
2173 friend class __dir_stream;
2174
2175 enum _CacheType : unsigned char {
2176 _Empty,
2177 _IterSymlink,
2178 _IterNonSymlink,
2179 _RefreshSymlink,
2180 _RefreshSymlinkUnresolved,
2181 _RefreshNonSymlink
2182 };
2183
2184 struct __cached_data {
2185 uintmax_t __size_;
2186 uintmax_t __nlink_;
2187 file_time_type __write_time_;
2188 perms __sym_perms_;
2189 perms __non_sym_perms_;
2190 file_type __type_;
2191 _CacheType __cache_type_;
2192
2193 _LIBCPP_INLINE_VISIBILITY
2194 __cached_data() noexcept { __reset(); }
2195
2196 _LIBCPP_INLINE_VISIBILITY
2197 void __reset() {
2198 __cache_type_ = _Empty;
2199 __type_ = file_type::none;
2200 __sym_perms_ = __non_sym_perms_ = perms::unknown;
2201 __size_ = __nlink_ = uintmax_t(-1);
2202 __write_time_ = file_time_type::min();
2203 }
2204 };
2205
2206 _LIBCPP_INLINE_VISIBILITY
2207 static __cached_data __create_iter_result(file_type __ft) {
2208 __cached_data __data;
2209 __data.__type_ = __ft;
2210 __data.__cache_type_ = [&]() {
2211 switch (__ft) {
2212 case file_type::none:
2213 return _Empty;
2214 case file_type::symlink:
2215 return _IterSymlink;
2216 default:
2217 return _IterNonSymlink;
2218 }
2219 }();
2220 return __data;
2221 }
2222
2223 _LIBCPP_INLINE_VISIBILITY
2224 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
2225 __p_ = std::move(__p);
2226 __data_ = __dt;
2227 }
2228
2229 _LIBCPP_FUNC_VIS
2230 error_code __do_refresh() noexcept;
2231
2232 _LIBCPP_INLINE_VISIBILITY
2233 static bool __is_dne_error(error_code const& __ec) {
2234 if (!__ec)
2235 return true;
2236 switch (static_cast<errc>(__ec.value())) {
2237 case errc::no_such_file_or_directory:
2238 case errc::not_a_directory:
2239 return true;
2240 default:
2241 return false;
2242 }
2243 }
2244
2245 _LIBCPP_INLINE_VISIBILITY
2246 void __handle_error(const char* __msg, error_code* __dest_ec,
2247 error_code const& __ec, bool __allow_dne = false) const {
2248 if (__dest_ec) {
2249 *__dest_ec = __ec;
2250 return;
2251 }
2252 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
2253 __throw_filesystem_error(__msg, __p_, __ec);
2254 }
2255
2256 _LIBCPP_INLINE_VISIBILITY
2257 void __refresh(error_code* __ec = nullptr) {
2258 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
2259 /*allow_dne*/ true);
2260 }
2261
2262 _LIBCPP_INLINE_VISIBILITY
2263 file_type __get_sym_ft(error_code* __ec = nullptr) const {
2264 switch (__data_.__cache_type_) {
2265 case _Empty:
2266 return __symlink_status(__p_, __ec).type();
2267 case _IterSymlink:
2268 case _RefreshSymlink:
2269 case _RefreshSymlinkUnresolved:
2270 if (__ec)
2271 __ec->clear();
2272 return file_type::symlink;
2273 case _IterNonSymlink:
2274 case _RefreshNonSymlink:
2275 file_status __st(__data_.__type_);
2276 if (__ec && !_VSTD_FS::exists(__st))
2277 *__ec = make_error_code(errc::no_such_file_or_directory);
2278 else if (__ec)
2279 __ec->clear();
2280 return __data_.__type_;
2281 }
2282 _LIBCPP_UNREACHABLE();
2283 }
2284
2285 _LIBCPP_INLINE_VISIBILITY
2286 file_type __get_ft(error_code* __ec = nullptr) const {
2287 switch (__data_.__cache_type_) {
2288 case _Empty:
2289 case _IterSymlink:
2290 case _RefreshSymlinkUnresolved:
2291 return __status(__p_, __ec).type();
2292 case _IterNonSymlink:
2293 case _RefreshNonSymlink:
2294 case _RefreshSymlink: {
2295 file_status __st(__data_.__type_);
2296 if (__ec && !_VSTD_FS::exists(__st))
2297 *__ec = make_error_code(errc::no_such_file_or_directory);
2298 else if (__ec)
2299 __ec->clear();
2300 return __data_.__type_;
2301 }
2302 }
2303 _LIBCPP_UNREACHABLE();
2304 }
2305
2306 _LIBCPP_INLINE_VISIBILITY
2307 file_status __get_status(error_code* __ec = nullptr) const {
2308 switch (__data_.__cache_type_) {
2309 case _Empty:
2310 case _IterNonSymlink:
2311 case _IterSymlink:
2312 case _RefreshSymlinkUnresolved:
2313 return __status(__p_, __ec);
2314 case _RefreshNonSymlink:
2315 case _RefreshSymlink:
2316 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
2317 }
2318 _LIBCPP_UNREACHABLE();
2319 }
2320
2321 _LIBCPP_INLINE_VISIBILITY
2322 file_status __get_symlink_status(error_code* __ec = nullptr) const {
2323 switch (__data_.__cache_type_) {
2324 case _Empty:
2325 case _IterNonSymlink:
2326 case _IterSymlink:
2327 return __symlink_status(__p_, __ec);
2328 case _RefreshNonSymlink:
2329 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
2330 case _RefreshSymlink:
2331 case _RefreshSymlinkUnresolved:
2332 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
2333 }
2334 _LIBCPP_UNREACHABLE();
2335 }
2336
2337 _LIBCPP_INLINE_VISIBILITY
2338 uintmax_t __get_size(error_code* __ec = nullptr) const {
2339 switch (__data_.__cache_type_) {
2340 case _Empty:
2341 case _IterNonSymlink:
2342 case _IterSymlink:
2343 case _RefreshSymlinkUnresolved:
2344 return _VSTD_FS::__file_size(__p_, __ec);
2345 case _RefreshSymlink:
2346 case _RefreshNonSymlink: {
2347 error_code __m_ec;
2348 file_status __st(__get_ft(&__m_ec));
2349 __handle_error("in directory_entry::file_size", __ec, __m_ec);
2350 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
2351 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
2352 : errc::not_supported;
2353 __handle_error("in directory_entry::file_size", __ec,
2354 make_error_code(__err_kind));
2355 }
2356 return __data_.__size_;
2357 }
2358 }
2359 _LIBCPP_UNREACHABLE();
2360 }
2361
2362 _LIBCPP_INLINE_VISIBILITY
2363 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
2364 switch (__data_.__cache_type_) {
2365 case _Empty:
2366 case _IterNonSymlink:
2367 case _IterSymlink:
2368 case _RefreshSymlinkUnresolved:
2369 return _VSTD_FS::__hard_link_count(__p_, __ec);
2370 case _RefreshSymlink:
2371 case _RefreshNonSymlink: {
2372 error_code __m_ec;
2373 (void)__get_ft(&__m_ec);
2374 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
2375 return __data_.__nlink_;
2376 }
2377 }
2378 _LIBCPP_UNREACHABLE();
2379 }
2380
2381 _LIBCPP_INLINE_VISIBILITY
2382 file_time_type __get_write_time(error_code* __ec = nullptr) const {
2383 switch (__data_.__cache_type_) {
2384 case _Empty:
2385 case _IterNonSymlink:
2386 case _IterSymlink:
2387 case _RefreshSymlinkUnresolved:
2388 return _VSTD_FS::__last_write_time(__p_, __ec);
2389 case _RefreshSymlink:
2390 case _RefreshNonSymlink: {
2391 error_code __m_ec;
2392 file_status __st(__get_ft(&__m_ec));
2393 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
2394 if (_VSTD_FS::exists(__st) &&
2395 __data_.__write_time_ == file_time_type::min())
2396 __handle_error("in directory_entry::last_write_time", __ec,
2397 make_error_code(errc::value_too_large));
2398 return __data_.__write_time_;
2399 }
2400 }
2401 _LIBCPP_UNREACHABLE();
2402 }
2403
2404private:
2405 _Path __p_;
2406 __cached_data __data_;
2407};
2408
2409class __dir_element_proxy {
2410public:
2411 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
2412 return _VSTD::move(__elem_);
2413 }
2414
2415private:
2416 friend class directory_iterator;
2417 friend class recursive_directory_iterator;
2418 explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
2419 __dir_element_proxy(__dir_element_proxy&& __o)
2420 : __elem_(_VSTD::move(__o.__elem_)) {}
2421 directory_entry __elem_;
2422};
2423
2424class directory_iterator {
2425public:
2426 typedef directory_entry value_type;
2427 typedef ptrdiff_t difference_type;
2428 typedef value_type const* pointer;
2429 typedef value_type const& reference;
2430 typedef input_iterator_tag iterator_category;
2431
2432public:
2433 //ctor & dtor
2434 directory_iterator() noexcept {}
2435
2436 explicit directory_iterator(const path& __p)
2437 : directory_iterator(__p, nullptr) {}
2438
2439 directory_iterator(const path& __p, directory_options __opts)
2440 : directory_iterator(__p, nullptr, __opts) {}
2441
2442 directory_iterator(const path& __p, error_code& __ec)
2443 : directory_iterator(__p, &__ec) {}
2444
2445 directory_iterator(const path& __p, directory_options __opts,
2446 error_code& __ec)
2447 : directory_iterator(__p, &__ec, __opts) {}
2448
2449 directory_iterator(const directory_iterator&) = default;
2450 directory_iterator(directory_iterator&&) = default;
2451 directory_iterator& operator=(const directory_iterator&) = default;
2452
2453 directory_iterator& operator=(directory_iterator&& __o) noexcept {
2454 // non-default implementation provided to support self-move assign.
2455 if (this != &__o) {
2456 __imp_ = _VSTD::move(__o.__imp_);
2457 }
2458 return *this;
2459 }
2460
2461 ~directory_iterator() = default;
2462
2463 const directory_entry& operator*() const {
2464 _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
2465 return __dereference();
2466 }
2467
2468 const directory_entry* operator->() const { return &**this; }
2469
2470 directory_iterator& operator++() { return __increment(); }
2471
2472 __dir_element_proxy operator++(int) {
2473 __dir_element_proxy __p(**this);
2474 __increment();
2475 return __p;
2476 }
2477
2478 directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
2479
2480private:
2481 inline _LIBCPP_INLINE_VISIBILITY friend bool
2482 operator==(const directory_iterator& __lhs,
2483 const directory_iterator& __rhs) noexcept;
2484
2485 // construct the dir_stream
2486 _LIBCPP_FUNC_VIS
2487 directory_iterator(const path&, error_code*,
2488 directory_options = directory_options::none);
2489
2490 _LIBCPP_FUNC_VIS
2491 directory_iterator& __increment(error_code* __ec = nullptr);
2492
2493 _LIBCPP_FUNC_VIS
2494 const directory_entry& __dereference() const;
2495
2496private:
2497 shared_ptr<__dir_stream> __imp_;
2498};
2499
2500inline _LIBCPP_INLINE_VISIBILITY bool
2501operator==(const directory_iterator& __lhs,
2502 const directory_iterator& __rhs) noexcept {
2503 return __lhs.__imp_ == __rhs.__imp_;
2504}
2505
2506inline _LIBCPP_INLINE_VISIBILITY bool
2507operator!=(const directory_iterator& __lhs,
2508 const directory_iterator& __rhs) noexcept {
2509 return !(__lhs == __rhs);
2510}
2511
2512// enable directory_iterator range-based for statements
2513inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2514begin(directory_iterator __iter) noexcept {
2515 return __iter;
2516}
2517
2518inline _LIBCPP_INLINE_VISIBILITY directory_iterator
2519end(const directory_iterator&) noexcept {
2520 return directory_iterator();
2521}
2522
2523class recursive_directory_iterator {
2524public:
2525 using value_type = directory_entry;
2526 using difference_type = std::ptrdiff_t;
2527 using pointer = directory_entry const*;
2528 using reference = directory_entry const&;
2529 using iterator_category = std::input_iterator_tag;
2530
2531public:
2532 // constructors and destructor
2533 _LIBCPP_INLINE_VISIBILITY
2534 recursive_directory_iterator() noexcept : __rec_(false) {}
2535
2536 _LIBCPP_INLINE_VISIBILITY
2537 explicit recursive_directory_iterator(
2538 const path& __p, directory_options __xoptions = directory_options::none)
2539 : recursive_directory_iterator(__p, __xoptions, nullptr) {}
2540
2541 _LIBCPP_INLINE_VISIBILITY
2542 recursive_directory_iterator(const path& __p, directory_options __xoptions,
2543 error_code& __ec)
2544 : recursive_directory_iterator(__p, __xoptions, &__ec) {}
2545
2546 _LIBCPP_INLINE_VISIBILITY
2547 recursive_directory_iterator(const path& __p, error_code& __ec)
2548 : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
2549
2550 recursive_directory_iterator(const recursive_directory_iterator&) = default;
2551 recursive_directory_iterator(recursive_directory_iterator&&) = default;
2552
2553 recursive_directory_iterator&
2554 operator=(const recursive_directory_iterator&) = default;
2555
2556 _LIBCPP_INLINE_VISIBILITY
2557 recursive_directory_iterator&
2558 operator=(recursive_directory_iterator&& __o) noexcept {
2559 // non-default implementation provided to support self-move assign.
2560 if (this != &__o) {
2561 __imp_ = _VSTD::move(__o.__imp_);
2562 __rec_ = __o.__rec_;
2563 }
2564 return *this;
2565 }
2566
2567 ~recursive_directory_iterator() = default;
2568
2569 _LIBCPP_INLINE_VISIBILITY
2570 const directory_entry& operator*() const { return __dereference(); }
2571
2572 _LIBCPP_INLINE_VISIBILITY
2573 const directory_entry* operator->() const { return &__dereference(); }
2574
2575 recursive_directory_iterator& operator++() { return __increment(); }
2576
2577 _LIBCPP_INLINE_VISIBILITY
2578 __dir_element_proxy operator++(int) {
2579 __dir_element_proxy __p(**this);
2580 __increment();
2581 return __p;
2582 }
2583
2584 _LIBCPP_INLINE_VISIBILITY
2585 recursive_directory_iterator& increment(error_code& __ec) {
2586 return __increment(&__ec);
2587 }
2588
2589 _LIBCPP_FUNC_VIS directory_options options() const;
2590 _LIBCPP_FUNC_VIS int depth() const;
2591
2592 _LIBCPP_INLINE_VISIBILITY
2593 void pop() { __pop(); }
2594
2595 _LIBCPP_INLINE_VISIBILITY
2596 void pop(error_code& __ec) { __pop(&__ec); }
2597
2598 _LIBCPP_INLINE_VISIBILITY
2599 bool recursion_pending() const { return __rec_; }
2600
2601 _LIBCPP_INLINE_VISIBILITY
2602 void disable_recursion_pending() { __rec_ = false; }
2603
2604private:
Louis Dionne0ba10dc2019-08-13 15:02:53 +00002605 _LIBCPP_FUNC_VIS
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002606 recursive_directory_iterator(const path& __p, directory_options __opt,
2607 error_code* __ec);
2608
2609 _LIBCPP_FUNC_VIS
2610 const directory_entry& __dereference() const;
2611
2612 _LIBCPP_FUNC_VIS
2613 bool __try_recursion(error_code* __ec);
2614
2615 _LIBCPP_FUNC_VIS
2616 void __advance(error_code* __ec = nullptr);
2617
2618 _LIBCPP_FUNC_VIS
2619 recursive_directory_iterator& __increment(error_code* __ec = nullptr);
2620
2621 _LIBCPP_FUNC_VIS
2622 void __pop(error_code* __ec = nullptr);
2623
2624 inline _LIBCPP_INLINE_VISIBILITY friend bool
2625 operator==(const recursive_directory_iterator&,
2626 const recursive_directory_iterator&) noexcept;
2627
Louis Dionne48ae8892019-03-19 17:47:53 +00002628 struct _LIBCPP_HIDDEN __shared_imp;
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002629 shared_ptr<__shared_imp> __imp_;
2630 bool __rec_;
2631}; // class recursive_directory_iterator
2632
2633inline _LIBCPP_INLINE_VISIBILITY bool
2634operator==(const recursive_directory_iterator& __lhs,
2635 const recursive_directory_iterator& __rhs) noexcept {
2636 return __lhs.__imp_ == __rhs.__imp_;
2637}
2638
2639_LIBCPP_INLINE_VISIBILITY
2640inline bool operator!=(const recursive_directory_iterator& __lhs,
2641 const recursive_directory_iterator& __rhs) noexcept {
2642 return !(__lhs == __rhs);
2643}
2644// enable recursive_directory_iterator range-based for statements
2645inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2646begin(recursive_directory_iterator __iter) noexcept {
2647 return __iter;
2648}
2649
2650inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
2651end(const recursive_directory_iterator&) noexcept {
2652 return recursive_directory_iterator();
2653}
2654
Louis Dionnef6bf76a2019-03-20 21:18:14 +00002655_LIBCPP_AVAILABILITY_FILESYSTEM_POP
2656
Eric Fiselier02cea5e2018-07-27 03:07:09 +00002657_LIBCPP_END_NAMESPACE_FILESYSTEM
2658
2659#endif // !_LIBCPP_CXX03_LANG
2660
2661_LIBCPP_POP_MACROS
2662
2663#endif // _LIBCPP_FILESYSTEM