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