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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 compatable with Win32.
28 * Note that to avoid unexpected behaviour, the size of a bitmap should be set
29 * to a multiple of 32.
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
39 /* Bits set from LSB to MSB; used as mask for runs < 8 bits */
40 static const BYTE NTDLL_maskBits
[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };
42 /* Number of set bits for each value of a nibble; used for counting */
43 static const BYTE NTDLL_nibbleBitCount
[16] = {
44 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
47 /* First set bit in a nibble; used for determining least significant bit */
48 static const BYTE NTDLL_leastSignificant
[16] = {
49 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
52 /* Last set bit in a nibble; used for determining most significant bit */
53 static const signed char NTDLL_mostSignificant
[16] = {
54 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
57 /*************************************************************************
58 * RtlInitializeBitMap [NTDLL.@]
60 * Initialise a new bitmap.
63 * lpBits [I] Bitmap pointer
64 * lpBuff [I] Memory for the bitmap
65 * ulSize [I] Size of lpBuff in bits
71 * lpBuff must be aligned on a ULONG suitable boundary, to a multiple of 32 bytes
72 * in size (irrespective of ulSize given).
74 #undef RtlInitializeBitMap
75 VOID WINAPI
RtlInitializeBitMap(PRTL_BITMAP lpBits
, LPBYTE lpBuff
, ULONG ulSize
)
77 TRACE("(%p,%p,%ld)\n", lpBits
,lpBuff
,ulSize
);
78 lpBits
->SizeOfBitMap
= ulSize
;
79 lpBits
->BitMapBuffer
= lpBuff
;
82 /*************************************************************************
83 * RtlSetAllBits [NTDLL.@]
85 * Set all bits in a bitmap.
88 * lpBits [I] Bitmap pointer
94 VOID WINAPI
RtlSetAllBits(PRTL_BITMAP lpBits
)
96 TRACE("(%p)\n", lpBits
);
97 memset(lpBits
->BitMapBuffer
, 0xff, ((lpBits
->SizeOfBitMap
+ 31) & 0xffffffe0) >> 3);
100 /*************************************************************************
101 * RtlClearAllBits [NTDLL.@]
103 * Clear all bits in a bitmap.
106 * lpBit [I] Bitmap pointer
111 #undef RtlClearAllBits
112 VOID WINAPI
RtlClearAllBits(PRTL_BITMAP lpBits
)
114 TRACE("(%p)\n", lpBits
);
115 memset(lpBits
->BitMapBuffer
, 0, ((lpBits
->SizeOfBitMap
+ 31) & 0xffffffe0) >> 3);
118 /*************************************************************************
119 * RtlSetBits [NTDLL.@]
121 * Set a range of bits in a bitmap.
124 * lpBits [I] Bitmap pointer
125 * ulStart [I] First bit to set
126 * ulCount [I] Number of consecutive bits to set
131 VOID WINAPI
RtlSetBits(PRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
135 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
137 if (!lpBits
|| !ulCount
|| ulStart
+ ulCount
> lpBits
->SizeOfBitMap
)
140 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
142 /* Set bits in first byte, if ulStart isn't a byte boundary */
147 /* Set from start bit to the end of the byte */
148 *lpOut
++ |= 0xff << (ulStart
& 7);
149 ulCount
-= (8 - (ulStart
& 7));
153 /* Set from the start bit, possibly into the next byte also */
154 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
156 *lpOut
++ |= (initialWord
& 0xff);
157 *lpOut
|= (initialWord
>> 8);
162 /* Set bits up to complete byte count */
165 memset(lpOut
, 0xff, ulCount
>> 3);
166 lpOut
= lpOut
+ (ulCount
>> 3);
169 /* Set remaining bits, if any */
170 *lpOut
|= NTDLL_maskBits
[ulCount
& 0x7];
173 /*************************************************************************
174 * RtlClearBits [NTDLL.@]
176 * Clear bits in a bitmap.
179 * lpBits [I] Bitmap pointer
180 * ulStart [I] First bit to set
181 * ulCount [I] Number of consecutive bits to clear
186 VOID WINAPI
RtlClearBits(PRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
190 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
192 if (!lpBits
|| !ulCount
|| ulStart
+ ulCount
> lpBits
->SizeOfBitMap
)
195 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
197 /* Clear bits in first byte, if ulStart isn't a byte boundary */
202 /* Clear from start bit to the end of the byte */
203 *lpOut
++ &= ~(0xff << (ulStart
& 7));
204 ulCount
-= (8 - (ulStart
& 7));
208 /* Clear from the start bit, possibly into the next byte also */
209 USHORT initialWord
= ~(NTDLL_maskBits
[ulCount
] << (ulStart
& 7));
211 *lpOut
++ &= (initialWord
& 0xff);
212 *lpOut
&= (initialWord
>> 8);
217 /* Clear bits (in blocks of 8) on whole byte boundaries */
220 memset(lpOut
, 0, ulCount
>> 3);
221 lpOut
= lpOut
+ (ulCount
>> 3);
224 /* Clear remaining bits, if any */
226 *lpOut
&= ~NTDLL_maskBits
[ulCount
& 0x7];
229 /*************************************************************************
230 * RtlAreBitsSet [NTDLL.@]
232 * Determine if part of a bitmap is set.
235 * lpBits [I] Bitmap pointer
236 * ulStart [I] First bit to check from
237 * ulCount [I] Number of consecutive bits to check
240 * TRUE, If ulCount bits from ulStart are set.
243 BOOLEAN WINAPI
RtlAreBitsSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
248 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
250 if (!lpBits
|| !ulCount
|| ulStart
+ ulCount
> lpBits
->SizeOfBitMap
)
253 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
255 /* Check bits in first byte, if ulStart isn't a byte boundary */
260 /* Check from start bit to the end of the byte */
262 ((0xff << (ulStart
& 7))) & 0xff) != ((0xff << (ulStart
& 7) & 0xff)))
265 ulCount
-= (8 - (ulStart
& 7));
269 /* Check from the start bit, possibly into the next byte also */
270 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
272 if ((*lpOut
& (initialWord
& 0xff)) != (initialWord
& 0xff))
274 if ((initialWord
& 0xff00) &&
275 ((lpOut
[1] & (initialWord
>> 8)) != (initialWord
>> 8)))
281 /* Check bits in blocks of 8 bytes */
282 ulRemainder
= ulCount
& 7;
286 if (*lpOut
++ != 0xff)
290 /* Check remaining bits, if any */
292 (*lpOut
& NTDLL_maskBits
[ulRemainder
]) != NTDLL_maskBits
[ulRemainder
])
297 /*************************************************************************
298 * RtlAreBitsClear [NTDLL.@]
300 * Determine if part of a bitmap is clear.
303 * lpBits [I] Bitmap pointer
304 * ulStart [I] First bit to check from
305 * ulCount [I] Number of consecutive bits to check
308 * TRUE, If ulCount bits from ulStart are clear.
311 BOOLEAN WINAPI
RtlAreBitsClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
316 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
318 if (!lpBits
|| !ulCount
|| ulStart
+ ulCount
> lpBits
->SizeOfBitMap
)
321 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
323 /* Check bits in first byte, if ulStart isn't a byte boundary */
328 /* Check from start bit to the end of the byte */
329 if (*lpOut
& ((0xff << (ulStart
& 7)) & 0xff))
332 ulCount
-= (8 - (ulStart
& 7));
336 /* Check from the start bit, possibly into the next byte also */
337 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
339 if (*lpOut
& (initialWord
& 0xff))
341 if ((initialWord
& 0xff00) && (lpOut
[1] & (initialWord
>> 8)))
347 /* Check bits in blocks of 8 bytes */
348 ulRemainder
= ulCount
& 7;
356 /* Check remaining bits, if any */
357 if (ulRemainder
&& *lpOut
& NTDLL_maskBits
[ulRemainder
])
362 /*************************************************************************
363 * RtlFindSetBits [NTDLL.@]
365 * Find a block of set bits in a bitmap.
368 * lpBits [I] Bitmap pointer
369 * ulCount [I] Number of consecutive set bits to find
370 * ulHint [I] Suggested starting position for set bits
373 * The bit at which the match was found, or -1 if no match was found.
375 ULONG WINAPI
RtlFindSetBits(PCRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
379 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
381 if (!lpBits
|| !ulCount
|| ulCount
> lpBits
->SizeOfBitMap
)
384 ulEnd
= lpBits
->SizeOfBitMap
;
386 if (ulHint
+ ulCount
> lpBits
->SizeOfBitMap
)
391 while (ulPos
< ulEnd
)
393 /* FIXME: This could be made a _lot_ more efficient */
394 if (RtlAreBitsSet(lpBits
, ulPos
, ulCount
))
397 /* Start from the beginning if we hit the end and had a hint */
398 if (ulPos
== ulEnd
- 1 && ulHint
)
409 /*************************************************************************
410 * RtlFindClearBits [NTDLL.@]
412 * Find a block of clear bits in a bitmap.
415 * lpBits [I] Bitmap pointer
416 * ulCount [I] Number of consecutive clear bits to find
417 * ulHint [I] Suggested starting position for clear bits
420 * The bit at which the match was found, or -1 if no match was found.
422 ULONG WINAPI
RtlFindClearBits(PCRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
426 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
428 if (!lpBits
|| !ulCount
|| ulCount
> lpBits
->SizeOfBitMap
)
431 ulEnd
= lpBits
->SizeOfBitMap
;
433 if (ulHint
+ ulCount
> lpBits
->SizeOfBitMap
)
438 while (ulPos
< ulEnd
)
440 /* FIXME: This could be made a _lot_ more efficient */
441 if (RtlAreBitsClear(lpBits
, ulPos
, ulCount
))
444 /* Start from the beginning if we hit the end and started from ulHint */
445 if (ulPos
== ulEnd
- 1 && ulHint
)
456 /*************************************************************************
457 * RtlFindSetBitsAndClear [NTDLL.@]
459 * Find a block of set bits in a bitmap, and clear them if found.
462 * lpBits [I] Bitmap pointer
463 * ulCount [I] Number of consecutive set bits to find
464 * ulHint [I] Suggested starting position for set bits
467 * The bit at which the match was found, or -1 if no match was found.
469 ULONG WINAPI
RtlFindSetBitsAndClear(PRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
473 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
475 ulPos
= RtlFindSetBits(lpBits
, ulCount
, ulHint
);
477 RtlClearBits(lpBits
, ulPos
, ulCount
);
481 /*************************************************************************
482 * RtlFindClearBitsAndSet [NTDLL.@]
484 * Find a block of clear bits in a bitmap, and set them if found.
487 * lpBits [I] Bitmap pointer
488 * ulCount [I] Number of consecutive clear bits to find
489 * ulHint [I] Suggested starting position for clear bits
492 * The bit at which the match was found, or -1 if no match was found.
494 ULONG WINAPI
RtlFindClearBitsAndSet(PRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
498 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
500 ulPos
= RtlFindClearBits(lpBits
, ulCount
, ulHint
);
502 RtlSetBits(lpBits
, ulPos
, ulCount
);
506 /*************************************************************************
507 * RtlNumberOfSetBits [NTDLL.@]
509 * Find the number of set bits in a bitmap.
512 * lpBits [I] Bitmap pointer
515 * The number of set bits.
517 ULONG WINAPI
RtlNumberOfSetBits(PCRTL_BITMAP lpBits
)
521 TRACE("(%p)\n", lpBits
);
525 LPBYTE lpOut
= lpBits
->BitMapBuffer
;
526 ULONG ulCount
, ulRemainder
;
529 ulCount
= lpBits
->SizeOfBitMap
>> 3;
530 ulRemainder
= lpBits
->SizeOfBitMap
& 0x7;
534 ulSet
+= NTDLL_nibbleBitCount
[*lpOut
>> 4];
535 ulSet
+= NTDLL_nibbleBitCount
[*lpOut
& 0xf];
539 bMasked
= *lpOut
& NTDLL_maskBits
[ulRemainder
];
540 ulSet
+= NTDLL_nibbleBitCount
[bMasked
>> 4];
541 ulSet
+= NTDLL_nibbleBitCount
[bMasked
& 0xf];
546 /*************************************************************************
547 * RtlNumberOfClearBits [NTDLL.@]
549 * Find the number of clear bits in a bitmap.
552 * lpBits [I] Bitmap pointer
555 * The number of clear bits.
557 ULONG WINAPI
RtlNumberOfClearBits(PCRTL_BITMAP lpBits
)
559 TRACE("(%p)\n", lpBits
);
562 return lpBits
->SizeOfBitMap
- RtlNumberOfSetBits(lpBits
);
566 /*************************************************************************
567 * RtlFindMostSignificantBit [NTDLL.@]
569 * Find the most significant bit in a 64 bit integer.
572 * The position of the most significant bit.
574 CCHAR WINAPI
RtlFindMostSignificantBit(ULONGLONG ulLong
)
576 signed char ret
= 32;
579 if (!(dw
= (ulLong
>> 32)))
599 return ret
+ NTDLL_mostSignificant
[dw
];
602 /*************************************************************************
603 * RtlFindLeastSignificantBit [NTDLL.@]
605 * Find the least significant bit in a 64 bit integer.
608 * The position of the least significant bit.
610 CCHAR WINAPI
RtlFindLeastSignificantBit(ULONGLONG ulLong
)
615 if (!(dw
= (DWORD
)ulLong
))
618 if (!(dw
= ulLong
>> 32)) return -1;
635 return ret
+ NTDLL_leastSignificant
[dw
& 0x0f];
638 /*************************************************************************
641 * Internal helper: qsort comparison function for RTL_BITMAP_RUN arrays
643 static int NTDLL_RunSortFn(const void *lhs
, const void *rhs
)
645 if (((PCRTL_BITMAP_RUN
)lhs
)->SizeOfRun
> ((PRTL_BITMAP_RUN
)rhs
)->SizeOfRun
)
650 /*************************************************************************
653 * Internal helper: Find the next run of set bits in a bitmap.
655 static ULONG
NTDLL_FindSetRun(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpSize
)
658 ULONG ulFoundAt
= 0, ulCount
= 0;
660 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
664 /* Check bits in first byte */
665 const BYTE bMask
= (0xff << (ulStart
& 7)) & 0xff;
666 const BYTE bFirst
= *lpOut
& bMask
;
670 /* Have a set bit in first byte */
673 /* Not every bit is set */
677 ulOffset
= NTDLL_leastSignificant
[bFirst
& 0x0f];
679 ulOffset
= 4 + NTDLL_leastSignificant
[bFirst
>> 4];
682 for (;ulOffset
< 8; ulOffset
++)
684 if (!(bFirst
& (1 << ulOffset
)))
687 return ulFoundAt
; /* Set from start, but not until the end */
692 /* Set to the end - go on to count further bits */
696 /* every bit from start until the end of the byte is set */
698 ulCount
= 8 - (ulStart
& 7);
699 ulStart
= (ulStart
& ~7u) + 8;
703 ulStart
= (ulStart
& ~7u) + 8;
705 if (ulStart
>= lpBits
->SizeOfBitMap
)
709 /* Count blocks of 8 set bits */
710 while (*lpOut
== 0xff)
714 if (ulStart
>= lpBits
->SizeOfBitMap
)
716 *lpSize
= ulCount
- (ulStart
- lpBits
->SizeOfBitMap
);
722 /* Count remaining contigious bits, if any */
727 for (;ulOffset
< 7u; ulOffset
++)
729 if (!(*lpOut
& (1 << ulOffset
)))
738 /*************************************************************************
741 * Internal helper: Find the next run of set bits in a bitmap.
743 static ULONG
NTDLL_FindClearRun(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpSize
)
746 ULONG ulFoundAt
= 0, ulCount
= 0;
748 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
752 /* Check bits in first byte */
753 const BYTE bMask
= (0xff << (ulStart
& 7)) & 0xff;
754 const BYTE bFirst
= (~*lpOut
) & bMask
;
758 /* Have a clear bit in first byte */
761 /* Not every bit is clear */
765 ulOffset
= NTDLL_leastSignificant
[bFirst
& 0x0f];
767 ulOffset
= 4 + NTDLL_leastSignificant
[bFirst
>> 4];
770 for (;ulOffset
< 8; ulOffset
++)
772 if (!(bFirst
& (1 << ulOffset
)))
775 return ulFoundAt
; /* Clear from start, but not until the end */
780 /* Clear to the end - go on to count further bits */
784 /* Every bit from start until the end of the byte is clear */
786 ulCount
= 8 - (ulStart
& 7);
787 ulStart
= (ulStart
& ~7u) + 8;
791 ulStart
= (ulStart
& ~7u) + 8;
793 if (ulStart
>= lpBits
->SizeOfBitMap
)
797 /* Count blocks of 8 clear bits */
802 if (ulStart
>= lpBits
->SizeOfBitMap
)
804 *lpSize
= ulCount
- (ulStart
- lpBits
->SizeOfBitMap
);
810 /* Count remaining contigious bits, if any */
815 for (;ulOffset
< 7u; ulOffset
++)
817 if (*lpOut
& (1 << ulOffset
))
826 /*************************************************************************
827 * RtlFindNextForwardRunSet [NTDLL.@]
829 * Find the next run of set bits in a bitmap.
832 * lpBits [I] Bitmap pointer
833 * ulStart [I] Bit position to start searching from
834 * lpPos [O] Start of run
837 * Success: The length of the next set run in the bitmap. lpPos is set to
838 * the start of the run.
839 * Failure: 0, if no run is found or any parameters are invalid.
841 ULONG WINAPI
RtlFindNextForwardRunSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
845 TRACE("(%p,%ld,%p)\n", lpBits
, ulStart
, lpPos
);
847 if (lpBits
&& ulStart
< lpBits
->SizeOfBitMap
&& lpPos
)
848 *lpPos
= NTDLL_FindSetRun(lpBits
, ulStart
, &ulSize
);
853 /*************************************************************************
854 * RtlFindNextForwardRunClear [NTDLL.@]
856 * Find the next run of clear bits in a bitmap.
859 * lpBits [I] Bitmap pointer
860 * ulStart [I] Bit position to start searching from
861 * lpPos [O] Start of run
864 * Success: The length of the next clear run in the bitmap. lpPos is set to
865 * the start of the run.
866 * Failure: 0, if no run is found or any parameters are invalid.
868 ULONG WINAPI
RtlFindNextForwardRunClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
872 TRACE("(%p,%ld,%p)\n", lpBits
, ulStart
, lpPos
);
874 if (lpBits
&& ulStart
< lpBits
->SizeOfBitMap
&& lpPos
)
875 *lpPos
= NTDLL_FindClearRun(lpBits
, ulStart
, &ulSize
);
880 /*************************************************************************
881 * RtlFindLastBackwardRunSet [NTDLL.@]
883 * Find a previous run of set bits in a bitmap.
886 * lpBits [I] Bitmap pointer
887 * ulStart [I] Bit position to start searching from
888 * lpPos [O] Start of run
891 * Success: The length of the previous set run in the bitmap. lpPos is set to
892 * the start of the run.
893 * Failure: 0, if no run is found or any parameters are invalid.
895 ULONG WINAPI
RtlFindLastBackwardRunSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
897 FIXME("(%p,%ld,%p)-stub!\n", lpBits
, ulStart
, lpPos
);
901 /*************************************************************************
902 * RtlFindLastBackwardRunClear [NTDLL.@]
904 * Find a previous run of clear bits in a bitmap.
907 * lpBits [I] Bitmap pointer
908 * ulStart [I] Bit position to start searching from
909 * lpPos [O] Start of run
912 * Success: The length of the previous clear run in the bitmap. lpPos is set
913 * to the start of the run.
914 * Failure: 0, if no run is found or any parameters are invalid.
916 ULONG WINAPI
RtlFindLastBackwardRunClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
918 FIXME("(%p,%ld,%p)-stub!\n", lpBits
, ulStart
, lpPos
);
922 /*************************************************************************
925 * Internal implementation of RtlFindSetRuns/RtlFindClearRuns.
927 static ULONG WINAPI
NTDLL_FindRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
928 ULONG ulCount
, BOOLEAN bLongest
,
929 ULONG (*fn
)(PCRTL_BITMAP
,ULONG
,PULONG
))
931 BOOL bNeedSort
= ulCount
> 1 ? TRUE
: FALSE
;
932 ULONG ulPos
= 0, ulRuns
= 0;
934 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
939 while (ulPos
< lpBits
->SizeOfBitMap
)
941 /* Find next set/clear run */
942 ULONG ulSize
, ulNextPos
= fn(lpBits
, ulPos
, &ulSize
);
944 if (ulNextPos
== -1u)
947 if (bLongest
&& ulRuns
== ulCount
)
949 /* Sort runs with shortest at end, if they are out of order */
951 qsort(lpSeries
, ulRuns
, sizeof(RTL_BITMAP_RUN
), NTDLL_RunSortFn
);
953 /* Replace last run if this one is bigger */
954 if (ulSize
> lpSeries
[ulRuns
- 1].SizeOfRun
)
956 lpSeries
[ulRuns
- 1].StartOfRun
= ulNextPos
;
957 lpSeries
[ulRuns
- 1].SizeOfRun
= ulSize
;
959 /* We need to re-sort the array, _if_ we didn't leave it sorted */
960 if (ulRuns
> 1 && ulSize
> lpSeries
[ulRuns
- 2].SizeOfRun
)
966 /* Append to found runs */
967 lpSeries
[ulRuns
].StartOfRun
= ulNextPos
;
968 lpSeries
[ulRuns
].SizeOfRun
= ulSize
;
971 if (!bLongest
&& ulRuns
== ulCount
)
974 ulPos
= ulNextPos
+ ulSize
;
979 /*************************************************************************
980 * RtlFindSetRuns [NTDLL.@]
982 * Find a series of set runs in a bitmap.
985 * lpBits [I] Bitmap pointer
986 * ulSeries [O] Array for each run found
987 * ulCount [I] Number of runs to find
988 * bLongest [I] Whether to find the very longest runs or not
991 * The number of set runs found.
993 ULONG WINAPI
RtlFindSetRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
994 ULONG ulCount
, BOOLEAN bLongest
)
996 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
998 return NTDLL_FindRuns(lpBits
, lpSeries
, ulCount
, bLongest
, NTDLL_FindSetRun
);
1001 /*************************************************************************
1002 * RtlFindClearRuns [NTDLL.@]
1004 * Find a series of clear runs in a bitmap.
1007 * lpBits [I] Bitmap pointer
1008 * ulSeries [O] Array for each run found
1009 * ulCount [I] Number of runs to find
1010 * bLongest [I] Whether to find the very longest runs or not
1013 * The number of clear runs found.
1015 ULONG WINAPI
RtlFindClearRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
1016 ULONG ulCount
, BOOLEAN bLongest
)
1018 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
1020 return NTDLL_FindRuns(lpBits
, lpSeries
, ulCount
, bLongest
, NTDLL_FindClearRun
);
1023 /*************************************************************************
1024 * RtlFindLongestRunSet [NTDLL.@]
1026 * Find the longest set run in a bitmap.
1029 * lpBits [I] Bitmap pointer
1030 * pulStart [O] Destination for start of run
1033 * The length of the run found, or 0 if no run is found.
1035 ULONG WINAPI
RtlFindLongestRunSet(PCRTL_BITMAP lpBits
, PULONG pulStart
)
1039 TRACE("(%p,%p)\n", lpBits
, pulStart
);
1041 if (RtlFindSetRuns(lpBits
, &br
, 1, TRUE
) == 1)
1044 *pulStart
= br
.StartOfRun
;
1045 return br
.SizeOfRun
;
1050 /*************************************************************************
1051 * RtlFindLongestRunClear [NTDLL.@]
1053 * Find the longest clear run in a bitmap.
1056 * lpBits [I] Bitmap pointer
1057 * pulStart [O] Destination for start of run
1060 * The length of the run found, or 0 if no run is found.
1062 ULONG WINAPI
RtlFindLongestRunClear(PCRTL_BITMAP lpBits
, PULONG pulStart
)
1066 TRACE("(%p,%p)\n", lpBits
, pulStart
);
1068 if (RtlFindClearRuns(lpBits
, &br
, 1, TRUE
) == 1)
1071 *pulStart
= br
.StartOfRun
;
1072 return br
.SizeOfRun
;