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//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H
11#define _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H
12
13#include <__assert>
14#include <__availability>
15#include <__config>
16#include <__filesystem/directory_entry.h>
17#include <__filesystem/directory_options.h>
18#include <__filesystem/path.h>
19#include <__iterator/iterator_traits.h>
20#include <__memory/shared_ptr.h>
21#include <__ranges/enable_borrowed_range.h>
22#include <__ranges/enable_view.h>
23#include <cstddef>
24#include <system_error>
25
26#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27#  pragma GCC system_header
28#endif
29
30#ifndef _LIBCPP_CXX03_LANG
31
32_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
33
34_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
35
36class _LIBCPP_HIDDEN __dir_stream;
37class directory_iterator {
38public:
39  typedef directory_entry value_type;
40  typedef ptrdiff_t difference_type;
41  typedef value_type const* pointer;
42  typedef value_type const& reference;
43  typedef input_iterator_tag iterator_category;
44
45public:
46  //ctor & dtor
47  _LIBCPP_HIDE_FROM_ABI
48  directory_iterator() noexcept {}
49
50  _LIBCPP_HIDE_FROM_ABI
51  explicit directory_iterator(const path& __p)
52      : directory_iterator(__p, nullptr) {}
53
54  _LIBCPP_HIDE_FROM_ABI
55  directory_iterator(const path& __p, directory_options __opts)
56      : directory_iterator(__p, nullptr, __opts) {}
57
58  _LIBCPP_HIDE_FROM_ABI
59  directory_iterator(const path& __p, error_code& __ec)
60      : directory_iterator(__p, &__ec) {}
61
62  _LIBCPP_HIDE_FROM_ABI
63  directory_iterator(const path& __p, directory_options __opts,
64                     error_code& __ec)
65      : directory_iterator(__p, &__ec, __opts) {}
66
67  _LIBCPP_HIDE_FROM_ABI directory_iterator(const directory_iterator&) = default;
68  _LIBCPP_HIDE_FROM_ABI directory_iterator(directory_iterator&&) = default;
69  _LIBCPP_HIDE_FROM_ABI directory_iterator& operator=(const directory_iterator&) = default;
70
71  _LIBCPP_HIDE_FROM_ABI
72  directory_iterator& operator=(directory_iterator&& __o) noexcept {
73    // non-default implementation provided to support self-move assign.
74    if (this != &__o) {
75      __imp_ = _VSTD::move(__o.__imp_);
76    }
77    return *this;
78  }
79
80  _LIBCPP_HIDE_FROM_ABI ~directory_iterator() = default;
81
82  _LIBCPP_HIDE_FROM_ABI
83  const directory_entry& operator*() const {
84    _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
85    return __dereference();
86  }
87
88  _LIBCPP_HIDE_FROM_ABI
89  const directory_entry* operator->() const { return &**this; }
90
91  _LIBCPP_HIDE_FROM_ABI
92  directory_iterator& operator++() { return __increment(); }
93
94  _LIBCPP_HIDE_FROM_ABI
95  __dir_element_proxy operator++(int) {
96    __dir_element_proxy __p(**this);
97    __increment();
98    return __p;
99  }
100
101  _LIBCPP_HIDE_FROM_ABI
102  directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
103
104private:
105  inline _LIBCPP_HIDE_FROM_ABI friend bool
106  operator==(const directory_iterator& __lhs,
107             const directory_iterator& __rhs) noexcept;
108
109  // construct the dir_stream
110  _LIBCPP_FUNC_VIS
111  directory_iterator(const path&, error_code*,
112                     directory_options = directory_options::none);
113
114  _LIBCPP_FUNC_VIS
115  directory_iterator& __increment(error_code* __ec = nullptr);
116
117  _LIBCPP_FUNC_VIS
118  const directory_entry& __dereference() const;
119
120private:
121  shared_ptr<__dir_stream> __imp_;
122};
123
124inline _LIBCPP_HIDE_FROM_ABI bool
125operator==(const directory_iterator& __lhs,
126           const directory_iterator& __rhs) noexcept {
127  return __lhs.__imp_ == __rhs.__imp_;
128}
129
130inline _LIBCPP_HIDE_FROM_ABI bool
131operator!=(const directory_iterator& __lhs,
132           const directory_iterator& __rhs) noexcept {
133  return !(__lhs == __rhs);
134}
135
136// enable directory_iterator range-based for statements
137inline _LIBCPP_HIDE_FROM_ABI directory_iterator
138begin(directory_iterator __iter) noexcept {
139  return __iter;
140}
141
142inline _LIBCPP_HIDE_FROM_ABI directory_iterator
143end(directory_iterator) noexcept {
144  return directory_iterator();
145}
146
147_LIBCPP_AVAILABILITY_FILESYSTEM_POP
148
149_LIBCPP_END_NAMESPACE_FILESYSTEM
150
151#if _LIBCPP_STD_VER > 17
152
153template <>
154_LIBCPP_AVAILABILITY_FILESYSTEM
155inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::directory_iterator> = true;
156
157template <>
158_LIBCPP_AVAILABILITY_FILESYSTEM
159inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::directory_iterator> = true;
160
161#endif // _LIBCPP_STD_VER > 17
162
163#endif // _LIBCPP_CXX03_LANG
164
165#endif // _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H
166