Note that there are some explanatory texts on larger screens.

plurals
  1. POHow might I wrap the FindXFile-style APIs to the STL-style Iterator Pattern in C++?
    text
    copied!<p>I'm working on wrapping up the ugly innards of the <code>FindFirstFile</code>/<code>FindNextFile</code> loop (though my question applies to other similar APIs, such as <code>RegEnumKeyEx</code> or <code>RegEnumValue</code>, etc.) inside iterators that work in a manner similar to the Standard Template Library's <code>istream_iterator</code>s.</p> <p>I have two problems here. The first is with the termination condition of most "foreach" style loops. STL style iterators typically use <code>operator!=</code> inside the exit condition of the for, i.e.</p> <pre><code>std::vector&lt;int&gt; test; for(std::vector&lt;int&gt;::iterator it = test.begin(); it != test.end(); it++) { //Do stuff } </code></pre> <p>My problem is I'm unsure how to implement <code>operator!=</code> with such a directory enumeration, because I do not know when the enumeration is complete until I've actually finished with it. I have sort of a hack together solution in place now that enumerates the entire directory at once, where each iterator simply tracks a reference counted vector, but this seems like a kludge which can be done a better way.</p> <p>The second problem I have is that there are multiple pieces of data returned by the FindXFile APIs. For that reason, there's no obvious way to overload <code>operator*</code> as required for iterator semantics. When I overload that item, do I return the file name? The size? The modified date? How might I convey the multiple pieces of data to which such an iterator must refer to later in an ideomatic way? I've tried ripping off the C# style <code>MoveNext</code> design but I'm concerned about not following the standard idioms here.</p> <pre><code>class SomeIterator { public: bool next(); //Advances the iterator and returns true if successful, false if the iterator is at the end. std::wstring fileName() const; //other kinds of data.... }; </code></pre> <p>EDIT: And the caller would look like:</p> <pre><code>SomeIterator x = ??; //Construct somehow while(x.next()) { //Do stuff } </code></pre> <p>Thanks!</p> <p>Billy3</p> <p>EDIT2: I have fixed some bugs and written some tests.</p> <p>Implementation:</p> <pre><code>#pragma once #include &lt;queue&gt; #include &lt;string&gt; #include &lt;boost/noncopyable.hpp&gt; #include &lt;boost/make_shared.hpp&gt; #include &lt;boost/iterator/iterator_facade.hpp&gt; #include &lt;Windows.h&gt; #include &lt;Shlwapi.h&gt; #pragma comment(lib, "shlwapi.lib") #include "../Exception.hpp" namespace WindowsAPI { namespace FileSystem { template &lt;typename Filter_T = AllResults, typename Recurse_T = NonRecursiveEnumeration&gt; class DirectoryIterator; //For unit testing struct RealFindXFileFunctions { static HANDLE FindFirst(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) { return FindFirstFile(lpFileName, lpFindFileData); }; static BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) { return FindNextFile(hFindFile, lpFindFileData); }; static BOOL Close(HANDLE hFindFile) { return FindClose(hFindFile); }; }; inline std::wstring::const_iterator GetLastSlash(std::wstring const&amp;pathSpec) { return std::find(pathSpec.rbegin(), pathSpec.rend(), L'\\').base(); } class Win32FindData { WIN32_FIND_DATA internalData; std::wstring rootPath; public: Win32FindData(const std::wstring&amp; root, const WIN32_FIND_DATA&amp; data) : rootPath(root), internalData(data) {}; DWORD GetAttributes() const { return internalData.dwFileAttributes; }; bool IsDirectory() const { return (internalData.dwFileAttributes &amp; FILE_ATTRIBUTE_DIRECTORY) != 0; }; bool IsFile() const { return !IsDirectory(); }; unsigned __int64 GetSize() const { ULARGE_INTEGER intValue; intValue.LowPart = internalData.nFileSizeLow; intValue.HighPart = internalData.nFileSizeHigh; return intValue.QuadPart; }; std::wstring GetFolderPath() const { return rootPath; }; std::wstring GetFileName() const { return internalData.cFileName; }; std::wstring GetFullFileName() const { return rootPath + L"\\" + internalData.cFileName; }; std::wstring GetShortFileName() const { return internalData.cAlternateFileName; }; FILETIME GetCreationTime() const { return internalData.ftCreationTime; }; FILETIME GetLastAccessTime() const { return internalData.ftLastAccessTime; }; FILETIME GetLastWriteTime() const { return internalData.ftLastWriteTime; }; }; template &lt;typename FindXFileFunctions_T&gt; class BasicNonRecursiveEnumeration : public boost::noncopyable { WIN32_FIND_DATAW currentData; HANDLE hFind; std::wstring currentDirectory; void IncrementCurrentDirectory() { if (hFind == INVALID_HANDLE_VALUE) return; BOOL success = FindXFileFunctions_T::FindNext(hFind, &amp;currentData); if (success) return; DWORD error = GetLastError(); if (error == ERROR_NO_MORE_FILES) { FindXFileFunctions_T::Close(hFind); hFind = INVALID_HANDLE_VALUE; } else { WindowsApiException::Throw(error); } }; bool IsValidDotDirectory() { return !Valid() &amp;&amp; (!wcscmp(currentData.cFileName, L".") || !wcscmp(currentData.cFileName, L"..")); }; void IncrementPastDotDirectories() { while (IsValidDotDirectory()) { IncrementCurrentDirectory(); } }; void PerformFindFirstFile(std::wstring const&amp;pathSpec) { hFind = FindXFileFunctions_T::FindFirst(pathSpec.c_str(), &amp;currentData); if (Valid() &amp;&amp; GetLastError() != ERROR_PATH_NOT_FOUND &amp;&amp; GetLastError() != ERROR_FILE_NOT_FOUND) WindowsApiException::ThrowFromLastError(); }; public: BasicNonRecursiveEnumeration() : hFind(INVALID_HANDLE_VALUE) {}; BasicNonRecursiveEnumeration(const std::wstring&amp; pathSpec) : hFind(INVALID_HANDLE_VALUE) { std::wstring::const_iterator lastSlash = GetLastSlash(pathSpec); if (lastSlash != pathSpec.begin()) currentDirectory.assign(pathSpec.begin(), lastSlash-1); PerformFindFirstFile(pathSpec); IncrementPastDotDirectories(); }; bool equal(const BasicNonRecursiveEnumeration&lt;FindXFileFunctions_T&gt;&amp; other) const { if (this == &amp;other) return true; return hFind == other.hFind; }; Win32FindData dereference() { return Win32FindData(currentDirectory, currentData); }; void increment() { IncrementCurrentDirectory(); }; bool Valid() { return hFind == INVALID_HANDLE_VALUE; }; virtual ~BasicNonRecursiveEnumeration() { if (!Valid()) FindXFileFunctions_T::Close(hFind); }; }; typedef BasicNonRecursiveEnumeration&lt;RealFindXFileFunctions&gt; NonRecursiveEnumeration; template &lt;typename FindXFileFunctions_T&gt; class BasicRecursiveEnumeration : public boost::noncopyable { std::wstring fileSpec; std::deque&lt;std::deque&lt;Win32FindData&gt; &gt; enumeratedData; void EnumerateDirectory(const std::wstring&amp; nextPathSpec) { std::deque&lt;Win32FindData&gt; newDeck; BasicNonRecursiveEnumeration&lt;FindXFileFunctions_T&gt; begin(nextPathSpec), end; for(; !begin.equal(end); begin.increment()) { newDeck.push_back(begin.dereference()); } if (!newDeck.empty()) { enumeratedData.push_back(std::deque&lt;Win32FindData&gt;()); //Swaptimization enumeratedData.back().swap(newDeck); } }; void PerformIncrement() { if (enumeratedData.empty()) return; if (enumeratedData.back().front().IsDirectory()) { std::wstring nextSpec(enumeratedData.back().front().GetFullFileName()); nextSpec.append(L"\\*"); enumeratedData.back().pop_front(); EnumerateDirectory(nextSpec); } else { enumeratedData.back().pop_front(); } while (Valid() &amp;&amp; enumeratedData.back().empty()) enumeratedData.pop_back(); } bool CurrentPositionNoMatchFileSpec() const { return !enumeratedData.empty() &amp;&amp; !PathMatchSpecW(enumeratedData.back().front().GetFileName().c_str(), fileSpec.c_str()); } public: BasicRecursiveEnumeration() {}; BasicRecursiveEnumeration(const std::wstring&amp; pathSpec) { std::wstring::const_iterator lastSlash = GetLastSlash(pathSpec); if (lastSlash == pathSpec.begin()) { fileSpec = pathSpec; EnumerateDirectory(L"*"); } else { fileSpec.assign(lastSlash, pathSpec.end()); std::wstring firstQuery(pathSpec.begin(), lastSlash); firstQuery.push_back(L'*'); EnumerateDirectory(firstQuery); while (CurrentPositionNoMatchFileSpec()) PerformIncrement(); } }; void increment() { do { PerformIncrement(); } while (CurrentPositionNoMatchFileSpec()); }; bool equal(const BasicRecursiveEnumeration&lt;FindXFileFunctions_T&gt;&amp; other) const { if (!Valid()) return !other.Valid(); if (!other.Valid()) return false; return this == &amp;other; }; Win32FindData dereference() const { return enumeratedData.back().front(); }; bool Valid() const { return !enumeratedData.empty(); }; }; typedef BasicRecursiveEnumeration&lt;RealFindXFileFunctions&gt; RecursiveEnumeration; struct AllResults { bool operator()(const Win32FindData&amp;) { return true; }; }; struct FilesOnly { bool operator()(const Win32FindData&amp; arg) { return arg.IsFile(); }; }; template &lt;typename Filter_T, typename Recurse_T&gt; class DirectoryIterator : public boost::iterator_facade&lt; DirectoryIterator&lt;Filter_T, Recurse_T&gt;, Win32FindData, std::input_iterator_tag, Win32FindData &gt; { friend class boost::iterator_core_access; boost::shared_ptr&lt;Recurse_T&gt; impl; Filter_T filter; void increment() { do { impl-&gt;increment(); } while (impl-&gt;Valid() &amp;&amp; !filter(impl-&gt;dereference())); }; bool equal(const DirectoryIterator&amp; other) const { return impl-&gt;equal(*other.impl); }; Win32FindData dereference() const { return impl-&gt;dereference(); }; public: DirectoryIterator(Filter_T functor = Filter_T()) : impl(boost::make_shared&lt;Recurse_T&gt;()), filter(functor) { }; explicit DirectoryIterator(const std::wstring&amp; pathSpec, Filter_T functor = Filter_T()) : impl(boost::make_shared&lt;Recurse_T&gt;(pathSpec)), filter(functor) { }; }; }} </code></pre> <p>Tests:</p> <pre><code>#include &lt;queue&gt; #include "../WideCharacterOutput.hpp" #include &lt;boost/test/unit_test.hpp&gt; #include "../../WindowsAPI++/FileSystem/Enumerator.hpp" using namespace WindowsAPI::FileSystem; struct SimpleFakeFindXFileFunctions { static std::deque&lt;WIN32_FIND_DATAW&gt; fakeData; static std::wstring insertedFileName; static HANDLE FindFirst(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) { insertedFileName.assign(lpFileName); if (fakeData.empty()) { SetLastError(ERROR_PATH_NOT_FOUND); return INVALID_HANDLE_VALUE; } *lpFindFileData = fakeData.front(); fakeData.pop_front(); return reinterpret_cast&lt;HANDLE&gt;(42); }; static BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) { BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile); if (fakeData.empty()) { SetLastError(ERROR_NO_MORE_FILES); return 0; } *lpFindFileData = fakeData.front(); fakeData.pop_front(); return 1; }; static BOOL Close(HANDLE hFindFile) { BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile); return 1; }; }; std::deque&lt;WIN32_FIND_DATAW&gt; SimpleFakeFindXFileFunctions::fakeData; std::wstring SimpleFakeFindXFileFunctions::insertedFileName; struct ErroneousFindXFileFunctionFirst { static HANDLE FindFirst(LPCWSTR, LPWIN32_FIND_DATAW) { SetLastError(ERROR_ACCESS_DENIED); return INVALID_HANDLE_VALUE; }; static BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW) { BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile); return 1; }; static BOOL Close(HANDLE hFindFile) { BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile); return 1; }; }; struct ErroneousFindXFileFunctionNext { static HANDLE FindFirst(LPCWSTR, LPWIN32_FIND_DATAW) { return reinterpret_cast&lt;HANDLE&gt;(42); }; static BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW) { BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile); SetLastError(ERROR_INVALID_PARAMETER); return 0; }; static BOOL Close(HANDLE hFindFile) { BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile); return 1; }; }; struct DirectoryIteratorTestsFixture { typedef SimpleFakeFindXFileFunctions fakeFunctor; DirectoryIteratorTestsFixture() { WIN32_FIND_DATAW test; wcscpy_s(test.cFileName, L"."); wcscpy_s(test.cAlternateFileName, L"."); test.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; GetSystemTimeAsFileTime(&amp;test.ftCreationTime); test.ftLastWriteTime = test.ftCreationTime; test.ftLastAccessTime = test.ftCreationTime; test.nFileSizeHigh = 0; test.nFileSizeLow = 0; fakeFunctor::fakeData.push_back(test); wcscpy_s(test.cFileName, L".."); wcscpy_s(test.cAlternateFileName, L".."); fakeFunctor::fakeData.push_back(test); wcscpy_s(test.cFileName, L"File.txt"); wcscpy_s(test.cAlternateFileName, L"FILE.TXT"); test.nFileSizeLow = 1024; test.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; fakeFunctor::fakeData.push_back(test); wcscpy_s(test.cFileName, L"System32"); wcscpy_s(test.cAlternateFileName, L"SYSTEM32"); test.nFileSizeLow = 0; test.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; fakeFunctor::fakeData.push_back(test); }; ~DirectoryIteratorTestsFixture() { fakeFunctor::fakeData.clear(); }; }; BOOST_FIXTURE_TEST_SUITE( DirectoryIteratorTests, DirectoryIteratorTestsFixture ) template&lt;typename fakeFunctor&gt; static void NonRecursiveIteratorAssertions() { typedef DirectoryIterator&lt;AllResults ,BasicNonRecursiveEnumeration&lt;SimpleFakeFindXFileFunctions&gt; &gt; testType; testType begin(L"C:\\Windows\\*"); testType end; BOOST_CHECK_EQUAL(fakeFunctor::insertedFileName, L"C:\\Windows\\*"); BOOST_CHECK(begin-&gt;GetFolderPath() == L"C:\\Windows"); BOOST_CHECK(begin-&gt;GetFileName() == L"File.txt"); BOOST_CHECK(begin-&gt;GetFullFileName() == L"C:\\Windows\\File.txt"); BOOST_CHECK(begin-&gt;GetShortFileName() == L"FILE.TXT"); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 1024); BOOST_CHECK(begin-&gt;IsFile()); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin-&gt;GetFileName() == L"System32"); BOOST_CHECK(begin-&gt;GetFullFileName() == L"C:\\Windows\\System32"); BOOST_CHECK(begin-&gt;GetShortFileName() == L"SYSTEM32"); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 0); BOOST_CHECK(begin-&gt;IsDirectory()); begin++; BOOST_CHECK(begin == end); } BOOST_AUTO_TEST_CASE( BasicEnumeration ) { NonRecursiveIteratorAssertions&lt;fakeFunctor&gt;(); } BOOST_AUTO_TEST_CASE( NoRootDirectories ) { fakeFunctor::fakeData.pop_front(); fakeFunctor::fakeData.pop_front(); NonRecursiveIteratorAssertions&lt;fakeFunctor&gt;(); } static void EmptyIteratorAssertions() { typedef DirectoryIterator&lt;AllResults ,BasicNonRecursiveEnumeration&lt;SimpleFakeFindXFileFunctions&gt; &gt; testType; testType begin(L"C:\\Windows\\*"); testType end; BOOST_CHECK(begin == end); } BOOST_AUTO_TEST_CASE( Empty1 ) { fakeFunctor::fakeData.clear(); EmptyIteratorAssertions(); } BOOST_AUTO_TEST_CASE( Empty2 ) { fakeFunctor::fakeData.erase(fakeFunctor::fakeData.begin() + 2, fakeFunctor::fakeData.end()); EmptyIteratorAssertions(); } BOOST_AUTO_TEST_CASE( CorrectDestruction ) { typedef DirectoryIterator&lt;AllResults ,BasicNonRecursiveEnumeration&lt;SimpleFakeFindXFileFunctions&gt; &gt; testType; testType begin(L"C:\\Windows\\*"); testType end; } BOOST_AUTO_TEST_CASE( Exceptions ) { typedef DirectoryIterator&lt;AllResults,BasicNonRecursiveEnumeration&lt;ErroneousFindXFileFunctionFirst&gt; &gt; firstFailType; BOOST_CHECK_THROW(firstFailType(L"C:\\Windows\\*"), WindowsAPI::ErrorAccessDeniedException); typedef DirectoryIterator&lt;AllResults,BasicNonRecursiveEnumeration&lt;ErroneousFindXFileFunctionNext&gt; &gt; nextFailType; nextFailType constructedOkay(L"C:\\Windows\\*"); BOOST_CHECK_THROW(constructedOkay++, WindowsAPI::ErrorInvalidParameterException); } BOOST_AUTO_TEST_SUITE_END() struct RecursiveFakeFindXFileFunctions { static std::deque&lt;std::pair&lt;std::deque&lt;WIN32_FIND_DATA&gt; , std::wstring&gt; &gt; fakeData; static std::size_t openHandles; static HANDLE FindFirst(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) { BOOST_REQUIRE(!fakeData.empty()); BOOST_REQUIRE_EQUAL(lpFileName, fakeData.front().second); openHandles++; BOOST_REQUIRE_EQUAL(openHandles, 1); if (fakeData.front().first.empty()) { openHandles--; SetLastError(ERROR_PATH_NOT_FOUND); return INVALID_HANDLE_VALUE; } *lpFindFileData = fakeData.front().first.front(); fakeData.front().first.pop_front(); return reinterpret_cast&lt;HANDLE&gt;(42); }; static BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) { BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile); if (fakeData.front().first.empty()) { SetLastError(ERROR_NO_MORE_FILES); return 0; } *lpFindFileData = fakeData.front().first.front(); fakeData.front().first.pop_front(); return 1; }; static BOOL Close(HANDLE hFindFile) { BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile); openHandles--; BOOST_REQUIRE_EQUAL(openHandles, 0); fakeData.pop_front(); return 1; }; }; std::deque&lt;std::pair&lt;std::deque&lt;WIN32_FIND_DATA&gt; , std::wstring&gt; &gt; RecursiveFakeFindXFileFunctions::fakeData; std::size_t RecursiveFakeFindXFileFunctions::openHandles; struct RecursiveDirectoryFixture { RecursiveDirectoryFixture() { WIN32_FIND_DATAW tempData; ZeroMemory(&amp;tempData, sizeof(tempData)); std::deque&lt;WIN32_FIND_DATAW&gt; dequeData; wcscpy_s(tempData.cFileName, L"."); wcscpy_s(tempData.cAlternateFileName, L"."); tempData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; GetSystemTimeAsFileTime(&amp;tempData.ftCreationTime); tempData.ftLastWriteTime = tempData.ftCreationTime; tempData.ftLastAccessTime = tempData.ftCreationTime; dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L".."); wcscpy_s(tempData.cAlternateFileName, L".."); dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L"MySubDirectory"); wcscpy_s(tempData.cAlternateFileName, L"MYSUBD~1"); dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L"MyFile.txt"); wcscpy_s(tempData.cAlternateFileName, L"MYFILE.TXT"); tempData.nFileSizeLow = 500; tempData.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; dequeData.push_back(tempData); RecursiveFakeFindXFileFunctions::fakeData.push_back (std::make_pair(dequeData, L"C:\\Windows\\*")); dequeData.clear(); wcscpy_s(tempData.cFileName, L"."); wcscpy_s(tempData.cAlternateFileName, L"."); tempData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; GetSystemTimeAsFileTime(&amp;tempData.ftCreationTime); tempData.ftLastWriteTime = tempData.ftCreationTime; tempData.ftLastAccessTime = tempData.ftCreationTime; dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L".."); wcscpy_s(tempData.cAlternateFileName, L".."); dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L"MyFile2.txt"); wcscpy_s(tempData.cAlternateFileName, L"NYFILE2.TXT"); tempData.nFileSizeLow = 1024; tempData.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; dequeData.push_back(tempData); RecursiveFakeFindXFileFunctions::fakeData.push_back (std::make_pair(dequeData, L"C:\\Windows\\MySubDirectory\\*")); }; ~RecursiveDirectoryFixture() { RecursiveFakeFindXFileFunctions::fakeData.clear(); }; }; BOOST_AUTO_TEST_SUITE( RecursiveDirectoryIteratorTests ) BOOST_AUTO_TEST_CASE( BasicEnumerationTxt ) { RecursiveDirectoryFixture DataFixture; typedef DirectoryIterator&lt;AllResults ,BasicRecursiveEnumeration&lt;RecursiveFakeFindXFileFunctions&gt; &gt; testType; testType begin(L"C:\\Windows\\*.txt"); testType end; BOOST_CHECK(begin-&gt;IsFile()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 1024); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows\\MySubDirectory"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"MyFile2.txt"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\MySubDirectory\\MyFile2.txt"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin-&gt;IsFile()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 500); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"MyFile.txt"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\MyFile.txt"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin == end); } BOOST_AUTO_TEST_CASE( BasicEnumerationAll ) { RecursiveDirectoryFixture DataFixture; typedef DirectoryIterator&lt;AllResults ,BasicRecursiveEnumeration&lt;RecursiveFakeFindXFileFunctions&gt; &gt; testType; testType begin(L"C:\\Windows\\*"); testType end; BOOST_CHECK(begin-&gt;IsDirectory()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 0); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"MySubDirectory"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\MySubDirectory"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin-&gt;IsFile()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 1024); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows\\MySubDirectory"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"MyFile2.txt"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\MySubDirectory\\MyFile2.txt"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin-&gt;IsFile()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 500); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"MyFile.txt"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\MyFile.txt"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin == end); } BOOST_AUTO_TEST_CASE( RecursionOrderMaintained ) { WIN32_FIND_DATAW tempData; ZeroMemory(&amp;tempData, sizeof(tempData)); std::deque&lt;WIN32_FIND_DATAW&gt; dequeData; wcscpy_s(tempData.cFileName, L"."); wcscpy_s(tempData.cAlternateFileName, L"."); tempData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; GetSystemTimeAsFileTime(&amp;tempData.ftCreationTime); tempData.ftLastWriteTime = tempData.ftCreationTime; tempData.ftLastAccessTime = tempData.ftCreationTime; dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L".."); wcscpy_s(tempData.cAlternateFileName, L".."); dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L"MySubDirectory"); wcscpy_s(tempData.cAlternateFileName, L"MYSUBD~1"); dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L"MyFile.txt"); wcscpy_s(tempData.cAlternateFileName, L"MYFILE.TXT"); tempData.nFileSizeLow = 500; tempData.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L"Zach"); wcscpy_s(tempData.cAlternateFileName, L"ZACH"); tempData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; tempData.nFileSizeLow = 0; dequeData.push_back(tempData); RecursiveFakeFindXFileFunctions::fakeData.push_back (std::make_pair(dequeData, L"C:\\Windows\\*")); dequeData.clear(); wcscpy_s(tempData.cFileName, L"."); wcscpy_s(tempData.cAlternateFileName, L"."); tempData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; GetSystemTimeAsFileTime(&amp;tempData.ftCreationTime); tempData.ftLastWriteTime = tempData.ftCreationTime; tempData.ftLastAccessTime = tempData.ftCreationTime; dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L".."); wcscpy_s(tempData.cAlternateFileName, L".."); dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L"MyFile2.txt"); wcscpy_s(tempData.cAlternateFileName, L"NYFILE2.TXT"); tempData.nFileSizeLow = 1024; tempData.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; dequeData.push_back(tempData); RecursiveFakeFindXFileFunctions::fakeData.push_back (std::make_pair(dequeData, L"C:\\Windows\\MySubDirectory\\*")); dequeData.clear(); wcscpy_s(tempData.cFileName, L"."); wcscpy_s(tempData.cAlternateFileName, L"."); tempData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; GetSystemTimeAsFileTime(&amp;tempData.ftCreationTime); tempData.ftLastWriteTime = tempData.ftCreationTime; tempData.ftLastAccessTime = tempData.ftCreationTime; dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L".."); wcscpy_s(tempData.cAlternateFileName, L".."); dequeData.push_back(tempData); wcscpy_s(tempData.cFileName, L"ZachFile.txt"); wcscpy_s(tempData.cAlternateFileName, L"ZACHFILE.TXT"); tempData.nFileSizeLow = 1024; tempData.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; dequeData.push_back(tempData); RecursiveFakeFindXFileFunctions::fakeData.push_back (std::make_pair(dequeData, L"C:\\Windows\\Zach\\*")); typedef DirectoryIterator&lt;AllResults ,BasicRecursiveEnumeration&lt;RecursiveFakeFindXFileFunctions&gt; &gt; testType; testType begin(L"C:\\Windows\\*"); testType end; BOOST_CHECK(begin-&gt;IsDirectory()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 0); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"MySubDirectory"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\MySubDirectory"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin-&gt;IsFile()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 1024); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows\\MySubDirectory"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"MyFile2.txt"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\MySubDirectory\\MyFile2.txt"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin-&gt;IsFile()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 500); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"MyFile.txt"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\MyFile.txt"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin-&gt;IsDirectory()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 0); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"Zach"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\Zach"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin-&gt;IsFile()); BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 1024); BOOST_CHECK_EQUAL(begin-&gt;GetFolderPath(), L"C:\\Windows\\Zach"); BOOST_CHECK_EQUAL(begin-&gt;GetFileName(), L"ZachFile.txt"); BOOST_CHECK_EQUAL(begin-&gt;GetFullFileName(), L"C:\\Windows\\Zach\\ZachFile.txt"); BOOST_CHECK(begin != end); begin++; BOOST_CHECK(begin == end); } BOOST_AUTO_TEST_CASE( Exceptions ) { typedef DirectoryIterator&lt;AllResults,BasicRecursiveEnumeration&lt;ErroneousFindXFileFunctionFirst&gt; &gt; firstFailType; BOOST_CHECK_THROW(firstFailType(L"C:\\Windows\\*"), WindowsAPI::ErrorAccessDeniedException); typedef DirectoryIterator&lt;AllResults,BasicRecursiveEnumeration&lt;ErroneousFindXFileFunctionNext&gt; &gt; nextFailType; BOOST_CHECK_THROW(nextFailType(L"C:\\Windows\\*"), WindowsAPI::ErrorInvalidParameterException); } BOOST_AUTO_TEST_SUITE_END() </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload