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.

556 lines
8.5 KiB

  1. /*++
  2. Copyright (C) 2000 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. list.cxx
  6. Abstract:
  7. List template class.
  8. Author:
  9. Steve Kiraly (SteveKi) 03-Mar-2000
  10. Revision History:
  11. --*/
  12. /********************************************************************
  13. List class, used for intrusive list.
  14. ********************************************************************/
  15. template<class T>
  16. TList<T>::
  17. TList(
  18. VOID
  19. )
  20. {
  21. }
  22. template<class T>
  23. TList<T>::
  24. ~TList(
  25. VOID
  26. )
  27. {
  28. //
  29. // Release all the nodes.
  30. //
  31. TLink *pLink = m_Root.Next();
  32. TLink *pTemp = NULL;
  33. while (pLink != &m_Root)
  34. {
  35. pTemp = pLink;
  36. pLink = pLink->Next();
  37. delete pTemp;
  38. }
  39. }
  40. template<class T>
  41. HRESULT
  42. TList<T>::
  43. IsValid(
  44. VOID
  45. ) const
  46. {
  47. return S_OK;
  48. }
  49. template<class T>
  50. BOOL
  51. TList<T>::
  52. IsEmpty(
  53. VOID
  54. )
  55. {
  56. //
  57. // If the next pointer is ourself the list is empty.
  58. //
  59. return &m_Root == m_Root.Next();
  60. }
  61. template<class T>
  62. BOOL
  63. TList<T>::
  64. IsLast(
  65. IN TLink *pLink
  66. )
  67. {
  68. //
  69. // If the next pointer is ourself the link is the last one.
  70. //
  71. return pLink->Next() == &m_Root;
  72. }
  73. template<class T>
  74. HRESULT
  75. TList<T>::
  76. AddAtHead(
  77. IN TLink *pLink
  78. )
  79. {
  80. //
  81. // Check if the node is valid.
  82. //
  83. HRESULT hRetval = pLink ? pLink->IsValid() : E_INVALIDARG;
  84. if (SUCCEEDED(hRetval))
  85. {
  86. //
  87. // Add the node at the head of the list.
  88. //
  89. hRetval = m_Root.Link(pLink);
  90. }
  91. return hRetval;
  92. }
  93. template<class T>
  94. HRESULT
  95. TList<T>::
  96. AddAtTail(
  97. IN TLink *pLink
  98. )
  99. {
  100. //
  101. // Check if the node is valid.
  102. //
  103. HRESULT hRetval = pLink ? pLink->IsValid() : E_INVALIDARG;
  104. if (SUCCEEDED(hRetval))
  105. {
  106. //
  107. // Add the node at the tail of the list.
  108. //
  109. hRetval = m_Root.Prev()->Link(pLink);
  110. }
  111. return hRetval;
  112. }
  113. template<class T>
  114. HRESULT
  115. TList<T>::
  116. Insert(
  117. IN TLink *pLink,
  118. IN TLink *pHere
  119. )
  120. {
  121. //
  122. // Check if the node is valid.
  123. //
  124. HRESULT hRetval = pLink ? pLink->IsValid() : E_INVALIDARG;
  125. if (SUCCEEDED(hRetval))
  126. {
  127. hRetval = pHere ? pHere->IsValid() : E_INVALIDARG;
  128. if (SUCCEEDED(hRetval))
  129. {
  130. //
  131. // Link the specified node just after the apecified node.
  132. //
  133. hRetval = pHere->Link(pLink);
  134. }
  135. else
  136. {
  137. //
  138. // Link this node to the head of the list.
  139. //
  140. hRetval = m_Root.Link(pLink);
  141. }
  142. }
  143. return hRetval;
  144. }
  145. template<class T>
  146. T *
  147. TList<T>::
  148. RemoveAtHead(
  149. VOID
  150. )
  151. {
  152. TLink *pLink = m_Root.Next();
  153. pLink->UnLink();
  154. return pLink != &m_Root ? reinterpret_cast<T *>(pLink) : NULL;
  155. }
  156. template<class T>
  157. T *
  158. TList<T>::
  159. RemoveAtTail(
  160. VOID
  161. )
  162. {
  163. TLink *pLink = m_Root.Prev();
  164. pLink->UnLink();
  165. return pLink != &m_Root ? reinterpret_cast<T *>(pLink) : NULL;
  166. }
  167. template<class T>
  168. HRESULT
  169. TList<T>::
  170. Remove(
  171. IN TLink *pLink
  172. )
  173. {
  174. //
  175. // We only succeed if work was done.
  176. //
  177. HRESULT hRetval = E_FAIL;
  178. if (pLink)
  179. {
  180. //
  181. // Release the node, the caller must delete themselves.
  182. //
  183. pLink->UnLink();
  184. hRetval = S_OK;
  185. }
  186. return hRetval;
  187. }
  188. template<class T>
  189. T *
  190. TList<T>::
  191. Head(
  192. VOID
  193. ) const
  194. {
  195. TLink *pLink = m_Root.Next();
  196. return pLink != &m_Root ? reinterpret_cast<T *>(pLink) : NULL;
  197. }
  198. template<class T>
  199. T *
  200. TList<T>::
  201. Tail(
  202. VOID
  203. ) const
  204. {
  205. TLink *pLink = m_Root.Prev();
  206. return pLink != &m_Root ? reinterpret_cast<T *>(pLink) : NULL;
  207. }
  208. /********************************************************************
  209. List class, used for non intrusive list.
  210. ********************************************************************/
  211. template<class T>
  212. TLinkNi<T>::
  213. TLinkNi(
  214. IN T *pInfo
  215. ) : m_pInfo(pInfo)
  216. {
  217. }
  218. template<class T>
  219. TLinkNi<T>::
  220. ~TLinkNi(
  221. VOID
  222. )
  223. {
  224. m_pInfo = NULL;
  225. }
  226. template<class T>
  227. HRESULT
  228. TLinkNi<T>::
  229. IsValid(
  230. VOID
  231. ) const
  232. {
  233. return S_OK;
  234. }
  235. template<class T>
  236. T *
  237. TLinkNi<T>::
  238. Get(
  239. VOID
  240. ) const
  241. {
  242. return m_pInfo;
  243. }
  244. template<class T>
  245. TLinkNi<T> *
  246. TLinkNi<T>::
  247. Next(
  248. VOID
  249. ) const
  250. {
  251. return static_cast<TLinkNi<T> *>(TLink::Next());
  252. }
  253. template<class T>
  254. TLinkNi<T> *
  255. TLinkNi<T>::
  256. Prev(
  257. VOID
  258. ) const
  259. {
  260. return static_cast<TLinkNi<T> *>(TLink::Prev());
  261. }
  262. //
  263. // Spooler non instrusive list template.
  264. //
  265. template<class T>
  266. TListNi<T>::
  267. TListNi(
  268. VOID
  269. ) : m_Root(NULL)
  270. {
  271. }
  272. template<class T>
  273. TListNi<T>::
  274. ~TListNi(
  275. VOID
  276. )
  277. {
  278. //
  279. // Release all the nodes, the clients must release
  280. // their own data.
  281. //
  282. TLinkNi<T> *pNode = m_Root.Next();
  283. TLinkNi<T> *pTemp = NULL;
  284. while (pNode != &m_Root)
  285. {
  286. pTemp = pNode;
  287. pNode = pNode->Next();
  288. delete pTemp;
  289. }
  290. }
  291. template<class T>
  292. HRESULT
  293. TListNi<T>::
  294. IsValid(
  295. VOID
  296. ) const
  297. {
  298. return S_OK;
  299. }
  300. template<class T>
  301. BOOL
  302. TListNi<T>::
  303. IsEmpty(
  304. VOID
  305. ) const
  306. {
  307. //
  308. // If the next pointer is ourself the list is empty.
  309. //
  310. return &m_Root == m_Root.Next();
  311. }
  312. template<class T>
  313. HRESULT
  314. TListNi<T>::
  315. AddAtHead(
  316. IN T *pData
  317. )
  318. {
  319. return Insert(pData, &m_Root);
  320. }
  321. template<class T>
  322. HRESULT
  323. TListNi<T>::
  324. AddAtTail(
  325. IN T *pData
  326. )
  327. {
  328. return Insert(pData, m_Root.Prev());
  329. }
  330. template<class T>
  331. HRESULT
  332. TListNi<T>::
  333. Insert(
  334. IN T *pData,
  335. IN TLinkNi<T> *pHere
  336. )
  337. {
  338. HRESULT hRetval = E_FAIL;
  339. if (pData)
  340. {
  341. //
  342. // Create the new node with the data attached.
  343. //
  344. TLinkNi<T> *pNode = new TLinkNi<T>(pData);
  345. //
  346. // Check if the node is valid.
  347. //
  348. hRetval = pNode ? pNode->IsValid() : E_OUTOFMEMORY;
  349. if (SUCCEEDED(hRetval))
  350. {
  351. hRetval = pHere ? pHere->IsValid() : E_FAIL;
  352. if (SUCCEEDED(hRetval))
  353. {
  354. //
  355. // Link this node to the list.
  356. //
  357. hRetval = pHere->Link(pNode);
  358. }
  359. else
  360. {
  361. //
  362. // Link this node to the list.
  363. //
  364. hRetval = m_Root.Link(pNode);
  365. }
  366. }
  367. //
  368. // Something failed release the allocated node.
  369. //
  370. if (FAILED(hRetval))
  371. {
  372. delete pNode;
  373. }
  374. }
  375. return hRetval;
  376. }
  377. template<class T>
  378. T *
  379. TListNi<T>::
  380. RemoveAtHead(
  381. VOID
  382. )
  383. {
  384. T *pData = NULL;
  385. if (!IsEmpty())
  386. {
  387. pData = m_Root.Next()->Get();
  388. delete m_Root.Next();
  389. }
  390. return pData;
  391. }
  392. template<class T>
  393. T *
  394. TListNi<T>::
  395. RemoveAtTail(
  396. VOID
  397. )
  398. {
  399. T *pData = NULL;
  400. if (!IsEmpty())
  401. {
  402. pData = m_Root.Prev()->Get();
  403. delete m_Root.Prev();
  404. }
  405. return pData;
  406. }
  407. template<class T>
  408. HRESULT
  409. TListNi<T>::
  410. Remove(
  411. IN TLinkNi<T> *pNode
  412. )
  413. {
  414. HRESULT hRetval = pNode ? pNode->IsValid() : E_FAIL;
  415. if (SUCCEEDED(hRetval))
  416. {
  417. //
  418. // Release the link, its the callers responsibility to release thier data.
  419. //
  420. delete pNode;
  421. }
  422. return bRetval;
  423. }
  424. template<class T>
  425. HRESULT
  426. TListNi<T>::
  427. Remove(
  428. IN T *pData
  429. )
  430. {
  431. HRESULT hRetval = E_FAIL;
  432. if (pData)
  433. {
  434. //
  435. // Locate the data and delete the node, the data
  436. // is not deleted, it is the callers responsibility
  437. // to delete their own data.
  438. //
  439. TLinkNi<T> *pNode = m_Root.Next();
  440. for (; pNode != &m_Root; pNode = pNode->Next())
  441. {
  442. if (pNode->Get() == pData)
  443. {
  444. delete pNode;
  445. hRetval = S_OK;
  446. break;
  447. }
  448. }
  449. }
  450. return hRetval;
  451. }
  452. template<class T>
  453. T *
  454. TListNi<T>::
  455. Head(
  456. VOID
  457. ) const
  458. {
  459. TListNi<T> *pLink = m_Root.Next();
  460. return pLink != &m_Root ? reinterpret_cast<T *>(pLink->Get()) : NULL;
  461. }
  462. template<class T>
  463. T *
  464. TListNi<T>::
  465. Tail(
  466. VOID
  467. ) const
  468. {
  469. TListNi<T> *pLink = m_Root.Prev();
  470. return pLink != &m_Root ? reinterpret_cast<T *>(pLink->Get()) : NULL;
  471. }