Leaked source code of windows server 2003
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.

408 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1997
  6. //
  7. // File: glnk.h
  8. //
  9. //--------------------------------------------------------------------------
  10. //
  11. // GLNK.H
  12. //
  13. // This file defines base classes for smart linked lists.
  14. //
  15. #if !defined(_GLNK_H_)
  16. #define _GLNK_H_
  17. #include "basics.h"
  18. // Disable "warning C4355: 'this' : used in base member initializer list"
  19. #pragma warning ( disable : 4355 )
  20. // Disable warning about using 'bool'
  21. #pragma warning ( disable : 4237 )
  22. // Forward declarations
  23. class GLNK; // Just a linked list anchor
  24. class GELEM; // Base class for trees or dags
  25. class GLNKEL; // A linked element
  26. class GLNKCHN ; // An imbeddable element
  27. class GELEMLNK; // A containerizable element
  28. ////////////////////////////////////////////////////////////////////
  29. // class GLNKBASE: just a pair of pointers. Used as a basis for
  30. // linked lists and bidirectional pointers.
  31. //
  32. ////////////////////////////////////////////////////////////////////
  33. class GLNKBASE // A linked list anchor
  34. {
  35. protected:
  36. GLNKBASE * _plnkNext ; // The next link in the chain
  37. GLNKBASE * _plnkPrev ; // The previous link in the chain
  38. public:
  39. GLNKBASE ()
  40. : _plnkNext(NULL),
  41. _plnkPrev(NULL)
  42. {}
  43. ~ GLNKBASE () {};
  44. GLNKBASE * & PlnkNext () { return _plnkNext ; }
  45. GLNKBASE * & PlnkPrev () { return _plnkPrev ; }
  46. private:
  47. // Block compiler from generating invalid functions
  48. HIDE_UNSAFE(GLNKBASE);
  49. };
  50. // Template to generate a pair of pointers to given subclass
  51. template<class L>
  52. class XLBASE
  53. {
  54. protected:
  55. L * _plNext ;
  56. L * _plPrev ;
  57. public:
  58. XLBASE ()
  59. : _plNext(NULL),
  60. _plPrev(NULL)
  61. {}
  62. L * & PlnkNext () { return _plNext ; }
  63. L * & PlnkPrev () { return _plPrev ; }
  64. const L * PlnkNext () const { return _plNext ; }
  65. const L * PlnkPrev () const { return _plPrev ; }
  66. private:
  67. XLBASE(const XLBASE &);
  68. XLBASE & operator == (const XLBASE &);
  69. };
  70. ////////////////////////////////////////////////////////////////////
  71. // template XLSS: simple alias template using "source" and "sink"
  72. // terminology.
  73. ////////////////////////////////////////////////////////////////////
  74. template<class L>
  75. class XLSS : public XLBASE<L>
  76. {
  77. public:
  78. L * & PlnkSink () { return _plNext ; }
  79. L * & PlnkSource () { return _plPrev ; }
  80. L * PlnkSink () const { return _plNext ; }
  81. L * PlnkSource () const { return _plPrev ; }
  82. };
  83. ////////////////////////////////////////////////////////////////////
  84. // class GLNK: basic doubly-linked list. Linkage is always
  85. // done directly between LNKs, not their containing objects
  86. //
  87. ////////////////////////////////////////////////////////////////////
  88. class GLNK : public GLNKBASE // A linked list anchor
  89. {
  90. protected:
  91. void Empty ()
  92. {
  93. PlnkPrev() = this ;
  94. PlnkNext() = this ;
  95. }
  96. GLNK ()
  97. {
  98. Empty() ;
  99. }
  100. ~ GLNK ()
  101. {
  102. Unlink() ;
  103. }
  104. void Link ( GLNK * plnkNext )
  105. {
  106. Unlink() ;
  107. PlnkPrev() = plnkNext->PlnkPrev() ;
  108. PlnkNext() = plnkNext ;
  109. plnkNext->PlnkPrev()->PlnkNext() = this ;
  110. PlnkNext()->PlnkPrev() = this ;
  111. }
  112. void Unlink ()
  113. {
  114. PlnkNext()->PlnkPrev() = PlnkPrev() ;
  115. PlnkPrev()->PlnkNext() = PlnkNext() ;
  116. Empty() ;
  117. }
  118. // Const and non-const accessor to base pointer pair
  119. GLNK * & PlnkNext () { return (GLNK *&) _plnkNext ; }
  120. GLNK * & PlnkPrev () { return (GLNK *&) _plnkPrev ; }
  121. const GLNK * PlnkNext () const { return (GLNK *) _plnkNext ; }
  122. const GLNK * PlnkPrev () const { return (GLNK *) _plnkPrev ; }
  123. public:
  124. // Return count of elements on list, including self
  125. long Count () const
  126. {
  127. long cItem = 1 ;
  128. for ( GLNK * plnkNext = (CONST_CAST(GLNK *, this))->PlnkNext() ;
  129. plnkNext != this ;
  130. plnkNext = plnkNext->PlnkNext() )
  131. {
  132. cItem++ ;
  133. }
  134. return cItem ;
  135. }
  136. bool BIsEmpty () const { return PlnkNext() == this ; }
  137. private:
  138. // Block compiler from generating invalid functions
  139. HIDE_UNSAFE(GLNK);
  140. };
  141. ////////////////////////////////////////////////////////////////////
  142. // class GELEM: Base class for linkable objects
  143. ////////////////////////////////////////////////////////////////////
  144. const int g_IGelemTypeInc = 10000;
  145. class GELEM
  146. {
  147. friend class GLNKCHN ;
  148. public:
  149. GELEM() {}
  150. virtual ~ GELEM () {}
  151. enum EGELMTYPE
  152. {
  153. EGELM_NONE = 0,
  154. EGELM_NODE = EGELM_NONE + g_IGelemTypeInc,
  155. EGELM_EDGE = EGELM_NODE + g_IGelemTypeInc,
  156. EGELM_BRANCH = EGELM_EDGE + g_IGelemTypeInc,
  157. EGELM_LEAF = EGELM_BRANCH + g_IGelemTypeInc,
  158. EGELM_GRAPH = EGELM_LEAF + g_IGelemTypeInc,
  159. EGELM_TREE = EGELM_GRAPH + g_IGelemTypeInc,
  160. EGELM_CLIQUE = EGELM_GRAPH + g_IGelemTypeInc
  161. };
  162. virtual INT EType () const
  163. { return EGELM_NONE ; }
  164. bool BIsEType ( INT egelmType )
  165. {
  166. INT etype = egelmType / g_IGelemTypeInc;
  167. INT etypeThis = EType() / g_IGelemTypeInc;
  168. return etype == etypeThis;
  169. }
  170. protected:
  171. // Return the offset of the given pointer pair from the element.
  172. int CbOffsetFrom ( const GLNKBASE * p ) const
  173. // One could assert that the GLNKCHN really lies within object
  174. // boundaries by using a virtualized "sizeof" accessor. Also,
  175. // check mod-4 and other validity conditions.
  176. { return ((char*)p) - ((char*)this) ; }
  177. };
  178. ////////////////////////////////////////////////////////////////////
  179. // class GLNKCHN:
  180. // A GLNK which knows its offset within the containing object.
  181. //
  182. // To perform doubly-linked list operations, two pieces of information
  183. // are necessary: the location of the pointer pair and the location
  184. // of the containing object. By giving the GLNKCHN its offset from
  185. // the start of the object during construction, it can perform all
  186. // necessary operations, including automatically unlinking during
  187. // destruction.
  188. ////////////////////////////////////////////////////////////////////
  189. class GLNKCHN : public GLNK
  190. {
  191. private:
  192. int _cbOffset ; // Number of bytes offset from
  193. // start of owning structure
  194. public:
  195. GLNKCHN ( GELEM * pgelemOwner )
  196. : _cbOffset(0)
  197. {
  198. _cbOffset = pgelemOwner->CbOffsetFrom( this );
  199. }
  200. ~ GLNKCHN () {}
  201. void Link ( GELEM * pgelemNext )
  202. {
  203. // Assuming that the GLNKCHN onto which we're linking is at the
  204. // same offset in the given GLNKEL as it is in *this, link it.
  205. GLNKCHN * plnkchn = PlnkchnPtr( pgelemNext );
  206. GLNK::Link( plnkchn ) ;
  207. }
  208. void Unlink ()
  209. {
  210. GLNK::Unlink() ;
  211. }
  212. GELEM * PgelemNext ()
  213. {
  214. return BIsEmpty()
  215. ? NULL
  216. : PlnkchnNext()->PgelemChainOwnerPtr() ;
  217. }
  218. GELEM * PgelemPrev ()
  219. {
  220. return BIsEmpty()
  221. ? NULL
  222. : PlnkchnPrev()->PgelemChainOwnerPtr() ;
  223. }
  224. protected:
  225. // Return a pointer to the base object. given a pointer to one of
  226. // its GLNKCHN member objects.
  227. GELEM * PgelemChainOwnerPtr () const
  228. { return (GELEM *) (((SZC) this) - _cbOffset) ; }
  229. // Given a pointer to a GELEM presumed to be of the same base
  230. // type as this object's container, return a pointer to the
  231. // corresponding GLNKCHN in it.
  232. GLNKCHN * PlnkchnPtr ( const GELEM * pgelem ) const
  233. {
  234. #ifdef _DEBUG
  235. // Debug version does error checking
  236. GLNKCHN * plnkchn = (GLNKCHN *) (((SZC) pgelem) + _cbOffset);
  237. if ( _cbOffset != plnkchn->_cbOffset )
  238. throw GMException(EC_LINK_OFFSET,"invalid GLNKCHN offset");
  239. return plnkchn;
  240. #else
  241. return (GLNKCHN *) (((SZC) pgelem) + _cbOffset);
  242. #endif
  243. }
  244. // Protected accessors to GLNK pointers cast to GLNKCHN pointers
  245. GLNKCHN * PlnkchnNext () { return (GLNKCHN *) GLNK::PlnkNext() ; }
  246. GLNKCHN * PlnkchnPrev () { return (GLNKCHN *) GLNK::PlnkPrev() ; }
  247. private:
  248. HIDE_UNSAFE(GLNKCHN);
  249. };
  250. ////////////////////////////////////////////////////////////////////
  251. // template XCHN:
  252. // for creating types of chains given a containing object
  253. // which is a subclass of GELEM
  254. ////////////////////////////////////////////////////////////////////
  255. template<class XOBJ>
  256. class XCHN : public GLNKCHN
  257. {
  258. public:
  259. XCHN ( XOBJ * pgelemOwner )
  260. : GLNKCHN(pgelemOwner)
  261. {}
  262. void Link ( XOBJ * pgelemNext )
  263. { GLNKCHN::Link(pgelemNext); }
  264. void Unlink ()
  265. { GLNKCHN::Unlink(); }
  266. XOBJ * PgelemNext ()
  267. { return (XOBJ *) GLNKCHN::PgelemNext(); }
  268. XOBJ * PgelemPrev ()
  269. { return (XOBJ *) GLNKCHN::PgelemPrev(); }
  270. XOBJ * PgelemThis ()
  271. { return PgelemChainOwnerPtr(); }
  272. protected:
  273. XOBJ * PgelemChainOwnerPtr () const
  274. { return (XOBJ *) GLNKCHN::PgelemChainOwnerPtr(); }
  275. XCHN * PlnkchnPtr ( const XOBJ * pgelem ) const
  276. { return (XCHN *) GLNKCHN::PlnkchnPtr(pgelem); }
  277. XCHN * PlnkchnNext () { return (XCHN *) GLNKCHN::PlnkchnNext() ; }
  278. XCHN * PlnkchnPrev () { return (XCHN *) GLNKCHN::PlnkchnPrev() ; }
  279. private:
  280. XCHN(const XCHN &);
  281. XCHN & operator == (const XCHN &);
  282. };
  283. ////////////////////////////////////////////////////////////////////
  284. // Class GLNKEL:
  285. // Simple base class for things managed as members of linked lists.
  286. // One or more LNKCHNs or LNKs can be contained within subclass objects;
  287. // it contains one "implicit" GLNKCHN for linking siblings in the
  288. // implicit tree created by NTREE.
  289. // Trees are based upon this type.
  290. ////////////////////////////////////////////////////////////////////
  291. class GLNKEL : public GELEM
  292. {
  293. public:
  294. // Internal class for chains (doubly-linked lists)
  295. typedef XCHN<GLNKEL> CHN;
  296. GLNKEL ()
  297. : _chn( this ),
  298. _iType(0),
  299. _iMark(0)
  300. {}
  301. virtual ~ GLNKEL () {}
  302. CHN & Chn ()
  303. { return _chn ; }
  304. GLNKEL * PlnkelPrev ()
  305. { return Chn().PgelemPrev() ; }
  306. GLNKEL * PlnkelNext ()
  307. { return Chn().PgelemNext() ; }
  308. // Return the mutable (user-definable) object type
  309. INT & IType () { return _iType; }
  310. INT IType() const { return _iType; }
  311. INT & IMark () { return _iMark; }
  312. INT IMark () const { return _iMark; }
  313. protected:
  314. CHN _chn ; // Primary association chain
  315. INT _iType; // User-definable type
  316. INT _iMark; // Network walking mark
  317. protected:
  318. // Throw an exception when an invalid cloning operation occurs
  319. void ThrowInvalidClone ( const GLNKEL & t );
  320. HIDE_UNSAFE(GLNKEL);
  321. };
  322. ////////////////////////////////////////////////////////////////////
  323. // Class GELEMLNK:
  324. // Base class for linkable objects in a collection, such as
  325. // graph. Trees are NOT based upon this type, since trees
  326. // are not forests (they cannot have associated but disjoint
  327. // sets of objects).
  328. ////////////////////////////////////////////////////////////////////
  329. class GELEMLNK : public GLNKEL
  330. {
  331. public:
  332. // Internal class for chains (doubly-linked lists)
  333. typedef XCHN<GELEMLNK> CHN;
  334. GELEMLNK () {}
  335. virtual ~ GELEMLNK () {}
  336. // Locate an element (other than 'this') by type
  337. GELEMLNK * PglnkFind ( EGELMTYPE eType, bool bExact = false )
  338. {
  339. for ( GELEMLNK * pg = this;
  340. pg->ChnColl().PgelemThis() != this;
  341. pg = pg->ChnColl().PgelemNext() )
  342. {
  343. if ( bExact ? pg->EType() == eType : pg->BIsEType(eType) )
  344. return pg;
  345. }
  346. return NULL;
  347. }
  348. // Element chain: all items belonging to this collection
  349. CHN & ChnColl ()
  350. { return (CHN &) _chn ; }
  351. private:
  352. HIDE_UNSAFE(GELEMLNK);
  353. };
  354. #endif // !defined(_GLNK_H_)
  355. // End of glnk.h