Author: arty Date: Mon Sep 25 05:43:46 2006 New Revision: 24265
URL: http://svn.reactos.org/svn/reactos?rev=24265&view=rev Log: Add missing file from the branch. Preparing to move build hosts.
Added: branches/powerpc/reactos/lib/rtl/bitmap.c
Added: branches/powerpc/reactos/lib/rtl/bitmap.c URL: http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/lib/rtl/bitmap.c... ============================================================================== --- branches/powerpc/reactos/lib/rtl/bitmap.c (added) +++ branches/powerpc/reactos/lib/rtl/bitmap.c Mon Sep 25 05:43:46 2006 @@ -1,0 +1,979 @@ +/* COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/rtl/bitmap.c + * PURPOSE: Bitmap functions + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include <rtl.h> + +#define NDEBUG +#include <debug.h> + +/* MACROS *******************************************************************/ + +/* Bits set from LSB to MSB; used as mask for runs < 8 bits */ +static const BYTE NTDLL_maskBits[8] = { 0, 1, 3, 7, 15, 31, 63, 127 }; + +/* Number of set bits for each value of a nibble; used for counting */ +static const BYTE NTDLL_nibbleBitCount[16] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 +}; + +/* First set bit in a nibble; used for determining least significant bit */ +static const BYTE NTDLL_leastSignificant[16] = { + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Last set bit in a nibble; used for determining most significant bit */ +static const signed char NTDLL_mostSignificant[16] = { + -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 +}; + +/* PRIVATE FUNCTIONS *********************************************************/ + +static +int +NTDLL_RunSortFn(const void *lhs, + const void *rhs) +{ + if (((const RTL_BITMAP_RUN*)lhs)->NumberOfBits > ((const RTL_BITMAP_RUN*)rhs)->NumberOfBits) + return -1; + return 1; +} + +static +ULONG +WINAPI +NTDLL_FindRuns(PRTL_BITMAP lpBits, + PRTL_BITMAP_RUN lpSeries, + ULONG ulCount, + BOOLEAN bLongest, + ULONG (*fn)(PRTL_BITMAP,ULONG,PULONG)) +{ + BOOL bNeedSort = ulCount > 1 ? TRUE : FALSE; + ULONG ulPos = 0, ulRuns = 0; + + if (!ulCount) + return ~0U; + + while (ulPos < lpBits->SizeOfBitMap) + { + /* Find next set/clear run */ + ULONG ulSize, ulNextPos = fn(lpBits, ulPos, &ulSize); + + if (ulNextPos == ~0U) + break; + + if (bLongest && ulRuns == ulCount) + { + /* Sort runs with shortest at end, if they are out of order */ + if (bNeedSort) + qsort(lpSeries, ulRuns, sizeof(RTL_BITMAP_RUN), NTDLL_RunSortFn); + + /* Replace last run if this one is bigger */ + if (ulSize > lpSeries[ulRuns - 1].NumberOfBits) + { + lpSeries[ulRuns - 1].StartingIndex = ulNextPos; + lpSeries[ulRuns - 1].NumberOfBits = ulSize; + + /* We need to re-sort the array, _if_ we didn't leave it sorted */ + if (ulRuns > 1 && ulSize > lpSeries[ulRuns - 2].NumberOfBits) + bNeedSort = TRUE; + } + } + else + { + /* Append to found runs */ + lpSeries[ulRuns].StartingIndex = ulNextPos; + lpSeries[ulRuns].NumberOfBits = ulSize; + ulRuns++; + + if (!bLongest && ulRuns == ulCount) + break; + } + ulPos = ulNextPos + ulSize; + } + return ulRuns; +} + +static +ULONG +NTDLL_FindSetRun(PRTL_BITMAP lpBits, + ULONG ulStart, + PULONG lpSize) +{ + LPBYTE lpOut; + ULONG ulFoundAt = 0, ulCount = 0; + + /* FIXME: It might be more efficient/cleaner to manipulate four bytes + * at a time. But beware of the pointer arithmetics... + */ + lpOut = ((BYTE*)lpBits->Buffer) + (ulStart >> 3u); + + while (1) + { + /* Check bits in first byte */ + const BYTE bMask = (0xff << (ulStart & 7)) & 0xff; + const BYTE bFirst = *lpOut & bMask; + + if (bFirst) + { + /* Have a set bit in first byte */ + if (bFirst != bMask) + { + /* Not every bit is set */ + ULONG ulOffset; + + if (bFirst & 0x0f) + ulOffset = NTDLL_leastSignificant[bFirst & 0x0f]; + else + ulOffset = 4 + NTDLL_leastSignificant[bFirst >> 4]; + ulStart += ulOffset; + ulFoundAt = ulStart; + for (;ulOffset < 8; ulOffset++) + { + if (!(bFirst & (1 << ulOffset))) + { + *lpSize = ulCount; + return ulFoundAt; /* Set from start, but not until the end */ + } + ulCount++; + ulStart++; + } + /* Set to the end - go on to count further bits */ + lpOut++; + break; + } + /* every bit from start until the end of the byte is set */ + ulFoundAt = ulStart; + ulCount = 8 - (ulStart & 7); + ulStart = (ulStart & ~7u) + 8; + lpOut++; + break; + } + ulStart = (ulStart & ~7u) + 8; + lpOut++; + if (ulStart >= lpBits->SizeOfBitMap) + return ~0U; + } + + /* Count blocks of 8 set bits */ + while (*lpOut == 0xff) + { + ulCount += 8; + ulStart += 8; + if (ulStart >= lpBits->SizeOfBitMap) + { + *lpSize = ulCount - (ulStart - lpBits->SizeOfBitMap); + return ulFoundAt; + } + lpOut++; + } + + /* Count remaining contiguous bits, if any */ + if (*lpOut & 1) + { + ULONG ulOffset = 0; + + for (;ulOffset < 7u; ulOffset++) + { + if (!(*lpOut & (1 << ulOffset))) + break; + ulCount++; + } + } + *lpSize = ulCount; + return ulFoundAt; +} + +static +ULONG +NTDLL_FindClearRun(PRTL_BITMAP lpBits, + ULONG ulStart, + PULONG lpSize) +{ + LPBYTE lpOut; + ULONG ulFoundAt = 0, ulCount = 0; + + /* FIXME: It might be more efficient/cleaner to manipulate four bytes + * at a time. But beware of the pointer arithmetics... + */ + lpOut = ((BYTE*)lpBits->Buffer) + (ulStart >> 3u); + + while (1) + { + /* Check bits in first byte */ + const BYTE bMask = (0xff << (ulStart & 7)) & 0xff; + const BYTE bFirst = (~*lpOut) & bMask; + + if (bFirst) + { + /* Have a clear bit in first byte */ + if (bFirst != bMask) + { + /* Not every bit is clear */ + ULONG ulOffset; + + if (bFirst & 0x0f) + ulOffset = NTDLL_leastSignificant[bFirst & 0x0f]; + else + ulOffset = 4 + NTDLL_leastSignificant[bFirst >> 4]; + ulStart += ulOffset; + ulFoundAt = ulStart; + for (;ulOffset < 8; ulOffset++) + { + if (!(bFirst & (1 << ulOffset))) + { + *lpSize = ulCount; + return ulFoundAt; /* Clear from start, but not until the end */ + } + ulCount++; + ulStart++; + } + /* Clear to the end - go on to count further bits */ + lpOut++; + break; + } + /* Every bit from start until the end of the byte is clear */ + ulFoundAt = ulStart; + ulCount = 8 - (ulStart & 7); + ulStart = (ulStart & ~7u) + 8; + lpOut++; + break; + } + ulStart = (ulStart & ~7u) + 8; + lpOut++; + if (ulStart >= lpBits->SizeOfBitMap) + return ~0U; + } + + /* Count blocks of 8 clear bits */ + while (!*lpOut) + { + ulCount += 8; + ulStart += 8; + if (ulStart >= lpBits->SizeOfBitMap) + { + *lpSize = ulCount - (ulStart - lpBits->SizeOfBitMap); + return ulFoundAt; + } + lpOut++; + } + + /* Count remaining contiguous bits, if any */ + if (!(*lpOut & 1)) + { + ULONG ulOffset = 0; + + for (;ulOffset < 7u; ulOffset++) + { + if (*lpOut & (1 << ulOffset)) + break; + ulCount++; + } + } + *lpSize = ulCount; + return ulFoundAt; +} + +/* FUNCTIONS ****************************************************************/ + +/* + * @implemented + */ +VOID +NTAPI +RtlInitializeBitMap(IN PRTL_BITMAP BitMapHeader, + IN PULONG BitMapBuffer, + IN ULONG SizeOfBitMap) +{ + /* Setup the bitmap header */ + BitMapHeader->SizeOfBitMap = SizeOfBitMap; + BitMapHeader->Buffer = BitMapBuffer; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +RtlAreBitsClear(IN PRTL_BITMAP BitMapHeader, + IN ULONG StartingIndex, + IN ULONG Length) +{ + LPBYTE lpOut; + ULONG ulRemainder; + + if (!BitMapHeader || !Length || + StartingIndex >= BitMapHeader->SizeOfBitMap || + Length > BitMapHeader->SizeOfBitMap - StartingIndex) + return FALSE; + + /* FIXME: It might be more efficient/cleaner to manipulate four bytes + * at a time. But beware of the pointer arithmetics... + */ + lpOut = ((BYTE*)BitMapHeader->Buffer) + (StartingIndex >> 3u); + + /* Check bits in first byte, if StartingIndex isn't a byte boundary */ + if (StartingIndex & 7) + { + if (Length > 7) + { + /* Check from start bit to the end of the byte */ + if (*lpOut & ((0xff << (StartingIndex & 7)) & 0xff)) + return FALSE; + lpOut++; + Length -= (8 - (StartingIndex & 7)); + } + else + { + /* Check from the start bit, possibly into the next byte also */ + USHORT initialWord = NTDLL_maskBits[Length] << (StartingIndex & 7); + + if (*lpOut & (initialWord & 0xff)) + return FALSE; + if ((initialWord & 0xff00) && (lpOut[1] & (initialWord >> 8))) + return FALSE; + return TRUE; + } + } + + /* Check bits in blocks of 8 bytes */ + ulRemainder = Length & 7; + Length >>= 3; + while (Length--) + { + if (*lpOut++) + return FALSE; + } + + /* Check remaining bits, if any */ + if (ulRemainder && *lpOut & NTDLL_maskBits[ulRemainder]) + return FALSE; + return TRUE; +} + + +/* + * @implemented + */ +BOOLEAN NTAPI +RtlAreBitsSet(PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length) +{ + LPBYTE lpOut; + ULONG ulRemainder; + + + if (!BitMapHeader || !Length || + StartingIndex >= BitMapHeader->SizeOfBitMap || + Length > BitMapHeader->SizeOfBitMap - StartingIndex) + return FALSE; + + /* FIXME: It might be more efficient/cleaner to manipulate four bytes + * at a time. But beware of the pointer arithmetics... + */ + lpOut = ((BYTE*)BitMapHeader->Buffer) + (StartingIndex >> 3u); + + /* Check bits in first byte, if StartingIndex isn't a byte boundary */ + if (StartingIndex & 7) + { + if (Length > 7) + { + /* Check from start bit to the end of the byte */ + if ((*lpOut & + ((0xff << (StartingIndex & 7))) & 0xff) != ((0xff << (StartingIndex & 7) & 0xff))) + return FALSE; + lpOut++; + Length -= (8 - (StartingIndex & 7)); + } + else + { + /* Check from the start bit, possibly into the next byte also */ + USHORT initialWord = NTDLL_maskBits[Length] << (StartingIndex & 7); + + if ((*lpOut & (initialWord & 0xff)) != (initialWord & 0xff)) + return FALSE; + if ((initialWord & 0xff00) && + ((lpOut[1] & (initialWord >> 8)) != (initialWord >> 8))) + return FALSE; + return TRUE; + } + } + + /* Check bits in blocks of 8 bytes */ + ulRemainder = Length & 7; + Length >>= 3; + while (Length--) + { + if (*lpOut++ != 0xff) + return FALSE; + } + + /* Check remaining bits, if any */ + if (ulRemainder && + (*lpOut & NTDLL_maskBits[ulRemainder]) != NTDLL_maskBits[ulRemainder]) + return FALSE; + return TRUE; +} + + +/* + * @implemented + */ +VOID NTAPI +RtlClearAllBits(IN OUT PRTL_BITMAP BitMapHeader) +{ + memset(BitMapHeader->Buffer, 0, ((BitMapHeader->SizeOfBitMap + 31) & ~31) >> 3); +} + +/* + * @implemented + */ +VOID +NTAPI +RtlClearBit(PRTL_BITMAP BitMapHeader, + ULONG BitNumber) +{ + PULONG Ptr; + + if (BitNumber >= BitMapHeader->SizeOfBitMap) return; + + Ptr = (PULONG)BitMapHeader->Buffer + (BitNumber / 32); + *Ptr &= ~(1 << (BitNumber % 32)); +} + +/* + * @implemented + */ +VOID +NTAPI +RtlClearBits(IN PRTL_BITMAP BitMapHeader, + IN ULONG StartingIndex, + IN ULONG NumberToClear) +{ + LPBYTE lpOut; + + if (!BitMapHeader || !NumberToClear || + StartingIndex >= BitMapHeader->SizeOfBitMap || + NumberToClear > BitMapHeader->SizeOfBitMap - StartingIndex) + return; + + /* FIXME: It might be more efficient/cleaner to manipulate four bytes + * at a time. But beware of the pointer arithmetics... + */ + lpOut = ((BYTE*)BitMapHeader->Buffer) + (StartingIndex >> 3u); + + /* Clear bits in first byte, if StartingIndex isn't a byte boundary */ + if (StartingIndex & 7) + { + if (NumberToClear > 7) + { + /* Clear from start bit to the end of the byte */ + *lpOut++ &= ~(0xff << (StartingIndex & 7)); + NumberToClear -= (8 - (StartingIndex & 7)); + } + else + { + /* Clear from the start bit, possibly into the next byte also */ + USHORT initialWord = ~(NTDLL_maskBits[NumberToClear] << (StartingIndex & 7)); + + *lpOut++ &= (initialWord & 0xff); + *lpOut &= (initialWord >> 8); + return; + } + } + + /* Clear bits (in blocks of 8) on whole byte boundaries */ + if (NumberToClear >> 3) + { + memset(lpOut, 0, NumberToClear >> 3); + lpOut = lpOut + (NumberToClear >> 3); + } + + /* Clear remaining bits, if any */ + if (NumberToClear & 0x7) + *lpOut &= ~NTDLL_maskBits[NumberToClear & 0x7]; +} + + +/* + * @implemented + */ +ULONG NTAPI +RtlFindClearBits(PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex) +{ + ULONG ulPos, ulEnd; + + if (!BitMapHeader || !NumberToFind || NumberToFind > BitMapHeader->SizeOfBitMap) + return ~0U; + + ulEnd = BitMapHeader->SizeOfBitMap; + + if (HintIndex + NumberToFind > BitMapHeader->SizeOfBitMap) + HintIndex = 0; + + ulPos = HintIndex; + + while (ulPos < ulEnd) + { + /* FIXME: This could be made a _lot_ more efficient */ + if (RtlAreBitsClear(BitMapHeader, ulPos, NumberToFind)) + return ulPos; + + /* Start from the beginning if we hit the end and started from HintIndex */ + if (ulPos == ulEnd - 1 && HintIndex) + { + ulEnd = HintIndex; + ulPos = HintIndex = 0; + } + else + ulPos++; + } + return ~0U; +} + + + + + + + +/* + * @implemented + */ +ULONG NTAPI +RtlFindClearRuns(PRTL_BITMAP BitMapHeader, + PRTL_BITMAP_RUN RunArray, + ULONG SizeOfRunArray, + BOOLEAN LocateLongestRuns) +{ + return NTDLL_FindRuns(BitMapHeader, RunArray, SizeOfRunArray, LocateLongestRuns, NTDLL_FindClearRun); +} + + +/* + * @unimplemented + */ +ULONG NTAPI +RtlFindLastBackwardRunClear(IN PRTL_BITMAP BitMapHeader, + IN ULONG FromIndex, + IN PULONG StartingRunIndex) +{ + UNIMPLEMENTED; + return 0; +} + +/* + * @implemented + */ +ULONG NTAPI +RtlFindNextForwardRunClear(IN PRTL_BITMAP BitMapHeader, + IN ULONG FromIndex, + IN PULONG StartingRunIndex) +{ + ULONG ulSize = 0; + + if (BitMapHeader && FromIndex < BitMapHeader->SizeOfBitMap && StartingRunIndex) + *StartingRunIndex = NTDLL_FindClearRun(BitMapHeader, FromIndex, &ulSize); + + return ulSize; +} + +/* + * @implemented + */ +ULONG NTAPI +RtlFindFirstRunSet(IN PRTL_BITMAP BitMapHeader, + IN PULONG StartingIndex) +{ + ULONG Size; + ULONG Index; + ULONG Count; + PULONG Ptr; + ULONG Mask; + + Size = BitMapHeader->SizeOfBitMap; + if (*StartingIndex > Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + + Index = *StartingIndex; + Ptr = (PULONG)BitMapHeader->Buffer + (Index / 32); + Mask = 1 << (Index & 0x1F); + + /* Skip clear bits */ + for (; Index < Size && ~*Ptr & Mask; Index++) + { + Mask <<= 1; + + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* Return index of first set bit */ + if (Index >= Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + else + { + *StartingIndex = Index; + } + + /* Count set bits */ + for (Count = 0; Index < Size && *Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +/* + * @implemented + */ +ULONG NTAPI +RtlFindLongestRunClear(PRTL_BITMAP BitMapHeader, + PULONG StartingIndex) +{ + RTL_BITMAP_RUN br; + + if (RtlFindClearRuns(BitMapHeader, &br, 1, TRUE) == 1) + { + if (StartingIndex) + *StartingIndex = br.StartingIndex; + return br.NumberOfBits; + } + return 0; +} + + +/* + * @implemented + */ +ULONG NTAPI +RtlFindLongestRunSet(PRTL_BITMAP BitMapHeader, + PULONG StartingIndex) +{ + RTL_BITMAP_RUN br; + + if (NTDLL_FindRuns(BitMapHeader, &br, 1, TRUE, NTDLL_FindSetRun) == 1) + { + if (StartingIndex) + *StartingIndex = br.StartingIndex; + return br.NumberOfBits; + } + return 0; +} + + +/* + * @implemented + */ +ULONG NTAPI +RtlFindSetBits(PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex) +{ + ULONG ulPos, ulEnd; + + if (!BitMapHeader || !NumberToFind || NumberToFind > BitMapHeader->SizeOfBitMap) + return ~0U; + + ulEnd = BitMapHeader->SizeOfBitMap; + + if (HintIndex + NumberToFind > BitMapHeader->SizeOfBitMap) + HintIndex = 0; + + ulPos = HintIndex; + + while (ulPos < ulEnd) + { + /* FIXME: This could be made a _lot_ more efficient */ + if (RtlAreBitsSet(BitMapHeader, ulPos, NumberToFind)) + return ulPos; + + /* Start from the beginning if we hit the end and had a hint */ + if (ulPos == ulEnd - 1 && HintIndex) + { + ulEnd = HintIndex; + ulPos = HintIndex = 0; + } + else + ulPos++; + } + return ~0U; +} + + +/* + * @implemented + */ +ULONG NTAPI +RtlFindSetBitsAndClear(PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex) +{ + ULONG ulPos; + + ulPos = RtlFindSetBits(BitMapHeader, NumberToFind, HintIndex); + if (ulPos != ~0U) + RtlClearBits(BitMapHeader, ulPos, NumberToFind); + return ulPos; +} + + + + + +/* + * @implemented + */ +ULONG NTAPI +RtlNumberOfSetBits(PRTL_BITMAP BitMapHeader) +{ + ULONG ulSet = 0; + + if (BitMapHeader) + { + LPBYTE lpOut = (BYTE *)BitMapHeader->Buffer; + ULONG Length, ulRemainder; + BYTE bMasked; + + Length = BitMapHeader->SizeOfBitMap >> 3; + ulRemainder = BitMapHeader->SizeOfBitMap & 0x7; + + while (Length--) + { + ulSet += NTDLL_nibbleBitCount[*lpOut >> 4]; + ulSet += NTDLL_nibbleBitCount[*lpOut & 0xf]; + lpOut++; + } + + bMasked = *lpOut & NTDLL_maskBits[ulRemainder]; + ulSet += NTDLL_nibbleBitCount[bMasked >> 4]; + ulSet += NTDLL_nibbleBitCount[bMasked & 0xf]; + } + return ulSet; +} + + +/* + * @implemented + */ +VOID NTAPI +RtlSetAllBits(IN OUT PRTL_BITMAP BitMapHeader) +{ + memset(BitMapHeader->Buffer, 0xff, ((BitMapHeader->SizeOfBitMap + 31) & ~31) >> 3); +} + + +/* + * @implemented + */ +VOID NTAPI +RtlSetBit(PRTL_BITMAP BitMapHeader, + ULONG BitNumber) +{ + PULONG Ptr; + + if (BitNumber >= BitMapHeader->SizeOfBitMap) + return; + + Ptr = (PULONG)BitMapHeader->Buffer + (BitNumber / 32); + + *Ptr |= (1 << (BitNumber % 32)); +} + + +/* + * @implemented + */ +VOID NTAPI +RtlSetBits(PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToSet) +{ + LPBYTE lpOut; + + if (!BitMapHeader || !NumberToSet || + StartingIndex >= BitMapHeader->SizeOfBitMap || + NumberToSet > BitMapHeader->SizeOfBitMap - StartingIndex) + return; + + /* FIXME: It might be more efficient/cleaner to manipulate four bytes + * at a time. But beware of the pointer arithmetics... + */ + lpOut = ((BYTE*)BitMapHeader->Buffer) + (StartingIndex >> 3u); + + /* Set bits in first byte, if StartingIndex isn't a byte boundary */ + if (StartingIndex & 7) + { + if (NumberToSet > 7) + { + /* Set from start bit to the end of the byte */ + *lpOut++ |= 0xff << (StartingIndex & 7); + NumberToSet -= (8 - (StartingIndex & 7)); + } + else + { + /* Set from the start bit, possibly into the next byte also */ + USHORT initialWord = NTDLL_maskBits[NumberToSet] << (StartingIndex & 7); + + *lpOut++ |= (initialWord & 0xff); + *lpOut |= (initialWord >> 8); + return; + } + } + + /* Set bits up to complete byte count */ + if (NumberToSet >> 3) + { + memset(lpOut, 0xff, NumberToSet >> 3); + lpOut = lpOut + (NumberToSet >> 3); + } + + /* Set remaining bits, if any */ + *lpOut |= NTDLL_maskBits[NumberToSet & 0x7]; +} + + +/* + * @implemented + */ +BOOLEAN NTAPI +RtlTestBit(PRTL_BITMAP BitMapHeader, + ULONG BitNumber) +{ + PULONG Ptr; + + if (BitNumber >= BitMapHeader->SizeOfBitMap) + return FALSE; + + Ptr = (PULONG)BitMapHeader->Buffer + (BitNumber / 32); + + return (*Ptr & (1 << (BitNumber % 32))); +} + +/* + * @implemented + */ +ULONG NTAPI +RtlFindFirstRunClear(PRTL_BITMAP BitMapHeader, + PULONG StartingIndex) +{ + return RtlFindNextForwardRunClear(BitMapHeader, 0, StartingIndex); +} + +/* + * @implemented + */ +ULONG NTAPI +RtlNumberOfClearBits(PRTL_BITMAP BitMapHeader) +{ + + if (BitMapHeader) + return BitMapHeader->SizeOfBitMap - RtlNumberOfSetBits(BitMapHeader); + return 0; +} + +/* + * @implemented + */ +ULONG NTAPI +RtlFindClearBitsAndSet(PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex) +{ + ULONG ulPos; + + ulPos = RtlFindClearBits(BitMapHeader, NumberToFind, HintIndex); + if (ulPos != ~0U) + RtlSetBits(BitMapHeader, ulPos, NumberToFind); + return ulPos; +} + +/* + * @implemented + */ +CCHAR WINAPI RtlFindMostSignificantBit(ULONGLONG ulLong) +{ + signed char ret = 32; + DWORD dw; + + if (!(dw = (ulLong >> 32))) + { + ret = 0; + dw = (DWORD)ulLong; + } + if (dw & 0xffff0000) + { + dw >>= 16; + ret += 16; + } + if (dw & 0xff00) + { + dw >>= 8; + ret += 8; + } + if (dw & 0xf0) + { + dw >>= 4; + ret += 4; + } + return ret + NTDLL_mostSignificant[dw]; +} + +/* + * @implemented + */ +CCHAR WINAPI RtlFindLeastSignificantBit(ULONGLONG ulLong) +{ + signed char ret = 0; + DWORD dw; + + if (!(dw = (DWORD)ulLong)) + { + ret = 32; + if (!(dw = ulLong >> 32)) return -1; + } + if (!(dw & 0xffff)) + { + dw >>= 16; + ret += 16; + } + if (!(dw & 0xff)) + { + dw >>= 8; + ret += 8; + } + if (!(dw & 0x0f)) + { + dw >>= 4; + ret += 4; + } + return ret + NTDLL_leastSignificant[dw & 0x0f]; +} + +/* EOF */