// // RecursiveDirectoryIteratorStategies.cpp // // $Id$ // // Library: Foundation // Package: Filesystem // Module: RecursiveDirectoryIterator // // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // // Permission is hereby granted, free of charge, to any person or organization // obtaining a copy of the software and accompanying documentation covered by // this license (the "Software") to use, reproduce, display, distribute, // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: // // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // #include "Poco/DirectoryIteratorStrategy.h" namespace Poco { // // TraverseBase // TraverseBase::TraverseBase(DepthFunPtr depthDeterminer, UInt16 maxDepth) : _depthDeterminer(depthDeterminer), _maxDepth(maxDepth) { } inline bool TraverseBase::isFiniteDepth() { return _maxDepth != D_INFINITE; } // // ChildrenFirstTraverse // ChildrenFirstTraverse::ChildrenFirstTraverse(DepthFunPtr depthDeterminer, UInt16 maxDepth) : TraverseBase(depthDeterminer, maxDepth) { } const std::string ChildrenFirstTraverse::next(Stack* itStack, bool* isFinished) { // pointer mustn't point to NULL and iteration mustn't be finished poco_check_ptr(isFinished); poco_assert(!(*isFinished)); std::stack it; //_depthDeterminer(it); // go deeper into not empty directory // (if depth limit allows) bool isDepthLimitReached = isFiniteDepth() && _depthDeterminer(*itStack) >= _maxDepth; if (!isDepthLimitReached && itStack->top()->isDirectory()) { DirectoryIterator child_it(itStack->top().path()); // check if directory is empty if (child_it != _itEnd) { itStack->push(child_it); return child_it->path(); } } ++(itStack->top()); poco_assert(!itStack->empty()); // return up until there isn't right sibling while (itStack->top() == _itEnd) { itStack->pop(); // detect end of traversal if (itStack->empty()) { *isFinished = true; return _itEnd->path(); } else { ++(itStack->top()); } } return itStack->top()->path(); } // // SiblingsFirstTraverse // SiblingsFirstTraverse::SiblingsFirstTraverse(DepthFunPtr depthDeterminer, UInt16 maxDepth) : TraverseBase(depthDeterminer, maxDepth) { _dirsStack.push(std::queue()); } const std::string SiblingsFirstTraverse::next(Stack* itStack, bool* isFinished) { // pointer mustn't point to NULL and iteration mustn't be finished poco_check_ptr(isFinished); poco_assert(!(*isFinished)); // add dirs to queue (if depth limit allows) bool isDepthLimitReached = isFiniteDepth() && _depthDeterminer(*itStack) >= _maxDepth; if (!isDepthLimitReached && itStack->top()->isDirectory()) { const std::string& p = itStack->top()->path(); _dirsStack.top().push(p); } ++(itStack->top()); poco_assert(!itStack->empty()); // return up until there isn't right sibling while (itStack->top() == _itEnd) { // try to find first not empty directory and go deeper while (!_dirsStack.top().empty()) { std::string dir = _dirsStack.top().front(); _dirsStack.top().pop(); DirectoryIterator child_it(dir); // check if directory is empty if (child_it != _itEnd) { itStack->push(child_it); _dirsStack.push(std::queue()); return child_it->path(); } } // if fail go upper itStack->pop(); _dirsStack.pop(); // detect end of traversal if (itStack->empty()) { *isFinished = true; return _itEnd->path(); } } return itStack->top()->path(); } } // namespace Poco