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.

365 lines
18 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. splutil.hxx
  6. Abstract:
  7. Common utils.
  8. Author:
  9. Albert Ting (AlbertT) 29-May-1994
  10. Revision History:
  11. --*/
  12. #ifndef _SPLUTIL_HXX
  13. #define _SPLUTIL_HXX
  14. //
  15. // Double linked list. DLINK must be the same as DLINKBASE, except
  16. // with differnt constructors.
  17. //
  18. typedef struct DLINK {
  19. DLINK()
  20. { FLink = NULL; }
  21. DLINK* FLink;
  22. DLINK* BLink;
  23. } *PDLINK;
  24. typedef struct DLINKBASE {
  25. DLINKBASE()
  26. { FLink = BLink = (PDLINK)this; }
  27. DLINK* FLink;
  28. DLINK* BLink;
  29. } *PDLINKBASE;
  30. class TIter {
  31. public:
  32. PDLINK _pdlink;
  33. PDLINK _pdlBase;
  34. BOOL
  35. bValid()
  36. { return _pdlink != _pdlBase; }
  37. VOID
  38. vNext()
  39. { _pdlink = _pdlink->FLink; }
  40. VOID
  41. vPrev()
  42. { _pdlink = _pdlink->BLink; }
  43. operator PDLINK()
  44. { return _pdlink; }
  45. };
  46. VOID
  47. LinkListDump(
  48. PDLINK pHead,
  49. DWORD offset,
  50. LPCSTR pcszType,
  51. LPCSTR pcszName
  52. );
  53. /********************************************************************
  54. // Forward reference.
  55. class TLink;
  56. TBase has two linked lists of TLink.
  57. class TBase {
  58. DLINK_BASE( TLink, Link, Link );
  59. DLINK_BASE( TLink, Link2, Link2 );
  60. };
  61. class TLink {
  62. DLINK( TLink, Link );
  63. DLINK( TLink, Link2 );
  64. };
  65. //
  66. // Append pLink to the end of the Link2 list.
  67. //
  68. pBase->Link2_vAppend( pLink );
  69. //
  70. // Insert pLinkInsert right after pLinkMiddle.
  71. //
  72. pBase->Link_vInsert( pLinkMiddle, pLinkInsert );
  73. //
  74. // Get to the head.
  75. //
  76. pLinkHead = pBase->Link_pHead();
  77. //
  78. // To get to the next element in the list.
  79. //
  80. pLink = pLinkHead->Link_pNext();
  81. //
  82. // Remove an element from the list.
  83. //
  84. pLink->pLink_vDelinkSelf();
  85. //
  86. // Using the iter class.
  87. //
  88. TIter Iter;
  89. for( Link_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); Iter.vNext( )){
  90. //
  91. // Use pLink.
  92. //
  93. vLinkOperation( pLink );
  94. }
  95. ********************************************************************/
  96. #define DLINK_BASE( type, name, linkname ) \
  97. VOID name##_vReset() \
  98. { pdl##name()->FLink = pdl##name()->BLink = pdl##name(); } \
  99. \
  100. PDLINK name##_pdlHead() const \
  101. { return pdl##name()->FLink; } \
  102. \
  103. PDLINK name##_pdlBase() const \
  104. { return pdl##name(); } \
  105. \
  106. type* name##_pHead( VOID ) const \
  107. { \
  108. return name##_bValid( name##_pdlHead() ) ? \
  109. (type*)((PBYTE)name##_pdlHead() - OFFSETOF( type, \
  110. _dl##linkname )) : \
  111. NULL; \
  112. } \
  113. \
  114. BOOL name##_bValid( PDLINK pdlink ) const \
  115. { return pdlink != pdl##name(); } \
  116. \
  117. VOID name##_vAdd( type* pType ) \
  118. { name##_vInsert( pdl##name(), pType->pdl##linkname( )); } \
  119. \
  120. VOID name##_vAppend( type* pType ) \
  121. { name##_vInsert( pdl##name()->BLink, pType->pdl##linkname( )); } \
  122. \
  123. VOID name##_vInsert( PDLINK pdlink1, type* pType2 ) \
  124. { name##_vInsert( pdlink1, pType2->pdl##linkname() ); } \
  125. \
  126. VOID name##_vInsert( PDLINK pdlink1, PDLINK pdlink2 ) \
  127. { \
  128. SPLASSERT( !pdlink2->FLink ); \
  129. pdlink1->FLink->BLink = pdlink2; \
  130. \
  131. pdlink2->BLink = pdlink1; \
  132. pdlink2->FLink = pdlink1->FLink; \
  133. \
  134. pdlink1->FLink = pdlink2; \
  135. } \
  136. \
  137. VOID name##_vInsertBefore( PDLINK pdlink1, type* pType2 ) \
  138. { name##_vInsertBefore( pdlink1, pType2->pdl##linkname() ); } \
  139. \
  140. VOID name##_vInsertBefore( PDLINK pdlink1, PDLINK pdlink2 ) \
  141. { \
  142. SPLASSERT( !pdlink2->FLink ); \
  143. pdlink1->BLink->FLink = pdlink2; \
  144. \
  145. pdlink2->FLink = pdlink1; \
  146. pdlink2->BLink = pdlink1->BLink; \
  147. \
  148. pdlink1->BLink = pdlink2; \
  149. } \
  150. \
  151. VOID name##_vDelink( type* pType ) \
  152. { name##_vDelink( pType->pdl##linkname( )); } \
  153. \
  154. VOID name##_vDelink( PDLINK pdlink ) \
  155. { \
  156. pdlink->FLink->BLink = pdlink->BLink; \
  157. pdlink->BLink->FLink = pdlink->FLink; \
  158. pdlink->FLink = NULL; \
  159. } \
  160. \
  161. type* name##_pFind( type* pType ) const \
  162. { \
  163. PDLINK pdlinkT; \
  164. PDLINK pdlink = pType->pdl##linkname(); \
  165. \
  166. for( pdlinkT = name##_pdlHead(); \
  167. name##_bValid( pdlinkT ); \
  168. pdlinkT = pdlinkT->FLink ){ \
  169. \
  170. if( pType->pdl##linkname() == pdlinkT ) \
  171. return (type*)((PBYTE)pdlink - OFFSETOF( type, \
  172. _dl##linkname )); \
  173. } \
  174. return NULL; \
  175. } \
  176. \
  177. PDLINK name##_pdlFind( PDLINK pdlink ) const \
  178. { \
  179. PDLINK pdlinkT; \
  180. for( pdlinkT = name##_pdlHead(); \
  181. name##_bValid( pdlinkT ); \
  182. pdlinkT = pdlinkT->FLink ){ \
  183. \
  184. if( pdlink == pdlinkT ) \
  185. return pdlink; \
  186. } \
  187. return NULL; \
  188. } \
  189. \
  190. PDLINK name##_pdlGetByIndex( UINT uIndex ) const \
  191. { \
  192. PDLINK pdlink; \
  193. for( pdlink = name##_pdlHead(); \
  194. uIndex; \
  195. uIndex--, pdlink = pdlink->FLink ){ \
  196. \
  197. SPLASSERT( name##_bValid( pdlink )); \
  198. } \
  199. return pdlink; \
  200. } \
  201. \
  202. type* name##_pGetByIndex( UINT uIndex ) const \
  203. { \
  204. PDLINK pdlink; \
  205. for( pdlink = name##_pdlHead(); \
  206. uIndex; \
  207. uIndex--, pdlink = pdlink->FLink ){ \
  208. \
  209. SPLASSERT( name##_bValid( pdlink )); \
  210. } \
  211. return name##_pConvert( pdlink ); \
  212. } \
  213. \
  214. VOID name##_vDump( VOID ) const \
  215. { \
  216. LinkListDump( pdl##name(), \
  217. OFFSETOF( type, _dl##linkname ), \
  218. #type, \
  219. #name ); \
  220. } \
  221. \
  222. static PDLINK name##_pdlNext( PDLINK pdlink ) \
  223. { return pdlink->FLink; } \
  224. \
  225. static type* name##_pConvert( PDLINK pdlink ) \
  226. { return (type*)( (PBYTE)pdlink - OFFSETOF( type, _dl##linkname )); } \
  227. \
  228. PDLINK pdl##name( VOID ) const \
  229. { return (PDLINK)&_dlb##name; } \
  230. \
  231. BOOL name##_bEmpty() const \
  232. { return pdl##name()->FLink == pdl##name(); } \
  233. \
  234. VOID name##_vIterInit( TIter& Iter ) const \
  235. { Iter._pdlBase = Iter._pdlink = (PDLINK)&_dlb##name; } \
  236. \
  237. DLINKBASE _dlb##name;
  238. \
  239. #define DLINK( type, name ) \
  240. PDLINK pdl##name() \
  241. { return &_dl##name; } \
  242. \
  243. VOID name##_vDelinkSelf( VOID ) \
  244. { \
  245. _dl##name.FLink->BLink = _dl##name.BLink; \
  246. _dl##name.BLink->FLink = _dl##name.FLink; \
  247. _dl##name.FLink = NULL; \
  248. } \
  249. \
  250. BOOL name##_bLinked() const \
  251. { return _dl##name.FLink != NULL; } \
  252. \
  253. PDLINK name##_pdlNext( VOID ) const \
  254. { return _dl##name.FLink; } \
  255. \
  256. PDLINK name##_pdlPrev( VOID ) const \
  257. { return _dl##name.BLink; } \
  258. \
  259. type* name##_pNext( VOID ) const \
  260. { return name##_pConvert( _dl##name.FLink ); } \
  261. \
  262. type* name##_pPrev( VOID ) const \
  263. { return name##_pConvert( _dl##name.BLink ); } \
  264. \
  265. static type* name##_pConvert( PDLINK pdlink ) \
  266. { return (type*)( (PBYTE)pdlink - OFFSETOF( type, _dl##name )); } \
  267. \
  268. DLINK _dl##name
  269. //
  270. // Generic MEntry class that allows objects to be stored on a list
  271. // and searched by name.
  272. //
  273. class MEntry {
  274. SIGNATURE( 'entr' )
  275. public:
  276. DLINK( MEntry, Entry );
  277. TString _strName;
  278. BOOL bValid()
  279. {
  280. return _strName.bValid();
  281. }
  282. static MEntry* pFindEntry( PDLINK pdlink, LPCTSTR pszName );
  283. };
  284. #define ENTRY_BASE( type, name ) \
  285. friend MEntry; \
  286. type* name##_pFindByName( LPCTSTR pszName ) const \
  287. { \
  288. MEntry* pEntry = MEntry::pFindEntry( name##_pdlBase(), pszName ); \
  289. return pEntry ? (type*)pEntry : NULL; \
  290. } \
  291. static type* name##_pConvertEntry( PDLINK pdlink ) \
  292. { \
  293. return (type*)name##_pConvert( pdlink ); \
  294. } \
  295. DLINK_BASE( MEntry, name, Entry )
  296. #define DELETE_ENTRY_LIST( type, name ) \
  297. { \
  298. PDLINK pdlink; \
  299. type* pType; \
  300. \
  301. for( pdlink = name##_pdlHead(); name##_bValid( pdlink ); ){ \
  302. \
  303. pType = name##_pConvertEntry( pdlink ); \
  304. pdlink = name##_pdlNext( pdlink ); \
  305. \
  306. pType->vDelete(); \
  307. } \
  308. }
  309. #endif // ndef _SPLUTIL_HXX