cmLinkedTree.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2015 Stephen Kelly <[email protected]>
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #ifndef cmLinkedTree_h
  11. #define cmLinkedTree_h
  12. #include "cmStandardIncludes.h"
  13. #include <assert.h>
  14. /**
  15. @brief A adaptor for traversing a tree structure in a vector
  16. This class is not intended to be wholly generic like a standard library
  17. container adaptor. Mostly it exists to facilitate code sharing for the
  18. needs of the cmState. For example, the Truncate() method is a specific
  19. requirement of the cmState.
  20. An empty cmLinkedTree provides a Root() method, and an Push() method,
  21. each of which return iterators. A Tree can be built up by extending
  22. from the root, and then extending from any other iterator.
  23. An iterator resulting from this tree construction can be
  24. forward-only-iterated toward the root. Extending the tree never
  25. invalidates existing iterators.
  26. */
  27. template<typename T>
  28. class cmLinkedTree
  29. {
  30. typedef typename std::vector<T>::size_type PositionType;
  31. typedef T* PointerType;
  32. typedef T& ReferenceType;
  33. public:
  34. class iterator : public std::iterator<std::forward_iterator_tag, T>
  35. {
  36. friend class cmLinkedTree;
  37. cmLinkedTree* Tree;
  38. // The Position is always 'one past the end'.
  39. PositionType Position;
  40. iterator(cmLinkedTree* tree, PositionType pos)
  41. : Tree(tree), Position(pos)
  42. {
  43. }
  44. public:
  45. iterator()
  46. : Tree(0), Position(0)
  47. {
  48. }
  49. void operator++()
  50. {
  51. assert(this->Tree);
  52. assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
  53. assert(this->Position <= this->Tree->Data.size());
  54. assert(this->Position > 0);
  55. this->Position = this->Tree->UpPositions[this->Position - 1];
  56. }
  57. PointerType operator->() const
  58. {
  59. assert(this->Tree);
  60. assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
  61. assert(this->Position <= this->Tree->Data.size());
  62. assert(this->Position > 0);
  63. return this->Tree->GetPointer(this->Position - 1);
  64. }
  65. PointerType operator->()
  66. {
  67. assert(this->Tree);
  68. assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
  69. assert(this->Position <= this->Tree->Data.size());
  70. assert(this->Position > 0);
  71. return this->Tree->GetPointer(this->Position - 1);
  72. }
  73. ReferenceType operator*() const
  74. {
  75. assert(this->Tree);
  76. assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
  77. assert(this->Position <= this->Tree->Data.size());
  78. assert(this->Position > 0);
  79. return this->Tree->GetReference(this->Position - 1);
  80. }
  81. ReferenceType operator*()
  82. {
  83. assert(this->Tree);
  84. assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
  85. assert(this->Position <= this->Tree->Data.size());
  86. assert(this->Position > 0);
  87. return this->Tree->GetReference(this->Position - 1);
  88. }
  89. bool operator==(iterator other) const
  90. {
  91. assert(this->Tree);
  92. assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
  93. assert(this->Tree == other.Tree);
  94. return this->Position == other.Position;
  95. }
  96. bool operator!=(iterator other) const
  97. {
  98. assert(this->Tree);
  99. assert(this->Tree->UpPositions.size() == this->Tree->Data.size());
  100. return !(*this == other);
  101. }
  102. bool IsValid() const
  103. {
  104. if (!this->Tree)
  105. {
  106. return false;
  107. }
  108. return this->Position <= this->Tree->Data.size();
  109. }
  110. bool StrictWeakOrdered(iterator other) const
  111. {
  112. assert(this->Tree);
  113. assert(this->Tree == other.Tree);
  114. return this->Position < other.Position;
  115. }
  116. };
  117. iterator Root() const
  118. {
  119. return iterator(const_cast<cmLinkedTree*>(this), 0);
  120. }
  121. iterator Push(iterator it)
  122. {
  123. return Push_impl(it, T());
  124. }
  125. iterator Push(iterator it, T t)
  126. {
  127. return Push_impl(it, t);
  128. }
  129. bool IsLast(iterator it)
  130. {
  131. return it.Position == this->Data.size();
  132. }
  133. iterator Pop(iterator it)
  134. {
  135. assert(!this->Data.empty());
  136. assert(this->UpPositions.size() == this->Data.size());
  137. bool const isLast = this->IsLast(it);
  138. ++it;
  139. // If this is the last entry then no other entry can refer
  140. // to it so we can drop its storage.
  141. if (isLast)
  142. {
  143. this->Data.pop_back();
  144. this->UpPositions.pop_back();
  145. }
  146. return it;
  147. }
  148. iterator Truncate()
  149. {
  150. assert(this->UpPositions.size() > 0);
  151. this->UpPositions.erase(this->UpPositions.begin() + 1,
  152. this->UpPositions.end());
  153. assert(this->Data.size() > 0);
  154. this->Data.erase(this->Data.begin() + 1, this->Data.end());
  155. return iterator(this, 1);
  156. }
  157. void Clear()
  158. {
  159. this->UpPositions.clear();
  160. this->Data.clear();
  161. }
  162. private:
  163. T& GetReference(PositionType pos)
  164. {
  165. return this->Data[pos];
  166. }
  167. T* GetPointer(PositionType pos)
  168. {
  169. return &this->Data[pos];
  170. }
  171. iterator Push_impl(iterator it, T t)
  172. {
  173. assert(this->UpPositions.size() == this->Data.size());
  174. assert(it.Position <= this->UpPositions.size());
  175. this->UpPositions.push_back(it.Position);
  176. this->Data.push_back(t);
  177. return iterator(this, this->UpPositions.size());
  178. }
  179. std::vector<T> Data;
  180. std::vector<PositionType> UpPositions;
  181. };
  182. #endif