382 lines
10 KiB
C++
382 lines
10 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft WMIOLE DB Provider
|
|
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// This contains an implementation of a bit array class currently used by the Internal Buffer to
|
|
// mark released or unreleased rows.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#include "headers.h"
|
|
#include "bitarray.h"
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Constructor for this class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CBitArray::CBitArray ( void )
|
|
{
|
|
m_rgbBit = NULL;
|
|
m_cPageMax = 0;
|
|
m_cPageCurrent = 0;
|
|
m_cslotCurrent = 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Destructor for this class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CBitArray:: ~CBitArray (void )
|
|
{
|
|
if (m_rgbBit){
|
|
|
|
if (m_cPageCurrent){
|
|
VirtualFree((VOID *) m_rgbBit, m_cPageCurrent *m_cbPage, MEM_DECOMMIT );
|
|
}
|
|
|
|
VirtualFree((VOID *) m_rgbBit, 0, MEM_RELEASE );
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Allocate and Initialize the array of bits
|
|
//
|
|
// HRESULT indicating routines status
|
|
// S_OK | Initialization succeeded
|
|
// E_OUTOFMEMORY | Not enough memory to allocate bit array
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CBitArray::FInit( HSLOT cslotMax, //IN Maximum number of slot
|
|
ULONG cbPage //IN Count of bytes per page
|
|
)
|
|
{
|
|
LONG_PTR cPage;
|
|
BYTE ib;
|
|
HRESULT hr = S_OK;
|
|
|
|
cPage = (cslotMax / 8 + 1) / cbPage + 1;
|
|
m_rgbBit = (BYTE *) VirtualAlloc( NULL, cbPage *cPage, MEM_RESERVE, PAGE_READWRITE );
|
|
|
|
if (m_rgbBit == NULL){
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else{
|
|
|
|
m_cPageMax = cPage;
|
|
m_cbPage = cbPage;
|
|
|
|
for (ib =0; ib < 8; ib++){
|
|
m_rgbBitMask[ib] = (1 << ib);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Set a range of bit slots
|
|
//
|
|
// HRESULT indicating routines status
|
|
// S_OK Initialization succeeded
|
|
// E_OUTOFMEMORY Not enough memory to allocate bit array
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CBitArray::SetSlots ( HSLOT islotFirst, //IN First slot in range to set
|
|
HSLOT islotLast //IN Last slot in range to set
|
|
)
|
|
{
|
|
HSLOT islot;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (islotLast >= m_cslotCurrent){
|
|
|
|
ULONG_PTR cPageAdd;
|
|
|
|
cPageAdd = ((islotLast - m_cslotCurrent + 1) / 8 + 1) / m_cbPage + 1;
|
|
|
|
if ((cPageAdd + m_cPageCurrent) > (ULONG_PTR)m_cPageMax || VirtualAlloc( m_rgbBit + m_cPageCurrent*m_cbPage, cPageAdd *m_cbPage, MEM_COMMIT, PAGE_READWRITE ) == NULL){
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else{
|
|
memset( m_rgbBit + m_cPageCurrent*m_cbPage, 0x00, cPageAdd *m_cbPage );
|
|
m_cPageCurrent += cPageAdd;
|
|
m_cslotCurrent += cPageAdd *m_cbPage *8;
|
|
}
|
|
}
|
|
|
|
if( hr == S_OK ){
|
|
|
|
//=======================================================================================================
|
|
// Only do this top section if we have at least 2 byte's worth of bits to set. Although no real speedup
|
|
// until we have 3 byte's worth. Note really ought to be ((ilast-ifirst+1) >= 2*8).
|
|
// (Note could use CHAR_BIT, num bits in a char.) Also optimized end cases, so nothing is done
|
|
// if the start or end is byte aligned. Need this copied into ResetSlots.
|
|
//if((islotLast -islotFirst) > 2*sizeof(BYTE))
|
|
//=======================================================================================================
|
|
if (islotLast - islotFirst > 2 * 8){
|
|
|
|
HSLOT ibFirst, ibLast;
|
|
int iFixFirst, iFixLast;
|
|
|
|
ibFirst = islotFirst / 8;
|
|
ibLast = islotLast / 8;
|
|
iFixFirst = (islotFirst % 8 != 0); // set to 1 if first byte not totally set
|
|
iFixLast = (islotLast % 8 != 7); // set to 1 if last byte not totally set
|
|
|
|
if (iFixFirst){
|
|
for (islot = islotFirst; (islot / 8) == ibFirst; islot++){
|
|
m_rgbBit[islot / 8] |= m_rgbBitMask[islot % 8];
|
|
}
|
|
}
|
|
|
|
memset( &m_rgbBit[ibFirst + iFixFirst], 0xff, ibLast - ibFirst + 1 - iFixFirst - iFixLast );
|
|
|
|
if (iFixLast){
|
|
for (islot = islotLast; (islot / 8) == ibLast; islot--){
|
|
m_rgbBit[islot / 8] |= m_rgbBitMask[islot % 8];
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
for (islot = islotFirst; islot <= islotLast; islot++){
|
|
m_rgbBit[islot / 8] |= m_rgbBitMask[islot % 8];
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Clear all bit slots
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
VOID CBitArray::ResetAllSlots ( void )
|
|
{
|
|
memset( m_rgbBit, 0x00, m_cPageCurrent*m_cbPage );
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Reset a range of slots
|
|
//
|
|
// HRESULT indicating routines status
|
|
// S_OK Reset Succeeded
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CBitArray::ResetSlots( HSLOT islotFirst, //IN First slot in range to reset
|
|
HSLOT islotLast //IN Last slot in range to reset
|
|
)
|
|
{
|
|
HSLOT ibFirst, ibLast, islot;
|
|
|
|
if (islotFirst < m_cslotCurrent){
|
|
if (islotLast >= m_cslotCurrent){
|
|
islotLast = m_cslotCurrent - 1;
|
|
}
|
|
|
|
if ((islotLast - islotFirst) > 2*8){
|
|
ibFirst = islotFirst / 8;
|
|
ibLast = islotLast / 8;
|
|
for (islot = islotFirst; (islot / 8) == ibFirst; islot++){
|
|
m_rgbBit[islot / 8] &= ~m_rgbBitMask[islot % 8];
|
|
}
|
|
|
|
memset( &m_rgbBit[ibFirst + 1], 0x00, ibLast - ibFirst - 1 );
|
|
for (islot = islotLast; (islot / 8) == ibLast; islot--){
|
|
m_rgbBit[islot / 8] &= ~m_rgbBitMask[islot % 8];
|
|
}
|
|
}
|
|
else{
|
|
for (islot = islotFirst; islot <= islotLast; islot++){
|
|
m_rgbBit[islot / 8] &= ~m_rgbBitMask[islot % 8];
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Determines if any bits are set
|
|
//
|
|
// HRESULT indicating routines status
|
|
// S_OK Array is Empty
|
|
// S_FALSE Array contains set bits
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CBitArray::ArrayEmpty ( void )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_cPageCurrent){
|
|
ULONG_PTR idw, cdw, *rgdw;
|
|
|
|
cdw = m_cPageCurrent * (m_cbPage / sizeof( ULONG_PTR ));
|
|
rgdw = (ULONG_PTR *) m_rgbBit;
|
|
|
|
for (idw =0; idw < cdw; idw++){
|
|
if (rgdw[idw]){
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Determine if a particular bit slot is set
|
|
//
|
|
// HRESULT indicating routines status
|
|
// S_OK Slot is set
|
|
// E_OUTOFMEMORY Slot is not set
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CBitArray::IsSlotSet( HSLOT islot ) //IN Bit slot to check
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (islot >= m_cslotCurrent || (m_rgbBit[islot / 8] & m_rgbBitMask[islot % 8]) == 0x00){
|
|
hr = S_FALSE; // not set
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Find the first set slot within the bit array given a starting position
|
|
//
|
|
// HRESULT indicating routines status
|
|
// S_OK Initialization succeeded
|
|
// E_OUTOFMEMORY Not enough memory to allocate bit array
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CBitArray::FindSet( HSLOT islotStart, //IN Starting slot to search from
|
|
HSLOT islotLimit, //IN Number of slots to check
|
|
HSLOT *pislot //OUT Index of first set slot
|
|
)
|
|
{
|
|
HSLOT ibStart, ibLimit, idwStart, idwLimit, ibEnd, ib, islot, islotEnd, idw, *pdw;
|
|
HRESULT hr = E_FAIL;
|
|
BOOL bRet = FALSE;
|
|
BOOL bFound = FALSE;
|
|
|
|
islot = islotLimit;
|
|
|
|
if (islotStart > islotLimit)
|
|
{
|
|
|
|
ibStart = islotStart / 8;
|
|
ibLimit = islotLimit / 8;
|
|
|
|
if ((ibStart - ibLimit) > 1)
|
|
{
|
|
islotEnd = ibStart*8;
|
|
|
|
for (islot = islotStart; islot >= islotEnd; islot--){
|
|
if (m_rgbBit[islot / 8] & m_rgbBitMask[islot % 8]){
|
|
*pislot = islot;
|
|
hr = S_OK;
|
|
bRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(bRet == FALSE)
|
|
{
|
|
idwStart = islotStart / 32;
|
|
idwLimit = islotLimit / 32;
|
|
|
|
if (idwStart - idwLimit > 1)
|
|
{
|
|
ibEnd = idwStart*4;
|
|
|
|
for (ib = ibStart - 1; ib >= ibEnd; ib--)
|
|
{
|
|
|
|
if (m_rgbBit[ib]){
|
|
islot = ib*8 + 7;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( bFound == FALSE)
|
|
{
|
|
for (pdw = (HSLOT *) & m_rgbBit[ (idwStart - 1) *4], idw = idwStart - 1; idw > idwLimit; idw--, pdw--)
|
|
{
|
|
if (*pdw)
|
|
{
|
|
islot = idw*32 + 31;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if(bFound == FALSE)
|
|
{
|
|
ib = (idwLimit*4 + 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
ib = ibStart - 1;
|
|
}
|
|
|
|
if( bFound == FALSE)
|
|
{
|
|
for (; ib > ibLimit; ib--)
|
|
{
|
|
|
|
if (m_rgbBit[ib])
|
|
{
|
|
islot = ib*8 + 7;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if(bFound == FALSE)
|
|
{
|
|
islot = (ibLimit*8 + 7);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
islot = islotStart;
|
|
}
|
|
}
|
|
|
|
|
|
if(bFound == TRUE)
|
|
{
|
|
for (; islot >= islotLimit; islot--)
|
|
{
|
|
if (m_rgbBit[islot / 8] & m_rgbBitMask[islot % 8])
|
|
{
|
|
*pislot = islot;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
hr = S_FALSE; // not found
|
|
}
|
|
|
|
return hr;
|
|
}
|