Source code of Windows XP (NT5)
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.

349 lines
8.8 KiB

  1. #if !defined __DLINK_HXX__
  2. #define __DLINK_HXX__
  3. //+---------------------------------------------------------------------------
  4. //
  5. // File: DLINK.HXX
  6. //
  7. // Contents: Parametrized doubly linked list and iterators
  8. //
  9. // History: 15-Jun-92 BartoszM Created.
  10. //
  11. //----------------------------------------------------------------------------
  12. //+---------------------------------------------------------------------------
  13. //
  14. // Class: CDoubleLink
  15. //
  16. // Purpose: Linked element
  17. //
  18. // History: 15-Jun-92 BartoszM Created.
  19. //
  20. // Notes: Use as base for your class. No need to override anything.
  21. //
  22. // class CFoo: public CDoubleLink
  23. // {
  24. // // your data and code goes here
  25. // };
  26. //
  27. //----------------------------------------------------------------------------
  28. class CDoubleLink
  29. {
  30. public:
  31. CDoubleLink* Next() { return _next; }
  32. CDoubleLink* Prev() { return _prev; }
  33. void Close() { _next = this; _prev = this; }
  34. BOOL IsSingle() const { return _next == this; }
  35. void Unlink()
  36. {
  37. _next->_prev = _prev;
  38. _prev->_next = _next;
  39. }
  40. void InsertBefore ( CDoubleLink* pAfter )
  41. {
  42. CDoubleLink* pBefore = pAfter->_prev;
  43. _next = pAfter;
  44. _prev = pBefore;
  45. pAfter->_prev = this;
  46. pBefore->_next = this;
  47. }
  48. void InsertAfter ( CDoubleLink* pBefore )
  49. {
  50. CDoubleLink* pAfter = pBefore->_next;
  51. _next = pAfter;
  52. _prev = pBefore;
  53. pAfter->_prev = this;
  54. pBefore->_next = this;
  55. }
  56. protected:
  57. CDoubleLink* _next;
  58. CDoubleLink* _prev;
  59. };
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Class: CDoubleList
  63. //
  64. // Purpose: Linked list of indexes
  65. //
  66. // History: 15-Jun-92 BartoszM Created.
  67. // 15-Dec-94 SuChang Added _End() routine
  68. //
  69. // Notes: Use as base for your own class.
  70. // Add methods as needed.
  71. // To implement searches use forward and backward
  72. // iterators described below. For instance, if you implement
  73. // a SORTED list:
  74. //
  75. // Foo* CFooList::Insert ( CFoo* pFoo )
  76. // {
  77. // for ( CBackFooIter it(*this); !AtEnd(it); BackUp(it) )
  78. // {
  79. // if ( it->Size() <= pFoo->Size() ) // overloaded operator ->
  80. // {
  81. // pFoo->InsertAfter(it.GetFoo());
  82. // return;
  83. // }
  84. // }
  85. // // end of list
  86. // Push(pFoo);
  87. // }
  88. //
  89. //----------------------------------------------------------------------------
  90. class CDoubleList
  91. {
  92. friend class CForwardIter;
  93. friend class CBackwardIter;
  94. friend class CDoubleIter;
  95. public:
  96. class CDoubleIter
  97. {
  98. friend class CDoubleList;
  99. protected:
  100. CDoubleIter ( CDoubleLink* pLink ) : _pLinkCur(pLink) {}
  101. CDoubleLink* _pLinkCur;
  102. };
  103. CDoubleList()
  104. {
  105. _root.Close();
  106. }
  107. BOOL IsEmpty() const { return _root.IsSingle(); }
  108. void Advance ( CDoubleIter& it );
  109. void BackUp ( CDoubleIter& it );
  110. BOOL AtEnd ( CDoubleIter& it);
  111. // In derived class you can add your own Pop(), Top(), etc.
  112. // that will cast the results of _Pop(), _Top(), etc...
  113. protected:
  114. CDoubleLink* _Top() { return IsEmpty()? 0: _root.Next(); }
  115. CDoubleLink* _End() { return IsEmpty()? 0: _root.Prev(); }
  116. BOOL _IsRoot ( CDoubleLink* pLink ) const
  117. { return pLink == &_root; }
  118. void _Push ( CDoubleLink* pLink );
  119. void _Queue ( CDoubleLink* pLink );
  120. CDoubleLink* _Pop ( void );
  121. CDoubleLink _root;
  122. };
  123. //+---------------------------------------------------------------------------
  124. //
  125. // Class: CDoubleIter
  126. //
  127. // Purpose: Linked list iterator
  128. //
  129. // History: 17-Jun-92 BartoszM Created.
  130. //
  131. // Notes: Auxiliary class. See iterators below.
  132. //
  133. //----------------------------------------------------------------------------
  134. //+---------------------------------------------------------------------------
  135. //
  136. // Class: CForwardIter
  137. //
  138. // Purpose: Linked list iterator
  139. //
  140. // History: 17-Jun-92 BartoszM Created.
  141. //
  142. // Notes: Use as base for your own forward iterator.
  143. // Notice the overloading of operator ->
  144. // -------------------------------------
  145. // It lets you use iterator like a pointer to Foo.
  146. //
  147. // class CForFooIter : public CForwardIter
  148. // {
  149. // public:
  150. //
  151. // CForFooIter ( CFooList& list ) : CForwardIter(list) {}
  152. //
  153. // CFoo* operator->() { return (CFoo*) _pLinkCur; }
  154. // CFoo* GetFoo() { return (CFoo*) _pLinkCur; }
  155. // };
  156. //
  157. // Example of usage:
  158. // ----------------
  159. //
  160. // for ( CForFooIter it(fooList); !fooList.AtEnd(it); fooList.Advance(it))
  161. // {
  162. // it->FooMethod(); // operator ->
  163. // }
  164. //
  165. //----------------------------------------------------------------------------
  166. class CForwardIter: public CDoubleList::CDoubleIter
  167. {
  168. public:
  169. CForwardIter ( CDoubleList& list ): CDoubleIter(list._root.Next()) {}
  170. };
  171. //+---------------------------------------------------------------------------
  172. //
  173. // Class: CBackwardIter
  174. //
  175. // Purpose: Linked list iterator
  176. //
  177. // History: 17-Jun-92 BartoszM Created.
  178. //
  179. // Notes: See above.
  180. //
  181. //----------------------------------------------------------------------------
  182. class CBackwardIter: public CDoubleList::CDoubleIter
  183. {
  184. public:
  185. CBackwardIter ( CDoubleList& list ): CDoubleIter(list._root.Prev()) {}
  186. };
  187. //+---------------------------------------------------------------------------
  188. //
  189. // Member: CDoubleList::AtEnd, public
  190. //
  191. // Arguments: [it] -- iterator
  192. //
  193. // Returns: TRUE if iterator at end of list
  194. //
  195. // History: 17-Jun-92 BartoszM Created.
  196. //
  197. // Notes: Works for both iterators (forward and backward)
  198. //
  199. //----------------------------------------------------------------------------
  200. inline BOOL CDoubleList::AtEnd ( CDoubleIter& it)
  201. {
  202. return _IsRoot( it._pLinkCur );
  203. }
  204. //+---------------------------------------------------------------------------
  205. //
  206. // Member: CDoubleList::Advance, public
  207. //
  208. // Synopsis: Advances an iterator
  209. //
  210. // Arguments: [it] -- iterator
  211. //
  212. // History: 17-Jun-92 BartoszM Created.
  213. //
  214. //----------------------------------------------------------------------------
  215. inline void CDoubleList::Advance ( CDoubleIter& it )
  216. {
  217. Win4Assert ( !_IsRoot(it._pLinkCur) );
  218. it._pLinkCur = it._pLinkCur->Next();
  219. }
  220. //+---------------------------------------------------------------------------
  221. //
  222. // Member: CDoubleList::BackUp, public
  223. //
  224. // Synopsis: Backs up an iterator
  225. //
  226. // Arguments: [it] -- iterator
  227. //
  228. // History: 17-Jun-92 BartoszM Created.
  229. //
  230. //----------------------------------------------------------------------------
  231. inline void CDoubleList::BackUp ( CDoubleIter& it )
  232. {
  233. Win4Assert ( !_IsRoot(it._pLinkCur) );
  234. it._pLinkCur = it._pLinkCur->Prev();
  235. }
  236. //+---------------------------------------------------------------------------
  237. //
  238. // Member: CDoubleList::Queue, private
  239. //
  240. // Arguments: [pLink] -- link to be queued
  241. //
  242. // History: 17-Mar-93 WadeR Created. (based on Push, below)
  243. //
  244. // Notest: Override, accept only derived class (type safety!), e.g.
  245. //
  246. // void CFooList::Queue ( CFoo* pFoo )
  247. // {
  248. // _Queue ( pFoo );
  249. // }
  250. //
  251. //----------------------------------------------------------------------------
  252. inline void CDoubleList::_Queue ( CDoubleLink* pLink )
  253. {
  254. pLink->InsertBefore ( &_root );
  255. }
  256. //+---------------------------------------------------------------------------
  257. //
  258. // Member: CDoubleList::Push, private
  259. //
  260. // Arguments: [pLink] -- link to be pushed
  261. //
  262. // History: 17-Jun-92 BartoszM Created.
  263. //
  264. // Notest: Override, accept only derived class (type safety!), e.g.
  265. //
  266. // void CFooList::Push ( CFoo* pFoo )
  267. // {
  268. // _Push ( pFoo );
  269. // }
  270. //
  271. //----------------------------------------------------------------------------
  272. inline void CDoubleList::_Push ( CDoubleLink* pLink )
  273. {
  274. pLink->InsertAfter ( &_root );
  275. }
  276. //+---------------------------------------------------------------------------
  277. //
  278. // Member: CDoubleList::_Pop, private
  279. //
  280. // History: 17-Jun-92 BartoszM Created.
  281. //
  282. // Notes: Override: cast the result
  283. //
  284. // CFoo* CFooList::Pop()
  285. // {
  286. // return (CFoo*) _Pop();
  287. // }
  288. //
  289. //----------------------------------------------------------------------------
  290. inline CDoubleLink* CDoubleList::_Pop ( void )
  291. {
  292. CDoubleLink* pLink = 0;
  293. if ( !IsEmpty() )
  294. {
  295. pLink = _root.Next();
  296. pLink->Unlink();
  297. }
  298. return pLink;
  299. }
  300. #endif