fstraverseiterator.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #include "fstraverseiterator.h"
  2. bool QFileInfoLess::operator()(const QFileInfo & first,
  3. const QFileInfo & second) const
  4. {
  5. bool
  6. rv = first.absoluteFilePath() < second.absoluteFilePath();
  7. return rv;
  8. }
  9. FSGraph::FSGraph(bool filesAllowed)
  10. : m_filesAllowed(filesAllowed)
  11. {
  12. ;
  13. }
  14. FSTraverseIterator::FSTraverseIterator(const QString & startingAbsolutePath,
  15. int flags)
  16. : m_graph(true)
  17. , m_flags(flags)
  18. {
  19. QFileInfo
  20. startingPoint(startingAbsolutePath);
  21. if (startingPoint.exists())
  22. {
  23. setupFlagsAndColors();
  24. m_iterator = Iterator(m_graph,
  25. startingPoint,
  26. m_iteratorFlags);
  27. next(true);
  28. }
  29. }
  30. FSTraverseIterator::FSTraverseIterator(const QStringList & startingAbsolutePaths,
  31. int flags)
  32. : m_graph(true)
  33. , m_flags(flags)
  34. {
  35. QFileInfoList
  36. startingPoints;
  37. foreach (QString startingAbsolutePath, startingAbsolutePaths)
  38. {
  39. QFileInfo
  40. startingPoint(startingAbsolutePath);
  41. if (startingPoint.exists())
  42. {
  43. startingPoints.push_back(startingPoint);
  44. }
  45. }
  46. if (!startingPoints.empty())
  47. {
  48. setupFlagsAndColors();
  49. m_iterator = Iterator(m_graph,
  50. startingPoints.begin(),
  51. startingPoints.end(),
  52. m_iteratorFlags);
  53. next(true);
  54. }
  55. }
  56. FSTraverseIterator::FSTraverseIterator()
  57. : m_graph(false)
  58. , m_flags(0)
  59. {
  60. ;
  61. }
  62. QFileInfo * FSTraverseIterator::operator->()
  63. {
  64. return &m_currentFileInfo;
  65. }
  66. QFileInfo & FSTraverseIterator::operator*()
  67. {
  68. return m_currentFileInfo;
  69. }
  70. FSTraverseIterator & FSTraverseIterator::operator++()
  71. {
  72. next();
  73. return *this;
  74. }
  75. FSTraverseIterator FSTraverseIterator::operator++(int)
  76. {
  77. FSTraverseIterator
  78. tmp(*this);
  79. next();
  80. return tmp;
  81. }
  82. #define __yield_return(cn) {if(allowed(cn)){m_currentFileInfo=cn.m_node;break;}}
  83. void FSTraverseIterator::next(bool initializationTime)
  84. {
  85. Iterator
  86. endIt = Iterator();
  87. while (m_iterator != endIt)
  88. {
  89. // On creation, the m_iterator positions on the first
  90. // unseen item - no need to increment, but from that
  91. // point on, m_iterator either points to a seen item
  92. // or the "end".
  93. if (initializationTime)
  94. {
  95. initializationTime = false;
  96. }
  97. else
  98. {
  99. ++m_iterator;
  100. }
  101. if (m_iterator == endIt)
  102. {
  103. break;
  104. }
  105. ColoredNode<QFileInfo>
  106. coloredNode(*m_iterator);
  107. if (allowed(coloredNode))
  108. {
  109. __yield_return(coloredNode);
  110. }
  111. }
  112. }
  113. #undef __yield_return
  114. void FSTraverseIterator::setupFlagsAndColors()
  115. {
  116. // Here we are trying to map FSTraverseIterator::Flag flags
  117. // to Iterator::Flag flag values.
  118. //
  119. // enum Flag // <- FSTraverseIterator::Flag
  120. // {
  121. // DirsPreOrder = 1,
  122. // DirsPostOrder = 2,
  123. // DirsBoth = DirPreOrder | DirPostOrder,
  124. // Files = 8,
  125. // FilesAndDirs = DirsPreOrder | Files
  126. // };
  127. // enum Flag // <- Iterator::Flag
  128. // {
  129. // PreVisit = 1,
  130. // PostVisit = 2
  131. // };
  132. //
  133. // The FSTraverseIterator::Flag flags control
  134. // what kind of content is interesting (files, directories
  135. // or both) as well as at what point directories should
  136. // be iterated (before visiting its files, after
  137. // visiting its files, or both times).
  138. //
  139. // Files (that are leaf nodes (nodes without further
  140. // adjacents) from the point of view of depth first search
  141. // don't care if they are preorder or postorder visited.
  142. // Therefore it's up to the directory visiting (pre, post
  143. // or both) to decide what kind of flags we give to the
  144. // generic depth-first search.
  145. m_iteratorFlags = Iterator::PreVisit;
  146. m_allowedDirColors = NC_GRAY;
  147. m_allowedFileColor = NC_GRAY;
  148. if (m_flags & DirsPostOrder)
  149. {
  150. if (m_flags & DirsPreOrder)
  151. {
  152. // dirs are to be iterated both pre- and postvisit times
  153. m_iteratorFlags |= Iterator::PostVisit;
  154. m_allowedDirColors |= NC_BLACK;
  155. // m_allowedFileColor does not change here - we don't
  156. // intend to receive duplicate iterations on files
  157. }
  158. else
  159. {
  160. // dirs are to be visited only at postvisit times
  161. m_iteratorFlags = Iterator::PostVisit;
  162. m_allowedDirColors = NC_BLACK;
  163. // files will get iterated only at post visit times,
  164. // so we have better enable that
  165. m_allowedFileColor = NC_BLACK;
  166. }
  167. }
  168. else if (!(m_flags & DirsPreOrder))
  169. {
  170. // no directories are to be enumerated, after all (only traversed)
  171. m_allowedDirColors = 0;
  172. }
  173. if ((m_flags & Files) == 0)
  174. {
  175. // no files are to be enumerated, after all
  176. m_allowedFileColor = 0;
  177. m_graph = FSGraph(false);
  178. }
  179. }
  180. bool FSTraverseIterator::allowed(const ColoredNode<QFileInfo> & coloredNode)
  181. {
  182. bool
  183. rv = false;
  184. if (coloredNode.m_node.isFile())
  185. {
  186. rv = m_allowedFileColor == coloredNode.m_color;
  187. }
  188. else // it's a directory
  189. {
  190. rv = m_allowedDirColors & coloredNode.m_color;
  191. }
  192. return rv;
  193. }
  194. bool operator==(const FSTraverseIterator & first,
  195. const FSTraverseIterator & second)
  196. {
  197. typedef FSTraverseIterator::Iterator Iterator;
  198. return (first.m_iterator == Iterator() && second.m_iterator == Iterator())
  199. || (first.m_flags == second.m_flags
  200. && first.m_iterator == second.m_iterator
  201. && first.m_currentFileInfo == second.m_currentFileInfo
  202. );
  203. }
  204. bool operator!=(const FSTraverseIterator & first,
  205. const FSTraverseIterator & second)
  206. {
  207. return !(first == second);
  208. }