mirror of https://github.com/tongzx/nt5src
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
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;
|
|
}
|
|
|