Source code of Windows XP (NT5)
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.

361 lines
7.2 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: Stack.cpp
  8. //
  9. // History: 31-Mar-1997 pberkman created
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "global.hxx"
  13. #include "Stack.hxx"
  14. Stack_::Stack_(CRITICAL_SECTION *pCS)
  15. {
  16. dwStackCount = 0;
  17. psBottom = NULL;
  18. ppsSorted = NULL;
  19. ppsGet = NULL;
  20. pSortCriticalSection = pCS;
  21. }
  22. Stack_::~Stack_(void)
  23. {
  24. if (psBottom)
  25. {
  26. StackStruct_ *psCurrent;
  27. for (;;)
  28. {
  29. psCurrent = psBottom->psNext;
  30. delete psBottom->pvData;
  31. delete psBottom;
  32. psBottom = psCurrent;
  33. if (!(psBottom))
  34. {
  35. break;
  36. }
  37. }
  38. }
  39. DELETE_OBJECT(ppsSorted);
  40. FlushGetStack();
  41. }
  42. BOOL Stack_::Add(DWORD cbData, void *pvData)
  43. {
  44. BYTE *pb;
  45. if (pb = (BYTE *)this->Add(cbData))
  46. {
  47. memcpy(pb, pvData, cbData);
  48. return(TRUE);
  49. }
  50. return(FALSE);
  51. }
  52. void *Stack_::Add(DWORD cbData)
  53. {
  54. StackStruct_ *psWork;
  55. psWork = new StackStruct_;
  56. if (!(psWork))
  57. {
  58. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  59. return(NULL);
  60. }
  61. psWork->psNext = psBottom;
  62. psWork->pvData = new BYTE[cbData];
  63. if (!(psWork->pvData))
  64. {
  65. delete psWork;
  66. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  67. return(FALSE);
  68. }
  69. psWork->cbData = cbData;
  70. psBottom = psWork;
  71. dwStackCount++;
  72. FlushGetStack();
  73. return((void *)psWork->pvData);
  74. }
  75. void *Stack_::Get(DWORD dwPosition, DWORD *cbData)
  76. {
  77. DWORD i;
  78. StackStruct_ *psRet;
  79. if (!(psBottom))
  80. {
  81. return(NULL);
  82. }
  83. if (dwPosition > (dwStackCount - 1))
  84. {
  85. return(NULL);
  86. }
  87. if ( InitGetStackIfNecessary() == TRUE )
  88. {
  89. DWORD Index = dwPosition;
  90. if ( cbData != NULL )
  91. {
  92. *cbData = ppsGet[ Index ]->cbData;
  93. }
  94. return( ppsGet[ Index ]->pvData );
  95. }
  96. psRet = psBottom;
  97. if (cbData)
  98. {
  99. *cbData = 0;
  100. }
  101. for (i = 0; i < dwPosition; i++)
  102. {
  103. psRet = psRet->psNext;
  104. }
  105. if ((psRet) && (psRet->pvData))
  106. {
  107. if (cbData)
  108. {
  109. *cbData = psRet->cbData;
  110. }
  111. return(psRet->pvData);
  112. }
  113. return(NULL);
  114. }
  115. void *Stack_::Get(DWORD cbStartIn_pvData, DWORD cbLengthIn_pvData, BYTE fbType, void *pvMemberOf_pvData)
  116. {
  117. DWORD dwEnd;
  118. DWORD dwMiddle;
  119. DWORD dwStart;
  120. DWORD dwHalf;
  121. DWORD dwCur;
  122. void *pv;
  123. int cmp;
  124. dwStart = 0;
  125. dwEnd = this->Count();
  126. dwHalf = dwMiddle = dwEnd / 2L;
  127. dwCur = 0;
  128. for EVER
  129. {
  130. if (dwCur++ > this->Count())
  131. {
  132. break;
  133. }
  134. pv = this->Get(dwMiddle);
  135. if (!(pv))
  136. {
  137. break;
  138. }
  139. switch (fbType)
  140. {
  141. case STACK_SORTTYPE_PWSZ:
  142. cmp = wcscmp(*(WCHAR **)((BYTE *)pv + cbStartIn_pvData), (WCHAR *)pvMemberOf_pvData);
  143. break;
  144. case STACK_SORTTYPE_PSZ:
  145. cmp = strcmp(*(char **)((BYTE *)pv + cbStartIn_pvData), (char *)pvMemberOf_pvData);
  146. break;
  147. case STACK_SORTTYPE_PWSZ_I:
  148. cmp = _wcsicmp(*(WCHAR **)((BYTE *)pv + cbStartIn_pvData), (WCHAR *)pvMemberOf_pvData);
  149. break;
  150. case STACK_SORTTYPE_PSZ_I:
  151. cmp = _stricmp(*(char **)((BYTE *)pv + cbStartIn_pvData), (char *)pvMemberOf_pvData);
  152. break;
  153. default:
  154. cmp = memcmp((BYTE *)pv + cbStartIn_pvData, (BYTE *)pvMemberOf_pvData, cbLengthIn_pvData);
  155. break;
  156. }
  157. if (cmp == 0)
  158. {
  159. return(pv);
  160. }
  161. if ((dwMiddle == 0) || (dwMiddle == this->Count()) ||
  162. ((dwHalf == 0) && (dwMiddle == dwStart)))
  163. {
  164. break;
  165. }
  166. if (cmp < 0)
  167. {
  168. dwEnd = dwMiddle;
  169. }
  170. else
  171. {
  172. dwStart = dwMiddle;
  173. }
  174. dwHalf = (dwEnd - dwStart) / 2L;
  175. dwMiddle = dwStart + dwHalf;
  176. }
  177. return(NULL);
  178. }
  179. static DWORD cbSortOffset;
  180. static DWORD cbSortLength;
  181. static BYTE fbType;
  182. int __cdecl Stack_compare(const void *arg1, const void *arg2)
  183. {
  184. StackStruct_ **p1 = (StackStruct_ **)arg1;
  185. StackStruct_ **p2 = (StackStruct_ **)arg2;
  186. switch (fbType)
  187. {
  188. case STACK_SORTTYPE_PWSZ:
  189. return(wcscmp(*(WCHAR **)((BYTE *)(*p1)->pvData + cbSortOffset),
  190. *(WCHAR **)((BYTE *)(*p2)->pvData + cbSortOffset)));
  191. case STACK_SORTTYPE_PSZ:
  192. return(strcmp(*(char **)((BYTE *)(*p1)->pvData + cbSortOffset),
  193. *(char **)((BYTE *)(*p2)->pvData + cbSortOffset)));
  194. case STACK_SORTTYPE_PWSZ_I:
  195. return(_wcsicmp(*(WCHAR **)((BYTE *)(*p1)->pvData + cbSortOffset),
  196. *(WCHAR **)((BYTE *)(*p2)->pvData + cbSortOffset)));
  197. case STACK_SORTTYPE_PSZ_I:
  198. return(_stricmp(*(char **)((BYTE *)(*p1)->pvData + cbSortOffset),
  199. *(char **)((BYTE *)(*p2)->pvData + cbSortOffset)));
  200. case STACK_SORTTYPE_BINARY:
  201. default:
  202. break;
  203. }
  204. return(memcmp((void **)((BYTE *)(*p1)->pvData + cbSortOffset),
  205. (void **)((BYTE *)(*p2)->pvData + cbSortOffset), cbSortLength));
  206. }
  207. void Stack_::Sort(DWORD cbOffset_pvData, DWORD cbLength_pvData, BYTE fbTypeIn)
  208. {
  209. int i;
  210. if (!(psBottom))
  211. {
  212. return;
  213. }
  214. //
  215. // assign out offset & length for compare function
  216. //
  217. DELETE_OBJECT(ppsSorted); // wipe the last one.
  218. if (!(ppsSorted = new StackStruct_ * [this->Count()]))
  219. {
  220. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  221. return;
  222. }
  223. //
  224. // assign the contiguous array to be sorted.
  225. //
  226. ppsSorted[0] = psBottom;
  227. for (i = 1; i < (int)this->Count(); i++)
  228. {
  229. ppsSorted[i] = ppsSorted[i - 1]->psNext;
  230. }
  231. //
  232. // let's do the sort!
  233. //
  234. EnterCriticalSection(pSortCriticalSection);
  235. cbSortOffset = cbOffset_pvData;
  236. cbSortLength = cbLength_pvData;
  237. fbType = fbTypeIn;
  238. qsort( (void *)ppsSorted, (size_t)this->Count(), sizeof(StackStruct_ *), Stack_compare);
  239. LeaveCriticalSection(pSortCriticalSection);
  240. //
  241. // now, we need to adjust out psNext's
  242. //
  243. for (i = 0; i < (int)(this->Count() - 1); i++)
  244. {
  245. ppsSorted[i]->psNext = ppsSorted[i + 1];
  246. }
  247. ppsSorted[i]->psNext = NULL;
  248. psBottom = ppsSorted[0];
  249. FlushGetStack();
  250. }
  251. BOOL Stack_::InitGetStackIfNecessary ()
  252. {
  253. DWORD cCount;
  254. StackStruct_* psGet;
  255. if ( ppsGet != NULL )
  256. {
  257. return( TRUE );
  258. }
  259. ppsGet = new StackStruct_ * [ dwStackCount ];
  260. if ( ppsGet == NULL )
  261. {
  262. return( FALSE );
  263. }
  264. psGet = psBottom;
  265. for ( cCount = 0; cCount < dwStackCount; cCount++ )
  266. {
  267. ppsGet[ cCount ] = psGet;
  268. psGet = psGet->psNext;
  269. }
  270. return( TRUE );
  271. }
  272. VOID Stack_::FlushGetStack ()
  273. {
  274. delete ppsGet;
  275. ppsGet = NULL;
  276. }