18 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
20 #elif defined(_WIN32) || defined(_WIN64)
28 class DirectoryIterator::Impl
30 friend class SimpleImpl;
31 friend class RecursiveImpl;
34 explicit Impl(
const Path& parent) : _parent(parent), _current() {}
35 virtual ~Impl() =
default;
37 const Path& parent() const noexcept {
return _parent; }
38 const Path& current() const noexcept {
return _current; }
40 virtual Path Next() = 0;
47 class DirectoryIterator::SimpleImpl :
public DirectoryIterator::Impl
50 explicit SimpleImpl(
const Path& parent) :
DirectoryIterator::Impl(parent), _next(false), _end(false)
52 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
53 _directory = opendir(_parent.string().c_str());
54 if (_directory ==
nullptr)
55 throwex FileSystemException(
"Cannot open a directory!").Attach(_parent);
56 #elif defined(_WIN32) || defined(_WIN64)
57 _directory = FindFirstFileW((_parent /
"*").wstring().c_str(), &_entry);
58 if (_directory == INVALID_HANDLE_VALUE)
59 throwex FileSystemException(
"Cannot open a directory!").Attach(_parent);
65 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
66 if (_directory !=
nullptr)
68 int result = closedir(_directory);
70 fatality(FileSystemException(
"Cannot close the directory descriptor!").Attach(_parent));
72 #elif defined(_WIN32) || defined(_WIN64)
73 if (_directory != INVALID_HANDLE_VALUE)
75 if (!FindClose(_directory))
76 fatality(FileSystemException(
"Cannot close the directory handle!").Attach(_parent));
85 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
86 struct dirent* pentry;
87 while ((pentry = readdir(_directory)) !=
nullptr)
89 if (std::strncmp(pentry->d_name,
".",
sizeof(pentry->d_name)) == 0)
91 if (std::strncmp(pentry->d_name,
"..",
sizeof(pentry->d_name)) == 0)
93 _current = _parent / pentry->d_name;
96 #elif defined(_WIN32) || defined(_WIN64)
104 if (std::wcsncmp(_entry.cFileName, L
".",
countof(_entry.cFileName)) == 0)
106 if (std::wcsncmp(_entry.cFileName, L
"..",
countof(_entry.cFileName)) == 0)
109 _current = _parent / _entry.cFileName;
111 }
while (FindNextFileW(_directory, &_entry) != 0);
113 if (GetLastError() != ERROR_NO_MORE_FILES)
114 throwex FileSystemException(
"Cannot read directory entries!").Attach(_parent);
121 void Move(SimpleImpl& instance)
123 _parent = instance._parent;
124 _current = instance._current;
125 _directory = instance._directory;
126 _entry = instance._entry;
127 _next = instance._next;
128 _end = instance._end;
130 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
131 instance._directory =
nullptr;
132 #elif defined(_WIN32) || defined(_WIN64)
133 instance._directory = INVALID_HANDLE_VALUE;
137 void Swap(SimpleImpl& instance)
140 swap(_parent, instance._parent);
141 swap(_current, instance._current);
142 swap(_directory, instance._directory);
143 swap(_entry, instance._entry);
144 swap(_next, instance._next);
145 swap(_end, instance._end);
149 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
151 struct dirent _entry;
152 #elif defined(_WIN32) || defined(_WIN64)
154 WIN32_FIND_DATAW _entry;
160 class DirectoryIterator::RecursiveImpl :
public DirectoryIterator::Impl
163 explicit RecursiveImpl(
const Path& parent) :
DirectoryIterator::Impl(parent), _current(parent) {}
164 ~RecursiveImpl() =
default;
169 Path result = _current.Next();
177 _current.Swap(_stack.top());
179 return _current.current();
184 if (result.IsSymlink())
185 target = Symlink(target).target();
188 if (target.IsDirectory())
191 _stack.push(_current);
194 SimpleImpl subdir = SimpleImpl(result);
195 _current.Move(subdir);
206 std::stack<SimpleImpl> _stack;
219 DirectoryIterator::DirectoryIterator(
const Path& parent,
bool recursive) : _pimpl(recursive ? (Impl*)std::make_unique<RecursiveImpl>(parent).release() : (Impl*)std::make_unique<SimpleImpl>(parent).release())
221 _current = _pimpl->Next();
238 _pimpl = std::move(it._pimpl);
239 _current = it._current;
245 _pimpl = std::move(it._pimpl);
246 _current = std::move(it._current);
253 _current = _pimpl->Next();
Filesystem directory iterator.
DirectoryIterator & operator=(DirectoryIterator &it)
DirectoryIterator & operator++()
void swap(DirectoryIterator &it) noexcept
Swap two instances.
Static array countof definition.
Filesystem directory iterator definition.
#define throwex
Throw extended exception macro.
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
C++ Common project definitions.
constexpr size_t countof(const T(&)[N]) noexcept
Count of elements in static array.
void swap(FileCache &cache1, FileCache &cache2) noexcept
Filesystem symlink definition.