forked from xt-sys/exectos
Migrate RTL subsystem to C++
This commit is contained in:
614
xtoskrnl/rtl/bitmap.cc
Normal file
614
xtoskrnl/rtl/bitmap.cc
Normal file
@@ -0,0 +1,614 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtoskrnl/rtl/bitmap.cc
|
||||
* DESCRIPTION: Bit maps support related routines
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Clears all bits in the bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since NT 3.5
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
RTL::BitMap::ClearAllBits(IN PRTL_BITMAP BitMap)
|
||||
{
|
||||
/* Clear all bits */
|
||||
RTL::Memory::SetMemory(BitMap->Buffer, 0, ((BitMap->Size + BITS_PER_LONG - 1) / BITS_PER_LONG) * sizeof(ULONG_PTR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a single bit in the bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Bit
|
||||
* Specifies the number of the bit to be cleared.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since NT 5.1
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
RTL::BitMap::ClearBit(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Bit)
|
||||
{
|
||||
/* Check if bit is in range */
|
||||
if(Bit >= BitMap->Size)
|
||||
{
|
||||
/* Supplied bit exceeds bit map size */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear specified bit */
|
||||
BitMap->Buffer[Bit / BITS_PER_LONG] &= ~(1 << (Bit & (BITS_PER_LONG - 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a specified set of bits within a bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param StartingIndex
|
||||
* Supplies the starting index of the first bit to clear.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies the length (number of bits) to clear.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since NT 3.5
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
RTL::BitMap::ClearBits(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR StartingIndex,
|
||||
IN ULONG_PTR Length)
|
||||
{
|
||||
ULONG_PTR BitOffset, Mask;
|
||||
PULONG_PTR Buffer;
|
||||
|
||||
/* Make sure there is anything to clear */
|
||||
if(!Length)
|
||||
{
|
||||
/* No bits to clear */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get pointer to first byte to clear and calculate bit offset */
|
||||
Buffer = &BitMap->Buffer[StartingIndex / BITS_PER_LONG];
|
||||
BitOffset = StartingIndex & (BITS_PER_LONG - 1);
|
||||
|
||||
/* Check if bit offset is not zero */
|
||||
if(BitOffset)
|
||||
{
|
||||
/* Get mask and calculate new bit offset */
|
||||
Mask = MAXULONG_PTR << BitOffset;
|
||||
BitOffset = BITS_PER_LONG - BitOffset;
|
||||
|
||||
/* Check if there are enough bits to clear */
|
||||
if(Length < BitOffset)
|
||||
{
|
||||
/* Recalculate bit offset and fixup the mask */
|
||||
BitOffset -= Length;
|
||||
Mask = Mask << BitOffset >> BitOffset;
|
||||
|
||||
/* Clear bits and return */
|
||||
*Buffer &= ~Mask;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear bits, recalculate length and advance buffer pointer */
|
||||
*Buffer &= ~Mask;
|
||||
Length -= BitOffset;
|
||||
Buffer++;
|
||||
}
|
||||
|
||||
/* Clear remaining bits */
|
||||
RTL::Memory::SetMemory(Buffer, 0, Length >> 3);
|
||||
|
||||
/* Look for any remaining bits to clear */
|
||||
Buffer += Length / BITS_PER_LONG;
|
||||
Length &= BITS_PER_LONG - 1;
|
||||
if(Length)
|
||||
{
|
||||
/* Clear what's left */
|
||||
*Buffer &= MAXULONG_PTR << Length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the bit map for a contiguous region of set bits and clears them.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies the length of contiguous region (number of set bits) to look for.
|
||||
*
|
||||
* @param Index
|
||||
* Supplies the index of the first bit to start the search at a given position.
|
||||
*
|
||||
* @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
ULONG
|
||||
RTL::BitMap::ClearSetBits(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Length,
|
||||
IN ULONG_PTR Index)
|
||||
{
|
||||
ULONG_PTR StartingIndex;
|
||||
|
||||
/* Find set bits */
|
||||
StartingIndex = FindSetBits(BitMap, Length, Index);
|
||||
|
||||
/* Check if set bits were found */
|
||||
if(StartingIndex != MAXULONG_PTR)
|
||||
{
|
||||
/* Clear bits */
|
||||
ClearBits(BitMap, StartingIndex, Length);
|
||||
}
|
||||
|
||||
/* Return position of bits found */
|
||||
return StartingIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of either set or clear bits in the contiguous region of the bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies the maximum length (number of bits) to count.
|
||||
*
|
||||
* @param StartingIndex
|
||||
* Supplies the starting index of the first bit to count.
|
||||
*
|
||||
* @param SetBits
|
||||
* Specifies whether count bits that are set or clear.
|
||||
*
|
||||
* @return This routine returns the number of equal bits found in the contiguous region.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
ULONG_PTR
|
||||
RTL::BitMap::CountBits(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Length,
|
||||
IN ULONG_PTR StartingIndex,
|
||||
IN BOOLEAN SetBits)
|
||||
{
|
||||
PULONG_PTR Buffer, BufferEnd;
|
||||
ULONG_PTR BitOffset, Size;
|
||||
ULONGLONG Value;
|
||||
|
||||
/* Get pointers to first and last bytes to check */
|
||||
Buffer = &BitMap->Buffer[StartingIndex / BITS_PER_LONG];
|
||||
BufferEnd = Buffer + ((Length + BITS_PER_LONG - 1) / BITS_PER_LONG);
|
||||
|
||||
/* Get offset and value */
|
||||
BitOffset = StartingIndex & (BITS_PER_LONG - 1);
|
||||
Value = (SetBits ? ~*Buffer : *Buffer) >> BitOffset << BitOffset;
|
||||
|
||||
/* Find first bit set until the end of the buffer */
|
||||
while(!Value && Buffer + 1 < BufferEnd)
|
||||
{
|
||||
/* Advance buffer pointer and get value */
|
||||
Value = SetBits ? ~*(++Buffer) : *(++Buffer);
|
||||
}
|
||||
|
||||
/* Check if value found */
|
||||
if(!Value)
|
||||
{
|
||||
/* No bits found, return length */
|
||||
return Length;
|
||||
}
|
||||
|
||||
/* Calculate size */
|
||||
Size = ((Buffer - BitMap->Buffer) * BITS_PER_LONG) - StartingIndex + (ULONG_PTR)RTL::Math::CountTrailingZeroes64(Value);
|
||||
|
||||
/* Return whatever is smaller */
|
||||
return Size > Length ? Length : Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the contents of the bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
RTL::BitMap::DumpBitMap(IN PRTL_BITMAP BitMap)
|
||||
{
|
||||
ULONG_PTR Index;
|
||||
|
||||
/* Dump bit map buffer information */
|
||||
DebugPrint(L"BitMap Buffer: 0x%zX (%lu bytes)\n", BitMap->Buffer, BitMap->Size);
|
||||
|
||||
/* Dump bit map buffer content */
|
||||
for(Index = 0; Index < (BitMap->Size + BITS_PER_LONG - 1) / BITS_PER_LONG; Index++)
|
||||
{
|
||||
DebugPrint(L" %8zu: %08lx\n", Index, BitMap->Buffer[Index]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the bit map for a contiguous region of either set or clear bits.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies the length (number of equal bits) to look for.
|
||||
*
|
||||
* @param StartingIndex
|
||||
* Supplies the starting index of the first bit to start the search at a given position.
|
||||
*
|
||||
* @param SetBits
|
||||
* Specifies whether count bits that are set or clear.
|
||||
*
|
||||
* @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
ULONG_PTR
|
||||
RTL::BitMap::FindBits(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Length,
|
||||
IN ULONG_PTR StartingIndex,
|
||||
IN BOOLEAN SetBits)
|
||||
{
|
||||
ULONG_PTR BitMapEnd, BitOffset, Size;
|
||||
ULONG Tries;
|
||||
|
||||
/* Validate length */
|
||||
if(Length > BitMap->Size)
|
||||
{
|
||||
/* Length exceeds bit map size, return MAXULONG_PTR */
|
||||
return (ULONG_PTR)-1;
|
||||
}
|
||||
else if(!Length)
|
||||
{
|
||||
/* Length not specified, return starting index */
|
||||
return StartingIndex;
|
||||
}
|
||||
|
||||
/* Check if starting index is in range of bit map size */
|
||||
if(StartingIndex >= BitMap->Size)
|
||||
{
|
||||
/* Starting index exceeds bit map size, start from the beginning */
|
||||
StartingIndex = 0;
|
||||
}
|
||||
|
||||
/* Try from starting index */
|
||||
BitOffset = StartingIndex;
|
||||
BitMapEnd = BitMap->Size;
|
||||
|
||||
/* At least two tries are required */
|
||||
Tries = (StartingIndex != 0) + 2;
|
||||
while(Tries)
|
||||
{
|
||||
/* Find until the end of the bit map */
|
||||
while(BitOffset + Length < BitMapEnd)
|
||||
{
|
||||
/* Increment offset */
|
||||
BitOffset += CountBits(BitMap, BitMap->Size - BitOffset, BitOffset, (BOOLEAN)!SetBits);
|
||||
if(BitOffset + Length > BitMapEnd)
|
||||
{
|
||||
/* No match found, break loop execution */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Count bits in the contiguous region and check if match found */
|
||||
Size = CountBits(BitMap, Length, BitOffset, SetBits);
|
||||
if(Size >= Length)
|
||||
{
|
||||
/* Match found, return offset */
|
||||
return BitOffset;
|
||||
}
|
||||
|
||||
/* Increment offset */
|
||||
BitOffset += Size;
|
||||
}
|
||||
|
||||
/* Try again if possible */
|
||||
Tries--;
|
||||
if(Tries)
|
||||
{
|
||||
/* Restart from the beginning up to the starting index */
|
||||
BitOffset = 0;
|
||||
BitMapEnd = StartingIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/* No match found, return MAXULONG_PTR */
|
||||
return (ULONG_PTR)-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the bit map for a contiguous region of clear bits.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies the length of contiguous region (number of clear bits) to look for.
|
||||
*
|
||||
* @param Index
|
||||
* Supplies the index of the first bit to start the search at a given position.
|
||||
*
|
||||
* @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found.
|
||||
*
|
||||
* @since NT 3.5
|
||||
*/
|
||||
XTAPI
|
||||
ULONG_PTR
|
||||
RTL::BitMap::FindClearBits(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Length,
|
||||
IN ULONG_PTR Index)
|
||||
{
|
||||
/* Find clear bits */
|
||||
return FindBits(BitMap, Length, Index, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the bit map for a contiguous region of set bits.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies the length of contiguous region (number of set bits) to look for.
|
||||
*
|
||||
* @param Index
|
||||
* Supplies the index of the first bit to start the search at a given position.
|
||||
*
|
||||
* @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found.
|
||||
*
|
||||
* @since NT 3.5
|
||||
*/
|
||||
XTAPI
|
||||
ULONG_PTR
|
||||
RTL::BitMap::FindSetBits(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Length,
|
||||
IN ULONG_PTR Index)
|
||||
{
|
||||
/* Find set bits */
|
||||
return FindBits(BitMap, Length, Index, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map to initialize.
|
||||
*
|
||||
* @param Buffer
|
||||
* Supplies a pointer to the buffer that will be used as a bit map.
|
||||
*
|
||||
* @param Size
|
||||
* Supplies a size of the bit map.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since NT 3.5
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
RTL::BitMap::InitializeBitMap(IN PRTL_BITMAP BitMap,
|
||||
IN PULONG_PTR Buffer,
|
||||
IN ULONG Size)
|
||||
{
|
||||
/* Initialize bit map */
|
||||
BitMap->Buffer = Buffer;
|
||||
BitMap->Size = Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all bits in the bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since NT 3.5
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
RTL::BitMap::SetAllBits(IN PRTL_BITMAP BitMap)
|
||||
{
|
||||
/* Set all bits */
|
||||
RTL::Memory::SetMemory(BitMap->Buffer, 0xFF, ((BitMap->Size + BITS_PER_LONG - 1) / BITS_PER_LONG) * sizeof(ULONG_PTR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a single bit in the bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Bit
|
||||
* Specifies the number of the bit to be set.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since NT 5.1
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
RTL::BitMap::SetBit(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Bit)
|
||||
{
|
||||
/* Check if bit is in range */
|
||||
if(Bit >= BitMap->Size)
|
||||
{
|
||||
/* Supplied bit exceeds bit map size */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set specified bit */
|
||||
BitMap->Buffer[Bit / BITS_PER_LONG] |= 1 << (Bit & (BITS_PER_LONG - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specified set of bits within a bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param StartingIndex
|
||||
* Supplies the starting index of the first bit to set.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies the length (number of bits) to set.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since NT 3.5
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
RTL::BitMap::SetBits(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR StartingIndex,
|
||||
IN ULONG_PTR Length)
|
||||
{
|
||||
ULONG_PTR BitOffset, Mask;
|
||||
PULONG_PTR Buffer;
|
||||
|
||||
/* Make sure there is anything to set */
|
||||
if(!Length)
|
||||
{
|
||||
/* No bits to set */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get pointer to first byte to clear and calculate bit offset */
|
||||
Buffer = &BitMap->Buffer[StartingIndex / BITS_PER_LONG];
|
||||
BitOffset = StartingIndex & (BITS_PER_LONG - 1);
|
||||
|
||||
/* Check if bit offset is not zero */
|
||||
if(BitOffset)
|
||||
{
|
||||
/* Get mask and calculate new bit offset */
|
||||
Mask = MAXULONG_PTR << BitOffset;
|
||||
BitOffset = BITS_PER_LONG - BitOffset;
|
||||
|
||||
/* Check if there are enough bits to set */
|
||||
if(Length < BitOffset)
|
||||
{
|
||||
/* Recalculate bit offset and fixup the mask */
|
||||
BitOffset -= Length;
|
||||
Mask = Mask << BitOffset >> BitOffset;
|
||||
|
||||
/* Set bits and return */
|
||||
*Buffer |= Mask;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set bits, recalculate length and advance buffer pointer */
|
||||
*Buffer |= Mask;
|
||||
Buffer++;
|
||||
Length -= BitOffset;
|
||||
}
|
||||
|
||||
/* Set remaining bits */
|
||||
RTL::Memory::SetMemory(Buffer, 0xFF, Length >> 3);
|
||||
|
||||
/* Look for any remaining bits to set */
|
||||
Buffer += Length / BITS_PER_LONG;
|
||||
Length &= BITS_PER_LONG - 1;
|
||||
if(Length)
|
||||
{
|
||||
/* Set what's left */
|
||||
*Buffer |= ~(MAXULONG_PTR << Length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the bit map for a contiguous region of clear bits and sets them.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Length
|
||||
* Supplies the length of contiguous region (number of clear bits) to look for.
|
||||
*
|
||||
* @param Index
|
||||
* Supplies the index of the first bit to start the search at a given position.
|
||||
*
|
||||
* @return This routine returns the bit map index position of the contiguous region found, or MAXULONG_PTR if not found.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
ULONG
|
||||
RTL::BitMap::SetClearBits(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Length,
|
||||
IN ULONG_PTR Index)
|
||||
{
|
||||
ULONG_PTR StartingIndex;
|
||||
|
||||
/* Find clear bits */
|
||||
StartingIndex = FindClearBits(BitMap, Length, Index);
|
||||
|
||||
/* Check if clear bits were found */
|
||||
if(StartingIndex != MAXULONG_PTR)
|
||||
{
|
||||
/* Set bits */
|
||||
SetBits(BitMap, StartingIndex, Length);
|
||||
}
|
||||
|
||||
/* Return position of bits found */
|
||||
return StartingIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a state of a single bit in the bit map.
|
||||
*
|
||||
* @param BitMap
|
||||
* Supplies a pointer to the bit map.
|
||||
*
|
||||
* @param Bit
|
||||
* Specifies the number of the bit to be tested.
|
||||
*
|
||||
* @return This routine returns TRUE when bit is set, or FALSE otherwise.
|
||||
*
|
||||
* @since NT 5.1
|
||||
*/
|
||||
XTAPI
|
||||
BOOLEAN
|
||||
RTL::BitMap::TestBit(IN PRTL_BITMAP BitMap,
|
||||
IN ULONG_PTR Bit)
|
||||
{
|
||||
/* Check if bit is in range */
|
||||
if(Bit >= BitMap->Size)
|
||||
{
|
||||
/* Supplied bit exceeds bit map size, return FALSE */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Test specified bit and return result */
|
||||
return ((BitMap->Buffer[Bit / BITS_PER_LONG] >> (Bit & (BITS_PER_LONG - 1))) & 1) ? TRUE : FALSE;
|
||||
}
|
Reference in New Issue
Block a user