Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
6.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef __TREE_H__
  9. #define __TREE_H__
  10. #include "List.h"
  11. #include "ArrayStack.h"
  12. // NTreeNode: Class decleration and definition
  13. template <class T> class NTreeNode
  14. {
  15. public:
  16. // constructor
  17. NTreeNode<T>( T data );
  18. NTreeNode<T> *PrependChild( NTreeNode<T> *node );
  19. NTreeNode<T> *AppendChild( NTreeNode<T> *node );
  20. NTreeNode<T> *InsertChildAfterIndex( NTreeNode<T> *node, int index );
  21. NTreeNode<T> *InsertChildBeforeIndex( NTreeNode<T> *node, int index );
  22. NTreeNode<T> *RemoveChild( Position position );
  23. NTreeNode<T> *RemoveChild( int index );
  24. Position InsertAfter( NTreeNode<T> *node, Position position );
  25. Position InsertBefore( NTreeNode<T> *node, Position position );
  26. int GetNumChildren();
  27. Position GetChildPosition( int childNum );
  28. NTreeNode<T> *GetChild( int childNum );
  29. NTreeNode<T> *GetChild( Position position );
  30. int GetIndexRelativeToParent();
  31. T GetItem();
  32. NTreeNode<T> *GetParent();
  33. NTreeNode<T> *GetRoot();
  34. NTreeNode<T> *GetNextSibling();
  35. void Traverse( void (*VisitFunc)( T, int depth ), int maxTreeDepth );
  36. NTreeNode<T> *ReentrantTraversalGetFirst( int maxTreeDepth );
  37. NTreeNode<T> *ReentrantTraversalGetNext( void );
  38. protected:
  39. GList<NTreeNode<T> * > *list;
  40. T data;
  41. NTreeNode<T> *parent;
  42. ArrayStack<NTreeNode<T> *> *reentrantStack;
  43. };
  44. template <class T>
  45. NTreeNode<T>::NTreeNode( T data )
  46. {
  47. list = new GList<NTreeNode<T> * >;
  48. this->data = data;
  49. this->parent = NULL;
  50. this->reentrantStack = NULL;
  51. }
  52. template <class T>
  53. NTreeNode<T> *NTreeNode<T>::PrependChild( NTreeNode<T> *node )
  54. {
  55. node->parent = this;
  56. return list->GetItemAtPosition( list->InsertAtHead( node ) );
  57. }
  58. template <class T>
  59. NTreeNode<T> *NTreeNode<T>::AppendChild( NTreeNode<T> *node )
  60. {
  61. node->parent = this;
  62. return list->GetItemAtPosition( list->InsertAtTail( node ) );
  63. }
  64. template <class T>
  65. NTreeNode<T> *NTreeNode<T>::InsertChildAfterIndex( NTreeNode<T> *node, int index )
  66. {
  67. node->parent = this;
  68. if( index < 0 )
  69. {
  70. // if out of range in the negative direction, prepend
  71. this->PrependChild( node );
  72. }
  73. else if( index > list->GetNumItems() - 1 )
  74. {
  75. // if out of range, just append.
  76. this->AppendChild( node );
  77. }
  78. else
  79. {
  80. Position pos;
  81. pos = list->GetPositionAtIndex( index );
  82. list->InsertAfter( node, pos );
  83. }
  84. return node;
  85. }
  86. template <class T>
  87. NTreeNode<T> *NTreeNode<T>::InsertChildBeforeIndex( NTreeNode<T> *node, int index )
  88. {
  89. node->parent = this;
  90. if( index < 0 )
  91. {
  92. // if out of range in the negative direction, prepend
  93. this->PrependChild( node );
  94. }
  95. else if( index > list->GetNumItems() - 1 )
  96. {
  97. // if out of range, just append.
  98. this->AppendChild( node );
  99. }
  100. else
  101. {
  102. Position pos;
  103. pos = list->GetPositionAtIndex( index );
  104. list->InsertBefore( node, pos );
  105. }
  106. return node;
  107. }
  108. template <class T>
  109. NTreeNode<T> *NTreeNode<T>::RemoveChild( Position position )
  110. {
  111. NTreeNode<T> **node = ( NTreeNode<T> ** )( void * )position;
  112. ( *node )->parent = NULL;
  113. return list->Remove( position );
  114. }
  115. template <class T>
  116. NTreeNode<T> *NTreeNode<T>::RemoveChild( int index )
  117. {
  118. Position position = list->GetPositionAtIndex( index );
  119. NTreeNode<T> **node = ( NTreeNode<T> ** )( void * )position;
  120. ( *node )->parent = NULL;
  121. return list->Remove( position );
  122. }
  123. template <class T>
  124. Position NTreeNode<T>::InsertAfter( NTreeNode<T> *node, Position position )
  125. {
  126. node->parent = this;
  127. return list->InsertAfter( node, position );
  128. }
  129. template <class T>
  130. Position NTreeNode<T>::InsertBefore( NTreeNode<T> *node, Position position )
  131. {
  132. node->parent = this;
  133. return list->InsertBefore( node, position );
  134. }
  135. template <class T>
  136. int NTreeNode<T>::GetNumChildren()
  137. {
  138. return list->GetNumItems();
  139. }
  140. template <class T>
  141. Position NTreeNode<T>::GetChildPosition( int childNum )
  142. {
  143. return list->GetPositionAtIndex( childNum );
  144. }
  145. template <class T>
  146. NTreeNode<T> *NTreeNode<T>::GetChild( int childNum )
  147. {
  148. return list->GetItemAtIndex( childNum );
  149. }
  150. template <class T>
  151. NTreeNode<T> *NTreeNode<T>::GetChild( Position position )
  152. {
  153. return list->GetItemAtIndex( position );
  154. }
  155. template <class T>
  156. int NTreeNode<T>::GetIndexRelativeToParent()
  157. {
  158. if( !parent )
  159. {
  160. assert( 0 ); // hack
  161. return -1;
  162. }
  163. GListIterator<NTreeNode<T> *> iterator( parent->list );
  164. int i;
  165. for( i = 0, iterator.GotoHead(); !iterator.AtEnd(); iterator++, i++ )
  166. {
  167. if( iterator.GetCurrent() == this )
  168. {
  169. return i;
  170. }
  171. }
  172. assert( 0 ); // hack
  173. return -1;
  174. }
  175. template <class T>
  176. T NTreeNode<T>::GetItem()
  177. {
  178. return data;
  179. }
  180. template <class T>
  181. NTreeNode<T> *NTreeNode<T>::GetParent()
  182. {
  183. return parent;
  184. }
  185. template <class T>
  186. NTreeNode<T> *NTreeNode<T>::GetRoot()
  187. {
  188. NTreeNode<T> *node;
  189. node = this;
  190. while( node->GetParent() )
  191. {
  192. node = node->GetParent();
  193. }
  194. return node;
  195. }
  196. template <class T>
  197. NTreeNode<T> *NTreeNode<T>::GetNextSibling()
  198. {
  199. int currentID, siblingID;
  200. NTreeNode<T> *parent;
  201. parent = this->GetParent();
  202. if( !parent )
  203. {
  204. return NULL;
  205. }
  206. currentID = this->GetIndexRelativeToParent();
  207. siblingID = currentID + 1;
  208. if( siblingID < parent->GetNumChildren() )
  209. {
  210. return parent->GetChild( siblingID );
  211. }
  212. else
  213. {
  214. return NULL;
  215. }
  216. }
  217. template <class T>
  218. void NTreeNode<T>::Traverse( void (*VisitFunc)( T, int depth ), int maxTreeDepth )
  219. {
  220. ArrayStack<NTreeNode<T> *> stack( maxTreeDepth );
  221. NTreeNode<T> *current, *nextSibling;
  222. stack.Push( this );
  223. Visit( this->GetItem(), 0 );
  224. while( !stack.IsEmpty() )
  225. {
  226. current = stack.Pop();
  227. if( current->GetNumChildren() > 0 )
  228. {
  229. stack.Push( current );
  230. stack.Push( current->GetChild( 0 ) );
  231. Visit( current->GetChild( 0 )->GetItem(), stack.GetDepth() - 1 );
  232. }
  233. else
  234. {
  235. while( !stack.IsEmpty() && !( nextSibling = current->GetNextSibling() ) )
  236. {
  237. current = stack.Pop();
  238. }
  239. if( !stack.IsEmpty() )
  240. {
  241. stack.Push( nextSibling );
  242. Visit( nextSibling->GetItem(), stack.GetDepth() - 1 );
  243. }
  244. }
  245. }
  246. }
  247. template <class T>
  248. NTreeNode<T> *NTreeNode<T>::ReentrantTraversalGetFirst( int maxTreeDepth )
  249. {
  250. if( reentrantStack )
  251. {
  252. delete reentrantStack;
  253. }
  254. reentrantStack = new ArrayStack<NTreeNode<T> *>( maxTreeDepth );
  255. reentrantStack->Push( this );
  256. return this;
  257. }
  258. template <class T>
  259. NTreeNode<T> *NTreeNode<T>::ReentrantTraversalGetNext( void )
  260. {
  261. NTreeNode<T> *current, *nextSibling;
  262. while( !reentrantStack->IsEmpty() )
  263. {
  264. current = reentrantStack->Pop();
  265. if( current->GetNumChildren() > 0 )
  266. {
  267. reentrantStack->Push( current );
  268. reentrantStack->Push( current->GetChild( 0 ) );
  269. return current->GetChild( 0 );
  270. }
  271. else
  272. {
  273. while( !reentrantStack->IsEmpty() && !( nextSibling = current->GetNextSibling() ) )
  274. {
  275. current = reentrantStack->Pop();
  276. }
  277. if( !reentrantStack->IsEmpty() )
  278. {
  279. reentrantStack->Push( nextSibling );
  280. return nextSibling;
  281. }
  282. }
  283. }
  284. delete reentrantStack;
  285. reentrantStack = NULL;
  286. return NULL;
  287. }
  288. #endif /* __TREE_H__ */