1//
2// RecursiveDirectoryIterator.h
3//
4// Library: Foundation
5// Package: Filesystem
6// Module: RecursiveDirectoryIterator
7//
8// Definition of the RecursiveDirectoryIterator class.
9//
10// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_RecursiveDirectoryIterator_INCLUDED
18#define Foundation_RecursiveDirectoryIterator_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/File.h"
23#include "Poco/Path.h"
24#include "Poco/RecursiveDirectoryIteratorImpl.h"
25#include "Poco/DirectoryIteratorStrategy.h"
26
27
28namespace Poco {
29
30
31class DirectoryIterator;
32
33
34template<class TTravStr>
35class RecursiveDirectoryIteratorImpl;
36
37
38template<class TTravStr = ChildrenFirstTraverse>
39class RecursiveDirectoryIterator
40 /// The RecursiveDirectoryIterator class is used to enumerate
41 /// all files in a directory and its subdirectories.
42 ///
43 /// RecursiveDirectoryIterator has some limitations:
44 /// * only forward iteration (++) is supported
45 /// * an iterator copied from another one will always
46 /// point to the same file as the original iterator,
47 /// even is the original iterator has been advanced
48 /// (all copies of an iterator share their state with
49 /// the original iterator)
50 ///
51 /// The class can follow different traversal strategies:
52 /// * depth-first strategy;
53 /// * siblings-first strategy.
54 /// The strategies are set by template parameter.
55 /// There are two corresponding typedefs:
56 /// * SimpleRecursiveDirectoryIterator;
57 /// * SiblingsFirstRecursiveDirectoryIterator.
58 ///
59 /// The depth of traversal can be limited by constructor
60 /// parameter maxDepth (which sets the infinite depth by default).
61{
62public:
63 typedef RecursiveDirectoryIterator<TTravStr> MyType;
64
65 enum
66 {
67 D_INFINITE = 0 /// Constant for infinite traverse depth.
68 };
69
70 RecursiveDirectoryIterator()
71 /// Creates the end iterator.
72 : _pImpl(0)
73 {
74 }
75
76 RecursiveDirectoryIterator(const std::string& path, UInt16 maxDepth = D_INFINITE)
77 /// Creates a recursive directory iterator for the given path.
78 : _pImpl(new ImplType(path, maxDepth)), _path(Path(_pImpl->get())), _file(_path)
79 {
80 }
81
82 RecursiveDirectoryIterator(const MyType& iterator):
83 /// Creates a copy of another recursive directory iterator.
84 _pImpl(iterator._pImpl), _path(iterator._path), _file(iterator._file)
85 {
86 }
87
88 RecursiveDirectoryIterator(const DirectoryIterator& iterator, UInt16 maxDepth = D_INFINITE):
89 /// Creates a recursive directory iterator for the path of
90 /// non-recursive directory iterator.
91 _pImpl(new ImplType(iterator->path(), maxDepth)), _path(Path(_pImpl->get())), _file(_path)
92 {
93 }
94
95 RecursiveDirectoryIterator(const File& file, UInt16 maxDepth = D_INFINITE):
96 /// Creates a recursive directory iterator for the given path.
97 _pImpl(new ImplType(file.path(), maxDepth)), _path(Path(_pImpl->get())), _file(_path)
98 {
99 }
100
101 RecursiveDirectoryIterator(const Path& path, UInt16 maxDepth = D_INFINITE):
102 /// Creates a recursive directory iterator for the given path.
103 _pImpl(new ImplType(path.toString(), maxDepth)), _path(Path(_pImpl->get())), _file(_path)
104 {
105 }
106
107 ~RecursiveDirectoryIterator()
108 /// Destroys the DirectoryIterator.
109 {
110 if (_pImpl)
111 _pImpl->release();
112 }
113
114 const std::string& name() const
115 /// Returns the current filename.
116 {
117 return _path.getFileName();
118 }
119
120 const Poco::Path& path() const
121 /// Returns the current path.
122 {
123 return _path;
124 }
125
126 UInt16 depth() const
127 /// Depth of recursion (counting from 1).
128 {
129 return _pImpl->depth();
130 }
131
132 UInt16 maxDepth() const
133 /// Max depth of recursion (counting from 1).
134 {
135 return _pImpl->maxDepth();
136 }
137
138 template <typename T>
139 void onError(T& obj, void (T::*pCB)(const void*, const std::string&))
140 /// Binds the event to the given method.
141 ///
142 /// The callback method will be called if the Traverse class fails
143 /// to read a directory.
144 ///
145 /// Usage:
146 /// onError(*this, &MyClass::myCallback);
147 {
148 _pImpl->template onError<T>(obj, pCB);
149 }
150
151 MyType& operator = (const MyType& it)
152 {
153 if (_pImpl)
154 _pImpl->release();
155 _pImpl = it._pImpl;
156 if (_pImpl)
157 {
158 _pImpl->duplicate();
159 _path = it._path;
160 _file = _path;
161 }
162 return *this;
163 }
164
165 MyType& operator = (const File& file)
166 {
167 if (_pImpl)
168 _pImpl->release();
169 _pImpl = new ImplType(file.path());
170 _path = Path(_pImpl->get());
171 _file = _path;
172 return *this;
173 }
174
175
176 MyType& operator = (const Path& path)
177 {
178 if (_pImpl)
179 _pImpl->release();
180 _pImpl = new ImplType(path.toString());
181 _path = Path(_pImpl->get());
182 _file = _path;
183 return *this;
184 }
185
186 MyType& operator = (const std::string& path)
187 {
188 if (_pImpl)
189 _pImpl->release();
190 _pImpl = new ImplType(path);
191 _path = Path(_pImpl->get());
192 _file = _path;
193 return *this;
194 }
195
196 MyType& operator ++ ()
197 {
198 if (_pImpl)
199 {
200 _path = Path(_pImpl->next());
201 _file = _path;
202 }
203 return *this;
204 }
205
206 const File& operator * () const
207 {
208 return _file;
209 }
210
211 File& operator *()
212 {
213 return _file;
214 }
215
216 const File* operator -> () const
217 {
218 return &_file;
219 }
220
221 File* operator -> ()
222 {
223 return &_file;
224 }
225
226 template<class T1, class T2>
227 friend inline bool operator ==(const RecursiveDirectoryIterator<T1>& a, const RecursiveDirectoryIterator<T2>& b);
228 template<class T1, class T2>
229 friend inline bool operator !=(const RecursiveDirectoryIterator<T1>& a, const RecursiveDirectoryIterator<T2>& b);
230
231private:
232 typedef RecursiveDirectoryIteratorImpl<TTravStr> ImplType;
233
234 ImplType* _pImpl;
235 Path _path;
236 File _file;
237};
238
239
240//
241// friend comparsion operators
242//
243template<class T1, class T2>
244inline bool operator ==(const RecursiveDirectoryIterator<T1>& a, const RecursiveDirectoryIterator<T2>& b)
245{
246 return a.path().toString() == b.path().toString();;
247}
248
249template<class T1, class T2>
250inline bool operator !=(const RecursiveDirectoryIterator<T1>& a, const RecursiveDirectoryIterator<T2>& b)
251{
252 return a.path().toString() != b.path().toString();;
253}
254
255
256//
257// typedefs
258//
259typedef RecursiveDirectoryIterator<ChildrenFirstTraverse> SimpleRecursiveDirectoryIterator;
260typedef RecursiveDirectoryIterator<SiblingsFirstTraverse> SiblingsFirstRecursiveDirectoryIterator;
261
262
263} // namespace Poco
264
265
266#endif // Foundation_RecursiveDirectoryIterator_INCLUDED
267