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.
1157 lines
33 KiB
1157 lines
33 KiB
//================================================================================
|
|
// Copyright (C) 1997 Microsoft Corporation
|
|
// Author: RameshV
|
|
// Description: implements the basic structures for bitmasks
|
|
// ThreadSafe: no
|
|
// Locks: none
|
|
// Please read stdinfo.txt for programming style.
|
|
//================================================================================
|
|
#include <mm.h>
|
|
#include <array.h>
|
|
|
|
#include "bitmask.h"
|
|
|
|
|
|
DWORD _inline
|
|
MemBit1Init(
|
|
OUT PM_BITMASK1 *Bits,
|
|
IN DWORD nBits
|
|
)
|
|
{
|
|
PM_BITMASK1 Bits1;
|
|
|
|
Bits1 = MemAlloc(sizeof(*Bits1));
|
|
if( NULL == Bits1 ) return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
(*Bits) = Bits1;
|
|
Bits1->Size = nBits;
|
|
Bits1->AllocSize = (nBits + 8)/8;
|
|
Bits1->nSet = 0;
|
|
Bits1->Mask = NULL;
|
|
Bits1->nDirtyOps = 0;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit1Cleanup(
|
|
IN PM_BITMASK1 Bits
|
|
)
|
|
{
|
|
if( Bits->Mask ) MemFree(Bits->Mask);
|
|
MemFree(Bits);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit1SetAll(
|
|
IN OUT PM_BITMASK1 Bits
|
|
)
|
|
{
|
|
Bits->nDirtyOps ++;
|
|
Bits->nSet = Bits->Size;
|
|
if( Bits->Mask ) {
|
|
MemFree(Bits->Mask);
|
|
Bits->Mask = NULL;
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit1ClearAll(
|
|
IN OUT PM_BITMASK1 Bits
|
|
)
|
|
{
|
|
Bits->nDirtyOps ++;
|
|
Bits->nSet = 0;
|
|
if( Bits->Mask ) {
|
|
MemFree(Bits->Mask);
|
|
Bits->Mask = NULL;
|
|
}
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
// Be careful - the same set of masks are used in regread.c -- don't change this!!!!
|
|
|
|
static DWORD Masks[] = {
|
|
0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
|
|
};
|
|
|
|
DWORD
|
|
MemBit1SetOrClear(
|
|
IN OUT PM_BITMASK1 Bits,
|
|
IN DWORD Location,
|
|
IN BOOL fSet,
|
|
OUT LPBOOL fOldState // OPTIONAL
|
|
)
|
|
{
|
|
BOOL OldState;
|
|
|
|
Bits->nDirtyOps ++;
|
|
|
|
if( 0 == Bits->nSet ) {
|
|
// No existing bit, so it must all be clear..
|
|
|
|
if( fOldState ) *fOldState = FALSE;
|
|
if( !fSet ) return ERROR_SUCCESS;
|
|
|
|
// need to set the bit.. if we are setting only bit, don't bother..
|
|
Require(Bits->Size != 0);
|
|
|
|
if( 1 == Bits->Size ) {
|
|
Bits->nSet = 1;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// we have to allocate stuff to set the bit..
|
|
Bits->Mask = MemAlloc(Bits->AllocSize);
|
|
if( NULL == Bits->Mask ) return ERROR_NOT_ENOUGH_MEMORY;
|
|
memset(Bits->Mask, 0, Bits->AllocSize);
|
|
}
|
|
|
|
if( Bits->Size == Bits->nSet ) {
|
|
// All existing bits set, so prior state is "Set"
|
|
|
|
if( fOldState ) *fOldState = TRUE;
|
|
if( fSet ) return ERROR_SUCCESS;
|
|
|
|
// check to see if we got only one bit to clear, then we don't have to do nothing
|
|
if( 1 == Bits->Size ) {
|
|
Bits->nSet = 0;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// we have to allocate memory for teh bitmap..
|
|
Bits->Mask = MemAlloc(Bits->AllocSize);
|
|
if( NULL == Bits->Mask ) return ERROR_NOT_ENOUGH_MEMORY;
|
|
memset(Bits->Mask, 0xFF, Bits->AllocSize);
|
|
}
|
|
|
|
OldState = (Bits->Mask[Location/8] & Masks[Location%8])?TRUE:FALSE;
|
|
if( fOldState ) *fOldState = OldState;
|
|
|
|
if( fSet == OldState ) return ERROR_SUCCESS;
|
|
if( fSet ) {
|
|
if( Bits->Size == ++Bits->nSet ) {
|
|
if(Bits->Mask ) MemFree(Bits->Mask);
|
|
Bits->Mask = NULL;
|
|
} else {
|
|
Bits->Mask[Location/8] |= Masks[Location%8];
|
|
}
|
|
} else {
|
|
if( 0 == --Bits->nSet ) {
|
|
if(Bits->Mask) MemFree(Bits->Mask);
|
|
Bits->Mask = NULL;
|
|
} else {
|
|
Bits->Mask[Location/8] &= ~Masks[Location%8];
|
|
}
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
BOOL _inline
|
|
MemBit1IsSet(
|
|
IN PM_BITMASK1 Bits,
|
|
IN DWORD Location
|
|
)
|
|
{
|
|
if( 0 == Bits->nSet ) return FALSE;
|
|
if( Bits->Size == Bits->nSet ) return TRUE;
|
|
|
|
if( Bits->Mask[Location/8] & Masks[Location%8] )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD _inline
|
|
IsExcluded(
|
|
IN OUT DWORD *Try, // this is updated to 1 less than end of excl
|
|
IN DWORD StartAddress,
|
|
IN PARRAY Exclusions
|
|
)
|
|
{
|
|
DWORD Error;
|
|
ARRAY_LOCATION Loc;
|
|
PM_EXCL Excl;
|
|
|
|
if( NULL == Exclusions ) return FALSE;
|
|
|
|
Error = MemArrayInitLoc(Exclusions, &Loc);
|
|
while(ERROR_FILE_NOT_FOUND != Error) {
|
|
Error = MemArrayGetElement(Exclusions, &Loc, &Excl);
|
|
Error = MemArrayNextLoc(Exclusions, &Loc);
|
|
if( Excl->Start > StartAddress + *Try ) continue;
|
|
if( Excl->End < StartAddress + *Try ) continue;
|
|
|
|
*Try = Excl->End-StartAddress;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit1GetSomeClearedBit(
|
|
IN OUT PM_BITMASK1 Bits,
|
|
OUT LPDWORD Offset,
|
|
IN BOOL fAcquire, // is this address to be taken or just looked up?
|
|
IN DWORD StartAddress,
|
|
IN PARRAY Exclusions
|
|
)
|
|
{
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD Error;
|
|
DWORD OldState;
|
|
|
|
if( Bits->Size == Bits->nSet ) return ERROR_FILE_NOT_FOUND;
|
|
if( 0 == Bits->nSet ) { // got some memory..
|
|
for( i = 0; i < Bits->Size ; i ++ ) {
|
|
if( !IsExcluded(&i, StartAddress, Exclusions) )
|
|
break;
|
|
}
|
|
|
|
if( i >= Bits->Size ) { // we got no space at all? how odd?
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
// bit "i" is free for us!!
|
|
|
|
Error = MemBit1SetOrClear(Bits, i, TRUE, &OldState);
|
|
Require( ERROR_SUCCESS == Error );
|
|
|
|
if( ERROR_SUCCESS == Error ) *Offset = i;
|
|
return Error;
|
|
}
|
|
|
|
for( i = 0 ; i < Bits->AllocSize ; i ++ ) {
|
|
if( 0xFF != Bits->Mask[i] ) { // if "i" is part of an exclusion, skip to end of exclusion
|
|
for( j = 0; j < 8; j ++ ) {
|
|
if( !(Bits->Mask[i] & Masks[j] )){// available in the bitmask, but need to check if excluded..
|
|
DWORD x;
|
|
x = 8*i + j; // this is the actual bit position in the bitmask
|
|
if( !IsExcluded(&x, StartAddress, Exclusions) )
|
|
break; // this address is not excluded either..
|
|
j = x % 8; // choose the right offset after exclusion
|
|
if( x > 8*i + 7 ) { j = 8; i = -1 + x/8; break; }
|
|
}
|
|
}
|
|
if( j < 8 ) break; // found a good location..
|
|
}
|
|
}
|
|
|
|
if( i >= Bits->AllocSize ) return ERROR_FILE_NOT_FOUND;
|
|
Require( (j <= 7) );
|
|
|
|
*Offset = j + 8*i;
|
|
if( *Offset >= Bits->Size ) return ERROR_FILE_NOT_FOUND;
|
|
|
|
if( fAcquire ) {
|
|
if( Bits->Size == ++ Bits->nSet ) {
|
|
if( Bits->Mask ) MemFree(Bits->Mask);
|
|
Bits->Mask = NULL;
|
|
} else {
|
|
Bits->Mask[i] |= Masks[j];
|
|
}
|
|
Bits->nDirtyOps ++;
|
|
}
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
DWORD _inline
|
|
MemBit1GetSize(
|
|
IN PM_BITMASK1 Bits
|
|
)
|
|
{
|
|
return Bits->Size;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit1GetSetBitsInRange(
|
|
IN PM_BITMASK1 Bits,
|
|
IN DWORD dwFrom,
|
|
IN DWORD dwTo
|
|
)
|
|
{
|
|
DWORD i;
|
|
DWORD nOnes;
|
|
|
|
// simple case: no bits set to 1
|
|
if (Bits->nSet == 0)
|
|
return 0;
|
|
|
|
// simple case: all bits set to 1
|
|
if (Bits->nSet == Bits->Size)
|
|
return dwTo - dwFrom + 1;
|
|
|
|
// we have both types of bits; scan all the bytes concerned
|
|
for (nOnes = 0, i = dwFrom>>3; i <= dwTo>>3; i++)
|
|
{
|
|
BYTE Byte, Dup;
|
|
|
|
// dwFrom and dwTo should both be in the interval [0 .. Bits->Size-1]
|
|
Byte = Bits->Mask[i];
|
|
|
|
if (i == (dwFrom>>3))
|
|
{
|
|
// dwFrom
|
|
// v
|
|
// if first byte in the range: ...|...[.....|...
|
|
// mask Byte with 000 11111
|
|
Byte &= ~((1 << (dwFrom & 0x00000007)) - 1);
|
|
}
|
|
if (i == (dwTo>>3))
|
|
{
|
|
// if last byte in the range: ...|......]..|...
|
|
// mask Byte with 111111 00
|
|
// ^
|
|
// dwTo
|
|
Byte &= (1 << ((dwTo & 0x00000007) + 1)) - 1;
|
|
}
|
|
// now compute the nb. of '1' bits from the Byte.
|
|
// log(8) algorithm
|
|
|
|
Byte = (Byte & 0x55) + ((Byte & 0xAA) >> 1);
|
|
Byte = (Byte & 0x33) + ((Byte & 0xCC) >> 2);
|
|
Byte = (Byte & 0x0f) + ((Byte & 0xF0) >> 4);
|
|
|
|
nOnes += Byte;
|
|
}
|
|
|
|
return nOnes;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit1GetSetBitsSize( // n Set bits in this bitmask ?
|
|
IN PM_BITMASK1 Bits
|
|
)
|
|
{
|
|
return Bits->nSet;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit1DelBits(
|
|
IN OUT PM_BITMASK1 Bits,
|
|
IN DWORD nBits, // new size after contraction
|
|
IN BOOL fEnd // delete from end or start ?
|
|
)
|
|
{
|
|
LPBYTE Mask;
|
|
DWORD Diff;
|
|
DWORD i;
|
|
LONG j;
|
|
|
|
Bits->nDirtyOps ++;
|
|
|
|
Diff = Bits->Size - nBits;
|
|
if( Bits->Size == Bits->nSet ) {
|
|
Bits->Size = Bits->nSet = nBits;
|
|
Bits->AllocSize = (nBits + 8)/8;
|
|
Require(Bits->Mask == NULL);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
if( 0 == Bits->nSet ) {
|
|
Bits->AllocSize = (nBits+8)/8;
|
|
Bits->Size = nBits;
|
|
Require(Bits->Mask == NULL);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
Bits->Size = nBits;
|
|
if( fEnd && Bits->AllocSize == (nBits+8)/8) {
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
Mask = MemAlloc((nBits+8)/8);
|
|
if( NULL == Mask ) {
|
|
Require(FALSE); // what to do? lets live with it
|
|
Mask = Bits->Mask; // just use existing mask
|
|
} else {
|
|
memset(Mask, 0, (nBits+8)/8);
|
|
}
|
|
|
|
Bits->AllocSize = (nBits +8)/8;
|
|
|
|
if( fEnd ) {
|
|
memmove(Mask, Bits->Mask, Bits->AllocSize);
|
|
if(Mask != Bits->Mask ) MemFree(Bits->Mask);
|
|
Bits->Mask = Mask;
|
|
Bits->nSet = 0;
|
|
for( i = 0; i < Bits->Size ; i ++ ) // re-calculate # of set bits
|
|
if( Mask[i/8] & Masks[i%8] ) Bits->nSet ++;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
Bits->nSet = 0;
|
|
for( j = Bits->Size-1; j >=0 ; j -- ) {
|
|
if( Bits->Mask[(j+Diff)/8] & Masks[(j+Diff)%8] ) {
|
|
Mask[j/8] |= Masks[j%8];
|
|
Bits->nSet ++;
|
|
} else Mask[j/8] &= ~Masks[j%8];
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
const DWORD MaxBit1Size = MAX_BIT1SIZE;
|
|
|
|
DWORD _inline
|
|
MemBit2Init(
|
|
OUT PM_BITMASK2 *Bits,
|
|
IN DWORD nBits
|
|
)
|
|
{
|
|
PM_BITMASK2 Bits2;
|
|
DWORD nBit1;
|
|
DWORD i;
|
|
DWORD Error;
|
|
DWORD RetError;
|
|
DWORD Offset;
|
|
|
|
Bits2 = MemAlloc(sizeof(*Bits2));
|
|
if( NULL == Bits2 ) return ERROR_NOT_ENOUGH_MEMORY;
|
|
Error = MemArrayInit(&Bits2->Array);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
*Bits = Bits2;
|
|
Bits2->Size = nBits;
|
|
|
|
nBit1 = nBits/MaxBit1Size;
|
|
|
|
Bits2->Array.Ptrs = MemAlloc( sizeof( LPVOID ) * nBit1 );
|
|
if ( NULL == Bits2->Array.Ptrs ) {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
Bits2->Array.nAllocated = nBit1;
|
|
|
|
for( i = 0; i < nBit1; i ++ ) {
|
|
PM_BITMASK1 Bit1;
|
|
Error = MemBit1Init(&Bit1, MaxBit1Size);
|
|
if( ERROR_SUCCESS != Error) break;
|
|
|
|
Error = MemArrayAddElement(&Bits2->Array,Bit1);
|
|
if( ERROR_SUCCESS != Error) break;
|
|
|
|
Bit1->Offset = i * MaxBit1Size;
|
|
}
|
|
|
|
if( ERROR_SUCCESS == Error ) {
|
|
PM_BITMASK1 Bit1;
|
|
|
|
MemArrayInitLoc(&Bits2->Array, &((*Bits)->Loc));
|
|
|
|
if( 0 == (nBits % MaxBit1Size) ) return ERROR_SUCCESS;
|
|
|
|
Error = MemBit1Init(&Bit1, nBits % MaxBit1Size);
|
|
if( ERROR_SUCCESS == Error) {
|
|
Error = MemArrayAddElement(&Bits2->Array, Bit1);
|
|
Bit1->Offset = i * MaxBit1Size;
|
|
}
|
|
|
|
if( ERROR_SUCCESS == Error) return ERROR_SUCCESS;
|
|
}
|
|
|
|
// error, cleanup
|
|
*Bits = NULL;
|
|
|
|
RetError = Error;
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
PM_BITMASK1 Bit1;
|
|
|
|
Error = MemArrayInitLoc(&Bits2->Array, &Loc);
|
|
while(ERROR_FILE_NOT_FOUND != Error) {
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayGetElement(
|
|
&Bits2->Array,
|
|
&Loc,
|
|
(LPVOID*)&Bit1
|
|
);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemBit1Cleanup(Bit1);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayNextLoc(&Bits2->Array, &Loc);
|
|
}
|
|
|
|
Error = MemArrayCleanup(&Bits2->Array);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
MemFree(Bits2);
|
|
}
|
|
|
|
return RetError;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit2Cleanup(
|
|
IN PM_BITMASK2 Bits
|
|
)
|
|
{
|
|
DWORD Error;
|
|
ARRAY_LOCATION Loc;
|
|
PM_BITMASK1 Bit1;
|
|
|
|
Require(Bits->Size);
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
while(ERROR_FILE_NOT_FOUND != Error) {
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayGetElement(
|
|
&Bits->Array,
|
|
&Loc,
|
|
&Bit1
|
|
);
|
|
Require(ERROR_SUCCESS == Error && Bit1);
|
|
|
|
Error = MemBit1Cleanup(Bit1);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayNextLoc(&Bits->Array, &Loc);
|
|
}
|
|
|
|
Error = MemArrayCleanup(&Bits->Array);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
MemFree(Bits);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit2SetOrClearAll(
|
|
IN OUT PM_BITMASK2 Bits,
|
|
IN BOOL fSet
|
|
)
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
DWORD Error;
|
|
PM_BITMASK1 Bit1;
|
|
|
|
AssertRet(Bits, ERROR_INVALID_PARAMETER);
|
|
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
while( ERROR_FILE_NOT_FOUND != Error ) {
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayGetElement(
|
|
&Bits->Array,
|
|
&Loc,
|
|
&Bit1
|
|
);
|
|
Require(ERROR_SUCCESS == Error && NULL != Bit1);
|
|
|
|
if( fSet ) {
|
|
Error = MemBit1SetAll(Bit1);
|
|
} else {
|
|
Error = MemBit1ClearAll(Bit1);
|
|
}
|
|
Require(ERROR_SUCCESS == Error);
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD
|
|
MemBit2SetOrClear(
|
|
IN OUT PM_BITMASK2 Bits,
|
|
IN DWORD Location,
|
|
IN BOOL fSet,
|
|
OUT LPBOOL fOldState
|
|
)
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
DWORD Error;
|
|
DWORD SkippedSize;
|
|
DWORD Size;
|
|
DWORD Start, Mid, End;
|
|
PM_BITMASK1 Bit1;
|
|
|
|
AssertRet(Bits && Bits->Size > Location, ERROR_INVALID_PARAMETER);
|
|
|
|
//: need to expose a binary search in the array.h module....
|
|
Start = 0;
|
|
End = MemArraySize(&Bits->Array);
|
|
while( Start + 1 < End) {
|
|
Mid = (Start + End)/2;
|
|
|
|
Bit1 = Bits->Array.Ptrs[Mid];
|
|
if( Bit1->Offset <= Location ) {
|
|
Start = Mid;
|
|
} else {
|
|
End = Mid;
|
|
}
|
|
}
|
|
Require( Start <= MemArraySize(&Bits->Array));
|
|
Bit1 = Bits->Array.Ptrs[Start];
|
|
Require(Bit1->Offset <= Location && Location <= Bit1->Offset + Bit1->Size);
|
|
|
|
return( MemBit1SetOrClear(
|
|
Bit1,
|
|
Location - Bit1 -> Offset,
|
|
fSet,
|
|
fOldState ) );
|
|
}
|
|
|
|
BOOL _inline
|
|
MemBit2IsSet(
|
|
IN OUT PM_BITMASK2 Bits,
|
|
IN DWORD Location
|
|
)
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
DWORD Error;
|
|
DWORD SkippedSize;
|
|
DWORD Size;
|
|
DWORD Start, Mid, End;
|
|
PM_BITMASK1 Bit1;
|
|
|
|
AssertRet(Bits && Bits->Size > Location, ERROR_INVALID_PARAMETER);
|
|
|
|
//: need to expose binary search in the array.h module
|
|
|
|
Start = 0;
|
|
End = MemArraySize(&Bits->Array);
|
|
while( Start + 1 < End ) {
|
|
Mid = (Start + End)/2;
|
|
|
|
Bit1 = Bits->Array.Ptrs[Mid];
|
|
if( Bit1->Offset <= Location ) {
|
|
Start = Mid;
|
|
} else {
|
|
End = Mid;
|
|
}
|
|
}
|
|
|
|
Require( Start <= MemArraySize(&Bits->Array) );
|
|
Bit1 = Bits->Array.Ptrs[Start];
|
|
|
|
Require(Bit1->Offset <= Location && Location <= Bit1->Offset + Bit1->Size);
|
|
|
|
return MemBit1IsSet(
|
|
Bit1,
|
|
Location - Bit1->Offset
|
|
);
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit2GetSize(
|
|
IN PM_BITMASK2 Bits
|
|
)
|
|
{
|
|
AssertRet(Bits, ERROR_INVALID_PARAMETER );
|
|
|
|
return Bits->Size;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit2GetSetBitsInRange(
|
|
IN PM_BITMASK2 Bits,
|
|
IN DWORD dwFrom,
|
|
IN DWORD dwTo
|
|
)
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
PM_BITMASK1 Bit1;
|
|
DWORD nOnes;
|
|
DWORD Error;
|
|
|
|
AssertRet(Bits, ERROR_INVALID_PARAMETER);
|
|
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
nOnes = 0;
|
|
while(ERROR_FILE_NOT_FOUND != Error)
|
|
{
|
|
Error = MemArrayGetElement(
|
|
&Bits->Array,
|
|
&Loc,
|
|
&Bit1
|
|
);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
if (dwTo < Bit1->Offset)
|
|
break;
|
|
|
|
if (dwFrom < Bit1->Offset + Bit1->Size)
|
|
{
|
|
if (dwFrom < Bit1->Offset)
|
|
dwFrom = Bit1->Offset;
|
|
|
|
nOnes += MemBit1GetSetBitsInRange(Bit1,
|
|
dwFrom - Bit1->Offset,
|
|
dwTo < Bit1->Offset + Bit1->Size ? dwTo - Bit1->Offset: Bit1->Size - 1);
|
|
}
|
|
|
|
Error = MemArrayNextLoc(&Bits->Array, &Loc);
|
|
}
|
|
return nOnes;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit2GetSetBitsSize(
|
|
IN PM_BITMASK2 Bits
|
|
)
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
DWORD Error;
|
|
DWORD nSet;
|
|
PM_BITMASK1 Bit1;
|
|
|
|
AssertRet(Bits, ERROR_INVALID_PARAMETER);
|
|
|
|
nSet = 0;
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
while(ERROR_FILE_NOT_FOUND != Error) {
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayGetElement(
|
|
&Bits->Array,
|
|
&Loc,
|
|
&Bit1
|
|
);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
nSet += MemBit1GetSetBitsSize(Bit1);
|
|
|
|
Error = MemArrayNextLoc(&Bits->Array, &Loc);
|
|
}
|
|
return nSet;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit2DelBits(
|
|
IN OUT PM_BITMASK2 Bits,
|
|
IN DWORD nBitsToDelete,
|
|
IN BOOL fEnd
|
|
)
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
DWORD i;
|
|
DWORD Size;
|
|
DWORD Error;
|
|
PM_BITMASK1 Bit1, Bit1x;
|
|
|
|
AssertRet(Bits && nBitsToDelete && Bits->Size > nBitsToDelete, ERROR_INVALID_PARAMETER);
|
|
|
|
if( fEnd ) {
|
|
Error = MemArrayLastLoc(&Bits->Array, &Loc);
|
|
} else {
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
}
|
|
|
|
Require(ERROR_SUCCESS == Error);
|
|
while( nBitsToDelete ) {
|
|
Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Size = MemBit1GetSize(Bit1);
|
|
|
|
if( nBitsToDelete >= Size ) {
|
|
nBitsToDelete -= Size;
|
|
Bits->Size -= Size;
|
|
|
|
Error = MemBit1Cleanup(Bit1);
|
|
Require(ERROR_SUCCESS == Error);
|
|
Error = MemArrayDelElement(&Bits->Array, &Loc, &Bit1x);
|
|
Require(ERROR_SUCCESS == Error && Bit1x == Bit1);
|
|
|
|
// Reset the ptr to the FIRST/LAST location to read the next element
|
|
if( fEnd ) {
|
|
Error = MemArrayLastLoc(&Bits->Array, &Loc);
|
|
} else {
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
}
|
|
} else {
|
|
Size -= nBitsToDelete;
|
|
Bits->Size -= nBitsToDelete;
|
|
|
|
nBitsToDelete = 0;
|
|
|
|
Error = MemBit1DelBits(Bit1, Size, fEnd);
|
|
}
|
|
Require(ERROR_SUCCESS == Error);
|
|
}
|
|
|
|
Size = 0;
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
while(ERROR_FILE_NOT_FOUND != Error ) {
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
|
|
Require(ERROR_SUCCESS == Error && Bit1);
|
|
|
|
Bit1->Offset = Size;
|
|
Size += Bit1->Size;
|
|
|
|
Error = MemArrayNextLoc(&Bits->Array, &Loc);
|
|
}
|
|
|
|
MemArrayInitLoc( &Bits->Array, &Bits->Loc);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit2AddBits(
|
|
IN OUT PM_BITMASK2 Bits,
|
|
IN DWORD nBitsToAdd,
|
|
IN BOOL fEnd
|
|
)
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
DWORD i;
|
|
DWORD Size;
|
|
DWORD Error;
|
|
PM_BITMASK1 Bit1;
|
|
|
|
AssertRet(Bits && nBitsToAdd, ERROR_INVALID_PARAMETER);
|
|
|
|
while( nBitsToAdd ) {
|
|
Size = (nBitsToAdd > MaxBit1Size) ? MaxBit1Size : nBitsToAdd;
|
|
nBitsToAdd -= Size;
|
|
|
|
Error = MemBit1Init(&Bit1, Size);
|
|
if( ERROR_SUCCESS != Error ) break;
|
|
|
|
if( fEnd ) {
|
|
Error = MemArrayAddElement(
|
|
&Bits->Array,
|
|
Bit1
|
|
);
|
|
} else {
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayInsElement(
|
|
&Bits->Array,
|
|
&Loc,
|
|
Bit1
|
|
);
|
|
}
|
|
if( ERROR_SUCCESS != Error ) break;
|
|
Bits->Size += Size;
|
|
}
|
|
|
|
Size = 0;
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
while(ERROR_FILE_NOT_FOUND != Error) {
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
|
|
Require(ERROR_SUCCESS == Error && Bit1);
|
|
|
|
Bit1->Offset = Size;
|
|
Size += Bit1->Size;
|
|
|
|
Error = MemArrayNextLoc(&Bits->Array, &Loc);
|
|
}
|
|
|
|
MemArrayInitLoc( &Bits->Array, &Bits->Loc);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD _inline
|
|
MemBit2GetSomeClearedBit(
|
|
IN OUT PM_BITMASK2 Bits,
|
|
OUT LPDWORD Offset,
|
|
IN BOOL fAcquire, // if we find one, do we Set it?
|
|
IN DWORD StartAddress,
|
|
IN PARRAY Exclusions
|
|
)
|
|
{
|
|
ARRAY_LOCATION Loc;
|
|
DWORD Size;
|
|
DWORD Error;
|
|
DWORD nBit1s;
|
|
PM_BITMASK1 Bit1;
|
|
|
|
AssertRet(Bits && Offset, ERROR_INVALID_PARAMETER);
|
|
|
|
nBit1s = MemArraySize(&Bits->Array);
|
|
|
|
while( nBit1s-- != 0 ) {
|
|
|
|
Error = MemArrayGetElement(&Bits->Array, &Bits->Loc, (LPVOID *)&Bit1);
|
|
Require(ERROR_SUCCESS == Error);
|
|
|
|
Error = MemBit1GetSomeClearedBit(Bit1, &Size, fAcquire, StartAddress+Bit1->Offset, Exclusions);
|
|
if( ERROR_SUCCESS == Error ) {
|
|
*Offset = Bit1->Offset + Size;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
Error = MemArrayNextLoc(&Bits->Array, &Bits->Loc);
|
|
if( ERROR_SUCCESS != Error ) {
|
|
Error = MemArrayInitLoc(&Bits->Array, &Bits->Loc);
|
|
Require( ERROR_SUCCESS == Error );
|
|
}
|
|
}
|
|
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitInit(
|
|
OUT PM_BITMASK *Bits,
|
|
IN DWORD nBits
|
|
) //EndExport(function)
|
|
{
|
|
AssertRet(Bits && nBits, ERROR_INVALID_PARAMETER);
|
|
|
|
return MemBit2Init(Bits,nBits);
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitCleanup(
|
|
IN OUT PM_BITMASK Bits
|
|
) //EndExport(function)
|
|
{
|
|
AssertRet(Bits, ERROR_INVALID_PARAMETER);
|
|
|
|
return MemBit2Cleanup(Bits);
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitSetOrClearAll(
|
|
IN OUT PM_BITMASK Bits,
|
|
IN BOOL fSet
|
|
) //EndExport(function)
|
|
{
|
|
return MemBit2SetOrClearAll(Bits,fSet);
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitSetOrClear(
|
|
IN OUT PM_BITMASK Bits,
|
|
IN DWORD Location,
|
|
IN BOOL fSet,
|
|
IN LPBOOL fOldState
|
|
) //EndExport(function)
|
|
{
|
|
return MemBit2SetOrClear(Bits,Location,fSet, fOldState);
|
|
}
|
|
|
|
|
|
//BeginExport(function)
|
|
BOOL
|
|
MemBitIsSet(
|
|
IN OUT PM_BITMASK Bits,
|
|
IN DWORD Location
|
|
) //EndExport(function)
|
|
{
|
|
BOOL Test;
|
|
Test = MemBit2IsSet(Bits, Location);
|
|
return Test;
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitGetSize(
|
|
IN PM_BITMASK Bits
|
|
) //EndExport(function)
|
|
{
|
|
return MemBit2GetSize(Bits);
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitGetSetBitsInRange(
|
|
IN PM_BITMASK Bits,
|
|
IN DWORD dwFrom,
|
|
IN DWORD dwTo
|
|
) //EndExport(function)
|
|
{
|
|
return MemBit2GetSetBitsInRange(Bits, dwFrom, dwTo);
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitGetSetBitsSize(
|
|
IN PM_BITMASK Bits
|
|
) //EndExport(function)
|
|
{
|
|
return MemBit2GetSetBitsSize(Bits);
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitAddOrDelBits(
|
|
IN OUT PM_BITMASK Bits,
|
|
IN DWORD nBitsToAddOrDelete,
|
|
IN BOOL fAdd,
|
|
IN BOOL fEnd
|
|
) //EndExport(function)
|
|
{
|
|
if( fAdd ) return MemBit2AddBits(Bits, nBitsToAddOrDelete, fEnd);
|
|
return MemBit2DelBits(Bits,nBitsToAddOrDelete, fEnd);
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitGetSomeClearedBit(
|
|
IN OUT PM_BITMASK Bits,
|
|
OUT DWORD *Offset,
|
|
IN BOOL fAcquire, // Acquire or just lookup?
|
|
IN DWORD StartAddress,
|
|
IN PARRAY Exclusions
|
|
) //EndExport(function)
|
|
{
|
|
return MemBit2GetSomeClearedBit(Bits,Offset,fAcquire, StartAddress, Exclusions);
|
|
}
|
|
|
|
//BeginExport(function)
|
|
DWORD
|
|
MemBitConvertToCluster(
|
|
IN PM_BITMASK Bits,
|
|
IN DWORD StartAddress,
|
|
OUT LPBYTE *InUseClusters,
|
|
OUT DWORD *InUseClustersSize,
|
|
OUT LPBYTE *UsedClusters,
|
|
OUT DWORD *UsedClustersSize
|
|
) //EndExport(function)
|
|
{
|
|
DWORD Error;
|
|
DWORD Cluster;
|
|
DWORD i, j;
|
|
DWORD nBits;
|
|
DWORD nBit1s;
|
|
DWORD Size;
|
|
DWORD UsedSize;
|
|
DWORD InUseSize;
|
|
LPDWORD Used;
|
|
LPDWORD InUse;
|
|
PM_BITMASK1 Bit1;
|
|
ARRAY_LOCATION Loc;
|
|
|
|
nBits = MemBitGetSize(Bits);
|
|
if( 0 == nBits || 0 == MemBitGetSetBitsSize(Bits) ) {
|
|
InUse = MemAlloc(sizeof(DWORD));
|
|
Used = MemAlloc(sizeof(DWORD));
|
|
if( NULL == InUse || NULL == Used ) {
|
|
if( InUse ) MemFree(InUse);
|
|
if( Used ) MemFree(Used);
|
|
Require(FALSE);
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
*Used = *InUse = 0;
|
|
*InUseClusters = (LPBYTE)InUse;
|
|
*UsedClusters = (LPBYTE)Used;
|
|
*InUseClustersSize = *UsedClustersSize = sizeof(DWORD);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
nBit1s = MemArraySize(&Bits->Array);
|
|
Require(nBit1s);
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
UsedSize = InUseSize = 1; // no matter what, we always use a DWORD for total size
|
|
for(i = 0; i < nBit1s ; i ++ ) {
|
|
Require(ERROR_SUCCESS == Error);
|
|
Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
|
|
Require(ERROR_SUCCESS == Error && Bit1);
|
|
Error = MemArrayNextLoc(&Bits->Array, &Loc);
|
|
|
|
// : Dont touch Bit1 directly like below? not really clean
|
|
if( 0 == Bit1->nSet ) continue; // no bit is set, nothing to do..
|
|
if( Bit1->Size == Bit1->nSet ) { // all bits set, nothing to do except for few odd bits
|
|
UsedSize += Bit1->Size/32;
|
|
if( Bit1->Size % 32 ) InUseSize+=2; // fill the odd bits in InUse so that we dont mark extra bits as used
|
|
continue;
|
|
}
|
|
|
|
for( j = 0; j < Bit1->Size/32; j ++ ) {
|
|
if( 0xFFFFFFFF == ((LPDWORD)(Bit1->Mask))[j] ) {
|
|
UsedSize ++; // this 32-bit is completely filled
|
|
} else if ( 0 != ((LPDWORD)(Bit1->Mask))[j]) {
|
|
InUseSize += 2; // this 32 bit is partially filled, not quite empty
|
|
}
|
|
}
|
|
if( j * 32 < Bit1->Size ) InUseSize +=2; // for the last few bits..
|
|
}
|
|
|
|
InUse = MemAlloc(InUseSize * sizeof(DWORD));
|
|
Used = MemAlloc(UsedSize * sizeof(DWORD));
|
|
if( NULL == Used || NULL == InUse ) {
|
|
if( InUse ) MemFree(InUse);
|
|
if( Used ) MemFree(Used);
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
*InUseClustersSize = sizeof(DWORD)*InUseSize; // fill in the sizes and ptrs to be returned..
|
|
*InUseClusters = (LPBYTE)InUse;
|
|
*UsedClusters = (LPBYTE)Used;
|
|
*UsedClustersSize = sizeof(DWORD)*UsedSize;
|
|
|
|
Error = MemArrayInitLoc(&Bits->Array, &Loc);
|
|
UsedSize = InUseSize = 1;
|
|
for(i = 0; i < nBit1s ; i ++ ) {
|
|
Require(ERROR_SUCCESS == Error);
|
|
Error = MemArrayGetElement(&Bits->Array, &Loc, &Bit1);
|
|
Require(ERROR_SUCCESS == Error && Bit1);
|
|
Error = MemArrayNextLoc(&Bits->Array, &Loc);
|
|
|
|
// Dont touch Bit1 directly like below? not really clean
|
|
if( 0 == Bit1->nSet ) { // all bits clear ==> just ignore
|
|
StartAddress += Bit1->Size;
|
|
continue;
|
|
}
|
|
if( Bit1->nSet == Bit1->Size ) { // handle all bits set here (loose bits need to be handled later)
|
|
for( j = 0; j < Bit1->Size/32; j ++ ) {
|
|
Used[UsedSize++] = StartAddress + sizeof(DWORD)*j*8;
|
|
}
|
|
} else {
|
|
for( j = 0; j < Bit1->Size/32; j ++ ) {
|
|
if( 0xFFFFFFFF == ((LPDWORD)(Bit1->Mask))[j] ) {
|
|
Used[UsedSize++] = StartAddress + sizeof(DWORD)*j*8;
|
|
} else if ( 0 != ((LPDWORD)(Bit1->Mask))[j]) {
|
|
#ifdef _X86_ // on X86, the first byte is the lowest order byte..
|
|
Cluster = ((LPDWORD)(Bit1->Mask))[j];
|
|
#else // it maynot be so on other machines, so combine the bytes manually..
|
|
Cluster = Bit1->Mask[j*sizeof(DWORD)];
|
|
Cluster |= (Bit1->Mask[j*sizeof(DWORD)+1]) << 8;
|
|
Cluster |= (Bit1->Mask[j*sizeof(DWORD)+2]) << 16;
|
|
Cluster |= (Bit1->Mask[j*sizeof(DWORD)+3]) << 24;
|
|
#endif
|
|
InUse[InUseSize++] = StartAddress + sizeof(DWORD)*j*8;
|
|
InUse[InUseSize++] = Cluster;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( j * 32 < Bit1->Size ) { // copy the last few bits off..
|
|
InUse[InUseSize++] = StartAddress + sizeof(DWORD)*j*8;
|
|
Cluster = 0;
|
|
j *= 32;
|
|
while( j < Bit1->Size ) {
|
|
if( MemBit1IsSet(Bit1, j) ) Cluster |= (1 << (j%32));
|
|
j ++;
|
|
}
|
|
InUse[InUseSize++] = Cluster;
|
|
}
|
|
|
|
StartAddress += Bit1->Size; // move the start address fwd for the next set..
|
|
}
|
|
|
|
InUse[0] = (InUseSize -1)/2; // size in header does not include itself
|
|
Used[0] = UsedSize -1; // it is just the # of CLUSTERS..
|
|
|
|
Require(InUseSize*sizeof(DWORD) == *InUseClustersSize);
|
|
Require(UsedSize*sizeof(DWORD) == *UsedClustersSize);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//================================================================================
|
|
// End of file
|
|
//================================================================================
|
|
|