2 * NTDLL bitmap functions
4 * Copyright 2002 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * Bitmaps are an efficient type for manipulating large arrays of bits. They
22 * are commonly used by device drivers (e.g. For holding dirty/free blocks),
23 * but are also available to applications that need this functionality.
25 * Bits are set LSB to MSB in each consecutive byte, making this implementation
26 * binary compatible with Win32.
28 * Note that to avoid unexpected behaviour, the size of a bitmap should be set
29 * to a multiple of 32.
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
40 /* Bits set from LSB to MSB; used as mask for runs < 8 bits */
41 static const BYTE NTDLL_maskBits[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };
43 /* Number of set bits for each value of a nibble; used for counting */
44 static const BYTE NTDLL_nibbleBitCount[16] = {
45 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
48 /* First set bit in a nibble; used for determining least significant bit */
49 static const BYTE NTDLL_leastSignificant[16] = {
50 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
53 /* Last set bit in a nibble; used for determining most significant bit */
54 static const signed char NTDLL_mostSignificant[16] = {
55 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
58 /*************************************************************************
59 * RtlInitializeBitMap [NTDLL.@]
61 * Initialise a new bitmap.
64 * lpBits [I] Bitmap pointer
65 * lpBuff [I] Memory for the bitmap
66 * ulSize [I] Size of lpBuff in bits
72 * lpBuff must be aligned on a ULONG suitable boundary, to a multiple of 32 bytes
73 * in size (irrespective of ulSize given).
75 VOID WINAPI RtlInitializeBitMap(PRTL_BITMAP lpBits, PULONG lpBuff, ULONG ulSize)
77 TRACE("(%p,%p,%d)\n", lpBits,lpBuff,ulSize);
78 lpBits->SizeOfBitMap = ulSize;
79 lpBits->Buffer = lpBuff;
82 /*************************************************************************
83 * RtlSetAllBits [NTDLL.@]
85 * Set all bits in a bitmap.
88 * lpBits [I] Bitmap pointer
93 VOID WINAPI RtlSetAllBits(PRTL_BITMAP lpBits)
95 TRACE("(%p)\n", lpBits);
96 memset(lpBits->Buffer, 0xff, ((lpBits->SizeOfBitMap + 31) & ~31) >> 3);
99 /*************************************************************************
100 * RtlClearAllBits [NTDLL.@]
102 * Clear all bits in a bitmap.
105 * lpBit [I] Bitmap pointer
110 VOID WINAPI RtlClearAllBits(PRTL_BITMAP lpBits)
112 TRACE("(%p)\n", lpBits);
113 memset(lpBits->Buffer, 0, ((lpBits->SizeOfBitMap + 31) & ~31) >> 3);
116 /*************************************************************************
117 * RtlSetBits [NTDLL.@]
119 * Set a range of bits in a bitmap.
122 * lpBits [I] Bitmap pointer
123 * ulStart [I] First bit to set
124 * ulCount [I] Number of consecutive bits to set
129 VOID WINAPI RtlSetBits(PRTL_BITMAP lpBits, ULONG ulStart, ULONG ulCount)
133 TRACE("(%p,%d,%d)\n", lpBits, ulStart, ulCount);
135 if (!lpBits || !ulCount ||
136 ulStart >= lpBits->SizeOfBitMap ||
137 ulCount > lpBits->SizeOfBitMap - ulStart)
140 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
141 * at a time. But beware of the pointer arithmetics...
143 lpOut = ((BYTE*)lpBits->Buffer) + (ulStart >> 3u);
145 /* Set bits in first byte, if ulStart isn't a byte boundary */
150 /* Set from start bit to the end of the byte */
151 *lpOut++ |= 0xff << (ulStart & 7);
152 ulCount -= (8 - (ulStart & 7));
156 /* Set from the start bit, possibly into the next byte also */
157 USHORT initialWord = NTDLL_maskBits[ulCount] << (ulStart & 7);
159 *lpOut++ |= (initialWord & 0xff);
160 *lpOut |= (initialWord >> 8);
165 /* Set bits up to complete byte count */
168 memset(lpOut, 0xff, ulCount >> 3);
169 lpOut = lpOut + (ulCount >> 3);
172 /* Set remaining bits, if any */
173 *lpOut |= NTDLL_maskBits[ulCount & 0x7];
176 /*************************************************************************
177 * RtlClearBits [NTDLL.@]
179 * Clear bits in a bitmap.
182 * lpBits [I] Bitmap pointer
183 * ulStart [I] First bit to set
184 * ulCount [I] Number of consecutive bits to clear
189 VOID WINAPI RtlClearBits(PRTL_BITMAP lpBits, ULONG ulStart, ULONG ulCount)
193 TRACE("(%p,%d,%d)\n", lpBits, ulStart, ulCount);
195 if (!lpBits || !ulCount ||
196 ulStart >= lpBits->SizeOfBitMap ||
197 ulCount > lpBits->SizeOfBitMap - ulStart)
200 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
201 * at a time. But beware of the pointer arithmetics...
203 lpOut = ((BYTE*)lpBits->Buffer) + (ulStart >> 3u);
205 /* Clear bits in first byte, if ulStart isn't a byte boundary */
210 /* Clear from start bit to the end of the byte */
211 *lpOut++ &= ~(0xff << (ulStart & 7));
212 ulCount -= (8 - (ulStart & 7));
216 /* Clear from the start bit, possibly into the next byte also */
217 USHORT initialWord = ~(NTDLL_maskBits[ulCount] << (ulStart & 7));
219 *lpOut++ &= (initialWord & 0xff);
220 *lpOut &= (initialWord >> 8);
225 /* Clear bits (in blocks of 8) on whole byte boundaries */
228 memset(lpOut, 0, ulCount >> 3);
229 lpOut = lpOut + (ulCount >> 3);
232 /* Clear remaining bits, if any */
234 *lpOut &= ~NTDLL_maskBits[ulCount & 0x7];
237 /*************************************************************************
238 * RtlAreBitsSet [NTDLL.@]
240 * Determine if part of a bitmap is set.
243 * lpBits [I] Bitmap pointer
244 * ulStart [I] First bit to check from
245 * ulCount [I] Number of consecutive bits to check
248 * TRUE, If ulCount bits from ulStart are set.
251 BOOLEAN WINAPI RtlAreBitsSet(PCRTL_BITMAP lpBits, ULONG ulStart, ULONG ulCount)
256 TRACE("(%p,%d,%d)\n", lpBits, ulStart, ulCount);
258 if (!lpBits || !ulCount ||
259 ulStart >= lpBits->SizeOfBitMap ||
260 ulCount > lpBits->SizeOfBitMap - ulStart)
263 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
264 * at a time. But beware of the pointer arithmetics...
266 lpOut = ((BYTE*)lpBits->Buffer) + (ulStart >> 3u);
268 /* Check bits in first byte, if ulStart isn't a byte boundary */
273 /* Check from start bit to the end of the byte */
275 ((0xff << (ulStart & 7))) & 0xff) != ((0xff << (ulStart & 7) & 0xff)))
278 ulCount -= (8 - (ulStart & 7));
282 /* Check from the start bit, possibly into the next byte also */
283 USHORT initialWord = NTDLL_maskBits[ulCount] << (ulStart & 7);
285 if ((*lpOut & (initialWord & 0xff)) != (initialWord & 0xff))
287 if ((initialWord & 0xff00) &&
288 ((lpOut[1] & (initialWord >> 8)) != (initialWord >> 8)))
294 /* Check bits in blocks of 8 bytes */
295 ulRemainder = ulCount & 7;
299 if (*lpOut++ != 0xff)
303 /* Check remaining bits, if any */
305 (*lpOut & NTDLL_maskBits[ulRemainder]) != NTDLL_maskBits[ulRemainder])
310 /*************************************************************************
311 * RtlAreBitsClear [NTDLL.@]
313 * Determine if part of a bitmap is clear.
316 * lpBits [I] Bitmap pointer
317 * ulStart [I] First bit to check from
318 * ulCount [I] Number of consecutive bits to check
321 * TRUE, If ulCount bits from ulStart are clear.
324 BOOLEAN WINAPI RtlAreBitsClear(PCRTL_BITMAP lpBits, ULONG ulStart, ULONG ulCount)
329 TRACE("(%p,%d,%d)\n", lpBits, ulStart, ulCount);
331 if (!lpBits || !ulCount ||
332 ulStart >= lpBits->SizeOfBitMap ||
333 ulCount > lpBits->SizeOfBitMap - ulStart)
336 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
337 * at a time. But beware of the pointer arithmetics...
339 lpOut = ((BYTE*)lpBits->Buffer) + (ulStart >> 3u);
341 /* Check bits in first byte, if ulStart isn't a byte boundary */
346 /* Check from start bit to the end of the byte */
347 if (*lpOut & ((0xff << (ulStart & 7)) & 0xff))
350 ulCount -= (8 - (ulStart & 7));
354 /* Check from the start bit, possibly into the next byte also */
355 USHORT initialWord = NTDLL_maskBits[ulCount] << (ulStart & 7);
357 if (*lpOut & (initialWord & 0xff))
359 if ((initialWord & 0xff00) && (lpOut[1] & (initialWord >> 8)))
365 /* Check bits in blocks of 8 bytes */
366 ulRemainder = ulCount & 7;
374 /* Check remaining bits, if any */
375 if (ulRemainder && *lpOut & NTDLL_maskBits[ulRemainder])
380 /*************************************************************************
381 * RtlFindSetBits [NTDLL.@]
383 * Find a block of set bits in a bitmap.
386 * lpBits [I] Bitmap pointer
387 * ulCount [I] Number of consecutive set bits to find
388 * ulHint [I] Suggested starting position for set bits
391 * The bit at which the match was found, or -1 if no match was found.
393 ULONG WINAPI RtlFindSetBits(PCRTL_BITMAP lpBits, ULONG ulCount, ULONG ulHint)
397 TRACE("(%p,%d,%d)\n", lpBits, ulCount, ulHint);
399 if (!lpBits || !ulCount || ulCount > lpBits->SizeOfBitMap)
402 ulEnd = lpBits->SizeOfBitMap;
404 if (ulHint + ulCount > lpBits->SizeOfBitMap)
409 while (ulPos < ulEnd)
411 /* FIXME: This could be made a _lot_ more efficient */
412 if (RtlAreBitsSet(lpBits, ulPos, ulCount))
415 /* Start from the beginning if we hit the end and had a hint */
416 if (ulPos == ulEnd - 1 && ulHint)
427 /*************************************************************************
428 * RtlFindClearBits [NTDLL.@]
430 * Find a block of clear bits in a bitmap.
433 * lpBits [I] Bitmap pointer
434 * ulCount [I] Number of consecutive clear bits to find
435 * ulHint [I] Suggested starting position for clear bits
438 * The bit at which the match was found, or -1 if no match was found.
440 ULONG WINAPI RtlFindClearBits(PCRTL_BITMAP lpBits, ULONG ulCount, ULONG ulHint)
444 TRACE("(%p,%d,%d)\n", lpBits, ulCount, ulHint);
446 if (!lpBits || !ulCount || ulCount > lpBits->SizeOfBitMap)
449 ulEnd = lpBits->SizeOfBitMap;
451 if (ulHint + ulCount > lpBits->SizeOfBitMap)
456 while (ulPos < ulEnd)
458 /* FIXME: This could be made a _lot_ more efficient */
459 if (RtlAreBitsClear(lpBits, ulPos, ulCount))
462 /* Start from the beginning if we hit the end and started from ulHint */
463 if (ulPos == ulEnd - 1 && ulHint)
474 /*************************************************************************
475 * RtlFindSetBitsAndClear [NTDLL.@]
477 * Find a block of set bits in a bitmap, and clear them if found.
480 * lpBits [I] Bitmap pointer
481 * ulCount [I] Number of consecutive set bits to find
482 * ulHint [I] Suggested starting position for set bits
485 * The bit at which the match was found, or -1 if no match was found.
487 ULONG WINAPI RtlFindSetBitsAndClear(PRTL_BITMAP lpBits, ULONG ulCount, ULONG ulHint)
491 TRACE("(%p,%d,%d)\n", lpBits, ulCount, ulHint);
493 ulPos = RtlFindSetBits(lpBits, ulCount, ulHint);
495 RtlClearBits(lpBits, ulPos, ulCount);
499 /*************************************************************************
500 * RtlFindClearBitsAndSet [NTDLL.@]
502 * Find a block of clear bits in a bitmap, and set them if found.
505 * lpBits [I] Bitmap pointer
506 * ulCount [I] Number of consecutive clear bits to find
507 * ulHint [I] Suggested starting position for clear bits
510 * The bit at which the match was found, or -1 if no match was found.
512 ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP lpBits, ULONG ulCount, ULONG ulHint)
516 TRACE("(%p,%d,%d)\n", lpBits, ulCount, ulHint);
518 ulPos = RtlFindClearBits(lpBits, ulCount, ulHint);
520 RtlSetBits(lpBits, ulPos, ulCount);
524 /*************************************************************************
525 * RtlNumberOfSetBits [NTDLL.@]
527 * Find the number of set bits in a bitmap.
530 * lpBits [I] Bitmap pointer
533 * The number of set bits.
535 ULONG WINAPI RtlNumberOfSetBits(PCRTL_BITMAP lpBits)
539 TRACE("(%p)\n", lpBits);
543 LPBYTE lpOut = (BYTE *)lpBits->Buffer;
544 ULONG ulCount, ulRemainder;
547 ulCount = lpBits->SizeOfBitMap >> 3;
548 ulRemainder = lpBits->SizeOfBitMap & 0x7;
552 ulSet += NTDLL_nibbleBitCount[*lpOut >> 4];
553 ulSet += NTDLL_nibbleBitCount[*lpOut & 0xf];
557 bMasked = *lpOut & NTDLL_maskBits[ulRemainder];
558 ulSet += NTDLL_nibbleBitCount[bMasked >> 4];
559 ulSet += NTDLL_nibbleBitCount[bMasked & 0xf];
564 /*************************************************************************
565 * RtlNumberOfClearBits [NTDLL.@]
567 * Find the number of clear bits in a bitmap.
570 * lpBits [I] Bitmap pointer
573 * The number of clear bits.
575 ULONG WINAPI RtlNumberOfClearBits(PCRTL_BITMAP lpBits)
577 TRACE("(%p)\n", lpBits);
580 return lpBits->SizeOfBitMap - RtlNumberOfSetBits(lpBits);
584 /*************************************************************************
585 * RtlFindMostSignificantBit [NTDLL.@]
587 * Find the most significant bit in a 64 bit integer.
590 * The position of the most significant bit.
592 CCHAR WINAPI RtlFindMostSignificantBit(ULONGLONG ulLong)
594 signed char ret = 32;
597 if (!(dw = (ulLong >> 32)))
617 return ret + NTDLL_mostSignificant[dw];
620 /*************************************************************************
621 * RtlFindLeastSignificantBit [NTDLL.@]
623 * Find the least significant bit in a 64 bit integer.
626 * The position of the least significant bit.
628 CCHAR WINAPI RtlFindLeastSignificantBit(ULONGLONG ulLong)
633 if (!(dw = (DWORD)ulLong))
636 if (!(dw = ulLong >> 32)) return -1;
653 return ret + NTDLL_leastSignificant[dw & 0x0f];
656 /*************************************************************************
659 * Internal helper: qsort comparison function for RTL_BITMAP_RUN arrays
661 static int NTDLL_RunSortFn(const void *lhs, const void *rhs)
663 if (((const RTL_BITMAP_RUN*)lhs)->NumberOfBits > ((const RTL_BITMAP_RUN*)rhs)->NumberOfBits)
668 /*************************************************************************
671 * Internal helper: Find the next run of set bits in a bitmap.
673 static ULONG NTDLL_FindSetRun(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpSize)
676 ULONG ulFoundAt = 0, ulCount = 0;
678 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
679 * at a time. But beware of the pointer arithmetics...
681 lpOut = ((BYTE*)lpBits->Buffer) + (ulStart >> 3u);
685 /* Check bits in first byte */
686 const BYTE bMask = (0xff << (ulStart & 7)) & 0xff;
687 const BYTE bFirst = *lpOut & bMask;
691 /* Have a set bit in first byte */
694 /* Not every bit is set */
698 ulOffset = NTDLL_leastSignificant[bFirst & 0x0f];
700 ulOffset = 4 + NTDLL_leastSignificant[bFirst >> 4];
703 for (;ulOffset < 8; ulOffset++)
705 if (!(bFirst & (1 << ulOffset)))
708 return ulFoundAt; /* Set from start, but not until the end */
713 /* Set to the end - go on to count further bits */
717 /* every bit from start until the end of the byte is set */
719 ulCount = 8 - (ulStart & 7);
720 ulStart = (ulStart & ~7u) + 8;
724 ulStart = (ulStart & ~7u) + 8;
726 if (ulStart >= lpBits->SizeOfBitMap)
730 /* Count blocks of 8 set bits */
731 while (*lpOut == 0xff)
735 if (ulStart >= lpBits->SizeOfBitMap)
737 *lpSize = ulCount - (ulStart - lpBits->SizeOfBitMap);
743 /* Count remaining contiguous bits, if any */
748 for (;ulOffset < 7u; ulOffset++)
750 if (!(*lpOut & (1 << ulOffset)))
759 /*************************************************************************
762 * Internal helper: Find the next run of set bits in a bitmap.
764 static ULONG NTDLL_FindClearRun(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpSize)
767 ULONG ulFoundAt = 0, ulCount = 0;
769 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
770 * at a time. But beware of the pointer arithmetics...
772 lpOut = ((BYTE*)lpBits->Buffer) + (ulStart >> 3u);
776 /* Check bits in first byte */
777 const BYTE bMask = (0xff << (ulStart & 7)) & 0xff;
778 const BYTE bFirst = (~*lpOut) & bMask;
782 /* Have a clear bit in first byte */
785 /* Not every bit is clear */
789 ulOffset = NTDLL_leastSignificant[bFirst & 0x0f];
791 ulOffset = 4 + NTDLL_leastSignificant[bFirst >> 4];
794 for (;ulOffset < 8; ulOffset++)
796 if (!(bFirst & (1 << ulOffset)))
799 return ulFoundAt; /* Clear from start, but not until the end */
804 /* Clear to the end - go on to count further bits */
808 /* Every bit from start until the end of the byte is clear */
810 ulCount = 8 - (ulStart & 7);
811 ulStart = (ulStart & ~7u) + 8;
815 ulStart = (ulStart & ~7u) + 8;
817 if (ulStart >= lpBits->SizeOfBitMap)
821 /* Count blocks of 8 clear bits */
826 if (ulStart >= lpBits->SizeOfBitMap)
828 *lpSize = ulCount - (ulStart - lpBits->SizeOfBitMap);
834 /* Count remaining contiguous bits, if any */
839 for (;ulOffset < 7u; ulOffset++)
841 if (*lpOut & (1 << ulOffset))
850 /*************************************************************************
851 * RtlFindNextForwardRunSet [NTDLL.@]
853 * Find the next run of set bits in a bitmap.
856 * lpBits [I] Bitmap pointer
857 * ulStart [I] Bit position to start searching from
858 * lpPos [O] Start of run
861 * Success: The length of the next set run in the bitmap. lpPos is set to
862 * the start of the run.
863 * Failure: 0, if no run is found or any parameters are invalid.
865 ULONG WINAPI RtlFindNextForwardRunSet(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpPos)
869 TRACE("(%p,%d,%p)\n", lpBits, ulStart, lpPos);
871 if (lpBits && ulStart < lpBits->SizeOfBitMap && lpPos)
872 *lpPos = NTDLL_FindSetRun(lpBits, ulStart, &ulSize);
877 /*************************************************************************
878 * RtlFindNextForwardRunClear [NTDLL.@]
880 * Find the next run of clear bits in a bitmap.
883 * lpBits [I] Bitmap pointer
884 * ulStart [I] Bit position to start searching from
885 * lpPos [O] Start of run
888 * Success: The length of the next clear run in the bitmap. lpPos is set to
889 * the start of the run.
890 * Failure: 0, if no run is found or any parameters are invalid.
892 ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpPos)
896 TRACE("(%p,%d,%p)\n", lpBits, ulStart, lpPos);
898 if (lpBits && ulStart < lpBits->SizeOfBitMap && lpPos)
899 *lpPos = NTDLL_FindClearRun(lpBits, ulStart, &ulSize);
904 /*************************************************************************
905 * RtlFindLastBackwardRunSet [NTDLL.@]
907 * Find a previous run of set bits in a bitmap.
910 * lpBits [I] Bitmap pointer
911 * ulStart [I] Bit position to start searching from
912 * lpPos [O] Start of run
915 * Success: The length of the previous set run in the bitmap. lpPos is set to
916 * the start of the run.
917 * Failure: 0, if no run is found or any parameters are invalid.
919 ULONG WINAPI RtlFindLastBackwardRunSet(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpPos)
921 FIXME("(%p,%d,%p)-stub!\n", lpBits, ulStart, lpPos);
925 /*************************************************************************
926 * RtlFindLastBackwardRunClear [NTDLL.@]
928 * Find a previous run of clear bits in a bitmap.
931 * lpBits [I] Bitmap pointer
932 * ulStart [I] Bit position to start searching from
933 * lpPos [O] Start of run
936 * Success: The length of the previous clear run in the bitmap. lpPos is set
937 * to the start of the run.
938 * Failure: 0, if no run is found or any parameters are invalid.
940 ULONG WINAPI RtlFindLastBackwardRunClear(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpPos)
942 FIXME("(%p,%d,%p)-stub!\n", lpBits, ulStart, lpPos);
946 /*************************************************************************
949 * Internal implementation of RtlFindSetRuns/RtlFindClearRuns.
951 static ULONG WINAPI NTDLL_FindRuns(PCRTL_BITMAP lpBits, PRTL_BITMAP_RUN lpSeries,
952 ULONG ulCount, BOOLEAN bLongest,
953 ULONG (*fn)(PCRTL_BITMAP,ULONG,PULONG))
955 BOOL bNeedSort = ulCount > 1 ? TRUE : FALSE;
956 ULONG ulPos = 0, ulRuns = 0;
958 TRACE("(%p,%p,%d,%d)\n", lpBits, lpSeries, ulCount, bLongest);
963 while (ulPos < lpBits->SizeOfBitMap)
965 /* Find next set/clear run */
966 ULONG ulSize, ulNextPos = fn(lpBits, ulPos, &ulSize);
968 if (ulNextPos == ~0U)
971 if (bLongest && ulRuns == ulCount)
973 /* Sort runs with shortest at end, if they are out of order */
975 qsort(lpSeries, ulRuns, sizeof(RTL_BITMAP_RUN), NTDLL_RunSortFn);
977 /* Replace last run if this one is bigger */
978 if (ulSize > lpSeries[ulRuns - 1].NumberOfBits)
980 lpSeries[ulRuns - 1].StartingIndex = ulNextPos;
981 lpSeries[ulRuns - 1].NumberOfBits = ulSize;
983 /* We need to re-sort the array, _if_ we didn't leave it sorted */
984 if (ulRuns > 1 && ulSize > lpSeries[ulRuns - 2].NumberOfBits)
990 /* Append to found runs */
991 lpSeries[ulRuns].StartingIndex = ulNextPos;
992 lpSeries[ulRuns].NumberOfBits = ulSize;
995 if (!bLongest && ulRuns == ulCount)
998 ulPos = ulNextPos + ulSize;
1003 /*************************************************************************
1004 * RtlFindSetRuns [NTDLL.@]
1006 * Find a series of set runs in a bitmap.
1009 * lpBits [I] Bitmap pointer
1010 * lpSeries [O] Array for each run found
1011 * ulCount [I] Number of runs to find
1012 * bLongest [I] Whether to find the very longest runs or not
1015 * The number of set runs found.
1017 ULONG WINAPI RtlFindSetRuns(PCRTL_BITMAP lpBits, PRTL_BITMAP_RUN lpSeries,
1018 ULONG ulCount, BOOLEAN bLongest)
1020 TRACE("(%p,%p,%d,%d)\n", lpBits, lpSeries, ulCount, bLongest);
1022 return NTDLL_FindRuns(lpBits, lpSeries, ulCount, bLongest, NTDLL_FindSetRun);
1025 /*************************************************************************
1026 * RtlFindClearRuns [NTDLL.@]
1028 * Find a series of clear runs in a bitmap.
1031 * lpBits [I] Bitmap pointer
1032 * ulSeries [O] Array for each run found
1033 * ulCount [I] Number of runs to find
1034 * bLongest [I] Whether to find the very longest runs or not
1037 * The number of clear runs found.
1039 ULONG WINAPI RtlFindClearRuns(PCRTL_BITMAP lpBits, PRTL_BITMAP_RUN lpSeries,
1040 ULONG ulCount, BOOLEAN bLongest)
1042 TRACE("(%p,%p,%d,%d)\n", lpBits, lpSeries, ulCount, bLongest);
1044 return NTDLL_FindRuns(lpBits, lpSeries, ulCount, bLongest, NTDLL_FindClearRun);
1047 /*************************************************************************
1048 * RtlFindLongestRunSet [NTDLL.@]
1050 * Find the longest set run in a bitmap.
1053 * lpBits [I] Bitmap pointer
1054 * pulStart [O] Destination for start of run
1057 * The length of the run found, or 0 if no run is found.
1059 ULONG WINAPI RtlFindLongestRunSet(PCRTL_BITMAP lpBits, PULONG pulStart)
1063 TRACE("(%p,%p)\n", lpBits, pulStart);
1065 if (RtlFindSetRuns(lpBits, &br, 1, TRUE) == 1)
1068 *pulStart = br.StartingIndex;
1069 return br.NumberOfBits;
1074 /*************************************************************************
1075 * RtlFindLongestRunClear [NTDLL.@]
1077 * Find the longest clear run in a bitmap.
1080 * lpBits [I] Bitmap pointer
1081 * pulStart [O] Destination for start of run
1084 * The length of the run found, or 0 if no run is found.
1086 ULONG WINAPI RtlFindLongestRunClear(PCRTL_BITMAP lpBits, PULONG pulStart)
1090 TRACE("(%p,%p)\n", lpBits, pulStart);
1092 if (RtlFindClearRuns(lpBits, &br, 1, TRUE) == 1)
1095 *pulStart = br.StartingIndex;
1096 return br.NumberOfBits;