Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / include / __filesystem / directory_entry.h
blob6baaca0709edb5c22ddd53b16863755765b5a41d
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // 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
7 //
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H
11 #define _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H
13 #include <__availability>
14 #include <__chrono/time_point.h>
15 #include <__compare/ordering.h>
16 #include <__config>
17 #include <__filesystem/file_status.h>
18 #include <__filesystem/file_time_type.h>
19 #include <__filesystem/file_type.h>
20 #include <__filesystem/filesystem_error.h>
21 #include <__filesystem/operations.h>
22 #include <__filesystem/path.h>
23 #include <__filesystem/perms.h>
24 #include <__system_error/errc.h>
25 #include <__system_error/error_code.h>
26 #include <__utility/move.h>
27 #include <__utility/unreachable.h>
28 #include <cstdint>
30 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
31 # pragma GCC system_header
32 #endif
34 _LIBCPP_PUSH_MACROS
35 #include <__undef_macros>
37 #if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM)
39 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
41 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH
43 class directory_entry {
44 typedef _VSTD_FS::path _Path;
46 public:
47 // constructors and destructors
48 _LIBCPP_HIDE_FROM_ABI directory_entry() noexcept = default;
49 _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry const&) = default;
50 _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry&&) noexcept = default;
52 _LIBCPP_INLINE_VISIBILITY
53 explicit directory_entry(_Path const& __p) : __p_(__p) {
54 error_code __ec;
55 __refresh(&__ec);
58 _LIBCPP_INLINE_VISIBILITY
59 directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
60 __refresh(&__ec);
63 _LIBCPP_HIDE_FROM_ABI ~directory_entry() {}
65 _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry const&) = default;
66 _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry&&) noexcept = default;
68 _LIBCPP_INLINE_VISIBILITY
69 void assign(_Path const& __p) {
70 __p_ = __p;
71 error_code __ec;
72 __refresh(&__ec);
75 _LIBCPP_INLINE_VISIBILITY
76 void assign(_Path const& __p, error_code& __ec) {
77 __p_ = __p;
78 __refresh(&__ec);
81 _LIBCPP_INLINE_VISIBILITY
82 void replace_filename(_Path const& __p) {
83 __p_.replace_filename(__p);
84 error_code __ec;
85 __refresh(&__ec);
88 _LIBCPP_INLINE_VISIBILITY
89 void replace_filename(_Path const& __p, error_code& __ec) {
90 __p_ = __p_.parent_path() / __p;
91 __refresh(&__ec);
94 _LIBCPP_INLINE_VISIBILITY
95 void refresh() { __refresh(); }
97 _LIBCPP_INLINE_VISIBILITY
98 void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
100 _LIBCPP_INLINE_VISIBILITY
101 _Path const& path() const noexcept { return __p_; }
103 _LIBCPP_INLINE_VISIBILITY
104 operator const _Path&() const noexcept { return __p_; }
106 _LIBCPP_INLINE_VISIBILITY
107 bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
109 _LIBCPP_INLINE_VISIBILITY
110 bool exists(error_code& __ec) const noexcept {
111 return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
114 _LIBCPP_INLINE_VISIBILITY
115 bool is_block_file() const { return __get_ft() == file_type::block; }
117 _LIBCPP_INLINE_VISIBILITY
118 bool is_block_file(error_code& __ec) const noexcept {
119 return __get_ft(&__ec) == file_type::block;
122 _LIBCPP_INLINE_VISIBILITY
123 bool is_character_file() const { return __get_ft() == file_type::character; }
125 _LIBCPP_INLINE_VISIBILITY
126 bool is_character_file(error_code& __ec) const noexcept {
127 return __get_ft(&__ec) == file_type::character;
130 _LIBCPP_INLINE_VISIBILITY
131 bool is_directory() const { return __get_ft() == file_type::directory; }
133 _LIBCPP_INLINE_VISIBILITY
134 bool is_directory(error_code& __ec) const noexcept {
135 return __get_ft(&__ec) == file_type::directory;
138 _LIBCPP_INLINE_VISIBILITY
139 bool is_fifo() const { return __get_ft() == file_type::fifo; }
141 _LIBCPP_INLINE_VISIBILITY
142 bool is_fifo(error_code& __ec) const noexcept {
143 return __get_ft(&__ec) == file_type::fifo;
146 _LIBCPP_INLINE_VISIBILITY
147 bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
149 _LIBCPP_INLINE_VISIBILITY
150 bool is_other(error_code& __ec) const noexcept {
151 return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
154 _LIBCPP_INLINE_VISIBILITY
155 bool is_regular_file() const { return __get_ft() == file_type::regular; }
157 _LIBCPP_INLINE_VISIBILITY
158 bool is_regular_file(error_code& __ec) const noexcept {
159 return __get_ft(&__ec) == file_type::regular;
162 _LIBCPP_INLINE_VISIBILITY
163 bool is_socket() const { return __get_ft() == file_type::socket; }
165 _LIBCPP_INLINE_VISIBILITY
166 bool is_socket(error_code& __ec) const noexcept {
167 return __get_ft(&__ec) == file_type::socket;
170 _LIBCPP_INLINE_VISIBILITY
171 bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
173 _LIBCPP_INLINE_VISIBILITY
174 bool is_symlink(error_code& __ec) const noexcept {
175 return __get_sym_ft(&__ec) == file_type::symlink;
177 _LIBCPP_INLINE_VISIBILITY
178 uintmax_t file_size() const { return __get_size(); }
180 _LIBCPP_INLINE_VISIBILITY
181 uintmax_t file_size(error_code& __ec) const noexcept {
182 return __get_size(&__ec);
185 _LIBCPP_INLINE_VISIBILITY
186 uintmax_t hard_link_count() const { return __get_nlink(); }
188 _LIBCPP_INLINE_VISIBILITY
189 uintmax_t hard_link_count(error_code& __ec) const noexcept {
190 return __get_nlink(&__ec);
193 _LIBCPP_INLINE_VISIBILITY
194 file_time_type last_write_time() const { return __get_write_time(); }
196 _LIBCPP_INLINE_VISIBILITY
197 file_time_type last_write_time(error_code& __ec) const noexcept {
198 return __get_write_time(&__ec);
201 _LIBCPP_INLINE_VISIBILITY
202 file_status status() const { return __get_status(); }
204 _LIBCPP_INLINE_VISIBILITY
205 file_status status(error_code& __ec) const noexcept {
206 return __get_status(&__ec);
209 _LIBCPP_INLINE_VISIBILITY
210 file_status symlink_status() const { return __get_symlink_status(); }
212 _LIBCPP_INLINE_VISIBILITY
213 file_status symlink_status(error_code& __ec) const noexcept {
214 return __get_symlink_status(&__ec);
218 _LIBCPP_INLINE_VISIBILITY
219 bool operator==(directory_entry const& __rhs) const noexcept {
220 return __p_ == __rhs.__p_;
223 #if _LIBCPP_STD_VER <= 17
224 _LIBCPP_INLINE_VISIBILITY
225 bool operator!=(directory_entry const& __rhs) const noexcept {
226 return __p_ != __rhs.__p_;
229 _LIBCPP_INLINE_VISIBILITY
230 bool operator<(directory_entry const& __rhs) const noexcept {
231 return __p_ < __rhs.__p_;
234 _LIBCPP_INLINE_VISIBILITY
235 bool operator<=(directory_entry const& __rhs) const noexcept {
236 return __p_ <= __rhs.__p_;
239 _LIBCPP_INLINE_VISIBILITY
240 bool operator>(directory_entry const& __rhs) const noexcept {
241 return __p_ > __rhs.__p_;
244 _LIBCPP_INLINE_VISIBILITY
245 bool operator>=(directory_entry const& __rhs) const noexcept {
246 return __p_ >= __rhs.__p_;
249 #else // _LIBCPP_STD_VER <= 17
251 _LIBCPP_HIDE_FROM_ABI
252 strong_ordering operator<=>(const directory_entry& __rhs) const noexcept {
253 return __p_ <=> __rhs.__p_;
256 #endif // _LIBCPP_STD_VER <= 17
258 template <class _CharT, class _Traits>
259 _LIBCPP_INLINE_VISIBILITY
260 friend basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const directory_entry& __d) {
261 return __os << __d.path();
264 private:
265 friend class directory_iterator;
266 friend class recursive_directory_iterator;
267 friend class _LIBCPP_HIDDEN __dir_stream;
269 enum _CacheType : unsigned char {
270 _Empty,
271 _IterSymlink,
272 _IterNonSymlink,
273 _RefreshSymlink,
274 _RefreshSymlinkUnresolved,
275 _RefreshNonSymlink
278 struct __cached_data {
279 uintmax_t __size_;
280 uintmax_t __nlink_;
281 file_time_type __write_time_;
282 perms __sym_perms_;
283 perms __non_sym_perms_;
284 file_type __type_;
285 _CacheType __cache_type_;
287 _LIBCPP_INLINE_VISIBILITY
288 __cached_data() noexcept { __reset(); }
290 _LIBCPP_INLINE_VISIBILITY
291 void __reset() {
292 __cache_type_ = _Empty;
293 __type_ = file_type::none;
294 __sym_perms_ = __non_sym_perms_ = perms::unknown;
295 __size_ = __nlink_ = uintmax_t(-1);
296 __write_time_ = file_time_type::min();
300 _LIBCPP_INLINE_VISIBILITY
301 static __cached_data __create_iter_result(file_type __ft) {
302 __cached_data __data;
303 __data.__type_ = __ft;
304 __data.__cache_type_ = [&]() {
305 switch (__ft) {
306 case file_type::none:
307 return _Empty;
308 case file_type::symlink:
309 return _IterSymlink;
310 default:
311 return _IterNonSymlink;
313 }();
314 return __data;
317 _LIBCPP_INLINE_VISIBILITY
318 void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
319 __p_ = _VSTD::move(__p);
320 __data_ = __dt;
323 _LIBCPP_EXPORTED_FROM_ABI error_code __do_refresh() noexcept;
325 _LIBCPP_INLINE_VISIBILITY
326 static bool __is_dne_error(error_code const& __ec) {
327 if (!__ec)
328 return true;
329 switch (static_cast<errc>(__ec.value())) {
330 case errc::no_such_file_or_directory:
331 case errc::not_a_directory:
332 return true;
333 default:
334 return false;
338 _LIBCPP_INLINE_VISIBILITY
339 void __handle_error(const char* __msg, error_code* __dest_ec,
340 error_code const& __ec, bool __allow_dne = false) const {
341 if (__dest_ec) {
342 *__dest_ec = __ec;
343 return;
345 if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
346 __throw_filesystem_error(__msg, __p_, __ec);
349 _LIBCPP_INLINE_VISIBILITY
350 void __refresh(error_code* __ec = nullptr) {
351 __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
352 /*allow_dne*/ true);
355 _LIBCPP_INLINE_VISIBILITY
356 file_type __get_sym_ft(error_code* __ec = nullptr) const {
357 switch (__data_.__cache_type_) {
358 case _Empty:
359 return __symlink_status(__p_, __ec).type();
360 case _IterSymlink:
361 case _RefreshSymlink:
362 case _RefreshSymlinkUnresolved:
363 if (__ec)
364 __ec->clear();
365 return file_type::symlink;
366 case _IterNonSymlink:
367 case _RefreshNonSymlink:
368 file_status __st(__data_.__type_);
369 if (__ec && !_VSTD_FS::exists(__st))
370 *__ec = make_error_code(errc::no_such_file_or_directory);
371 else if (__ec)
372 __ec->clear();
373 return __data_.__type_;
375 __libcpp_unreachable();
378 _LIBCPP_INLINE_VISIBILITY
379 file_type __get_ft(error_code* __ec = nullptr) const {
380 switch (__data_.__cache_type_) {
381 case _Empty:
382 case _IterSymlink:
383 case _RefreshSymlinkUnresolved:
384 return __status(__p_, __ec).type();
385 case _IterNonSymlink:
386 case _RefreshNonSymlink:
387 case _RefreshSymlink: {
388 file_status __st(__data_.__type_);
389 if (__ec && !_VSTD_FS::exists(__st))
390 *__ec = make_error_code(errc::no_such_file_or_directory);
391 else if (__ec)
392 __ec->clear();
393 return __data_.__type_;
396 __libcpp_unreachable();
399 _LIBCPP_INLINE_VISIBILITY
400 file_status __get_status(error_code* __ec = nullptr) const {
401 switch (__data_.__cache_type_) {
402 case _Empty:
403 case _IterNonSymlink:
404 case _IterSymlink:
405 case _RefreshSymlinkUnresolved:
406 return __status(__p_, __ec);
407 case _RefreshNonSymlink:
408 case _RefreshSymlink:
409 return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
411 __libcpp_unreachable();
414 _LIBCPP_INLINE_VISIBILITY
415 file_status __get_symlink_status(error_code* __ec = nullptr) const {
416 switch (__data_.__cache_type_) {
417 case _Empty:
418 case _IterNonSymlink:
419 case _IterSymlink:
420 return __symlink_status(__p_, __ec);
421 case _RefreshNonSymlink:
422 return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
423 case _RefreshSymlink:
424 case _RefreshSymlinkUnresolved:
425 return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
427 __libcpp_unreachable();
430 _LIBCPP_INLINE_VISIBILITY
431 uintmax_t __get_size(error_code* __ec = nullptr) const {
432 switch (__data_.__cache_type_) {
433 case _Empty:
434 case _IterNonSymlink:
435 case _IterSymlink:
436 case _RefreshSymlinkUnresolved:
437 return _VSTD_FS::__file_size(__p_, __ec);
438 case _RefreshSymlink:
439 case _RefreshNonSymlink: {
440 error_code __m_ec;
441 file_status __st(__get_ft(&__m_ec));
442 __handle_error("in directory_entry::file_size", __ec, __m_ec);
443 if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
444 errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
445 : errc::not_supported;
446 __handle_error("in directory_entry::file_size", __ec,
447 make_error_code(__err_kind));
449 return __data_.__size_;
452 __libcpp_unreachable();
455 _LIBCPP_INLINE_VISIBILITY
456 uintmax_t __get_nlink(error_code* __ec = nullptr) const {
457 switch (__data_.__cache_type_) {
458 case _Empty:
459 case _IterNonSymlink:
460 case _IterSymlink:
461 case _RefreshSymlinkUnresolved:
462 return _VSTD_FS::__hard_link_count(__p_, __ec);
463 case _RefreshSymlink:
464 case _RefreshNonSymlink: {
465 error_code __m_ec;
466 (void)__get_ft(&__m_ec);
467 __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
468 return __data_.__nlink_;
471 __libcpp_unreachable();
474 _LIBCPP_INLINE_VISIBILITY
475 file_time_type __get_write_time(error_code* __ec = nullptr) const {
476 switch (__data_.__cache_type_) {
477 case _Empty:
478 case _IterNonSymlink:
479 case _IterSymlink:
480 case _RefreshSymlinkUnresolved:
481 return _VSTD_FS::__last_write_time(__p_, __ec);
482 case _RefreshSymlink:
483 case _RefreshNonSymlink: {
484 error_code __m_ec;
485 file_status __st(__get_ft(&__m_ec));
486 __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
487 if (_VSTD_FS::exists(__st) &&
488 __data_.__write_time_ == file_time_type::min())
489 __handle_error("in directory_entry::last_write_time", __ec,
490 make_error_code(errc::value_too_large));
491 return __data_.__write_time_;
494 __libcpp_unreachable();
497 private:
498 _Path __p_;
499 __cached_data __data_;
502 class __dir_element_proxy {
503 public:
504 inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
505 return _VSTD::move(__elem_);
508 private:
509 friend class directory_iterator;
510 friend class recursive_directory_iterator;
511 _LIBCPP_HIDE_FROM_ABI explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
512 _LIBCPP_HIDE_FROM_ABI __dir_element_proxy(__dir_element_proxy&& __o)
513 : __elem_(_VSTD::move(__o.__elem_)) {}
514 directory_entry __elem_;
517 _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP
519 _LIBCPP_END_NAMESPACE_FILESYSTEM
521 #endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM)
523 _LIBCPP_POP_MACROS
525 #endif // _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H