xref: /freebsd/contrib/kyua/utils/fs/directory.cpp (revision b0d29bc4)
1*b0d29bc4SBrooks Davis // Copyright 2015 The Kyua Authors.
2*b0d29bc4SBrooks Davis // All rights reserved.
3*b0d29bc4SBrooks Davis //
4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without
5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are
6*b0d29bc4SBrooks Davis // met:
7*b0d29bc4SBrooks Davis //
8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright
9*b0d29bc4SBrooks Davis //   notice, this list of conditions and the following disclaimer.
10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
11*b0d29bc4SBrooks Davis //   notice, this list of conditions and the following disclaimer in the
12*b0d29bc4SBrooks Davis //   documentation and/or other materials provided with the distribution.
13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
14*b0d29bc4SBrooks Davis //   may be used to endorse or promote products derived from this software
15*b0d29bc4SBrooks Davis //   without specific prior written permission.
16*b0d29bc4SBrooks Davis //
17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*b0d29bc4SBrooks Davis 
29*b0d29bc4SBrooks Davis #include "utils/fs/directory.hpp"
30*b0d29bc4SBrooks Davis 
31*b0d29bc4SBrooks Davis extern "C" {
32*b0d29bc4SBrooks Davis #include <sys/types.h>
33*b0d29bc4SBrooks Davis 
34*b0d29bc4SBrooks Davis #include <dirent.h>
35*b0d29bc4SBrooks Davis }
36*b0d29bc4SBrooks Davis 
37*b0d29bc4SBrooks Davis #include <cerrno>
38*b0d29bc4SBrooks Davis #include <memory>
39*b0d29bc4SBrooks Davis 
40*b0d29bc4SBrooks Davis #include "utils/format/macros.hpp"
41*b0d29bc4SBrooks Davis #include "utils/fs/exceptions.hpp"
42*b0d29bc4SBrooks Davis #include "utils/fs/path.hpp"
43*b0d29bc4SBrooks Davis #include "utils/noncopyable.hpp"
44*b0d29bc4SBrooks Davis #include "utils/sanity.hpp"
45*b0d29bc4SBrooks Davis #include "utils/text/operations.ipp"
46*b0d29bc4SBrooks Davis 
47*b0d29bc4SBrooks Davis namespace detail = utils::fs::detail;
48*b0d29bc4SBrooks Davis namespace fs = utils::fs;
49*b0d29bc4SBrooks Davis namespace text = utils::text;
50*b0d29bc4SBrooks Davis 
51*b0d29bc4SBrooks Davis 
52*b0d29bc4SBrooks Davis /// Constructs a new directory entry.
53*b0d29bc4SBrooks Davis ///
54*b0d29bc4SBrooks Davis /// \param name_ Name of the directory entry.
directory_entry(const std::string & name_)55*b0d29bc4SBrooks Davis fs::directory_entry::directory_entry(const std::string& name_) : name(name_)
56*b0d29bc4SBrooks Davis {
57*b0d29bc4SBrooks Davis }
58*b0d29bc4SBrooks Davis 
59*b0d29bc4SBrooks Davis 
60*b0d29bc4SBrooks Davis /// Checks if two directory entries are equal.
61*b0d29bc4SBrooks Davis ///
62*b0d29bc4SBrooks Davis /// \param other The entry to compare to.
63*b0d29bc4SBrooks Davis ///
64*b0d29bc4SBrooks Davis /// \return True if the two entries are equal; false otherwise.
65*b0d29bc4SBrooks Davis bool
operator ==(const directory_entry & other) const66*b0d29bc4SBrooks Davis fs::directory_entry::operator==(const directory_entry& other) const
67*b0d29bc4SBrooks Davis {
68*b0d29bc4SBrooks Davis     return name == other.name;
69*b0d29bc4SBrooks Davis }
70*b0d29bc4SBrooks Davis 
71*b0d29bc4SBrooks Davis 
72*b0d29bc4SBrooks Davis /// Checks if two directory entries are different.
73*b0d29bc4SBrooks Davis ///
74*b0d29bc4SBrooks Davis /// \param other The entry to compare to.
75*b0d29bc4SBrooks Davis ///
76*b0d29bc4SBrooks Davis /// \return True if the two entries are different; false otherwise.
77*b0d29bc4SBrooks Davis bool
operator !=(const directory_entry & other) const78*b0d29bc4SBrooks Davis fs::directory_entry::operator!=(const directory_entry& other) const
79*b0d29bc4SBrooks Davis {
80*b0d29bc4SBrooks Davis     return !(*this == other);
81*b0d29bc4SBrooks Davis }
82*b0d29bc4SBrooks Davis 
83*b0d29bc4SBrooks Davis 
84*b0d29bc4SBrooks Davis /// Checks if this entry sorts before another entry.
85*b0d29bc4SBrooks Davis ///
86*b0d29bc4SBrooks Davis /// \param other The entry to compare to.
87*b0d29bc4SBrooks Davis ///
88*b0d29bc4SBrooks Davis /// \return True if this entry sorts before the other entry; false otherwise.
89*b0d29bc4SBrooks Davis bool
operator <(const directory_entry & other) const90*b0d29bc4SBrooks Davis fs::directory_entry::operator<(const directory_entry& other) const
91*b0d29bc4SBrooks Davis {
92*b0d29bc4SBrooks Davis     return name < other.name;
93*b0d29bc4SBrooks Davis }
94*b0d29bc4SBrooks Davis 
95*b0d29bc4SBrooks Davis 
96*b0d29bc4SBrooks Davis /// Formats a directory entry.
97*b0d29bc4SBrooks Davis ///
98*b0d29bc4SBrooks Davis /// \param output Stream into which to inject the formatted entry.
99*b0d29bc4SBrooks Davis /// \param entry The entry to format.
100*b0d29bc4SBrooks Davis ///
101*b0d29bc4SBrooks Davis /// \return A reference to output.
102*b0d29bc4SBrooks Davis std::ostream&
operator <<(std::ostream & output,const directory_entry & entry)103*b0d29bc4SBrooks Davis fs::operator<<(std::ostream& output, const directory_entry& entry)
104*b0d29bc4SBrooks Davis {
105*b0d29bc4SBrooks Davis     output << F("directory_entry{name=%s}") % text::quote(entry.name, '\'');
106*b0d29bc4SBrooks Davis     return output;
107*b0d29bc4SBrooks Davis }
108*b0d29bc4SBrooks Davis 
109*b0d29bc4SBrooks Davis 
110*b0d29bc4SBrooks Davis /// Internal implementation details for the directory_iterator.
111*b0d29bc4SBrooks Davis ///
112*b0d29bc4SBrooks Davis /// In order to support multiple concurrent iterators over the same directory
113*b0d29bc4SBrooks Davis /// object, this class is the one that performs all directory-level accesses.
114*b0d29bc4SBrooks Davis /// In particular, even if it may seem surprising, this is the class that
115*b0d29bc4SBrooks Davis /// handles the DIR object for the directory.
116*b0d29bc4SBrooks Davis ///
117*b0d29bc4SBrooks Davis /// Note that iterators implemented by this class do not rely on the container
118*b0d29bc4SBrooks Davis /// directory class at all.  This should not be relied on for object lifecycle
119*b0d29bc4SBrooks Davis /// purposes.
120*b0d29bc4SBrooks Davis struct utils::fs::detail::directory_iterator::impl : utils::noncopyable {
121*b0d29bc4SBrooks Davis     /// Path of the directory accessed by this iterator.
122*b0d29bc4SBrooks Davis     const fs::path _path;
123*b0d29bc4SBrooks Davis 
124*b0d29bc4SBrooks Davis     /// Raw pointer to the system representation of the directory.
125*b0d29bc4SBrooks Davis     ///
126*b0d29bc4SBrooks Davis     /// We also use this to determine if the iterator is valid (at the end) or
127*b0d29bc4SBrooks Davis     /// not.  A null pointer means an invalid iterator.
128*b0d29bc4SBrooks Davis     ::DIR* _dirp;
129*b0d29bc4SBrooks Davis 
130*b0d29bc4SBrooks Davis     /// Raw representation of the system directory entry.
131*b0d29bc4SBrooks Davis     ///
132*b0d29bc4SBrooks Davis     /// We need to keep this at the class level so that we can use the
133*b0d29bc4SBrooks Davis     /// readdir_r(3) function.
134*b0d29bc4SBrooks Davis     ::dirent _dirent;
135*b0d29bc4SBrooks Davis 
136*b0d29bc4SBrooks Davis     /// Custom representation of the directory entry.
137*b0d29bc4SBrooks Davis     ///
138*b0d29bc4SBrooks Davis     /// This is separate from _dirent because this is the type we return to the
139*b0d29bc4SBrooks Davis     /// user.  We must keep this as a pointer so that we can support the common
140*b0d29bc4SBrooks Davis     /// operators (* and ->) over iterators.
141*b0d29bc4SBrooks Davis     std::auto_ptr< directory_entry > _entry;
142*b0d29bc4SBrooks Davis 
143*b0d29bc4SBrooks Davis     /// Constructs an iterator pointing to the "end" of the directory.
implutils::fs::detail::directory_iterator::impl144*b0d29bc4SBrooks Davis     impl(void) : _path("invalid-directory-entry"), _dirp(NULL)
145*b0d29bc4SBrooks Davis     {
146*b0d29bc4SBrooks Davis     }
147*b0d29bc4SBrooks Davis 
148*b0d29bc4SBrooks Davis     /// Constructs a new iterator to start scanning a directory.
149*b0d29bc4SBrooks Davis     ///
150*b0d29bc4SBrooks Davis     /// \param path The directory that will be scanned.
151*b0d29bc4SBrooks Davis     ///
152*b0d29bc4SBrooks Davis     /// \throw system_error If there is a problem opening the directory.
implutils::fs::detail::directory_iterator::impl153*b0d29bc4SBrooks Davis     explicit impl(const path& path) : _path(path)
154*b0d29bc4SBrooks Davis     {
155*b0d29bc4SBrooks Davis         DIR* dirp = ::opendir(_path.c_str());
156*b0d29bc4SBrooks Davis         if (dirp == NULL) {
157*b0d29bc4SBrooks Davis             const int original_errno = errno;
158*b0d29bc4SBrooks Davis             throw fs::system_error(F("opendir(%s) failed") % _path,
159*b0d29bc4SBrooks Davis                                    original_errno);
160*b0d29bc4SBrooks Davis         }
161*b0d29bc4SBrooks Davis         _dirp = dirp;
162*b0d29bc4SBrooks Davis 
163*b0d29bc4SBrooks Davis         // Initialize our first directory entry.  Note that this may actually
164*b0d29bc4SBrooks Davis         // close the directory we just opened if the directory happens to be
165*b0d29bc4SBrooks Davis         // empty -- but directories are never empty because they at least have
166*b0d29bc4SBrooks Davis         // '.' and '..' entries.
167*b0d29bc4SBrooks Davis         next();
168*b0d29bc4SBrooks Davis     }
169*b0d29bc4SBrooks Davis 
170*b0d29bc4SBrooks Davis     /// Destructor.
171*b0d29bc4SBrooks Davis     ///
172*b0d29bc4SBrooks Davis     /// This closes the directory if still open.
~implutils::fs::detail::directory_iterator::impl173*b0d29bc4SBrooks Davis     ~impl(void)
174*b0d29bc4SBrooks Davis     {
175*b0d29bc4SBrooks Davis         if (_dirp != NULL)
176*b0d29bc4SBrooks Davis             close();
177*b0d29bc4SBrooks Davis     }
178*b0d29bc4SBrooks Davis 
179*b0d29bc4SBrooks Davis     /// Closes the directory and invalidates the iterator.
180*b0d29bc4SBrooks Davis     void
closeutils::fs::detail::directory_iterator::impl181*b0d29bc4SBrooks Davis     close(void)
182*b0d29bc4SBrooks Davis     {
183*b0d29bc4SBrooks Davis         PRE(_dirp != NULL);
184*b0d29bc4SBrooks Davis         if (::closedir(_dirp) == -1) {
185*b0d29bc4SBrooks Davis             UNREACHABLE_MSG("Invalid dirp provided to closedir(3)");
186*b0d29bc4SBrooks Davis         }
187*b0d29bc4SBrooks Davis         _dirp = NULL;
188*b0d29bc4SBrooks Davis     }
189*b0d29bc4SBrooks Davis 
190*b0d29bc4SBrooks Davis     /// Advances the directory entry to the next one.
191*b0d29bc4SBrooks Davis     ///
192*b0d29bc4SBrooks Davis     /// It is possible to use this function on a new directory_entry object to
193*b0d29bc4SBrooks Davis     /// initialize the first entry.
194*b0d29bc4SBrooks Davis     ///
195*b0d29bc4SBrooks Davis     /// \throw system_error If the call to readdir_r fails.
196*b0d29bc4SBrooks Davis     void
nextutils::fs::detail::directory_iterator::impl197*b0d29bc4SBrooks Davis     next(void)
198*b0d29bc4SBrooks Davis     {
199*b0d29bc4SBrooks Davis         ::dirent* result;
200*b0d29bc4SBrooks Davis 
201*b0d29bc4SBrooks Davis         if (::readdir_r(_dirp, &_dirent, &result) == -1) {
202*b0d29bc4SBrooks Davis             const int original_errno = errno;
203*b0d29bc4SBrooks Davis             throw fs::system_error(F("readdir_r(%s) failed") % _path,
204*b0d29bc4SBrooks Davis                                    original_errno);
205*b0d29bc4SBrooks Davis         }
206*b0d29bc4SBrooks Davis         if (result == NULL) {
207*b0d29bc4SBrooks Davis             _entry.reset(NULL);
208*b0d29bc4SBrooks Davis             close();
209*b0d29bc4SBrooks Davis         } else {
210*b0d29bc4SBrooks Davis             _entry.reset(new directory_entry(_dirent.d_name));
211*b0d29bc4SBrooks Davis         }
212*b0d29bc4SBrooks Davis     }
213*b0d29bc4SBrooks Davis };
214*b0d29bc4SBrooks Davis 
215*b0d29bc4SBrooks Davis 
216*b0d29bc4SBrooks Davis /// Constructs a new directory iterator.
217*b0d29bc4SBrooks Davis ///
218*b0d29bc4SBrooks Davis /// \param pimpl The constructed internal implementation structure to use.
directory_iterator(std::shared_ptr<impl> pimpl)219*b0d29bc4SBrooks Davis detail::directory_iterator::directory_iterator(std::shared_ptr< impl > pimpl) :
220*b0d29bc4SBrooks Davis     _pimpl(pimpl)
221*b0d29bc4SBrooks Davis {
222*b0d29bc4SBrooks Davis }
223*b0d29bc4SBrooks Davis 
224*b0d29bc4SBrooks Davis 
225*b0d29bc4SBrooks Davis /// Destructor.
~directory_iterator(void)226*b0d29bc4SBrooks Davis detail::directory_iterator::~directory_iterator(void)
227*b0d29bc4SBrooks Davis {
228*b0d29bc4SBrooks Davis }
229*b0d29bc4SBrooks Davis 
230*b0d29bc4SBrooks Davis 
231*b0d29bc4SBrooks Davis /// Creates a new directory iterator for a directory.
232*b0d29bc4SBrooks Davis ///
233*b0d29bc4SBrooks Davis /// \return The directory iterator.  Note that the result may be invalid.
234*b0d29bc4SBrooks Davis ///
235*b0d29bc4SBrooks Davis /// \throw system_error If opening the directory or reading its first entry
236*b0d29bc4SBrooks Davis ///     fails.
237*b0d29bc4SBrooks Davis detail::directory_iterator
new_begin(const path & path)238*b0d29bc4SBrooks Davis detail::directory_iterator::new_begin(const path& path)
239*b0d29bc4SBrooks Davis {
240*b0d29bc4SBrooks Davis     return directory_iterator(std::shared_ptr< impl >(new impl(path)));
241*b0d29bc4SBrooks Davis }
242*b0d29bc4SBrooks Davis 
243*b0d29bc4SBrooks Davis 
244*b0d29bc4SBrooks Davis /// Creates a new invalid directory iterator.
245*b0d29bc4SBrooks Davis ///
246*b0d29bc4SBrooks Davis /// \return The invalid directory iterator.
247*b0d29bc4SBrooks Davis detail::directory_iterator
new_end(void)248*b0d29bc4SBrooks Davis detail::directory_iterator::new_end(void)
249*b0d29bc4SBrooks Davis {
250*b0d29bc4SBrooks Davis     return directory_iterator(std::shared_ptr< impl >(new impl()));
251*b0d29bc4SBrooks Davis }
252*b0d29bc4SBrooks Davis 
253*b0d29bc4SBrooks Davis 
254*b0d29bc4SBrooks Davis /// Checks if two iterators are equal.
255*b0d29bc4SBrooks Davis ///
256*b0d29bc4SBrooks Davis /// We consider two iterators to be equal if both of them are invalid or,
257*b0d29bc4SBrooks Davis /// otherwise, if they have the exact same internal representation (as given by
258*b0d29bc4SBrooks Davis /// equality of the pimpl pointers).
259*b0d29bc4SBrooks Davis ///
260*b0d29bc4SBrooks Davis /// \param other The object to compare to.
261*b0d29bc4SBrooks Davis ///
262*b0d29bc4SBrooks Davis /// \return True if the two iterators are equal; false otherwise.
263*b0d29bc4SBrooks Davis bool
operator ==(const directory_iterator & other) const264*b0d29bc4SBrooks Davis detail::directory_iterator::operator==(const directory_iterator& other) const
265*b0d29bc4SBrooks Davis {
266*b0d29bc4SBrooks Davis     return (_pimpl->_dirp == NULL && other._pimpl->_dirp == NULL) ||
267*b0d29bc4SBrooks Davis         _pimpl == other._pimpl;
268*b0d29bc4SBrooks Davis }
269*b0d29bc4SBrooks Davis 
270*b0d29bc4SBrooks Davis 
271*b0d29bc4SBrooks Davis /// Checks if two iterators are different.
272*b0d29bc4SBrooks Davis ///
273*b0d29bc4SBrooks Davis /// \param other The object to compare to.
274*b0d29bc4SBrooks Davis ///
275*b0d29bc4SBrooks Davis /// \return True if the two iterators are different; false otherwise.
276*b0d29bc4SBrooks Davis bool
operator !=(const directory_iterator & other) const277*b0d29bc4SBrooks Davis detail::directory_iterator::operator!=(const directory_iterator& other) const
278*b0d29bc4SBrooks Davis {
279*b0d29bc4SBrooks Davis     return !(*this == other);
280*b0d29bc4SBrooks Davis }
281*b0d29bc4SBrooks Davis 
282*b0d29bc4SBrooks Davis 
283*b0d29bc4SBrooks Davis /// Moves the iterator one element forward.
284*b0d29bc4SBrooks Davis ///
285*b0d29bc4SBrooks Davis /// \return A reference to the iterator.
286*b0d29bc4SBrooks Davis ///
287*b0d29bc4SBrooks Davis /// \throw system_error If advancing the iterator fails.
288*b0d29bc4SBrooks Davis detail::directory_iterator&
operator ++(void)289*b0d29bc4SBrooks Davis detail::directory_iterator::operator++(void)
290*b0d29bc4SBrooks Davis {
291*b0d29bc4SBrooks Davis     _pimpl->next();
292*b0d29bc4SBrooks Davis     return *this;
293*b0d29bc4SBrooks Davis }
294*b0d29bc4SBrooks Davis 
295*b0d29bc4SBrooks Davis 
296*b0d29bc4SBrooks Davis /// Dereferences the iterator to its contents.
297*b0d29bc4SBrooks Davis ///
298*b0d29bc4SBrooks Davis /// \return A reference to the directory entry pointed to by the iterator.
299*b0d29bc4SBrooks Davis const fs::directory_entry&
operator *(void) const300*b0d29bc4SBrooks Davis detail::directory_iterator::operator*(void) const
301*b0d29bc4SBrooks Davis {
302*b0d29bc4SBrooks Davis     PRE(_pimpl->_entry.get() != NULL);
303*b0d29bc4SBrooks Davis     return *_pimpl->_entry;
304*b0d29bc4SBrooks Davis }
305*b0d29bc4SBrooks Davis 
306*b0d29bc4SBrooks Davis 
307*b0d29bc4SBrooks Davis /// Dereferences the iterator to its contents.
308*b0d29bc4SBrooks Davis ///
309*b0d29bc4SBrooks Davis /// \return A pointer to the directory entry pointed to by the iterator.
310*b0d29bc4SBrooks Davis const fs::directory_entry*
operator ->(void) const311*b0d29bc4SBrooks Davis detail::directory_iterator::operator->(void) const
312*b0d29bc4SBrooks Davis {
313*b0d29bc4SBrooks Davis     PRE(_pimpl->_entry.get() != NULL);
314*b0d29bc4SBrooks Davis     return _pimpl->_entry.get();
315*b0d29bc4SBrooks Davis }
316*b0d29bc4SBrooks Davis 
317*b0d29bc4SBrooks Davis 
318*b0d29bc4SBrooks Davis /// Internal implementation details for the directory.
319*b0d29bc4SBrooks Davis struct utils::fs::directory::impl : utils::noncopyable {
320*b0d29bc4SBrooks Davis     /// Path to the directory to scan.
321*b0d29bc4SBrooks Davis     fs::path _path;
322*b0d29bc4SBrooks Davis 
323*b0d29bc4SBrooks Davis     /// Constructs a new directory.
324*b0d29bc4SBrooks Davis     ///
325*b0d29bc4SBrooks Davis     /// \param path_ Path to the directory to scan.
implutils::fs::directory::impl326*b0d29bc4SBrooks Davis     impl(const fs::path& path_) : _path(path_)
327*b0d29bc4SBrooks Davis     {
328*b0d29bc4SBrooks Davis     }
329*b0d29bc4SBrooks Davis };
330*b0d29bc4SBrooks Davis 
331*b0d29bc4SBrooks Davis 
332*b0d29bc4SBrooks Davis /// Constructs a new directory.
333*b0d29bc4SBrooks Davis ///
334*b0d29bc4SBrooks Davis /// \param path_ Path to the directory to scan.
directory(const path & path_)335*b0d29bc4SBrooks Davis fs::directory::directory(const path& path_) : _pimpl(new impl(path_))
336*b0d29bc4SBrooks Davis {
337*b0d29bc4SBrooks Davis }
338*b0d29bc4SBrooks Davis 
339*b0d29bc4SBrooks Davis 
340*b0d29bc4SBrooks Davis /// Returns an iterator to start scanning the directory.
341*b0d29bc4SBrooks Davis ///
342*b0d29bc4SBrooks Davis /// \return An iterator on the directory.
343*b0d29bc4SBrooks Davis ///
344*b0d29bc4SBrooks Davis /// \throw system_error If the directory cannot be opened to obtain its first
345*b0d29bc4SBrooks Davis ///     entry.
346*b0d29bc4SBrooks Davis fs::directory::const_iterator
begin(void) const347*b0d29bc4SBrooks Davis fs::directory::begin(void) const
348*b0d29bc4SBrooks Davis {
349*b0d29bc4SBrooks Davis     return const_iterator::new_begin(_pimpl->_path);
350*b0d29bc4SBrooks Davis }
351*b0d29bc4SBrooks Davis 
352*b0d29bc4SBrooks Davis 
353*b0d29bc4SBrooks Davis /// Returns an invalid iterator to check for the end of an scan.
354*b0d29bc4SBrooks Davis ///
355*b0d29bc4SBrooks Davis /// \return An invalid iterator.
356*b0d29bc4SBrooks Davis fs::directory::const_iterator
end(void) const357*b0d29bc4SBrooks Davis fs::directory::end(void) const
358*b0d29bc4SBrooks Davis {
359*b0d29bc4SBrooks Davis     return const_iterator::new_end();
360*b0d29bc4SBrooks Davis }
361