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.

308 lines
8.2 KiB

  1. /* (C) 1997-1999 Microsoft Corp.
  2. *
  3. * file : SList.c
  4. * authors : Christos Tsollis, Erik Mavrinac
  5. *
  6. * description: Implementation of list described in SList.h.
  7. */
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #include "mcsimpl.h"
  11. void SListInit(PSList pSL, unsigned NItems)
  12. {
  13. // Initialize the private member variables. Use preallocated array for
  14. // initial node array.
  15. pSL->Hdr.NEntries = 0;
  16. pSL->Hdr.MaxEntries = SListDefaultNumEntries;
  17. pSL->Hdr.HeadOffset = 0;
  18. pSL->Hdr.CurrOffset = 0xFFFFFFFF;
  19. pSL->Hdr.Entries = pSL->InitialList;
  20. }
  21. void SListDestroy(PSList pSL)
  22. {
  23. // Only free if we have a pool-allocated array.
  24. if (pSL->Hdr.Entries != pSL->InitialList) {
  25. ExFreePool(pSL->Hdr.Entries);
  26. pSL->Hdr.Entries = pSL->InitialList;
  27. pSL->Hdr.MaxEntries = SListDefaultNumEntries;
  28. }
  29. pSL->Hdr.NEntries = 0;
  30. }
  31. /*
  32. * Expand
  33. * Private function to double the storage of the SList. Returns FALSE on
  34. * error.
  35. */
  36. static BOOLEAN SListExpand(PSList pSL)
  37. {
  38. unsigned Temp;
  39. _SListNode *OldEntries; // Keeps a copy of the old array of values.
  40. ASSERT(pSL->Hdr.Entries != NULL);
  41. // The current array of entries is full, so we need to allocate a bigger
  42. // one. The new array has twice the size of the old one.
  43. OldEntries = pSL->Hdr.Entries;
  44. pSL->Hdr.Entries = ExAllocatePoolWithTag(PagedPool, pSL->Hdr.MaxEntries *
  45. 2 * sizeof(_SListNode), MCS_POOL_TAG);
  46. if (pSL->Hdr.Entries == NULL) {
  47. // We failed; we have to return
  48. pSL->Hdr.Entries = OldEntries;
  49. return FALSE;
  50. }
  51. // Copy the old entries into the new array, starting from the head.
  52. Temp = pSL->Hdr.MaxEntries - pSL->Hdr.HeadOffset;
  53. memcpy(pSL->Hdr.Entries, OldEntries + pSL->Hdr.HeadOffset, Temp *
  54. sizeof(_SListNode));
  55. memcpy(pSL->Hdr.Entries + Temp, OldEntries, pSL->Hdr.HeadOffset *
  56. sizeof(_SListNode));
  57. // Free the old array of entries if not the initial array.
  58. if (OldEntries != pSL->InitialList)
  59. ExFreePool(OldEntries);
  60. // Set the instance variables
  61. pSL->Hdr.MaxEntries *= 2;
  62. pSL->Hdr.HeadOffset = 0;
  63. return TRUE;
  64. }
  65. /*
  66. * Append
  67. * Inserts a value at the end of a list. Returns FALSE on error.
  68. */
  69. BOOLEAN SListAppend(PSList pSL, UINT_PTR NewKey, void *NewValue)
  70. {
  71. unsigned Temp;
  72. if (pSL->Hdr.NEntries < pSL->Hdr.MaxEntries ||
  73. (pSL->Hdr.NEntries >= pSL->Hdr.MaxEntries && SListExpand(pSL))) {
  74. Temp = pSL->Hdr.HeadOffset + pSL->Hdr.NEntries;
  75. if (Temp >= pSL->Hdr.MaxEntries)
  76. Temp -= pSL->Hdr.MaxEntries;
  77. pSL->Hdr.Entries[Temp].Key = NewKey;
  78. pSL->Hdr.Entries[Temp].Value = NewValue;
  79. pSL->Hdr.NEntries++;
  80. return TRUE;
  81. }
  82. else {
  83. return FALSE;
  84. }
  85. }
  86. #ifdef NotUsed
  87. /*
  88. * Prepend
  89. * Inserts a value at the beginning of a list. Returns FALSE on error.
  90. */
  91. BOOLEAN SListPrepend(PSList pSL, UINT_PTR NewKey, void *NewValue)
  92. {
  93. if (pSL->Hdr.NEntries >= pSL->Hdr.MaxEntries)
  94. if (!SListExpand(pSL))
  95. return FALSE;
  96. ASSERT(pSL->Hdr.Entries != NULL);
  97. ASSERT(pSL->Hdr.NEntries < pSL->Hdr.MaxEntries);
  98. if (pSL->Hdr.HeadOffset == 0)
  99. pSL->Hdr.HeadOffset = pSL->Hdr.MaxEntries - 1;
  100. else
  101. pSL->Hdr.HeadOffset--;
  102. pSL->Hdr.Entries[pSL->Hdr.HeadOffset].Key = NewKey;
  103. pSL->Hdr.Entries[pSL->Hdr.HeadOffset].Value = NewValue;
  104. pSL->Hdr.NEntries++;
  105. // Reset iteration.
  106. pSL->Hdr.CurrOffset = 0xFFFFFFFF;
  107. return TRUE;
  108. }
  109. #endif // NotUsed
  110. /*
  111. * Remove
  112. * Removes a value from the list, returning the value in *pValue. Returns
  113. * NULL in *pValue if the key does not exist. pValue can be NULL.
  114. */
  115. void SListRemove(PSList pSL, UINT_PTR Key, void **pValue)
  116. {
  117. unsigned i, Temp, CurItem;
  118. // Find Key in the list.
  119. CurItem = pSL->Hdr.HeadOffset;
  120. for (i = 0; i < pSL->Hdr.NEntries; i++) {
  121. if (Key == pSL->Hdr.Entries[CurItem].Key) {
  122. // Found it; now move the last value in the list into its place.
  123. // (Remember we aren't trying to preserve ordering here.)
  124. if (pValue != NULL)
  125. *pValue = pSL->Hdr.Entries[CurItem].Value;
  126. // Move the last item in the list into the open place.
  127. Temp = pSL->Hdr.HeadOffset + pSL->Hdr.NEntries - 1;
  128. if (Temp >= pSL->Hdr.MaxEntries)
  129. Temp -= pSL->Hdr.MaxEntries;
  130. pSL->Hdr.Entries[CurItem] = pSL->Hdr.Entries[Temp];
  131. pSL->Hdr.NEntries--;
  132. pSL->Hdr.CurrOffset = 0xFFFFFFFF; // Reset iteration.
  133. return;
  134. }
  135. // Advance CurItem, wrapping at end of list.
  136. CurItem++;
  137. if (CurItem == pSL->Hdr.MaxEntries)
  138. CurItem = 0;
  139. }
  140. if (pValue != NULL)
  141. *pValue = NULL;
  142. }
  143. /*
  144. * RemoveFirst
  145. * Reads and removes the 1st item from the list. Returns the value removed,
  146. * or zero if the list is empty.
  147. */
  148. void SListRemoveFirst(PSList pSL, UINT_PTR *pKey, void **pValue)
  149. {
  150. if (pSL->Hdr.NEntries < 1) {
  151. *pKey = 0;
  152. *pValue = NULL;
  153. return;
  154. }
  155. // Reset iteration.
  156. pSL->Hdr.CurrOffset = 0xFFFFFFFF;
  157. *pKey = (pSL->Hdr.Entries + pSL->Hdr.HeadOffset)->Key;
  158. *pValue = (pSL->Hdr.Entries + pSL->Hdr.HeadOffset)->Value;
  159. pSL->Hdr.NEntries--;
  160. pSL->Hdr.HeadOffset++;
  161. if (pSL->Hdr.HeadOffset >= pSL->Hdr.MaxEntries)
  162. pSL->Hdr.HeadOffset = 0;
  163. }
  164. /*
  165. * GetByKey
  166. * Searches the list and returns in *pValue the value corresponding to the
  167. * given key. If the key is not present, returns FALSE and NULL in
  168. * *pValue. If key is found, reurns nonzero.
  169. */
  170. BOOLEAN SListGetByKey(PSList pSL, UINT_PTR Key, void **pValue)
  171. {
  172. unsigned i, Temp;
  173. _SListNode *pItem;
  174. // Find Key in the list.
  175. pItem = pSL->Hdr.Entries + pSL->Hdr.HeadOffset;
  176. for (i = 0; i < pSL->Hdr.NEntries; i++) {
  177. if (Key == pItem->Key) {
  178. // Found it; set *pValue and return.
  179. *pValue = pItem->Value;
  180. return TRUE;
  181. }
  182. // Advance pItem, wrapping at end of list.
  183. pItem++;
  184. if ((unsigned)(pItem - pSL->Hdr.Entries) >= pSL->Hdr.MaxEntries)
  185. pItem = pSL->Hdr.Entries;
  186. }
  187. *pValue = NULL;
  188. return FALSE;
  189. }
  190. #ifdef NotUsed
  191. /*
  192. * RemoveLast
  193. * Removes the value at the end of the lst and returns it. If the list is
  194. * empty, returns zero.
  195. */
  196. void SListRemoveLast(PSList pSL, UINT_PTR *pKey, void **pValue)
  197. {
  198. unsigned Temp;
  199. if (pSL->Hdr.NEntries < 1) {
  200. *pKey = 0;
  201. *pValue = NULL;
  202. return;
  203. }
  204. // Reset iteration.
  205. pSL->Hdr.CurrOffset = 0xFFFFFFFF;
  206. pSL->Hdr.NEntries--;
  207. Temp = pSL->Hdr.HeadOffset + pSL->Hdr.NEntries - 1;
  208. if (Temp >= pSL->Hdr.MaxEntries)
  209. Temp -= pSL->Hdr.MaxEntries;
  210. *pKey = (pSL->Hdr.Entries + Temp)->Key;
  211. *pValue = (pSL->Hdr.Entries + Temp)->Value;
  212. }
  213. #endif // NotUsed
  214. /*
  215. * Iterate
  216. * Iterates through the items of a list. CurrOffset is used as a current
  217. * iteration pointer, so this function can be called in a loop. Returns
  218. * FALSE if the iteration has completed, nonzero if the iteration continues
  219. * (and *pKey is valid).
  220. */
  221. BOOLEAN SListIterate(PSList pSL, UINT_PTR *pKey, void **pValue)
  222. {
  223. unsigned Temp;
  224. if (pSL->Hdr.NEntries >= 1) {
  225. if (pSL->Hdr.CurrOffset != 0xFFFFFFFF) {
  226. pSL->Hdr.CurrOffset++;
  227. if (pSL->Hdr.CurrOffset >= pSL->Hdr.NEntries) {
  228. // Reset the iterator.
  229. pSL->Hdr.CurrOffset = 0xFFFFFFFF;
  230. return FALSE;
  231. }
  232. }
  233. else {
  234. // Start from the beginning.
  235. pSL->Hdr.CurrOffset = 0;
  236. }
  237. Temp = pSL->Hdr.CurrOffset + pSL->Hdr.HeadOffset;
  238. if (Temp >= pSL->Hdr.MaxEntries)
  239. Temp -= pSL->Hdr.MaxEntries;
  240. *pKey = pSL->Hdr.Entries[Temp].Key;
  241. *pValue = pSL->Hdr.Entries[Temp].Value;
  242. return TRUE;
  243. }
  244. return FALSE;
  245. }