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
;