DirectoryIteratorStrategy.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. //
  2. // RecursiveDirectoryIteratorStategies.cpp
  3. //
  4. // $Id$
  5. //
  6. // Library: Foundation
  7. // Package: Filesystem
  8. // Module: RecursiveDirectoryIterator
  9. //
  10. // Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #include "Poco/DirectoryIteratorStrategy.h"
  16. namespace Poco {
  17. //
  18. // TraverseBase
  19. //
  20. TraverseBase::TraverseBase(DepthFunPtr depthDeterminer, UInt16 maxDepth)
  21. : _depthDeterminer(depthDeterminer), _maxDepth(maxDepth)
  22. {
  23. }
  24. inline bool TraverseBase::isFiniteDepth()
  25. {
  26. return _maxDepth != D_INFINITE;
  27. }
  28. bool TraverseBase::isDirectory(Poco::File& file)
  29. {
  30. try
  31. {
  32. return file.isDirectory();
  33. }
  34. catch (...)
  35. {
  36. return false;
  37. }
  38. }
  39. //
  40. // ChildrenFirstTraverse
  41. //
  42. ChildrenFirstTraverse::ChildrenFirstTraverse(DepthFunPtr depthDeterminer, UInt16 maxDepth)
  43. : TraverseBase(depthDeterminer, maxDepth)
  44. {
  45. }
  46. const std::string ChildrenFirstTraverse::next(Stack* itStack, bool* isFinished)
  47. {
  48. // pointer mustn't point to NULL and iteration mustn't be finished
  49. poco_check_ptr(isFinished);
  50. poco_assert(!(*isFinished));
  51. std::stack<DirectoryIterator> it;
  52. //_depthDeterminer(it);
  53. // go deeper into not empty directory
  54. // (if depth limit allows)
  55. bool isDepthLimitReached = isFiniteDepth() && _depthDeterminer(*itStack) >= _maxDepth;
  56. if (!isDepthLimitReached && isDirectory(*itStack->top()))
  57. {
  58. DirectoryIterator child_it(itStack->top().path());
  59. // check if directory is empty
  60. if (child_it != _itEnd)
  61. {
  62. itStack->push(child_it);
  63. return child_it->path();
  64. }
  65. }
  66. ++(itStack->top());
  67. poco_assert(!itStack->empty());
  68. // return up until there isn't right sibling
  69. while (itStack->top() == _itEnd)
  70. {
  71. itStack->pop();
  72. // detect end of traversal
  73. if (itStack->empty())
  74. {
  75. *isFinished = true;
  76. return _itEnd->path();
  77. }
  78. else
  79. {
  80. ++(itStack->top());
  81. }
  82. }
  83. return itStack->top()->path();
  84. }
  85. //
  86. // SiblingsFirstTraverse
  87. //
  88. SiblingsFirstTraverse::SiblingsFirstTraverse(DepthFunPtr depthDeterminer, UInt16 maxDepth)
  89. : TraverseBase(depthDeterminer, maxDepth)
  90. {
  91. _dirsStack.push(std::queue<std::string>());
  92. }
  93. const std::string SiblingsFirstTraverse::next(Stack* itStack, bool* isFinished)
  94. {
  95. // pointer mustn't point to NULL and iteration mustn't be finished
  96. poco_check_ptr(isFinished);
  97. poco_assert(!(*isFinished));
  98. // add dirs to queue (if depth limit allows)
  99. bool isDepthLimitReached = isFiniteDepth() && _depthDeterminer(*itStack) >= _maxDepth;
  100. if (!isDepthLimitReached && isDirectory(*itStack->top()))
  101. {
  102. const std::string& p = itStack->top()->path();
  103. _dirsStack.top().push(p);
  104. }
  105. ++(itStack->top());
  106. poco_assert(!itStack->empty());
  107. // return up until there isn't right sibling
  108. while (itStack->top() == _itEnd)
  109. {
  110. // try to find first not empty directory and go deeper
  111. while (!_dirsStack.top().empty())
  112. {
  113. std::string dir = _dirsStack.top().front();
  114. _dirsStack.top().pop();
  115. DirectoryIterator child_it(dir);
  116. // check if directory is empty
  117. if (child_it != _itEnd)
  118. {
  119. itStack->push(child_it);
  120. _dirsStack.push(std::queue<std::string>());
  121. return child_it->path();
  122. }
  123. }
  124. // if fail go upper
  125. itStack->pop();
  126. _dirsStack.pop();
  127. // detect end of traversal
  128. if (itStack->empty())
  129. {
  130. *isFinished = true;
  131. return _itEnd->path();
  132. }
  133. }
  134. return itStack->top()->path();
  135. }
  136. } // namespace Poco