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 compatible with Win32.
28 * Note that to avoid unexpected behaviour, the size of a bitmap should be set
29 * to a multiple of 32.
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
43 /* Bits set from LSB to MSB; used as mask for runs < 8 bits */
44 static const BYTE NTDLL_maskBits
[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };
46 /* Number of set bits for each value of a nibble; used for counting */
47 static const BYTE NTDLL_nibbleBitCount
[16] = {
48 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
51 /* First set bit in a nibble; used for determining least significant bit */
52 static const BYTE NTDLL_leastSignificant
[16] = {
53 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
56 /* Last set bit in a nibble; used for determining most significant bit */
57 static const signed char NTDLL_mostSignificant
[16] = {
58 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
61 /*************************************************************************
62 * RtlInitializeBitMap [NTDLL.@]
64 * Initialise a new bitmap.
67 * lpBits [I] Bitmap pointer
68 * lpBuff [I] Memory for the bitmap
69 * ulSize [I] Size of lpBuff in bits
75 * lpBuff must be aligned on a ULONG suitable boundary, to a multiple of 32 bytes
76 * in size (irrespective of ulSize given).
78 #undef RtlInitializeBitMap
79 VOID WINAPI
RtlInitializeBitMap(PRTL_BITMAP lpBits
, LPBYTE lpBuff
, ULONG ulSize
)
81 TRACE("(%p,%p,%ld)\n", lpBits
,lpBuff
,ulSize
);
82 lpBits
->SizeOfBitMap
= ulSize
;
83 lpBits
->BitMapBuffer
= lpBuff
;
86 /*************************************************************************
87 * RtlSetAllBits [NTDLL.@]
89 * Set all bits in a bitmap.
92 * lpBits [I] Bitmap pointer
98 VOID WINAPI
RtlSetAllBits(PRTL_BITMAP lpBits
)
100 TRACE("(%p)\n", lpBits
);
101 memset(lpBits
->BitMapBuffer
, 0xff, ((lpBits
->SizeOfBitMap
+ 31) & ~31) >> 3);
104 /*************************************************************************
105 * RtlClearAllBits [NTDLL.@]
107 * Clear all bits in a bitmap.
110 * lpBit [I] Bitmap pointer
115 #undef RtlClearAllBits
116 VOID WINAPI
RtlClearAllBits(PRTL_BITMAP lpBits
)
118 TRACE("(%p)\n", lpBits
);
119 memset(lpBits
->BitMapBuffer
, 0, ((lpBits
->SizeOfBitMap
+ 31) & ~31) >> 3);
122 /*************************************************************************
123 * RtlSetBits [NTDLL.@]
125 * Set a range of bits in a bitmap.
128 * lpBits [I] Bitmap pointer
129 * ulStart [I] First bit to set
130 * ulCount [I] Number of consecutive bits to set
135 VOID WINAPI
RtlSetBits(PRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
139 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
141 if (!lpBits
|| !ulCount
||
142 ulStart
>= lpBits
->SizeOfBitMap
||
143 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
146 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
148 /* Set bits in first byte, if ulStart isn't a byte boundary */
153 /* Set from start bit to the end of the byte */
154 *lpOut
++ |= 0xff << (ulStart
& 7);
155 ulCount
-= (8 - (ulStart
& 7));
159 /* Set from the start bit, possibly into the next byte also */
160 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
162 *lpOut
++ |= (initialWord
& 0xff);
163 *lpOut
|= (initialWord
>> 8);
168 /* Set bits up to complete byte count */
171 memset(lpOut
, 0xff, ulCount
>> 3);
172 lpOut
= lpOut
+ (ulCount
>> 3);
175 /* Set remaining bits, if any */
176 *lpOut
|= NTDLL_maskBits
[ulCount
& 0x7];
179 /*************************************************************************
180 * RtlClearBits [NTDLL.@]
182 * Clear bits in a bitmap.
185 * lpBits [I] Bitmap pointer
186 * ulStart [I] First bit to set
187 * ulCount [I] Number of consecutive bits to clear
192 VOID WINAPI
RtlClearBits(PRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
196 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
198 if (!lpBits
|| !ulCount
||
199 ulStart
>= lpBits
->SizeOfBitMap
||
200 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
203 lpOut
= lpBits
->BitMapBuffer
+ (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,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
258 if (!lpBits
|| !ulCount
||
259 ulStart
>= lpBits
->SizeOfBitMap
||
260 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
263 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
265 /* Check bits in first byte, if ulStart isn't a byte boundary */
270 /* Check from start bit to the end of the byte */
272 ((0xff << (ulStart
& 7))) & 0xff) != ((0xff << (ulStart
& 7) & 0xff)))
275 ulCount
-= (8 - (ulStart
& 7));
279 /* Check from the start bit, possibly into the next byte also */
280 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
282 if ((*lpOut
& (initialWord
& 0xff)) != (initialWord
& 0xff))
284 if ((initialWord
& 0xff00) &&
285 ((lpOut
[1] & (initialWord
>> 8)) != (initialWord
>> 8)))
291 /* Check bits in blocks of 8 bytes */
292 ulRemainder
= ulCount
& 7;
296 if (*lpOut
++ != 0xff)
300 /* Check remaining bits, if any */
302 (*lpOut
& NTDLL_maskBits
[ulRemainder
]) != NTDLL_maskBits
[ulRemainder
])
307 /*************************************************************************
308 * RtlAreBitsClear [NTDLL.@]
310 * Determine if part of a bitmap is clear.
313 * lpBits [I] Bitmap pointer
314 * ulStart [I] First bit to check from
315 * ulCount [I] Number of consecutive bits to check
318 * TRUE, If ulCount bits from ulStart are clear.
321 BOOLEAN WINAPI
RtlAreBitsClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
326 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
328 if (!lpBits
|| !ulCount
||
329 ulStart
>= lpBits
->SizeOfBitMap
||
330 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
333 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
335 /* Check bits in first byte, if ulStart isn't a byte boundary */
340 /* Check from start bit to the end of the byte */
341 if (*lpOut
& ((0xff << (ulStart
& 7)) & 0xff))
344 ulCount
-= (8 - (ulStart
& 7));
348 /* Check from the start bit, possibly into the next byte also */
349 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
351 if (*lpOut
& (initialWord
& 0xff))
353 if ((initialWord
& 0xff00) && (lpOut
[1] & (initialWord
>> 8)))
359 /* Check bits in blocks of 8 bytes */
360 ulRemainder
= ulCount
& 7;
368 /* Check remaining bits, if any */
369 if (ulRemainder
&& *lpOut
& NTDLL_maskBits
[ulRemainder
])
374 /*************************************************************************
375 * RtlFindSetBits [NTDLL.@]
377 * Find a block of set bits in a bitmap.
380 * lpBits [I] Bitmap pointer
381 * ulCount [I] Number of consecutive set bits to find
382 * ulHint [I] Suggested starting position for set bits
385 * The bit at which the match was found, or -1 if no match was found.
387 ULONG WINAPI
RtlFindSetBits(PCRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
391 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
393 if (!lpBits
|| !ulCount
|| ulCount
> lpBits
->SizeOfBitMap
)
396 ulEnd
= lpBits
->SizeOfBitMap
;
398 if (ulHint
+ ulCount
> lpBits
->SizeOfBitMap
)
403 while (ulPos
< ulEnd
)
405 /* FIXME: This could be made a _lot_ more efficient */
406 if (RtlAreBitsSet(lpBits
, ulPos
, ulCount
))
409 /* Start from the beginning if we hit the end and had a hint */
410 if (ulPos
== ulEnd
- 1 && ulHint
)
421 /*************************************************************************
422 * RtlFindClearBits [NTDLL.@]
424 * Find a block of clear bits in a bitmap.
427 * lpBits [I] Bitmap pointer
428 * ulCount [I] Number of consecutive clear bits to find
429 * ulHint [I] Suggested starting position for clear bits
432 * The bit at which the match was found, or -1 if no match was found.
434 ULONG WINAPI
RtlFindClearBits(PCRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
438 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
440 if (!lpBits
|| !ulCount
|| ulCount
> lpBits
->SizeOfBitMap
)
443 ulEnd
= lpBits
->SizeOfBitMap
;
445 if (ulHint
+ ulCount
> lpBits
->SizeOfBitMap
)
450 while (ulPos
< ulEnd
)
452 /* FIXME: This could be made a _lot_ more efficient */
453 if (RtlAreBitsClear(lpBits
, ulPos
, ulCount
))
456 /* Start from the beginning if we hit the end and started from ulHint */
457 if (ulPos
== ulEnd
- 1 && ulHint
)
468 /*************************************************************************
469 * RtlFindSetBitsAndClear [NTDLL.@]
471 * Find a block of set bits in a bitmap, and clear them if found.
474 * lpBits [I] Bitmap pointer
475 * ulCount [I] Number of consecutive set bits to find
476 * ulHint [I] Suggested starting position for set bits
479 * The bit at which the match was found, or -1 if no match was found.
481 ULONG WINAPI
RtlFindSetBitsAndClear(PRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
485 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
487 ulPos
= RtlFindSetBits(lpBits
, ulCount
, ulHint
);
489 RtlClearBits(lpBits
, ulPos
, ulCount
);
493 /*************************************************************************
494 * RtlFindClearBitsAndSet [NTDLL.@]
496 * Find a block of clear bits in a bitmap, and set them if found.
499 * lpBits [I] Bitmap pointer
500 * ulCount [I] Number of consecutive clear bits to find
501 * ulHint [I] Suggested starting position for clear bits
504 * The bit at which the match was found, or -1 if no match was found.
506 ULONG WINAPI
RtlFindClearBitsAndSet(PRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
510 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
512 ulPos
= RtlFindClearBits(lpBits
, ulCount
, ulHint
);
514 RtlSetBits(lpBits
, ulPos
, ulCount
);
518 /*************************************************************************
519 * RtlNumberOfSetBits [NTDLL.@]
521 * Find the number of set bits in a bitmap.
524 * lpBits [I] Bitmap pointer
527 * The number of set bits.
529 ULONG WINAPI
RtlNumberOfSetBits(PCRTL_BITMAP lpBits
)
533 TRACE("(%p)\n", lpBits
);
537 LPBYTE lpOut
= lpBits
->BitMapBuffer
;
538 ULONG ulCount
, ulRemainder
;
541 ulCount
= lpBits
->SizeOfBitMap
>> 3;
542 ulRemainder
= lpBits
->SizeOfBitMap
& 0x7;
546 ulSet
+= NTDLL_nibbleBitCount
[*lpOut
>> 4];
547 ulSet
+= NTDLL_nibbleBitCount
[*lpOut
& 0xf];
551 bMasked
= *lpOut
& NTDLL_maskBits
[ulRemainder
];
552 ulSet
+= NTDLL_nibbleBitCount
[bMasked
>> 4];
553 ulSet
+= NTDLL_nibbleBitCount
[bMasked
& 0xf];
558 /*************************************************************************
559 * RtlNumberOfClearBits [NTDLL.@]
561 * Find the number of clear bits in a bitmap.
564 * lpBits [I] Bitmap pointer
567 * The number of clear bits.
569 ULONG WINAPI
RtlNumberOfClearBits(PCRTL_BITMAP lpBits
)
571 TRACE("(%p)\n", lpBits
);
574 return lpBits
->SizeOfBitMap
- RtlNumberOfSetBits(lpBits
);
578 /*************************************************************************
579 * RtlFindMostSignificantBit [NTDLL.@]
581 * Find the most significant bit in a 64 bit integer.
584 * The position of the most significant bit.
586 CCHAR WINAPI
RtlFindMostSignificantBit(ULONGLONG ulLong
)
588 signed char ret
= 32;
591 if (!(dw
= (ulLong
>> 32)))
611 return ret
+ NTDLL_mostSignificant
[dw
];
614 /*************************************************************************
615 * RtlFindLeastSignificantBit [NTDLL.@]
617 * Find the least significant bit in a 64 bit integer.
620 * The position of the least significant bit.
622 CCHAR WINAPI
RtlFindLeastSignificantBit(ULONGLONG ulLong
)
627 if (!(dw
= (DWORD
)ulLong
))
630 if (!(dw
= ulLong
>> 32)) return -1;
647 return ret
+ NTDLL_leastSignificant
[dw
& 0x0f];
650 /*************************************************************************
653 * Internal helper: qsort comparison function for RTL_BITMAP_RUN arrays
655 static int NTDLL_RunSortFn(const void *lhs
, const void *rhs
)
657 if (((PCRTL_BITMAP_RUN
)lhs
)->SizeOfRun
> ((PRTL_BITMAP_RUN
)rhs
)->SizeOfRun
)
662 /*************************************************************************
665 * Internal helper: Find the next run of set bits in a bitmap.
667 static ULONG
NTDLL_FindSetRun(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpSize
)
670 ULONG ulFoundAt
= 0, ulCount
= 0;
672 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
676 /* Check bits in first byte */
677 const BYTE bMask
= (0xff << (ulStart
& 7)) & 0xff;
678 const BYTE bFirst
= *lpOut
& bMask
;
682 /* Have a set bit in first byte */
685 /* Not every bit is set */
689 ulOffset
= NTDLL_leastSignificant
[bFirst
& 0x0f];
691 ulOffset
= 4 + NTDLL_leastSignificant
[bFirst
>> 4];
694 for (;ulOffset
< 8; ulOffset
++)
696 if (!(bFirst
& (1 << ulOffset
)))
699 return ulFoundAt
; /* Set from start, but not until the end */
704 /* Set to the end - go on to count further bits */
708 /* every bit from start until the end of the byte is set */
710 ulCount
= 8 - (ulStart
& 7);
711 ulStart
= (ulStart
& ~7u) + 8;
715 ulStart
= (ulStart
& ~7u) + 8;
717 if (ulStart
>= lpBits
->SizeOfBitMap
)
721 /* Count blocks of 8 set bits */
722 while (*lpOut
== 0xff)
726 if (ulStart
>= lpBits
->SizeOfBitMap
)
728 *lpSize
= ulCount
- (ulStart
- lpBits
->SizeOfBitMap
);
734 /* Count remaining contigious bits, if any */
739 for (;ulOffset
< 7u; ulOffset
++)
741 if (!(*lpOut
& (1 << ulOffset
)))
750 /*************************************************************************
753 * Internal helper: Find the next run of set bits in a bitmap.
755 static ULONG
NTDLL_FindClearRun(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpSize
)
758 ULONG ulFoundAt
= 0, ulCount
= 0;
760 lpOut
= lpBits
->BitMapBuffer
+ (ulStart
>> 3u);
764 /* Check bits in first byte */
765 const BYTE bMask
= (0xff << (ulStart
& 7)) & 0xff;
766 const BYTE bFirst
= (~*lpOut
) & bMask
;
770 /* Have a clear bit in first byte */
773 /* Not every bit is clear */
777 ulOffset
= NTDLL_leastSignificant
[bFirst
& 0x0f];
779 ulOffset
= 4 + NTDLL_leastSignificant
[bFirst
>> 4];
782 for (;ulOffset
< 8; ulOffset
++)
784 if (!(bFirst
& (1 << ulOffset
)))
787 return ulFoundAt
; /* Clear from start, but not until the end */
792 /* Clear to the end - go on to count further bits */
796 /* Every bit from start until the end of the byte is clear */
798 ulCount
= 8 - (ulStart
& 7);
799 ulStart
= (ulStart
& ~7u) + 8;
803 ulStart
= (ulStart
& ~7u) + 8;
805 if (ulStart
>= lpBits
->SizeOfBitMap
)
809 /* Count blocks of 8 clear bits */
814 if (ulStart
>= lpBits
->SizeOfBitMap
)
816 *lpSize
= ulCount
- (ulStart
- lpBits
->SizeOfBitMap
);
822 /* Count remaining contigious bits, if any */
827 for (;ulOffset
< 7u; ulOffset
++)
829 if (*lpOut
& (1 << ulOffset
))
838 /*************************************************************************
839 * RtlFindNextForwardRunSet [NTDLL.@]
841 * Find the next run of set bits in a bitmap.
844 * lpBits [I] Bitmap pointer
845 * ulStart [I] Bit position to start searching from
846 * lpPos [O] Start of run
849 * Success: The length of the next set run in the bitmap. lpPos is set to
850 * the start of the run.
851 * Failure: 0, if no run is found or any parameters are invalid.
853 ULONG WINAPI
RtlFindNextForwardRunSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
857 TRACE("(%p,%ld,%p)\n", lpBits
, ulStart
, lpPos
);
859 if (lpBits
&& ulStart
< lpBits
->SizeOfBitMap
&& lpPos
)
860 *lpPos
= NTDLL_FindSetRun(lpBits
, ulStart
, &ulSize
);
865 /*************************************************************************
866 * RtlFindNextForwardRunClear [NTDLL.@]
868 * Find the next run of clear bits in a bitmap.
871 * lpBits [I] Bitmap pointer
872 * ulStart [I] Bit position to start searching from
873 * lpPos [O] Start of run
876 * Success: The length of the next clear run in the bitmap. lpPos is set to
877 * the start of the run.
878 * Failure: 0, if no run is found or any parameters are invalid.
880 ULONG WINAPI
RtlFindNextForwardRunClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
884 TRACE("(%p,%ld,%p)\n", lpBits
, ulStart
, lpPos
);
886 if (lpBits
&& ulStart
< lpBits
->SizeOfBitMap
&& lpPos
)
887 *lpPos
= NTDLL_FindClearRun(lpBits
, ulStart
, &ulSize
);
892 /*************************************************************************
893 * RtlFindLastBackwardRunSet [NTDLL.@]
895 * Find a previous run of set bits in a bitmap.
898 * lpBits [I] Bitmap pointer
899 * ulStart [I] Bit position to start searching from
900 * lpPos [O] Start of run
903 * Success: The length of the previous set run in the bitmap. lpPos is set to
904 * the start of the run.
905 * Failure: 0, if no run is found or any parameters are invalid.
907 ULONG WINAPI
RtlFindLastBackwardRunSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
909 FIXME("(%p,%ld,%p)-stub!\n", lpBits
, ulStart
, lpPos
);
913 /*************************************************************************
914 * RtlFindLastBackwardRunClear [NTDLL.@]
916 * Find a previous run of clear bits in a bitmap.
919 * lpBits [I] Bitmap pointer
920 * ulStart [I] Bit position to start searching from
921 * lpPos [O] Start of run
924 * Success: The length of the previous clear run in the bitmap. lpPos is set
925 * to the start of the run.
926 * Failure: 0, if no run is found or any parameters are invalid.
928 ULONG WINAPI
RtlFindLastBackwardRunClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
930 FIXME("(%p,%ld,%p)-stub!\n", lpBits
, ulStart
, lpPos
);
934 /*************************************************************************
937 * Internal implementation of RtlFindSetRuns/RtlFindClearRuns.
939 static ULONG WINAPI
NTDLL_FindRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
940 ULONG ulCount
, BOOLEAN bLongest
,
941 ULONG (*fn
)(PCRTL_BITMAP
,ULONG
,PULONG
))
943 BOOL bNeedSort
= ulCount
> 1 ? TRUE
: FALSE
;
944 ULONG ulPos
= 0, ulRuns
= 0;
946 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
951 while (ulPos
< lpBits
->SizeOfBitMap
)
953 /* Find next set/clear run */
954 ULONG ulSize
, ulNextPos
= fn(lpBits
, ulPos
, &ulSize
);
956 if (ulNextPos
== ~0UL)
959 if (bLongest
&& ulRuns
== ulCount
)
961 /* Sort runs with shortest at end, if they are out of order */
963 qsort(lpSeries
, ulRuns
, sizeof(RTL_BITMAP_RUN
), NTDLL_RunSortFn
);
965 /* Replace last run if this one is bigger */
966 if (ulSize
> lpSeries
[ulRuns
- 1].SizeOfRun
)
968 lpSeries
[ulRuns
- 1].StartOfRun
= ulNextPos
;
969 lpSeries
[ulRuns
- 1].SizeOfRun
= ulSize
;
971 /* We need to re-sort the array, _if_ we didn't leave it sorted */
972 if (ulRuns
> 1 && ulSize
> lpSeries
[ulRuns
- 2].SizeOfRun
)
978 /* Append to found runs */
979 lpSeries
[ulRuns
].StartOfRun
= ulNextPos
;
980 lpSeries
[ulRuns
].SizeOfRun
= ulSize
;
983 if (!bLongest
&& ulRuns
== ulCount
)
986 ulPos
= ulNextPos
+ ulSize
;
991 /*************************************************************************
992 * RtlFindSetRuns [NTDLL.@]
994 * Find a series of set runs in a bitmap.
997 * lpBits [I] Bitmap pointer
998 * ulSeries [O] Array for each run found
999 * ulCount [I] Number of runs to find
1000 * bLongest [I] Whether to find the very longest runs or not
1003 * The number of set runs found.
1005 ULONG WINAPI
RtlFindSetRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
1006 ULONG ulCount
, BOOLEAN bLongest
)
1008 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
1010 return NTDLL_FindRuns(lpBits
, lpSeries
, ulCount
, bLongest
, NTDLL_FindSetRun
);
1013 /*************************************************************************
1014 * RtlFindClearRuns [NTDLL.@]
1016 * Find a series of clear runs in a bitmap.
1019 * lpBits [I] Bitmap pointer
1020 * ulSeries [O] Array for each run found
1021 * ulCount [I] Number of runs to find
1022 * bLongest [I] Whether to find the very longest runs or not
1025 * The number of clear runs found.
1027 ULONG WINAPI
RtlFindClearRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
1028 ULONG ulCount
, BOOLEAN bLongest
)
1030 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
1032 return NTDLL_FindRuns(lpBits
, lpSeries
, ulCount
, bLongest
, NTDLL_FindClearRun
);
1035 /*************************************************************************
1036 * RtlFindLongestRunSet [NTDLL.@]
1038 * Find the longest set run in a bitmap.
1041 * lpBits [I] Bitmap pointer
1042 * pulStart [O] Destination for start of run
1045 * The length of the run found, or 0 if no run is found.
1047 ULONG WINAPI
RtlFindLongestRunSet(PCRTL_BITMAP lpBits
, PULONG pulStart
)
1051 TRACE("(%p,%p)\n", lpBits
, pulStart
);
1053 if (RtlFindSetRuns(lpBits
, &br
, 1, TRUE
) == 1)
1056 *pulStart
= br
.StartOfRun
;
1057 return br
.SizeOfRun
;
1062 /*************************************************************************
1063 * RtlFindLongestRunClear [NTDLL.@]
1065 * Find the longest clear run in a bitmap.
1068 * lpBits [I] Bitmap pointer
1069 * pulStart [O] Destination for start of run
1072 * The length of the run found, or 0 if no run is found.
1074 ULONG WINAPI
RtlFindLongestRunClear(PCRTL_BITMAP lpBits
, PULONG pulStart
)
1078 TRACE("(%p,%p)\n", lpBits
, pulStart
);
1080 if (RtlFindClearRuns(lpBits
, &br
, 1, TRUE
) == 1)
1083 *pulStart
= br
.StartOfRun
;
1084 return br
.SizeOfRun
;