|
|
//================================================================================
// 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>
//BeginExport(typedef)
typedef struct _M_EXCL { DWORD Start; DWORD End; } M_EXCL, *PM_EXCL, *LPM_EXCL; //EndExport(typedef)
//BeginExport(defines)
#define MM_FLAG_ALLOW_DHCP 0x1
#define MM_FLAG_ALLOW_BOOTP 0x2
//EndExport(defines)
//BeginExport(typedef)
typedef struct _M_BITMASK1 { DWORD Size; // Size in # of bits
DWORD AllocSize; // Size in BYTES allocated
DWORD nSet; // nBits set
LPBYTE Mask; // making this DWORD would make things faster..
DWORD Offset; // used by Bit2 type..
ULONG nDirtyOps; // # of unsaved operations done on this bitmask?
} M_BITMASK1, *PM_BITMASK1, *LPM_BITMASK1; //EndExport(typedef)
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; }
//BeginExport(typedef)
typedef struct _M_BITMASK2 { DWORD Size; ARRAY_LOCATION Loc; // where to start off to look for a bit
ARRAY Array; // Array of bitmask 1 types
} M_BITMASK2, *PM_BITMASK2, *LPM_BITMASK2;
typedef M_BITMASK2 M_BITMASK; typedef PM_BITMASK2 PM_BITMASK; typedef LPM_BITMASK2 LPM_BITMASK; //EndExport(typedef)
//BeginExport(defines)
#define MAX_BIT1SIZE (512*4)
//EndExport(defines)
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; 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);
#if 0
SkippedSize = 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);
Size = MemBit1GetSize(Bit1);
if( SkippedSize + Size > Location ) { // got the bitmask1 struct we need
return MemBit1SetOrClear( Bit1, Location - SkippedSize, fSet, fOldState ); }
SkippedSize += Size;
Error = MemArrayNextLoc(&Bits->Array, &Loc); }
Require(FALSE); // should have found the right Bit1 before?
return Error; #else
//: 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 ) ); #endif
}
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);
#if 0
SkippedSize = 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);
Size = MemBit1GetSize(Bit1);
if( SkippedSize + Size > Location ) { // got the bitmask1 struct we need
return MemBit1IsSet( Bit1, Location - SkippedSize ); }
SkippedSize += Size;
Error = MemArrayNextLoc(&Bits->Array, &Loc); } Require(FALSE); // should have found the right Bit1 before?
return FALSE; #else
//: 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 );
#endif
}
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
//================================================================================
|