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 VOID WINAPI
RtlInitializeBitMap(PRTL_BITMAP lpBits
, PULONG lpBuff
, ULONG ulSize
)
80 TRACE("(%p,%p,%ld)\n", lpBits
,lpBuff
,ulSize
);
81 lpBits
->SizeOfBitMap
= ulSize
;
82 lpBits
->Buffer
= lpBuff
;
85 /*************************************************************************
86 * RtlSetAllBits [NTDLL.@]
88 * Set all bits in a bitmap.
91 * lpBits [I] Bitmap pointer
96 VOID WINAPI
RtlSetAllBits(PRTL_BITMAP lpBits
)
98 TRACE("(%p)\n", lpBits
);
99 memset(lpBits
->Buffer
, 0xff, ((lpBits
->SizeOfBitMap
+ 31) & ~31) >> 3);
102 /*************************************************************************
103 * RtlClearAllBits [NTDLL.@]
105 * Clear all bits in a bitmap.
108 * lpBit [I] Bitmap pointer
113 VOID WINAPI
RtlClearAllBits(PRTL_BITMAP lpBits
)
115 TRACE("(%p)\n", lpBits
);
116 memset(lpBits
->Buffer
, 0, ((lpBits
->SizeOfBitMap
+ 31) & ~31) >> 3);
119 /*************************************************************************
120 * RtlSetBits [NTDLL.@]
122 * Set a range of bits in a bitmap.
125 * lpBits [I] Bitmap pointer
126 * ulStart [I] First bit to set
127 * ulCount [I] Number of consecutive bits to set
132 VOID WINAPI
RtlSetBits(PRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
136 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
138 if (!lpBits
|| !ulCount
||
139 ulStart
>= lpBits
->SizeOfBitMap
||
140 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
143 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
144 * at a time. But beware of the pointer arithmetics...
146 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (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 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
204 * at a time. But beware of the pointer arithmetics...
206 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
208 /* Clear bits in first byte, if ulStart isn't a byte boundary */
213 /* Clear from start bit to the end of the byte */
214 *lpOut
++ &= ~(0xff << (ulStart
& 7));
215 ulCount
-= (8 - (ulStart
& 7));
219 /* Clear from the start bit, possibly into the next byte also */
220 USHORT initialWord
= ~(NTDLL_maskBits
[ulCount
] << (ulStart
& 7));
222 *lpOut
++ &= (initialWord
& 0xff);
223 *lpOut
&= (initialWord
>> 8);
228 /* Clear bits (in blocks of 8) on whole byte boundaries */
231 memset(lpOut
, 0, ulCount
>> 3);
232 lpOut
= lpOut
+ (ulCount
>> 3);
235 /* Clear remaining bits, if any */
237 *lpOut
&= ~NTDLL_maskBits
[ulCount
& 0x7];
240 /*************************************************************************
241 * RtlAreBitsSet [NTDLL.@]
243 * Determine if part of a bitmap is set.
246 * lpBits [I] Bitmap pointer
247 * ulStart [I] First bit to check from
248 * ulCount [I] Number of consecutive bits to check
251 * TRUE, If ulCount bits from ulStart are set.
254 BOOLEAN WINAPI
RtlAreBitsSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
259 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
261 if (!lpBits
|| !ulCount
||
262 ulStart
>= lpBits
->SizeOfBitMap
||
263 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
266 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
267 * at a time. But beware of the pointer arithmetics...
269 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
271 /* Check bits in first byte, if ulStart isn't a byte boundary */
276 /* Check from start bit to the end of the byte */
278 ((0xff << (ulStart
& 7))) & 0xff) != ((0xff << (ulStart
& 7) & 0xff)))
281 ulCount
-= (8 - (ulStart
& 7));
285 /* Check from the start bit, possibly into the next byte also */
286 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
288 if ((*lpOut
& (initialWord
& 0xff)) != (initialWord
& 0xff))
290 if ((initialWord
& 0xff00) &&
291 ((lpOut
[1] & (initialWord
>> 8)) != (initialWord
>> 8)))
297 /* Check bits in blocks of 8 bytes */
298 ulRemainder
= ulCount
& 7;
302 if (*lpOut
++ != 0xff)
306 /* Check remaining bits, if any */
308 (*lpOut
& NTDLL_maskBits
[ulRemainder
]) != NTDLL_maskBits
[ulRemainder
])
313 /*************************************************************************
314 * RtlAreBitsClear [NTDLL.@]
316 * Determine if part of a bitmap is clear.
319 * lpBits [I] Bitmap pointer
320 * ulStart [I] First bit to check from
321 * ulCount [I] Number of consecutive bits to check
324 * TRUE, If ulCount bits from ulStart are clear.
327 BOOLEAN WINAPI
RtlAreBitsClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
332 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
334 if (!lpBits
|| !ulCount
||
335 ulStart
>= lpBits
->SizeOfBitMap
||
336 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
339 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
340 * at a time. But beware of the pointer arithmetics...
342 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
344 /* Check bits in first byte, if ulStart isn't a byte boundary */
349 /* Check from start bit to the end of the byte */
350 if (*lpOut
& ((0xff << (ulStart
& 7)) & 0xff))
353 ulCount
-= (8 - (ulStart
& 7));
357 /* Check from the start bit, possibly into the next byte also */
358 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
360 if (*lpOut
& (initialWord
& 0xff))
362 if ((initialWord
& 0xff00) && (lpOut
[1] & (initialWord
>> 8)))
368 /* Check bits in blocks of 8 bytes */
369 ulRemainder
= ulCount
& 7;
377 /* Check remaining bits, if any */
378 if (ulRemainder
&& *lpOut
& NTDLL_maskBits
[ulRemainder
])
383 /*************************************************************************
384 * RtlFindSetBits [NTDLL.@]
386 * Find a block of set bits in a bitmap.
389 * lpBits [I] Bitmap pointer
390 * ulCount [I] Number of consecutive set bits to find
391 * ulHint [I] Suggested starting position for set bits
394 * The bit at which the match was found, or -1 if no match was found.
396 ULONG WINAPI
RtlFindSetBits(PCRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
400 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
402 if (!lpBits
|| !ulCount
|| ulCount
> lpBits
->SizeOfBitMap
)
405 ulEnd
= lpBits
->SizeOfBitMap
;
407 if (ulHint
+ ulCount
> lpBits
->SizeOfBitMap
)
412 while (ulPos
< ulEnd
)
414 /* FIXME: This could be made a _lot_ more efficient */
415 if (RtlAreBitsSet(lpBits
, ulPos
, ulCount
))
418 /* Start from the beginning if we hit the end and had a hint */
419 if (ulPos
== ulEnd
- 1 && ulHint
)
430 /*************************************************************************
431 * RtlFindClearBits [NTDLL.@]
433 * Find a block of clear bits in a bitmap.
436 * lpBits [I] Bitmap pointer
437 * ulCount [I] Number of consecutive clear bits to find
438 * ulHint [I] Suggested starting position for clear bits
441 * The bit at which the match was found, or -1 if no match was found.
443 ULONG WINAPI
RtlFindClearBits(PCRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
447 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
449 if (!lpBits
|| !ulCount
|| ulCount
> lpBits
->SizeOfBitMap
)
452 ulEnd
= lpBits
->SizeOfBitMap
;
454 if (ulHint
+ ulCount
> lpBits
->SizeOfBitMap
)
459 while (ulPos
< ulEnd
)
461 /* FIXME: This could be made a _lot_ more efficient */
462 if (RtlAreBitsClear(lpBits
, ulPos
, ulCount
))
465 /* Start from the beginning if we hit the end and started from ulHint */
466 if (ulPos
== ulEnd
- 1 && ulHint
)
477 /*************************************************************************
478 * RtlFindSetBitsAndClear [NTDLL.@]
480 * Find a block of set bits in a bitmap, and clear them if found.
483 * lpBits [I] Bitmap pointer
484 * ulCount [I] Number of consecutive set bits to find
485 * ulHint [I] Suggested starting position for set bits
488 * The bit at which the match was found, or -1 if no match was found.
490 ULONG WINAPI
RtlFindSetBitsAndClear(PRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
494 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
496 ulPos
= RtlFindSetBits(lpBits
, ulCount
, ulHint
);
498 RtlClearBits(lpBits
, ulPos
, ulCount
);
502 /*************************************************************************
503 * RtlFindClearBitsAndSet [NTDLL.@]
505 * Find a block of clear bits in a bitmap, and set them if found.
508 * lpBits [I] Bitmap pointer
509 * ulCount [I] Number of consecutive clear bits to find
510 * ulHint [I] Suggested starting position for clear bits
513 * The bit at which the match was found, or -1 if no match was found.
515 ULONG WINAPI
RtlFindClearBitsAndSet(PRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
519 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
521 ulPos
= RtlFindClearBits(lpBits
, ulCount
, ulHint
);
523 RtlSetBits(lpBits
, ulPos
, ulCount
);
527 /*************************************************************************
528 * RtlNumberOfSetBits [NTDLL.@]
530 * Find the number of set bits in a bitmap.
533 * lpBits [I] Bitmap pointer
536 * The number of set bits.
538 ULONG WINAPI
RtlNumberOfSetBits(PCRTL_BITMAP lpBits
)
542 TRACE("(%p)\n", lpBits
);
546 LPBYTE lpOut
= (BYTE
*)lpBits
->Buffer
;
547 ULONG ulCount
, ulRemainder
;
550 ulCount
= lpBits
->SizeOfBitMap
>> 3;
551 ulRemainder
= lpBits
->SizeOfBitMap
& 0x7;
555 ulSet
+= NTDLL_nibbleBitCount
[*lpOut
>> 4];
556 ulSet
+= NTDLL_nibbleBitCount
[*lpOut
& 0xf];
560 bMasked
= *lpOut
& NTDLL_maskBits
[ulRemainder
];
561 ulSet
+= NTDLL_nibbleBitCount
[bMasked
>> 4];
562 ulSet
+= NTDLL_nibbleBitCount
[bMasked
& 0xf];
567 /*************************************************************************
568 * RtlNumberOfClearBits [NTDLL.@]
570 * Find the number of clear bits in a bitmap.
573 * lpBits [I] Bitmap pointer
576 * The number of clear bits.
578 ULONG WINAPI
RtlNumberOfClearBits(PCRTL_BITMAP lpBits
)
580 TRACE("(%p)\n", lpBits
);
583 return lpBits
->SizeOfBitMap
- RtlNumberOfSetBits(lpBits
);
587 /*************************************************************************
588 * RtlFindMostSignificantBit [NTDLL.@]
590 * Find the most significant bit in a 64 bit integer.
593 * The position of the most significant bit.
595 CCHAR WINAPI
RtlFindMostSignificantBit(ULONGLONG ulLong
)
597 signed char ret
= 32;
600 if (!(dw
= (ulLong
>> 32)))
620 return ret
+ NTDLL_mostSignificant
[dw
];
623 /*************************************************************************
624 * RtlFindLeastSignificantBit [NTDLL.@]
626 * Find the least significant bit in a 64 bit integer.
629 * The position of the least significant bit.
631 CCHAR WINAPI
RtlFindLeastSignificantBit(ULONGLONG ulLong
)
636 if (!(dw
= (DWORD
)ulLong
))
639 if (!(dw
= ulLong
>> 32)) return -1;
656 return ret
+ NTDLL_leastSignificant
[dw
& 0x0f];
659 /*************************************************************************
662 * Internal helper: qsort comparison function for RTL_BITMAP_RUN arrays
664 static int NTDLL_RunSortFn(const void *lhs
, const void *rhs
)
666 if (((const RTL_BITMAP_RUN
*)lhs
)->NumberOfBits
> ((const RTL_BITMAP_RUN
*)rhs
)->NumberOfBits
)
671 /*************************************************************************
674 * Internal helper: Find the next run of set bits in a bitmap.
676 static ULONG
NTDLL_FindSetRun(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpSize
)
679 ULONG ulFoundAt
= 0, ulCount
= 0;
681 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
682 * at a time. But beware of the pointer arithmetics...
684 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
688 /* Check bits in first byte */
689 const BYTE bMask
= (0xff << (ulStart
& 7)) & 0xff;
690 const BYTE bFirst
= *lpOut
& bMask
;
694 /* Have a set bit in first byte */
697 /* Not every bit is set */
701 ulOffset
= NTDLL_leastSignificant
[bFirst
& 0x0f];
703 ulOffset
= 4 + NTDLL_leastSignificant
[bFirst
>> 4];
706 for (;ulOffset
< 8; ulOffset
++)
708 if (!(bFirst
& (1 << ulOffset
)))
711 return ulFoundAt
; /* Set from start, but not until the end */
716 /* Set to the end - go on to count further bits */
720 /* every bit from start until the end of the byte is set */
722 ulCount
= 8 - (ulStart
& 7);
723 ulStart
= (ulStart
& ~7u) + 8;
727 ulStart
= (ulStart
& ~7u) + 8;
729 if (ulStart
>= lpBits
->SizeOfBitMap
)
733 /* Count blocks of 8 set bits */
734 while (*lpOut
== 0xff)
738 if (ulStart
>= lpBits
->SizeOfBitMap
)
740 *lpSize
= ulCount
- (ulStart
- lpBits
->SizeOfBitMap
);
746 /* Count remaining contigious bits, if any */
751 for (;ulOffset
< 7u; ulOffset
++)
753 if (!(*lpOut
& (1 << ulOffset
)))
762 /*************************************************************************
765 * Internal helper: Find the next run of set bits in a bitmap.
767 static ULONG
NTDLL_FindClearRun(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpSize
)
770 ULONG ulFoundAt
= 0, ulCount
= 0;
772 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
773 * at a time. But beware of the pointer arithmetics...
775 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
779 /* Check bits in first byte */
780 const BYTE bMask
= (0xff << (ulStart
& 7)) & 0xff;
781 const BYTE bFirst
= (~*lpOut
) & bMask
;
785 /* Have a clear bit in first byte */
788 /* Not every bit is clear */
792 ulOffset
= NTDLL_leastSignificant
[bFirst
& 0x0f];
794 ulOffset
= 4 + NTDLL_leastSignificant
[bFirst
>> 4];
797 for (;ulOffset
< 8; ulOffset
++)
799 if (!(bFirst
& (1 << ulOffset
)))
802 return ulFoundAt
; /* Clear from start, but not until the end */
807 /* Clear to the end - go on to count further bits */
811 /* Every bit from start until the end of the byte is clear */
813 ulCount
= 8 - (ulStart
& 7);
814 ulStart
= (ulStart
& ~7u) + 8;
818 ulStart
= (ulStart
& ~7u) + 8;
820 if (ulStart
>= lpBits
->SizeOfBitMap
)
824 /* Count blocks of 8 clear bits */
829 if (ulStart
>= lpBits
->SizeOfBitMap
)
831 *lpSize
= ulCount
- (ulStart
- lpBits
->SizeOfBitMap
);
837 /* Count remaining contigious bits, if any */
842 for (;ulOffset
< 7u; ulOffset
++)
844 if (*lpOut
& (1 << ulOffset
))
853 /*************************************************************************
854 * RtlFindNextForwardRunSet [NTDLL.@]
856 * Find the next run of set 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 set 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
RtlFindNextForwardRunSet(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_FindSetRun(lpBits
, ulStart
, &ulSize
);
880 /*************************************************************************
881 * RtlFindNextForwardRunClear [NTDLL.@]
883 * Find the next run of clear 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 next clear 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
RtlFindNextForwardRunClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
899 TRACE("(%p,%ld,%p)\n", lpBits
, ulStart
, lpPos
);
901 if (lpBits
&& ulStart
< lpBits
->SizeOfBitMap
&& lpPos
)
902 *lpPos
= NTDLL_FindClearRun(lpBits
, ulStart
, &ulSize
);
907 /*************************************************************************
908 * RtlFindLastBackwardRunSet [NTDLL.@]
910 * Find a previous run of set bits in a bitmap.
913 * lpBits [I] Bitmap pointer
914 * ulStart [I] Bit position to start searching from
915 * lpPos [O] Start of run
918 * Success: The length of the previous set run in the bitmap. lpPos is set to
919 * the start of the run.
920 * Failure: 0, if no run is found or any parameters are invalid.
922 ULONG WINAPI
RtlFindLastBackwardRunSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
924 FIXME("(%p,%ld,%p)-stub!\n", lpBits
, ulStart
, lpPos
);
928 /*************************************************************************
929 * RtlFindLastBackwardRunClear [NTDLL.@]
931 * Find a previous run of clear bits in a bitmap.
934 * lpBits [I] Bitmap pointer
935 * ulStart [I] Bit position to start searching from
936 * lpPos [O] Start of run
939 * Success: The length of the previous clear run in the bitmap. lpPos is set
940 * to the start of the run.
941 * Failure: 0, if no run is found or any parameters are invalid.
943 ULONG WINAPI
RtlFindLastBackwardRunClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
945 FIXME("(%p,%ld,%p)-stub!\n", lpBits
, ulStart
, lpPos
);
949 /*************************************************************************
952 * Internal implementation of RtlFindSetRuns/RtlFindClearRuns.
954 static ULONG WINAPI
NTDLL_FindRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
955 ULONG ulCount
, BOOLEAN bLongest
,
956 ULONG (*fn
)(PCRTL_BITMAP
,ULONG
,PULONG
))
958 BOOL bNeedSort
= ulCount
> 1 ? TRUE
: FALSE
;
959 ULONG ulPos
= 0, ulRuns
= 0;
961 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
966 while (ulPos
< lpBits
->SizeOfBitMap
)
968 /* Find next set/clear run */
969 ULONG ulSize
, ulNextPos
= fn(lpBits
, ulPos
, &ulSize
);
971 if (ulNextPos
== ~0UL)
974 if (bLongest
&& ulRuns
== ulCount
)
976 /* Sort runs with shortest at end, if they are out of order */
978 qsort(lpSeries
, ulRuns
, sizeof(RTL_BITMAP_RUN
), NTDLL_RunSortFn
);
980 /* Replace last run if this one is bigger */
981 if (ulSize
> lpSeries
[ulRuns
- 1].NumberOfBits
)
983 lpSeries
[ulRuns
- 1].StartingIndex
= ulNextPos
;
984 lpSeries
[ulRuns
- 1].NumberOfBits
= ulSize
;
986 /* We need to re-sort the array, _if_ we didn't leave it sorted */
987 if (ulRuns
> 1 && ulSize
> lpSeries
[ulRuns
- 2].NumberOfBits
)
993 /* Append to found runs */
994 lpSeries
[ulRuns
].StartingIndex
= ulNextPos
;
995 lpSeries
[ulRuns
].NumberOfBits
= ulSize
;
998 if (!bLongest
&& ulRuns
== ulCount
)
1001 ulPos
= ulNextPos
+ ulSize
;
1006 /*************************************************************************
1007 * RtlFindSetRuns [NTDLL.@]
1009 * Find a series of set runs in a bitmap.
1012 * lpBits [I] Bitmap pointer
1013 * lpSeries [O] Array for each run found
1014 * ulCount [I] Number of runs to find
1015 * bLongest [I] Whether to find the very longest runs or not
1018 * The number of set runs found.
1020 ULONG WINAPI
RtlFindSetRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
1021 ULONG ulCount
, BOOLEAN bLongest
)
1023 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
1025 return NTDLL_FindRuns(lpBits
, lpSeries
, ulCount
, bLongest
, NTDLL_FindSetRun
);
1028 /*************************************************************************
1029 * RtlFindClearRuns [NTDLL.@]
1031 * Find a series of clear runs in a bitmap.
1034 * lpBits [I] Bitmap pointer
1035 * ulSeries [O] Array for each run found
1036 * ulCount [I] Number of runs to find
1037 * bLongest [I] Whether to find the very longest runs or not
1040 * The number of clear runs found.
1042 ULONG WINAPI
RtlFindClearRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
1043 ULONG ulCount
, BOOLEAN bLongest
)
1045 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
1047 return NTDLL_FindRuns(lpBits
, lpSeries
, ulCount
, bLongest
, NTDLL_FindClearRun
);
1050 /*************************************************************************
1051 * RtlFindLongestRunSet [NTDLL.@]
1053 * Find the longest set 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
RtlFindLongestRunSet(PCRTL_BITMAP lpBits
, PULONG pulStart
)
1066 TRACE("(%p,%p)\n", lpBits
, pulStart
);
1068 if (RtlFindSetRuns(lpBits
, &br
, 1, TRUE
) == 1)
1071 *pulStart
= br
.StartingIndex
;
1072 return br
.NumberOfBits
;
1077 /*************************************************************************
1078 * RtlFindLongestRunClear [NTDLL.@]
1080 * Find the longest clear run in a bitmap.
1083 * lpBits [I] Bitmap pointer
1084 * pulStart [O] Destination for start of run
1087 * The length of the run found, or 0 if no run is found.
1089 ULONG WINAPI
RtlFindLongestRunClear(PCRTL_BITMAP lpBits
, PULONG pulStart
)
1093 TRACE("(%p,%p)\n", lpBits
, pulStart
);
1095 if (RtlFindClearRuns(lpBits
, &br
, 1, TRUE
) == 1)
1098 *pulStart
= br
.StartingIndex
;
1099 return br
.NumberOfBits
;