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.

314 lines
7.7 KiB

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