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.
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
42 /* Bits set from LSB to MSB; used as mask for runs < 8 bits */
43 static const BYTE NTDLL_maskBits
[8] = { 0, 1, 3, 7, 15, 31, 63, 127 };
45 /* Number of set bits for each value of a nibble; used for counting */
46 static const BYTE NTDLL_nibbleBitCount
[16] = {
47 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
50 /* First set bit in a nibble; used for determining least significant bit */
51 static const BYTE NTDLL_leastSignificant
[16] = {
52 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
55 /* Last set bit in a nibble; used for determining most significant bit */
56 static const signed char NTDLL_mostSignificant
[16] = {
57 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
60 /*************************************************************************
61 * RtlInitializeBitMap [NTDLL.@]
63 * Initialise a new bitmap.
66 * lpBits [I] Bitmap pointer
67 * lpBuff [I] Memory for the bitmap
68 * ulSize [I] Size of lpBuff in bits
74 * lpBuff must be aligned on a ULONG suitable boundary, to a multiple of 32 bytes
75 * in size (irrespective of ulSize given).
77 VOID WINAPI
RtlInitializeBitMap(PRTL_BITMAP lpBits
, PULONG lpBuff
, ULONG ulSize
)
79 TRACE("(%p,%p,%ld)\n", lpBits
,lpBuff
,ulSize
);
80 lpBits
->SizeOfBitMap
= ulSize
;
81 lpBits
->Buffer
= lpBuff
;
84 /*************************************************************************
85 * RtlSetAllBits [NTDLL.@]
87 * Set all bits in a bitmap.
90 * lpBits [I] Bitmap pointer
95 VOID WINAPI
RtlSetAllBits(PRTL_BITMAP lpBits
)
97 TRACE("(%p)\n", lpBits
);
98 memset(lpBits
->Buffer
, 0xff, ((lpBits
->SizeOfBitMap
+ 31) & ~31) >> 3);
101 /*************************************************************************
102 * RtlClearAllBits [NTDLL.@]
104 * Clear all bits in a bitmap.
107 * lpBit [I] Bitmap pointer
112 VOID WINAPI
RtlClearAllBits(PRTL_BITMAP lpBits
)
114 TRACE("(%p)\n", lpBits
);
115 memset(lpBits
->Buffer
, 0, ((lpBits
->SizeOfBitMap
+ 31) & ~31) >> 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
||
138 ulStart
>= lpBits
->SizeOfBitMap
||
139 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
142 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
143 * at a time. But beware of the pointer arithmetics...
145 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
147 /* Set bits in first byte, if ulStart isn't a byte boundary */
152 /* Set from start bit to the end of the byte */
153 *lpOut
++ |= 0xff << (ulStart
& 7);
154 ulCount
-= (8 - (ulStart
& 7));
158 /* Set from the start bit, possibly into the next byte also */
159 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
161 *lpOut
++ |= (initialWord
& 0xff);
162 *lpOut
|= (initialWord
>> 8);
167 /* Set bits up to complete byte count */
170 memset(lpOut
, 0xff, ulCount
>> 3);
171 lpOut
= lpOut
+ (ulCount
>> 3);
174 /* Set remaining bits, if any */
175 *lpOut
|= NTDLL_maskBits
[ulCount
& 0x7];
178 /*************************************************************************
179 * RtlClearBits [NTDLL.@]
181 * Clear bits in a bitmap.
184 * lpBits [I] Bitmap pointer
185 * ulStart [I] First bit to set
186 * ulCount [I] Number of consecutive bits to clear
191 VOID WINAPI
RtlClearBits(PRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
195 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
197 if (!lpBits
|| !ulCount
||
198 ulStart
>= lpBits
->SizeOfBitMap
||
199 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
202 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
203 * at a time. But beware of the pointer arithmetics...
205 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
207 /* Clear bits in first byte, if ulStart isn't a byte boundary */
212 /* Clear from start bit to the end of the byte */
213 *lpOut
++ &= ~(0xff << (ulStart
& 7));
214 ulCount
-= (8 - (ulStart
& 7));
218 /* Clear from the start bit, possibly into the next byte also */
219 USHORT initialWord
= ~(NTDLL_maskBits
[ulCount
] << (ulStart
& 7));
221 *lpOut
++ &= (initialWord
& 0xff);
222 *lpOut
&= (initialWord
>> 8);
227 /* Clear bits (in blocks of 8) on whole byte boundaries */
230 memset(lpOut
, 0, ulCount
>> 3);
231 lpOut
= lpOut
+ (ulCount
>> 3);
234 /* Clear remaining bits, if any */
236 *lpOut
&= ~NTDLL_maskBits
[ulCount
& 0x7];
239 /*************************************************************************
240 * RtlAreBitsSet [NTDLL.@]
242 * Determine if part of a bitmap is set.
245 * lpBits [I] Bitmap pointer
246 * ulStart [I] First bit to check from
247 * ulCount [I] Number of consecutive bits to check
250 * TRUE, If ulCount bits from ulStart are set.
253 BOOLEAN WINAPI
RtlAreBitsSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
258 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
260 if (!lpBits
|| !ulCount
||
261 ulStart
>= lpBits
->SizeOfBitMap
||
262 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
265 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
266 * at a time. But beware of the pointer arithmetics...
268 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
270 /* Check bits in first byte, if ulStart isn't a byte boundary */
275 /* Check from start bit to the end of the byte */
277 ((0xff << (ulStart
& 7))) & 0xff) != ((0xff << (ulStart
& 7) & 0xff)))
280 ulCount
-= (8 - (ulStart
& 7));
284 /* Check from the start bit, possibly into the next byte also */
285 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
287 if ((*lpOut
& (initialWord
& 0xff)) != (initialWord
& 0xff))
289 if ((initialWord
& 0xff00) &&
290 ((lpOut
[1] & (initialWord
>> 8)) != (initialWord
>> 8)))
296 /* Check bits in blocks of 8 bytes */
297 ulRemainder
= ulCount
& 7;
301 if (*lpOut
++ != 0xff)
305 /* Check remaining bits, if any */
307 (*lpOut
& NTDLL_maskBits
[ulRemainder
]) != NTDLL_maskBits
[ulRemainder
])
312 /*************************************************************************
313 * RtlAreBitsClear [NTDLL.@]
315 * Determine if part of a bitmap is clear.
318 * lpBits [I] Bitmap pointer
319 * ulStart [I] First bit to check from
320 * ulCount [I] Number of consecutive bits to check
323 * TRUE, If ulCount bits from ulStart are clear.
326 BOOLEAN WINAPI
RtlAreBitsClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, ULONG ulCount
)
331 TRACE("(%p,%ld,%ld)\n", lpBits
, ulStart
, ulCount
);
333 if (!lpBits
|| !ulCount
||
334 ulStart
>= lpBits
->SizeOfBitMap
||
335 ulCount
> lpBits
->SizeOfBitMap
- ulStart
)
338 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
339 * at a time. But beware of the pointer arithmetics...
341 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
343 /* Check bits in first byte, if ulStart isn't a byte boundary */
348 /* Check from start bit to the end of the byte */
349 if (*lpOut
& ((0xff << (ulStart
& 7)) & 0xff))
352 ulCount
-= (8 - (ulStart
& 7));
356 /* Check from the start bit, possibly into the next byte also */
357 USHORT initialWord
= NTDLL_maskBits
[ulCount
] << (ulStart
& 7);
359 if (*lpOut
& (initialWord
& 0xff))
361 if ((initialWord
& 0xff00) && (lpOut
[1] & (initialWord
>> 8)))
367 /* Check bits in blocks of 8 bytes */
368 ulRemainder
= ulCount
& 7;
376 /* Check remaining bits, if any */
377 if (ulRemainder
&& *lpOut
& NTDLL_maskBits
[ulRemainder
])
382 /*************************************************************************
383 * RtlFindSetBits [NTDLL.@]
385 * Find a block of set bits in a bitmap.
388 * lpBits [I] Bitmap pointer
389 * ulCount [I] Number of consecutive set bits to find
390 * ulHint [I] Suggested starting position for set bits
393 * The bit at which the match was found, or -1 if no match was found.
395 ULONG WINAPI
RtlFindSetBits(PCRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
399 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
401 if (!lpBits
|| !ulCount
|| ulCount
> lpBits
->SizeOfBitMap
)
404 ulEnd
= lpBits
->SizeOfBitMap
;
406 if (ulHint
+ ulCount
> lpBits
->SizeOfBitMap
)
411 while (ulPos
< ulEnd
)
413 /* FIXME: This could be made a _lot_ more efficient */
414 if (RtlAreBitsSet(lpBits
, ulPos
, ulCount
))
417 /* Start from the beginning if we hit the end and had a hint */
418 if (ulPos
== ulEnd
- 1 && ulHint
)
429 /*************************************************************************
430 * RtlFindClearBits [NTDLL.@]
432 * Find a block of clear bits in a bitmap.
435 * lpBits [I] Bitmap pointer
436 * ulCount [I] Number of consecutive clear bits to find
437 * ulHint [I] Suggested starting position for clear bits
440 * The bit at which the match was found, or -1 if no match was found.
442 ULONG WINAPI
RtlFindClearBits(PCRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
446 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
448 if (!lpBits
|| !ulCount
|| ulCount
> lpBits
->SizeOfBitMap
)
451 ulEnd
= lpBits
->SizeOfBitMap
;
453 if (ulHint
+ ulCount
> lpBits
->SizeOfBitMap
)
458 while (ulPos
< ulEnd
)
460 /* FIXME: This could be made a _lot_ more efficient */
461 if (RtlAreBitsClear(lpBits
, ulPos
, ulCount
))
464 /* Start from the beginning if we hit the end and started from ulHint */
465 if (ulPos
== ulEnd
- 1 && ulHint
)
476 /*************************************************************************
477 * RtlFindSetBitsAndClear [NTDLL.@]
479 * Find a block of set bits in a bitmap, and clear them if found.
482 * lpBits [I] Bitmap pointer
483 * ulCount [I] Number of consecutive set bits to find
484 * ulHint [I] Suggested starting position for set bits
487 * The bit at which the match was found, or -1 if no match was found.
489 ULONG WINAPI
RtlFindSetBitsAndClear(PRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
493 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
495 ulPos
= RtlFindSetBits(lpBits
, ulCount
, ulHint
);
497 RtlClearBits(lpBits
, ulPos
, ulCount
);
501 /*************************************************************************
502 * RtlFindClearBitsAndSet [NTDLL.@]
504 * Find a block of clear bits in a bitmap, and set them if found.
507 * lpBits [I] Bitmap pointer
508 * ulCount [I] Number of consecutive clear bits to find
509 * ulHint [I] Suggested starting position for clear bits
512 * The bit at which the match was found, or -1 if no match was found.
514 ULONG WINAPI
RtlFindClearBitsAndSet(PRTL_BITMAP lpBits
, ULONG ulCount
, ULONG ulHint
)
518 TRACE("(%p,%ld,%ld)\n", lpBits
, ulCount
, ulHint
);
520 ulPos
= RtlFindClearBits(lpBits
, ulCount
, ulHint
);
522 RtlSetBits(lpBits
, ulPos
, ulCount
);
526 /*************************************************************************
527 * RtlNumberOfSetBits [NTDLL.@]
529 * Find the number of set bits in a bitmap.
532 * lpBits [I] Bitmap pointer
535 * The number of set bits.
537 ULONG WINAPI
RtlNumberOfSetBits(PCRTL_BITMAP lpBits
)
541 TRACE("(%p)\n", lpBits
);
545 LPBYTE lpOut
= (BYTE
*)lpBits
->Buffer
;
546 ULONG ulCount
, ulRemainder
;
549 ulCount
= lpBits
->SizeOfBitMap
>> 3;
550 ulRemainder
= lpBits
->SizeOfBitMap
& 0x7;
554 ulSet
+= NTDLL_nibbleBitCount
[*lpOut
>> 4];
555 ulSet
+= NTDLL_nibbleBitCount
[*lpOut
& 0xf];
559 bMasked
= *lpOut
& NTDLL_maskBits
[ulRemainder
];
560 ulSet
+= NTDLL_nibbleBitCount
[bMasked
>> 4];
561 ulSet
+= NTDLL_nibbleBitCount
[bMasked
& 0xf];
566 /*************************************************************************
567 * RtlNumberOfClearBits [NTDLL.@]
569 * Find the number of clear bits in a bitmap.
572 * lpBits [I] Bitmap pointer
575 * The number of clear bits.
577 ULONG WINAPI
RtlNumberOfClearBits(PCRTL_BITMAP lpBits
)
579 TRACE("(%p)\n", lpBits
);
582 return lpBits
->SizeOfBitMap
- RtlNumberOfSetBits(lpBits
);
586 /*************************************************************************
587 * RtlFindMostSignificantBit [NTDLL.@]
589 * Find the most significant bit in a 64 bit integer.
592 * The position of the most significant bit.
594 CCHAR WINAPI
RtlFindMostSignificantBit(ULONGLONG ulLong
)
596 signed char ret
= 32;
599 if (!(dw
= (ulLong
>> 32)))
619 return ret
+ NTDLL_mostSignificant
[dw
];
622 /*************************************************************************
623 * RtlFindLeastSignificantBit [NTDLL.@]
625 * Find the least significant bit in a 64 bit integer.
628 * The position of the least significant bit.
630 CCHAR WINAPI
RtlFindLeastSignificantBit(ULONGLONG ulLong
)
635 if (!(dw
= (DWORD
)ulLong
))
638 if (!(dw
= ulLong
>> 32)) return -1;
655 return ret
+ NTDLL_leastSignificant
[dw
& 0x0f];
658 /*************************************************************************
661 * Internal helper: qsort comparison function for RTL_BITMAP_RUN arrays
663 static int NTDLL_RunSortFn(const void *lhs
, const void *rhs
)
665 if (((const RTL_BITMAP_RUN
*)lhs
)->NumberOfBits
> ((const RTL_BITMAP_RUN
*)rhs
)->NumberOfBits
)
670 /*************************************************************************
673 * Internal helper: Find the next run of set bits in a bitmap.
675 static ULONG
NTDLL_FindSetRun(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpSize
)
678 ULONG ulFoundAt
= 0, ulCount
= 0;
680 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
681 * at a time. But beware of the pointer arithmetics...
683 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
687 /* Check bits in first byte */
688 const BYTE bMask
= (0xff << (ulStart
& 7)) & 0xff;
689 const BYTE bFirst
= *lpOut
& bMask
;
693 /* Have a set bit in first byte */
696 /* Not every bit is set */
700 ulOffset
= NTDLL_leastSignificant
[bFirst
& 0x0f];
702 ulOffset
= 4 + NTDLL_leastSignificant
[bFirst
>> 4];
705 for (;ulOffset
< 8; ulOffset
++)
707 if (!(bFirst
& (1 << ulOffset
)))
710 return ulFoundAt
; /* Set from start, but not until the end */
715 /* Set to the end - go on to count further bits */
719 /* every bit from start until the end of the byte is set */
721 ulCount
= 8 - (ulStart
& 7);
722 ulStart
= (ulStart
& ~7u) + 8;
726 ulStart
= (ulStart
& ~7u) + 8;
728 if (ulStart
>= lpBits
->SizeOfBitMap
)
732 /* Count blocks of 8 set bits */
733 while (*lpOut
== 0xff)
737 if (ulStart
>= lpBits
->SizeOfBitMap
)
739 *lpSize
= ulCount
- (ulStart
- lpBits
->SizeOfBitMap
);
745 /* Count remaining contiguous bits, if any */
750 for (;ulOffset
< 7u; ulOffset
++)
752 if (!(*lpOut
& (1 << ulOffset
)))
761 /*************************************************************************
764 * Internal helper: Find the next run of set bits in a bitmap.
766 static ULONG
NTDLL_FindClearRun(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpSize
)
769 ULONG ulFoundAt
= 0, ulCount
= 0;
771 /* FIXME: It might be more efficient/cleaner to manipulate four bytes
772 * at a time. But beware of the pointer arithmetics...
774 lpOut
= ((BYTE
*)lpBits
->Buffer
) + (ulStart
>> 3u);
778 /* Check bits in first byte */
779 const BYTE bMask
= (0xff << (ulStart
& 7)) & 0xff;
780 const BYTE bFirst
= (~*lpOut
) & bMask
;
784 /* Have a clear bit in first byte */
787 /* Not every bit is clear */
791 ulOffset
= NTDLL_leastSignificant
[bFirst
& 0x0f];
793 ulOffset
= 4 + NTDLL_leastSignificant
[bFirst
>> 4];
796 for (;ulOffset
< 8; ulOffset
++)
798 if (!(bFirst
& (1 << ulOffset
)))
801 return ulFoundAt
; /* Clear from start, but not until the end */
806 /* Clear to the end - go on to count further bits */
810 /* Every bit from start until the end of the byte is clear */
812 ulCount
= 8 - (ulStart
& 7);
813 ulStart
= (ulStart
& ~7u) + 8;
817 ulStart
= (ulStart
& ~7u) + 8;
819 if (ulStart
>= lpBits
->SizeOfBitMap
)
823 /* Count blocks of 8 clear bits */
828 if (ulStart
>= lpBits
->SizeOfBitMap
)
830 *lpSize
= ulCount
- (ulStart
- lpBits
->SizeOfBitMap
);
836 /* Count remaining contiguous bits, if any */
841 for (;ulOffset
< 7u; ulOffset
++)
843 if (*lpOut
& (1 << ulOffset
))
852 /*************************************************************************
853 * RtlFindNextForwardRunSet [NTDLL.@]
855 * Find the next run of set bits in a bitmap.
858 * lpBits [I] Bitmap pointer
859 * ulStart [I] Bit position to start searching from
860 * lpPos [O] Start of run
863 * Success: The length of the next set run in the bitmap. lpPos is set to
864 * the start of the run.
865 * Failure: 0, if no run is found or any parameters are invalid.
867 ULONG WINAPI
RtlFindNextForwardRunSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
871 TRACE("(%p,%ld,%p)\n", lpBits
, ulStart
, lpPos
);
873 if (lpBits
&& ulStart
< lpBits
->SizeOfBitMap
&& lpPos
)
874 *lpPos
= NTDLL_FindSetRun(lpBits
, ulStart
, &ulSize
);
879 /*************************************************************************
880 * RtlFindNextForwardRunClear [NTDLL.@]
882 * Find the next run of clear bits in a bitmap.
885 * lpBits [I] Bitmap pointer
886 * ulStart [I] Bit position to start searching from
887 * lpPos [O] Start of run
890 * Success: The length of the next clear run in the bitmap. lpPos is set to
891 * the start of the run.
892 * Failure: 0, if no run is found or any parameters are invalid.
894 ULONG WINAPI
RtlFindNextForwardRunClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
898 TRACE("(%p,%ld,%p)\n", lpBits
, ulStart
, lpPos
);
900 if (lpBits
&& ulStart
< lpBits
->SizeOfBitMap
&& lpPos
)
901 *lpPos
= NTDLL_FindClearRun(lpBits
, ulStart
, &ulSize
);
906 /*************************************************************************
907 * RtlFindLastBackwardRunSet [NTDLL.@]
909 * Find a previous run of set bits in a bitmap.
912 * lpBits [I] Bitmap pointer
913 * ulStart [I] Bit position to start searching from
914 * lpPos [O] Start of run
917 * Success: The length of the previous set run in the bitmap. lpPos is set to
918 * the start of the run.
919 * Failure: 0, if no run is found or any parameters are invalid.
921 ULONG WINAPI
RtlFindLastBackwardRunSet(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
923 FIXME("(%p,%ld,%p)-stub!\n", lpBits
, ulStart
, lpPos
);
927 /*************************************************************************
928 * RtlFindLastBackwardRunClear [NTDLL.@]
930 * Find a previous run of clear bits in a bitmap.
933 * lpBits [I] Bitmap pointer
934 * ulStart [I] Bit position to start searching from
935 * lpPos [O] Start of run
938 * Success: The length of the previous clear run in the bitmap. lpPos is set
939 * to the start of the run.
940 * Failure: 0, if no run is found or any parameters are invalid.
942 ULONG WINAPI
RtlFindLastBackwardRunClear(PCRTL_BITMAP lpBits
, ULONG ulStart
, PULONG lpPos
)
944 FIXME("(%p,%ld,%p)-stub!\n", lpBits
, ulStart
, lpPos
);
948 /*************************************************************************
951 * Internal implementation of RtlFindSetRuns/RtlFindClearRuns.
953 static ULONG WINAPI
NTDLL_FindRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
954 ULONG ulCount
, BOOLEAN bLongest
,
955 ULONG (*fn
)(PCRTL_BITMAP
,ULONG
,PULONG
))
957 BOOL bNeedSort
= ulCount
> 1 ? TRUE
: FALSE
;
958 ULONG ulPos
= 0, ulRuns
= 0;
960 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
965 while (ulPos
< lpBits
->SizeOfBitMap
)
967 /* Find next set/clear run */
968 ULONG ulSize
, ulNextPos
= fn(lpBits
, ulPos
, &ulSize
);
970 if (ulNextPos
== ~0UL)
973 if (bLongest
&& ulRuns
== ulCount
)
975 /* Sort runs with shortest at end, if they are out of order */
977 qsort(lpSeries
, ulRuns
, sizeof(RTL_BITMAP_RUN
), NTDLL_RunSortFn
);
979 /* Replace last run if this one is bigger */
980 if (ulSize
> lpSeries
[ulRuns
- 1].NumberOfBits
)
982 lpSeries
[ulRuns
- 1].StartingIndex
= ulNextPos
;
983 lpSeries
[ulRuns
- 1].NumberOfBits
= ulSize
;
985 /* We need to re-sort the array, _if_ we didn't leave it sorted */
986 if (ulRuns
> 1 && ulSize
> lpSeries
[ulRuns
- 2].NumberOfBits
)
992 /* Append to found runs */
993 lpSeries
[ulRuns
].StartingIndex
= ulNextPos
;
994 lpSeries
[ulRuns
].NumberOfBits
= ulSize
;
997 if (!bLongest
&& ulRuns
== ulCount
)
1000 ulPos
= ulNextPos
+ ulSize
;
1005 /*************************************************************************
1006 * RtlFindSetRuns [NTDLL.@]
1008 * Find a series of set runs in a bitmap.
1011 * lpBits [I] Bitmap pointer
1012 * lpSeries [O] Array for each run found
1013 * ulCount [I] Number of runs to find
1014 * bLongest [I] Whether to find the very longest runs or not
1017 * The number of set runs found.
1019 ULONG WINAPI
RtlFindSetRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
1020 ULONG ulCount
, BOOLEAN bLongest
)
1022 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
1024 return NTDLL_FindRuns(lpBits
, lpSeries
, ulCount
, bLongest
, NTDLL_FindSetRun
);
1027 /*************************************************************************
1028 * RtlFindClearRuns [NTDLL.@]
1030 * Find a series of clear runs in a bitmap.
1033 * lpBits [I] Bitmap pointer
1034 * ulSeries [O] Array for each run found
1035 * ulCount [I] Number of runs to find
1036 * bLongest [I] Whether to find the very longest runs or not
1039 * The number of clear runs found.
1041 ULONG WINAPI
RtlFindClearRuns(PCRTL_BITMAP lpBits
, PRTL_BITMAP_RUN lpSeries
,
1042 ULONG ulCount
, BOOLEAN bLongest
)
1044 TRACE("(%p,%p,%ld,%d)\n", lpBits
, lpSeries
, ulCount
, bLongest
);
1046 return NTDLL_FindRuns(lpBits
, lpSeries
, ulCount
, bLongest
, NTDLL_FindClearRun
);
1049 /*************************************************************************
1050 * RtlFindLongestRunSet [NTDLL.@]
1052 * Find the longest set run in a bitmap.
1055 * lpBits [I] Bitmap pointer
1056 * pulStart [O] Destination for start of run
1059 * The length of the run found, or 0 if no run is found.
1061 ULONG WINAPI
RtlFindLongestRunSet(PCRTL_BITMAP lpBits
, PULONG pulStart
)
1065 TRACE("(%p,%p)\n", lpBits
, pulStart
);
1067 if (RtlFindSetRuns(lpBits
, &br
, 1, TRUE
) == 1)
1070 *pulStart
= br
.StartingIndex
;
1071 return br
.NumberOfBits
;
1076 /*************************************************************************
1077 * RtlFindLongestRunClear [NTDLL.@]
1079 * Find the longest clear run in a bitmap.
1082 * lpBits [I] Bitmap pointer
1083 * pulStart [O] Destination for start of run
1086 * The length of the run found, or 0 if no run is found.
1088 ULONG WINAPI
RtlFindLongestRunClear(PCRTL_BITMAP lpBits
, PULONG pulStart
)
1092 TRACE("(%p,%p)\n", lpBits
, pulStart
);
1094 if (RtlFindClearRuns(lpBits
, &br
, 1, TRUE
) == 1)
1097 *pulStart
= br
.StartingIndex
;
1098 return br
.NumberOfBits
;