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.

381 lines
10 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // This contains an implementation of a bit array class currently used by the Internal Buffer to
  7. // mark released or unreleased rows.
  8. //
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. #include "headers.h"
  11. #include "bitarray.h"
  12. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Constructor for this class
  15. //
  16. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. CBitArray::CBitArray ( void )
  18. {
  19. m_rgbBit = NULL;
  20. m_cPageMax = 0;
  21. m_cPageCurrent = 0;
  22. m_cslotCurrent = 0;
  23. }
  24. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  25. //
  26. // Destructor for this class
  27. //
  28. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  29. CBitArray:: ~CBitArray (void )
  30. {
  31. if (m_rgbBit){
  32. if (m_cPageCurrent){
  33. VirtualFree((VOID *) m_rgbBit, m_cPageCurrent *m_cbPage, MEM_DECOMMIT );
  34. }
  35. VirtualFree((VOID *) m_rgbBit, 0, MEM_RELEASE );
  36. }
  37. }
  38. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  39. //
  40. // Allocate and Initialize the array of bits
  41. //
  42. // HRESULT indicating routines status
  43. // S_OK | Initialization succeeded
  44. // E_OUTOFMEMORY | Not enough memory to allocate bit array
  45. //
  46. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  47. STDMETHODIMP CBitArray::FInit( HSLOT cslotMax, //IN Maximum number of slot
  48. ULONG cbPage //IN Count of bytes per page
  49. )
  50. {
  51. LONG_PTR cPage;
  52. BYTE ib;
  53. HRESULT hr = S_OK;
  54. cPage = (cslotMax / 8 + 1) / cbPage + 1;
  55. m_rgbBit = (BYTE *) VirtualAlloc( NULL, cbPage *cPage, MEM_RESERVE, PAGE_READWRITE );
  56. if (m_rgbBit == NULL){
  57. hr = E_OUTOFMEMORY;
  58. }
  59. else{
  60. m_cPageMax = cPage;
  61. m_cbPage = cbPage;
  62. for (ib =0; ib < 8; ib++){
  63. m_rgbBitMask[ib] = (1 << ib);
  64. }
  65. }
  66. return hr;
  67. }
  68. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  69. //
  70. // Set a range of bit slots
  71. //
  72. // HRESULT indicating routines status
  73. // S_OK Initialization succeeded
  74. // E_OUTOFMEMORY Not enough memory to allocate bit array
  75. //
  76. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  77. STDMETHODIMP CBitArray::SetSlots ( HSLOT islotFirst, //IN First slot in range to set
  78. HSLOT islotLast //IN Last slot in range to set
  79. )
  80. {
  81. HSLOT islot;
  82. HRESULT hr = S_OK;
  83. if (islotLast >= m_cslotCurrent){
  84. ULONG_PTR cPageAdd;
  85. cPageAdd = ((islotLast - m_cslotCurrent + 1) / 8 + 1) / m_cbPage + 1;
  86. if ((cPageAdd + m_cPageCurrent) > (ULONG_PTR)m_cPageMax || VirtualAlloc( m_rgbBit + m_cPageCurrent*m_cbPage, cPageAdd *m_cbPage, MEM_COMMIT, PAGE_READWRITE ) == NULL){
  87. hr = E_OUTOFMEMORY;
  88. }
  89. else{
  90. memset( m_rgbBit + m_cPageCurrent*m_cbPage, 0x00, cPageAdd *m_cbPage );
  91. m_cPageCurrent += cPageAdd;
  92. m_cslotCurrent += cPageAdd *m_cbPage *8;
  93. }
  94. }
  95. if( hr == S_OK ){
  96. //=======================================================================================================
  97. // Only do this top section if we have at least 2 byte's worth of bits to set. Although no real speedup
  98. // until we have 3 byte's worth. Note really ought to be ((ilast-ifirst+1) >= 2*8).
  99. // (Note could use CHAR_BIT, num bits in a char.) Also optimized end cases, so nothing is done
  100. // if the start or end is byte aligned. Need this copied into ResetSlots.
  101. //if((islotLast -islotFirst) > 2*sizeof(BYTE))
  102. //=======================================================================================================
  103. if (islotLast - islotFirst > 2 * 8){
  104. HSLOT ibFirst, ibLast;
  105. int iFixFirst, iFixLast;
  106. ibFirst = islotFirst / 8;
  107. ibLast = islotLast / 8;
  108. iFixFirst = (islotFirst % 8 != 0); // set to 1 if first byte not totally set
  109. iFixLast = (islotLast % 8 != 7); // set to 1 if last byte not totally set
  110. if (iFixFirst){
  111. for (islot = islotFirst; (islot / 8) == ibFirst; islot++){
  112. m_rgbBit[islot / 8] |= m_rgbBitMask[islot % 8];
  113. }
  114. }
  115. memset( &m_rgbBit[ibFirst + iFixFirst], 0xff, ibLast - ibFirst + 1 - iFixFirst - iFixLast );
  116. if (iFixLast){
  117. for (islot = islotLast; (islot / 8) == ibLast; islot--){
  118. m_rgbBit[islot / 8] |= m_rgbBitMask[islot % 8];
  119. }
  120. }
  121. }
  122. else{
  123. for (islot = islotFirst; islot <= islotLast; islot++){
  124. m_rgbBit[islot / 8] |= m_rgbBitMask[islot % 8];
  125. }
  126. }
  127. }
  128. return hr;
  129. }
  130. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. //
  132. // Clear all bit slots
  133. //
  134. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. VOID CBitArray::ResetAllSlots ( void )
  136. {
  137. memset( m_rgbBit, 0x00, m_cPageCurrent*m_cbPage );
  138. }
  139. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  140. //
  141. // Reset a range of slots
  142. //
  143. // HRESULT indicating routines status
  144. // S_OK Reset Succeeded
  145. //
  146. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  147. STDMETHODIMP CBitArray::ResetSlots( HSLOT islotFirst, //IN First slot in range to reset
  148. HSLOT islotLast //IN Last slot in range to reset
  149. )
  150. {
  151. HSLOT ibFirst, ibLast, islot;
  152. if (islotFirst < m_cslotCurrent){
  153. if (islotLast >= m_cslotCurrent){
  154. islotLast = m_cslotCurrent - 1;
  155. }
  156. if ((islotLast - islotFirst) > 2*8){
  157. ibFirst = islotFirst / 8;
  158. ibLast = islotLast / 8;
  159. for (islot = islotFirst; (islot / 8) == ibFirst; islot++){
  160. m_rgbBit[islot / 8] &= ~m_rgbBitMask[islot % 8];
  161. }
  162. memset( &m_rgbBit[ibFirst + 1], 0x00, ibLast - ibFirst - 1 );
  163. for (islot = islotLast; (islot / 8) == ibLast; islot--){
  164. m_rgbBit[islot / 8] &= ~m_rgbBitMask[islot % 8];
  165. }
  166. }
  167. else{
  168. for (islot = islotFirst; islot <= islotLast; islot++){
  169. m_rgbBit[islot / 8] &= ~m_rgbBitMask[islot % 8];
  170. }
  171. }
  172. }
  173. return S_OK;
  174. }
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. //
  177. // Determines if any bits are set
  178. //
  179. // HRESULT indicating routines status
  180. // S_OK Array is Empty
  181. // S_FALSE Array contains set bits
  182. //
  183. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  184. STDMETHODIMP CBitArray::ArrayEmpty ( void )
  185. {
  186. HRESULT hr = S_OK;
  187. if (m_cPageCurrent){
  188. ULONG_PTR idw, cdw, *rgdw;
  189. cdw = m_cPageCurrent * (m_cbPage / sizeof( ULONG_PTR ));
  190. rgdw = (ULONG_PTR *) m_rgbBit;
  191. for (idw =0; idw < cdw; idw++){
  192. if (rgdw[idw]){
  193. hr = S_FALSE;
  194. }
  195. }
  196. }
  197. return hr;
  198. }
  199. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  200. //
  201. // Determine if a particular bit slot is set
  202. //
  203. // HRESULT indicating routines status
  204. // S_OK Slot is set
  205. // E_OUTOFMEMORY Slot is not set
  206. //
  207. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  208. STDMETHODIMP CBitArray::IsSlotSet( HSLOT islot ) //IN Bit slot to check
  209. {
  210. HRESULT hr = S_OK;
  211. if (islot >= m_cslotCurrent || (m_rgbBit[islot / 8] & m_rgbBitMask[islot % 8]) == 0x00){
  212. hr = S_FALSE; // not set
  213. }
  214. return hr;
  215. }
  216. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  217. //
  218. // Find the first set slot within the bit array given a starting position
  219. //
  220. // HRESULT indicating routines status
  221. // S_OK Initialization succeeded
  222. // E_OUTOFMEMORY Not enough memory to allocate bit array
  223. //
  224. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  225. STDMETHODIMP CBitArray::FindSet( HSLOT islotStart, //IN Starting slot to search from
  226. HSLOT islotLimit, //IN Number of slots to check
  227. HSLOT *pislot //OUT Index of first set slot
  228. )
  229. {
  230. HSLOT ibStart, ibLimit, idwStart, idwLimit, ibEnd, ib, islot, islotEnd, idw, *pdw;
  231. HRESULT hr = E_FAIL;
  232. BOOL bRet = FALSE;
  233. BOOL bFound = FALSE;
  234. islot = islotLimit;
  235. if (islotStart > islotLimit)
  236. {
  237. ibStart = islotStart / 8;
  238. ibLimit = islotLimit / 8;
  239. if ((ibStart - ibLimit) > 1)
  240. {
  241. islotEnd = ibStart*8;
  242. for (islot = islotStart; islot >= islotEnd; islot--){
  243. if (m_rgbBit[islot / 8] & m_rgbBitMask[islot % 8]){
  244. *pislot = islot;
  245. hr = S_OK;
  246. bRet = TRUE;
  247. break;
  248. }
  249. }
  250. if(bRet == FALSE)
  251. {
  252. idwStart = islotStart / 32;
  253. idwLimit = islotLimit / 32;
  254. if (idwStart - idwLimit > 1)
  255. {
  256. ibEnd = idwStart*4;
  257. for (ib = ibStart - 1; ib >= ibEnd; ib--)
  258. {
  259. if (m_rgbBit[ib]){
  260. islot = ib*8 + 7;
  261. bFound = TRUE;
  262. break;
  263. }
  264. }
  265. if( bFound == FALSE)
  266. {
  267. for (pdw = (HSLOT *) & m_rgbBit[ (idwStart - 1) *4], idw = idwStart - 1; idw > idwLimit; idw--, pdw--)
  268. {
  269. if (*pdw)
  270. {
  271. islot = idw*32 + 31;
  272. bFound = TRUE;
  273. break;
  274. }
  275. }
  276. if(bFound == FALSE)
  277. {
  278. ib = (idwLimit*4 + 3);
  279. }
  280. }
  281. }
  282. else
  283. {
  284. ib = ibStart - 1;
  285. }
  286. if( bFound == FALSE)
  287. {
  288. for (; ib > ibLimit; ib--)
  289. {
  290. if (m_rgbBit[ib])
  291. {
  292. islot = ib*8 + 7;
  293. bFound = TRUE;
  294. break;
  295. }
  296. }
  297. if(bFound == FALSE)
  298. {
  299. islot = (ibLimit*8 + 7);
  300. }
  301. }
  302. }
  303. }
  304. else
  305. {
  306. islot = islotStart;
  307. }
  308. }
  309. if(bFound == TRUE)
  310. {
  311. for (; islot >= islotLimit; islot--)
  312. {
  313. if (m_rgbBit[islot / 8] & m_rgbBitMask[islot % 8])
  314. {
  315. *pislot = islot;
  316. hr = S_OK;
  317. }
  318. }
  319. hr = S_FALSE; // not found
  320. }
  321. return hr;
  322. }