4#include "Stroika/Foundation/StroikaPreComp.h"
6#if qStroika_Foundation_Common_Platform_Windows
8#elif qStroika_Foundation_Common_Platform_POSIX
17#include "Stroika/Foundation/Execution/Exceptions.h"
18#if qStroika_Foundation_Common_Platform_Windows
19#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
31using namespace Stroika::Foundation::IO;
33using namespace Stroika::Foundation::Traversal;
40class DirectoryIterator::Rep_ :
public Iterator<filesystem::path>::IRep {
42 IteratorReturnType fIteratorReturnType_;
44 filesystem::path fReportPrefix_;
45#if qStroika_Foundation_Common_Platform_POSIX
46 DIR* fDirIt_{
nullptr};
47 dirent* fCur_{
nullptr};
48#elif qStroika_Foundation_Common_Platform_Windows
49 HANDLE fHandle_{INVALID_HANDLE_VALUE};
50 WIN32_FIND_DATA fFindFileData_{};
55 Rep_ (
const String& dir, IteratorReturnType iteratorReturns)
56 : fIteratorReturnType_{iteratorReturns}
58 , fReportPrefix_{mkReportPrefix_ (dir.As<filesystem::path> (), iteratorReturns)}
59#if qStroika_Foundation_Common_Platform_POSIX
60 , fDirIt_{::opendir (dir.AsSDKString ().c_str ())}
63#if USE_NOISY_TRACE_IN_THIS_MODULE_
66#if qStroika_Foundation_Common_Platform_POSIX
67 if (fDirIt_ ==
nullptr) {
72 if ((fCur_ = ::readdir (fDirIt_)) ==
nullptr) {
77 if (fCur_ !=
nullptr and fCur_->d_name[0] ==
'.' and
78 (CString::Equals (fCur_->d_name, SDKSTR (
".")) or CString::Equals (fCur_->d_name, SDKSTR (
"..")))) {
79 optional<filesystem::path> tmphack;
80 More (&tmphack,
true);
82#elif qStroika_Foundation_Common_Platform_Windows
83 fHandle_ = ::FindFirstFile ((dir + L
"\\*").AsSDKString ().c_str (), &fFindFileData_);
84 while (fHandle_ != INVALID_HANDLE_VALUE and
85 (CString::Equals (fFindFileData_.cFileName, SDKSTR (
".")) or CString::Equals (fFindFileData_.cFileName, SDKSTR (
"..")))) {
86 optional<filesystem::path> tmphack;
87 More (&tmphack,
true);
91#if qStroika_Foundation_Common_Platform_POSIX
92 Rep_ (
const String& dirName,
const optional<ino_t>& curInode, IteratorReturnType iteratorReturns)
93 : fIteratorReturnType_{iteratorReturns}
95 , fReportPrefix_{mkReportPrefix_ (dirName.As<filesystem::path> (), iteratorReturns)}
96 , fDirIt_{::opendir (dirName.AsSDKString ().c_str ())}
98 if (fDirIt_ ==
nullptr) {
101#if USE_NOISY_TRACE_IN_THIS_MODULE_
106 fCur_ = ::readdir (fDirIt_);
107 }
while (fCur_ !=
nullptr and fCur_->d_ino != *curInode);
110#elif qStroika_Foundation_Common_Platform_Windows
112 Rep_ (
const String& dir,
const optional<String>& name, IteratorReturnType iteratorReturns)
113 : fIteratorReturnType_{iteratorReturns}
115 , fReportPrefix_{mkReportPrefix_ (dir.As<filesystem::path> (), iteratorReturns)}
117#if USE_NOISY_TRACE_IN_THIS_MODULE_
121 fHandle_ = ::FindFirstFile ((dir + L
"\\*").AsSDKString ().c_str (), &fFindFileData_);
122 while (fHandle_ != INVALID_HANDLE_VALUE and
String::FromSDKString (fFindFileData_.cFileName) != name) {
123 optional<filesystem::path> tmphack;
124 More (&tmphack,
true);
131#if qStroika_Foundation_Common_Platform_POSIX
132 if (fDirIt_ !=
nullptr) {
133 ::closedir (fDirIt_);
135#elif qStroika_Foundation_Common_Platform_Windows
136 if (fHandle_ != INVALID_HANDLE_VALUE) {
137 ::FindClose (fHandle_);
141 virtual void More (optional<filesystem::path>* result,
bool advance)
override
146#if qStroika_Foundation_Common_Platform_POSIX
152 fCur_ = ::readdir (fDirIt_);
153 if (fCur_ ==
nullptr) {
155 if (errno != EBADF and errno != 0) {
159 if (fCur_ !=
nullptr and fCur_->d_name[0] ==
'.' and
160 (CString::Equals (fCur_->d_name, SDKSTR (
".")) or CString::Equals (fCur_->d_name, SDKSTR (
"..")))) {
164 if (fCur_ !=
nullptr) {
165 *result = fReportPrefix_ / fCur_->d_name;
167#elif qStroika_Foundation_Common_Platform_Windows
170 Require (fHandle_ != INVALID_HANDLE_VALUE);
171 (void)::memset (&fFindFileData_, 0,
sizeof (fFindFileData_));
172 if (::FindNextFile (fHandle_, &fFindFileData_) == 0) {
173 ::FindClose (fHandle_);
174 fHandle_ = INVALID_HANDLE_VALUE;
176 if (fHandle_ != INVALID_HANDLE_VALUE and
177 (CString::Equals (fFindFileData_.cFileName, SDKSTR (
".")) or CString::Equals (fFindFileData_.cFileName, SDKSTR (
"..")))) {
181 if (fHandle_ != INVALID_HANDLE_VALUE) {
182 *result = fReportPrefix_ / fFindFileData_.cFileName;
191 const Rep_& rrhs = *Debug::UncheckedDynamicCast<const Rep_*> (rhs);
192#if qStroika_Foundation_Common_Platform_POSIX
193 return fDirName_ == rrhs.fDirName_ and fIteratorReturnType_ == rrhs.fIteratorReturnType_ and
194 ((fCur_ == rrhs.fCur_ and fCur_ ==
nullptr) or (rrhs.fCur_ !=
nullptr and fCur_->d_ino == rrhs.fCur_->d_ino));
195#elif qStroika_Foundation_Common_Platform_Windows
196 return fHandle_ == rrhs.fHandle_;
199 virtual unique_ptr<IRep> Clone ()
const override
201#if USE_NOISY_TRACE_IN_THIS_MODULE_
205#if qStroika_Foundation_Common_Platform_POSIX
236 return make_unique<Rep_> (fDirName_, fCur_ ==
nullptr ? optional<ino_t>{} : fCur_->d_ino, fIteratorReturnType_);
237#elif qStroika_Foundation_Common_Platform_Windows
238 return make_unique<Rep_> (fDirName_, fHandle_ == INVALID_HANDLE_VALUE ? optional<String>{} :
String::FromSDKString (fFindFileData_.cFileName),
239 fIteratorReturnType_);
244 static filesystem::path mkReportPrefix_ (
const filesystem::path& dirName, IteratorReturnType iteratorReturns)
246 switch (iteratorReturns) {
247 case IteratorReturnType::eFilenameOnly:
248 return filesystem::path{};
249 case IteratorReturnType::eDirPlusFilename:
251 case IteratorReturnType::eFullPathName:
252 return filesystem::absolute (dirName);
255 return filesystem::path{};
265DirectoryIterator::DirectoryIterator (
const filesystem::path& directoryName, IteratorReturnType iteratorReturns)
266 :
Iterator<filesystem::path>{make_unique<Rep_> (
String{directoryName}, iteratorReturns)}
#define RequireMember(p, c)
#define RequireNotNull(p)
#define AssertNotReached()
bool Equals(const T *lhs, const T *rhs)
strcmp or wsccmp() as appropriate == 0
String is like std::u32string, except it is much easier to use, often much more space efficient,...
static String FromSDKString(const SDKChar *from)
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
shared_lock< const AssertExternallySynchronizedMutex > ReadContext
Instantiate AssertExternallySynchronizedMutex::ReadContext to designate an area of code where protect...
unique_lock< AssertExternallySynchronizedMutex > WriteContext
Instantiate AssertExternallySynchronizedMutex::WriteContext to designate an area of code where protec...
static void ThrowPOSIXErrNo(errno_t errNo, const path &p1={}, const path &p2={})
treats errNo as a POSIX errno value, and throws a FileSystem::Exception (subclass of @std::filesystem...
Implementation detail for iterator implementors.
An Iterator<T> is a copyable object which allows traversing the contents of some container....
void ThrowPOSIXErrNo(errno_t errNo=errno)
treats errNo as a POSIX errno value, and throws a SystemError (subclass of @std::system_error) except...