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.
 
 
 
 
 
 

190 lines
4.4 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
bitmap.cxx
Abstract:
Author:
Erez Haba (erezh) 13-Apr-1996
Environment:
Kernel mode
Revision History:
--*/
#include "internal.h"
#include "bitmap.h"
#ifndef MQDUMP
#include "bitmap.tmh"
#endif
#define RightShiftUlong(E1, E2) ((E2) < 32 ? (E1) >> (E2) : 0)
#define LeftShiftUlong(E1, E2) ((E2) < 32 ? (E1) << (E2) : 0)
#define AndOrUlong(s, E1, E2) ((s) ? ((E1) |= (E2)) : ((E1) &= ~(E2)))
//---------------------------------------------------------
//
// class CBitmap
//
//---------------------------------------------------------
void CBitmap::FillBits(ULONG ulStartIndex, ULONG ulBitCount, BOOL fSetBits)
{
//KdPrint("ClearBits %08lx, ", ulBitCount);
//KdPrint("%08lx", ulStartIndex);
ASSERT(ulStartIndex + ulBitCount <= m_ulBitCount);
//
// Special case the situation where the number of bits to fill is zero.
// Turn this into a noop.
//
if(ulBitCount == 0)
{
return;
}
ULONG BitOffset = ulStartIndex % 32;
//
// Get a pointer to the first longword that needs to be filled
//
PULONG CurrentLong = &m_ulBuffer[ulStartIndex / 32];
//
// Check if we can only need to fill one longword.
//
ULONG ulMask;
ULONG ulBitState = (fSetBits) ? 0xFFFFFFFF : 0;
if((BitOffset + ulBitCount) <= 32)
{
//
// To build a mask of bits to fill we shift left to get the number
// of bits we're changing and then shift right to put it in position.
// We'll typecast the right shift to ULONG to make sure it doesn't
// do a sign extend.
//
ulMask = LeftShiftUlong(
RightShiftUlong((ULONG)0xFFFFFFFF, 32 - ulBitCount),
BitOffset
);
AndOrUlong(ulBitState, *CurrentLong, ulMask);
//
// And return to our caller
//
return;
}
//
// We can fill out to the end of the first longword so we'll
// do that right now.
//
ulMask = LeftShiftUlong(0xFFFFFFFF, BitOffset);
AndOrUlong(ulBitState, *CurrentLong, ulMask);
//
// And indicate what the next longword to fill is and how many
// bits are left to fill
//
CurrentLong += 1;
ulBitCount -= 32 - BitOffset;
//
// The bit position is now long aligned, so we can continue
// filling longwords until the number to fill is less than 32
//
while(ulBitCount >= 32)
{
*CurrentLong = ulBitState;
CurrentLong += 1;
ulBitCount -= 32;
}
//
// And now we can clear the remaining bits, if there are any, in the
// last longword
//
if(ulBitCount > 0)
{
ulMask = ~LeftShiftUlong(0xFFFFFFFF, ulBitCount);
AndOrUlong(ulBitState, *CurrentLong, ulMask);
}
//
// And return to our caller
//
return;
}
const LONG FillMask[] =
{
0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
};
inline ULONG ACpFindBitOffset(ULONG ulBits, ULONG ulFirst)
{
//
// Get first set bit in the mask
//
ULONG ulMask = FillMask[ulFirst] & -FillMask[ulFirst];
//
// find the first bit set
//
while((ulBits & ulMask) == 0)
{
ulMask <<= 1;
++ulFirst;
}
ASSERT(ulFirst < 32);
return ulFirst;
}
ULONG CBitmap::FindBit(ULONG ulStartIndex) const
{
while(ulStartIndex < m_ulBitCount)
{
ULONG BitOffset = ulStartIndex % 32;
//
// Get a pointer to the longword that needs to be check
//
ULONG ulCurrent = m_ulBuffer[ulStartIndex / 32];
//
// check if bits are set from the bit offset, if so return index
// to first bit set
//
if((ulCurrent & FillMask[BitOffset]) != 0)
{
//
// found a bit run, return the offset to this bit
//
return (ulStartIndex - BitOffset + ACpFindBitOffset(ulCurrent, BitOffset));
}
ulStartIndex += 32 - BitOffset;
}
return m_ulBitCount;
}