Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / ntdll / rtlbitmap.c
blob21abaf97bc201bea5fae2a17e25e74d95c107bf3
1 /*
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
20 * NOTES
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.
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include "ntstatus.h"
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winreg.h"
38 #include "winternl.h"
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.
66 * PARAMS
67 * lpBits [I] Bitmap pointer
68 * lpBuff [I] Memory for the bitmap
69 * ulSize [I] Size of lpBuff in bits
71 * RETURNS
72 * Nothing.
74 * NOTES
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.
91 * PARAMS
92 * lpBits [I] Bitmap pointer
94 * RETURNS
95 * Nothing.
97 #undef RtlSetAllBits
98 VOID WINAPI RtlSetAllBits(PRTL_BITMAP lpBits)
100 TRACE("(%p)\n", lpBits);
101 memset(lpBits->BitMapBuffer, 0xff, ((lpBits->SizeOfBitMap + 31) & 0xffffffe0) >> 3);
104 /*************************************************************************
105 * RtlClearAllBits [NTDLL.@]
107 * Clear all bits in a bitmap.
109 * PARAMS
110 * lpBit [I] Bitmap pointer
112 * RETURNS
113 * Nothing.
115 #undef RtlClearAllBits
116 VOID WINAPI RtlClearAllBits(PRTL_BITMAP lpBits)
118 TRACE("(%p)\n", lpBits);
119 memset(lpBits->BitMapBuffer, 0, ((lpBits->SizeOfBitMap + 31) & 0xffffffe0) >> 3);
122 /*************************************************************************
123 * RtlSetBits [NTDLL.@]
125 * Set a range of bits in a bitmap.
127 * PARAMS
128 * lpBits [I] Bitmap pointer
129 * ulStart [I] First bit to set
130 * ulCount [I] Number of consecutive bits to set
132 * RETURNS
133 * Nothing.
135 VOID WINAPI RtlSetBits(PRTL_BITMAP lpBits, ULONG ulStart, ULONG ulCount)
137 LPBYTE lpOut;
139 TRACE("(%p,%ld,%ld)\n", lpBits, ulStart, ulCount);
141 if (!lpBits || !ulCount || ulStart + ulCount > lpBits->SizeOfBitMap)
142 return;
144 lpOut = lpBits->BitMapBuffer + (ulStart >> 3u);
146 /* Set bits in first byte, if ulStart isn't a byte boundary */
147 if (ulStart & 7)
149 if (ulCount > 7)
151 /* Set from start bit to the end of the byte */
152 *lpOut++ |= 0xff << (ulStart & 7);
153 ulCount -= (8 - (ulStart & 7));
155 else
157 /* Set from the start bit, possibly into the next byte also */
158 USHORT initialWord = NTDLL_maskBits[ulCount] << (ulStart & 7);
160 *lpOut++ |= (initialWord & 0xff);
161 *lpOut |= (initialWord >> 8);
162 return;
166 /* Set bits up to complete byte count */
167 if (ulCount >> 3)
169 memset(lpOut, 0xff, ulCount >> 3);
170 lpOut = lpOut + (ulCount >> 3);
173 /* Set remaining bits, if any */
174 *lpOut |= NTDLL_maskBits[ulCount & 0x7];
177 /*************************************************************************
178 * RtlClearBits [NTDLL.@]
180 * Clear bits in a bitmap.
182 * PARAMS
183 * lpBits [I] Bitmap pointer
184 * ulStart [I] First bit to set
185 * ulCount [I] Number of consecutive bits to clear
187 * RETURNS
188 * Nothing.
190 VOID WINAPI RtlClearBits(PRTL_BITMAP lpBits, ULONG ulStart, ULONG ulCount)
192 LPBYTE lpOut;
194 TRACE("(%p,%ld,%ld)\n", lpBits, ulStart, ulCount);
196 if (!lpBits || !ulCount || ulStart + ulCount > lpBits->SizeOfBitMap)
197 return;
199 lpOut = lpBits->BitMapBuffer + (ulStart >> 3u);
201 /* Clear bits in first byte, if ulStart isn't a byte boundary */
202 if (ulStart & 7)
204 if (ulCount > 7)
206 /* Clear from start bit to the end of the byte */
207 *lpOut++ &= ~(0xff << (ulStart & 7));
208 ulCount -= (8 - (ulStart & 7));
210 else
212 /* Clear from the start bit, possibly into the next byte also */
213 USHORT initialWord = ~(NTDLL_maskBits[ulCount] << (ulStart & 7));
215 *lpOut++ &= (initialWord & 0xff);
216 *lpOut &= (initialWord >> 8);
217 return;
221 /* Clear bits (in blocks of 8) on whole byte boundaries */
222 if (ulCount >> 3)
224 memset(lpOut, 0, ulCount >> 3);
225 lpOut = lpOut + (ulCount >> 3);
228 /* Clear remaining bits, if any */
229 if (ulCount & 0x7)
230 *lpOut &= ~NTDLL_maskBits[ulCount & 0x7];
233 /*************************************************************************
234 * RtlAreBitsSet [NTDLL.@]
236 * Determine if part of a bitmap is set.
238 * PARAMS
239 * lpBits [I] Bitmap pointer
240 * ulStart [I] First bit to check from
241 * ulCount [I] Number of consecutive bits to check
243 * RETURNS
244 * TRUE, If ulCount bits from ulStart are set.
245 * FALSE, Otherwise.
247 BOOLEAN WINAPI RtlAreBitsSet(PCRTL_BITMAP lpBits, ULONG ulStart, ULONG ulCount)
249 LPBYTE lpOut;
250 ULONG ulRemainder;
252 TRACE("(%p,%ld,%ld)\n", lpBits, ulStart, ulCount);
254 if (!lpBits || !ulCount || ulStart + ulCount > lpBits->SizeOfBitMap)
255 return FALSE;
257 lpOut = lpBits->BitMapBuffer + (ulStart >> 3u);
259 /* Check bits in first byte, if ulStart isn't a byte boundary */
260 if (ulStart & 7)
262 if (ulCount > 7)
264 /* Check from start bit to the end of the byte */
265 if ((*lpOut &
266 ((0xff << (ulStart & 7))) & 0xff) != ((0xff << (ulStart & 7) & 0xff)))
267 return FALSE;
268 lpOut++;
269 ulCount -= (8 - (ulStart & 7));
271 else
273 /* Check from the start bit, possibly into the next byte also */
274 USHORT initialWord = NTDLL_maskBits[ulCount] << (ulStart & 7);
276 if ((*lpOut & (initialWord & 0xff)) != (initialWord & 0xff))
277 return FALSE;
278 if ((initialWord & 0xff00) &&
279 ((lpOut[1] & (initialWord >> 8)) != (initialWord >> 8)))
280 return FALSE;
281 return TRUE;
285 /* Check bits in blocks of 8 bytes */
286 ulRemainder = ulCount & 7;
287 ulCount >>= 3;
288 while (ulCount--)
290 if (*lpOut++ != 0xff)
291 return FALSE;
294 /* Check remaining bits, if any */
295 if (ulRemainder &&
296 (*lpOut & NTDLL_maskBits[ulRemainder]) != NTDLL_maskBits[ulRemainder])
297 return FALSE;
298 return TRUE;
301 /*************************************************************************
302 * RtlAreBitsClear [NTDLL.@]
304 * Determine if part of a bitmap is clear.
306 * PARAMS
307 * lpBits [I] Bitmap pointer
308 * ulStart [I] First bit to check from
309 * ulCount [I] Number of consecutive bits to check
311 * RETURNS
312 * TRUE, If ulCount bits from ulStart are clear.
313 * FALSE, Otherwise.
315 BOOLEAN WINAPI RtlAreBitsClear(PCRTL_BITMAP lpBits, ULONG ulStart, ULONG ulCount)
317 LPBYTE lpOut;
318 ULONG ulRemainder;
320 TRACE("(%p,%ld,%ld)\n", lpBits, ulStart, ulCount);
322 if (!lpBits || !ulCount || ulStart + ulCount > lpBits->SizeOfBitMap)
323 return FALSE;
325 lpOut = lpBits->BitMapBuffer + (ulStart >> 3u);
327 /* Check bits in first byte, if ulStart isn't a byte boundary */
328 if (ulStart & 7)
330 if (ulCount > 7)
332 /* Check from start bit to the end of the byte */
333 if (*lpOut & ((0xff << (ulStart & 7)) & 0xff))
334 return FALSE;
335 lpOut++;
336 ulCount -= (8 - (ulStart & 7));
338 else
340 /* Check from the start bit, possibly into the next byte also */
341 USHORT initialWord = NTDLL_maskBits[ulCount] << (ulStart & 7);
343 if (*lpOut & (initialWord & 0xff))
344 return FALSE;
345 if ((initialWord & 0xff00) && (lpOut[1] & (initialWord >> 8)))
346 return FALSE;
347 return TRUE;
351 /* Check bits in blocks of 8 bytes */
352 ulRemainder = ulCount & 7;
353 ulCount >>= 3;
354 while (ulCount--)
356 if (*lpOut++)
357 return FALSE;
360 /* Check remaining bits, if any */
361 if (ulRemainder && *lpOut & NTDLL_maskBits[ulRemainder])
362 return FALSE;
363 return TRUE;
366 /*************************************************************************
367 * RtlFindSetBits [NTDLL.@]
369 * Find a block of set bits in a bitmap.
371 * PARAMS
372 * lpBits [I] Bitmap pointer
373 * ulCount [I] Number of consecutive set bits to find
374 * ulHint [I] Suggested starting position for set bits
376 * RETURNS
377 * The bit at which the match was found, or -1 if no match was found.
379 ULONG WINAPI RtlFindSetBits(PCRTL_BITMAP lpBits, ULONG ulCount, ULONG ulHint)
381 ULONG ulPos, ulEnd;
383 TRACE("(%p,%ld,%ld)\n", lpBits, ulCount, ulHint);
385 if (!lpBits || !ulCount || ulCount > lpBits->SizeOfBitMap)
386 return -1u;
388 ulEnd = lpBits->SizeOfBitMap;
390 if (ulHint + ulCount > lpBits->SizeOfBitMap)
391 ulHint = 0;
393 ulPos = ulHint;
395 while (ulPos < ulEnd)
397 /* FIXME: This could be made a _lot_ more efficient */
398 if (RtlAreBitsSet(lpBits, ulPos, ulCount))
399 return ulPos;
401 /* Start from the beginning if we hit the end and had a hint */
402 if (ulPos == ulEnd - 1 && ulHint)
404 ulEnd = ulHint;
405 ulPos = ulHint = 0;
407 else
408 ulPos++;
410 return -1u;
413 /*************************************************************************
414 * RtlFindClearBits [NTDLL.@]
416 * Find a block of clear bits in a bitmap.
418 * PARAMS
419 * lpBits [I] Bitmap pointer
420 * ulCount [I] Number of consecutive clear bits to find
421 * ulHint [I] Suggested starting position for clear bits
423 * RETURNS
424 * The bit at which the match was found, or -1 if no match was found.
426 ULONG WINAPI RtlFindClearBits(PCRTL_BITMAP lpBits, ULONG ulCount, ULONG ulHint)
428 ULONG ulPos, ulEnd;
430 TRACE("(%p,%ld,%ld)\n", lpBits, ulCount, ulHint);
432 if (!lpBits || !ulCount || ulCount > lpBits->SizeOfBitMap)
433 return -1u;
435 ulEnd = lpBits->SizeOfBitMap;
437 if (ulHint + ulCount > lpBits->SizeOfBitMap)
438 ulHint = 0;
440 ulPos = ulHint;
442 while (ulPos < ulEnd)
444 /* FIXME: This could be made a _lot_ more efficient */
445 if (RtlAreBitsClear(lpBits, ulPos, ulCount))
446 return ulPos;
448 /* Start from the beginning if we hit the end and started from ulHint */
449 if (ulPos == ulEnd - 1 && ulHint)
451 ulEnd = ulHint;
452 ulPos = ulHint = 0;
454 else
455 ulPos++;
457 return -1u;
460 /*************************************************************************
461 * RtlFindSetBitsAndClear [NTDLL.@]
463 * Find a block of set bits in a bitmap, and clear them if found.
465 * PARAMS
466 * lpBits [I] Bitmap pointer
467 * ulCount [I] Number of consecutive set bits to find
468 * ulHint [I] Suggested starting position for set bits
470 * RETURNS
471 * The bit at which the match was found, or -1 if no match was found.
473 ULONG WINAPI RtlFindSetBitsAndClear(PRTL_BITMAP lpBits, ULONG ulCount, ULONG ulHint)
475 ULONG ulPos;
477 TRACE("(%p,%ld,%ld)\n", lpBits, ulCount, ulHint);
479 ulPos = RtlFindSetBits(lpBits, ulCount, ulHint);
480 if (ulPos != -1u)
481 RtlClearBits(lpBits, ulPos, ulCount);
482 return ulPos;
485 /*************************************************************************
486 * RtlFindClearBitsAndSet [NTDLL.@]
488 * Find a block of clear bits in a bitmap, and set them if found.
490 * PARAMS
491 * lpBits [I] Bitmap pointer
492 * ulCount [I] Number of consecutive clear bits to find
493 * ulHint [I] Suggested starting position for clear bits
495 * RETURNS
496 * The bit at which the match was found, or -1 if no match was found.
498 ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP lpBits, ULONG ulCount, ULONG ulHint)
500 ULONG ulPos;
502 TRACE("(%p,%ld,%ld)\n", lpBits, ulCount, ulHint);
504 ulPos = RtlFindClearBits(lpBits, ulCount, ulHint);
505 if (ulPos != -1u)
506 RtlSetBits(lpBits, ulPos, ulCount);
507 return ulPos;
510 /*************************************************************************
511 * RtlNumberOfSetBits [NTDLL.@]
513 * Find the number of set bits in a bitmap.
515 * PARAMS
516 * lpBits [I] Bitmap pointer
518 * RETURNS
519 * The number of set bits.
521 ULONG WINAPI RtlNumberOfSetBits(PCRTL_BITMAP lpBits)
523 ULONG ulSet = 0;
525 TRACE("(%p)\n", lpBits);
527 if (lpBits)
529 LPBYTE lpOut = lpBits->BitMapBuffer;
530 ULONG ulCount, ulRemainder;
531 BYTE bMasked;
533 ulCount = lpBits->SizeOfBitMap >> 3;
534 ulRemainder = lpBits->SizeOfBitMap & 0x7;
536 while (ulCount--)
538 ulSet += NTDLL_nibbleBitCount[*lpOut >> 4];
539 ulSet += NTDLL_nibbleBitCount[*lpOut & 0xf];
540 lpOut++;
543 bMasked = *lpOut & NTDLL_maskBits[ulRemainder];
544 ulSet += NTDLL_nibbleBitCount[bMasked >> 4];
545 ulSet += NTDLL_nibbleBitCount[bMasked & 0xf];
547 return ulSet;
550 /*************************************************************************
551 * RtlNumberOfClearBits [NTDLL.@]
553 * Find the number of clear bits in a bitmap.
555 * PARAMS
556 * lpBits [I] Bitmap pointer
558 * RETURNS
559 * The number of clear bits.
561 ULONG WINAPI RtlNumberOfClearBits(PCRTL_BITMAP lpBits)
563 TRACE("(%p)\n", lpBits);
565 if (lpBits)
566 return lpBits->SizeOfBitMap - RtlNumberOfSetBits(lpBits);
567 return 0;
570 /*************************************************************************
571 * RtlFindMostSignificantBit [NTDLL.@]
573 * Find the most significant bit in a 64 bit integer.
575 * RETURNS
576 * The position of the most significant bit.
578 CCHAR WINAPI RtlFindMostSignificantBit(ULONGLONG ulLong)
580 signed char ret = 32;
581 DWORD dw;
583 if (!(dw = (ulLong >> 32)))
585 ret = 0;
586 dw = (DWORD)ulLong;
588 if (dw & 0xffff0000)
590 dw >>= 16;
591 ret += 16;
593 if (dw & 0xff00)
595 dw >>= 8;
596 ret += 8;
598 if (dw & 0xf0)
600 dw >>= 4;
601 ret += 4;
603 return ret + NTDLL_mostSignificant[dw];
606 /*************************************************************************
607 * RtlFindLeastSignificantBit [NTDLL.@]
609 * Find the least significant bit in a 64 bit integer.
611 * RETURNS
612 * The position of the least significant bit.
614 CCHAR WINAPI RtlFindLeastSignificantBit(ULONGLONG ulLong)
616 signed char ret = 0;
617 DWORD dw;
619 if (!(dw = (DWORD)ulLong))
621 ret = 32;
622 if (!(dw = ulLong >> 32)) return -1;
624 if (!(dw & 0xffff))
626 dw >>= 16;
627 ret += 16;
629 if (!(dw & 0xff))
631 dw >>= 8;
632 ret += 8;
634 if (!(dw & 0x0f))
636 dw >>= 4;
637 ret += 4;
639 return ret + NTDLL_leastSignificant[dw & 0x0f];
642 /*************************************************************************
643 * NTDLL_RunSortFn
645 * Internal helper: qsort comparison function for RTL_BITMAP_RUN arrays
647 static int NTDLL_RunSortFn(const void *lhs, const void *rhs)
649 if (((PCRTL_BITMAP_RUN)lhs)->SizeOfRun > ((PRTL_BITMAP_RUN)rhs)->SizeOfRun)
650 return -1;
651 return 1;
654 /*************************************************************************
655 * NTDLL_FindSetRun
657 * Internal helper: Find the next run of set bits in a bitmap.
659 static ULONG NTDLL_FindSetRun(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpSize)
661 LPBYTE lpOut;
662 ULONG ulFoundAt = 0, ulCount = 0;
664 lpOut = lpBits->BitMapBuffer + (ulStart >> 3u);
666 while (1)
668 /* Check bits in first byte */
669 const BYTE bMask = (0xff << (ulStart & 7)) & 0xff;
670 const BYTE bFirst = *lpOut & bMask;
672 if (bFirst)
674 /* Have a set bit in first byte */
675 if (bFirst != bMask)
677 /* Not every bit is set */
678 ULONG ulOffset;
680 if (bFirst & 0x0f)
681 ulOffset = NTDLL_leastSignificant[bFirst & 0x0f];
682 else
683 ulOffset = 4 + NTDLL_leastSignificant[bFirst >> 4];
684 ulStart += ulOffset;
685 ulFoundAt = ulStart;
686 for (;ulOffset < 8; ulOffset++)
688 if (!(bFirst & (1 << ulOffset)))
690 *lpSize = ulCount;
691 return ulFoundAt; /* Set from start, but not until the end */
693 ulCount++;
694 ulStart++;
696 /* Set to the end - go on to count further bits */
697 lpOut++;
698 break;
700 /* every bit from start until the end of the byte is set */
701 ulFoundAt = ulStart;
702 ulCount = 8 - (ulStart & 7);
703 ulStart = (ulStart & ~7u) + 8;
704 lpOut++;
705 break;
707 ulStart = (ulStart & ~7u) + 8;
708 lpOut++;
709 if (ulStart >= lpBits->SizeOfBitMap)
710 return -1u;
713 /* Count blocks of 8 set bits */
714 while (*lpOut == 0xff)
716 ulCount += 8;
717 ulStart += 8;
718 if (ulStart >= lpBits->SizeOfBitMap)
720 *lpSize = ulCount - (ulStart - lpBits->SizeOfBitMap);
721 return ulFoundAt;
723 lpOut++;
726 /* Count remaining contigious bits, if any */
727 if (*lpOut & 1)
729 ULONG ulOffset = 0;
731 for (;ulOffset < 7u; ulOffset++)
733 if (!(*lpOut & (1 << ulOffset)))
734 break;
735 ulCount++;
738 *lpSize = ulCount;
739 return ulFoundAt;
742 /*************************************************************************
743 * NTDLL_FindClearRun
745 * Internal helper: Find the next run of set bits in a bitmap.
747 static ULONG NTDLL_FindClearRun(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpSize)
749 LPBYTE lpOut;
750 ULONG ulFoundAt = 0, ulCount = 0;
752 lpOut = lpBits->BitMapBuffer + (ulStart >> 3u);
754 while (1)
756 /* Check bits in first byte */
757 const BYTE bMask = (0xff << (ulStart & 7)) & 0xff;
758 const BYTE bFirst = (~*lpOut) & bMask;
760 if (bFirst)
762 /* Have a clear bit in first byte */
763 if (bFirst != bMask)
765 /* Not every bit is clear */
766 ULONG ulOffset;
768 if (bFirst & 0x0f)
769 ulOffset = NTDLL_leastSignificant[bFirst & 0x0f];
770 else
771 ulOffset = 4 + NTDLL_leastSignificant[bFirst >> 4];
772 ulStart += ulOffset;
773 ulFoundAt = ulStart;
774 for (;ulOffset < 8; ulOffset++)
776 if (!(bFirst & (1 << ulOffset)))
778 *lpSize = ulCount;
779 return ulFoundAt; /* Clear from start, but not until the end */
781 ulCount++;
782 ulStart++;
784 /* Clear to the end - go on to count further bits */
785 lpOut++;
786 break;
788 /* Every bit from start until the end of the byte is clear */
789 ulFoundAt = ulStart;
790 ulCount = 8 - (ulStart & 7);
791 ulStart = (ulStart & ~7u) + 8;
792 lpOut++;
793 break;
795 ulStart = (ulStart & ~7u) + 8;
796 lpOut++;
797 if (ulStart >= lpBits->SizeOfBitMap)
798 return -1u;
801 /* Count blocks of 8 clear bits */
802 while (!*lpOut)
804 ulCount += 8;
805 ulStart += 8;
806 if (ulStart >= lpBits->SizeOfBitMap)
808 *lpSize = ulCount - (ulStart - lpBits->SizeOfBitMap);
809 return ulFoundAt;
811 lpOut++;
814 /* Count remaining contigious bits, if any */
815 if (!(*lpOut & 1))
817 ULONG ulOffset = 0;
819 for (;ulOffset < 7u; ulOffset++)
821 if (*lpOut & (1 << ulOffset))
822 break;
823 ulCount++;
826 *lpSize = ulCount;
827 return ulFoundAt;
830 /*************************************************************************
831 * RtlFindNextForwardRunSet [NTDLL.@]
833 * Find the next run of set bits in a bitmap.
835 * PARAMS
836 * lpBits [I] Bitmap pointer
837 * ulStart [I] Bit position to start searching from
838 * lpPos [O] Start of run
840 * RETURNS
841 * Success: The length of the next set run in the bitmap. lpPos is set to
842 * the start of the run.
843 * Failure: 0, if no run is found or any parameters are invalid.
845 ULONG WINAPI RtlFindNextForwardRunSet(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpPos)
847 ULONG ulSize = 0;
849 TRACE("(%p,%ld,%p)\n", lpBits, ulStart, lpPos);
851 if (lpBits && ulStart < lpBits->SizeOfBitMap && lpPos)
852 *lpPos = NTDLL_FindSetRun(lpBits, ulStart, &ulSize);
854 return ulSize;
857 /*************************************************************************
858 * RtlFindNextForwardRunClear [NTDLL.@]
860 * Find the next run of clear bits in a bitmap.
862 * PARAMS
863 * lpBits [I] Bitmap pointer
864 * ulStart [I] Bit position to start searching from
865 * lpPos [O] Start of run
867 * RETURNS
868 * Success: The length of the next clear run in the bitmap. lpPos is set to
869 * the start of the run.
870 * Failure: 0, if no run is found or any parameters are invalid.
872 ULONG WINAPI RtlFindNextForwardRunClear(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpPos)
874 ULONG ulSize = 0;
876 TRACE("(%p,%ld,%p)\n", lpBits, ulStart, lpPos);
878 if (lpBits && ulStart < lpBits->SizeOfBitMap && lpPos)
879 *lpPos = NTDLL_FindClearRun(lpBits, ulStart, &ulSize);
881 return ulSize;
884 /*************************************************************************
885 * RtlFindLastBackwardRunSet [NTDLL.@]
887 * Find a previous run of set bits in a bitmap.
889 * PARAMS
890 * lpBits [I] Bitmap pointer
891 * ulStart [I] Bit position to start searching from
892 * lpPos [O] Start of run
894 * RETURNS
895 * Success: The length of the previous set run in the bitmap. lpPos is set to
896 * the start of the run.
897 * Failure: 0, if no run is found or any parameters are invalid.
899 ULONG WINAPI RtlFindLastBackwardRunSet(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpPos)
901 FIXME("(%p,%ld,%p)-stub!\n", lpBits, ulStart, lpPos);
902 return 0;
905 /*************************************************************************
906 * RtlFindLastBackwardRunClear [NTDLL.@]
908 * Find a previous run of clear bits in a bitmap.
910 * PARAMS
911 * lpBits [I] Bitmap pointer
912 * ulStart [I] Bit position to start searching from
913 * lpPos [O] Start of run
915 * RETURNS
916 * Success: The length of the previous clear run in the bitmap. lpPos is set
917 * to the start of the run.
918 * Failure: 0, if no run is found or any parameters are invalid.
920 ULONG WINAPI RtlFindLastBackwardRunClear(PCRTL_BITMAP lpBits, ULONG ulStart, PULONG lpPos)
922 FIXME("(%p,%ld,%p)-stub!\n", lpBits, ulStart, lpPos);
923 return 0;
926 /*************************************************************************
927 * NTDLL_FindRuns
929 * Internal implementation of RtlFindSetRuns/RtlFindClearRuns.
931 static ULONG WINAPI NTDLL_FindRuns(PCRTL_BITMAP lpBits, PRTL_BITMAP_RUN lpSeries,
932 ULONG ulCount, BOOLEAN bLongest,
933 ULONG (*fn)(PCRTL_BITMAP,ULONG,PULONG))
935 BOOL bNeedSort = ulCount > 1 ? TRUE : FALSE;
936 ULONG ulPos = 0, ulRuns = 0;
938 TRACE("(%p,%p,%ld,%d)\n", lpBits, lpSeries, ulCount, bLongest);
940 if (!ulCount)
941 return -1u;
943 while (ulPos < lpBits->SizeOfBitMap)
945 /* Find next set/clear run */
946 ULONG ulSize, ulNextPos = fn(lpBits, ulPos, &ulSize);
948 if (ulNextPos == -1u)
949 break;
951 if (bLongest && ulRuns == ulCount)
953 /* Sort runs with shortest at end, if they are out of order */
954 if (bNeedSort)
955 qsort(lpSeries, ulRuns, sizeof(RTL_BITMAP_RUN), NTDLL_RunSortFn);
957 /* Replace last run if this one is bigger */
958 if (ulSize > lpSeries[ulRuns - 1].SizeOfRun)
960 lpSeries[ulRuns - 1].StartOfRun = ulNextPos;
961 lpSeries[ulRuns - 1].SizeOfRun = ulSize;
963 /* We need to re-sort the array, _if_ we didn't leave it sorted */
964 if (ulRuns > 1 && ulSize > lpSeries[ulRuns - 2].SizeOfRun)
965 bNeedSort = TRUE;
968 else
970 /* Append to found runs */
971 lpSeries[ulRuns].StartOfRun = ulNextPos;
972 lpSeries[ulRuns].SizeOfRun = ulSize;
973 ulRuns++;
975 if (!bLongest && ulRuns == ulCount)
976 break;
978 ulPos = ulNextPos + ulSize;
980 return ulRuns;
983 /*************************************************************************
984 * RtlFindSetRuns [NTDLL.@]
986 * Find a series of set runs in a bitmap.
988 * PARAMS
989 * lpBits [I] Bitmap pointer
990 * ulSeries [O] Array for each run found
991 * ulCount [I] Number of runs to find
992 * bLongest [I] Whether to find the very longest runs or not
994 * RETURNS
995 * The number of set runs found.
997 ULONG WINAPI RtlFindSetRuns(PCRTL_BITMAP lpBits, PRTL_BITMAP_RUN lpSeries,
998 ULONG ulCount, BOOLEAN bLongest)
1000 TRACE("(%p,%p,%ld,%d)\n", lpBits, lpSeries, ulCount, bLongest);
1002 return NTDLL_FindRuns(lpBits, lpSeries, ulCount, bLongest, NTDLL_FindSetRun);
1005 /*************************************************************************
1006 * RtlFindClearRuns [NTDLL.@]
1008 * Find a series of clear runs in a bitmap.
1010 * PARAMS
1011 * lpBits [I] Bitmap pointer
1012 * ulSeries [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
1016 * RETURNS
1017 * The number of clear runs found.
1019 ULONG WINAPI RtlFindClearRuns(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_FindClearRun);
1027 /*************************************************************************
1028 * RtlFindLongestRunSet [NTDLL.@]
1030 * Find the longest set run in a bitmap.
1032 * PARAMS
1033 * lpBits [I] Bitmap pointer
1034 * pulStart [O] Destination for start of run
1036 * RETURNS
1037 * The length of the run found, or 0 if no run is found.
1039 ULONG WINAPI RtlFindLongestRunSet(PCRTL_BITMAP lpBits, PULONG pulStart)
1041 RTL_BITMAP_RUN br;
1043 TRACE("(%p,%p)\n", lpBits, pulStart);
1045 if (RtlFindSetRuns(lpBits, &br, 1, TRUE) == 1)
1047 if (pulStart)
1048 *pulStart = br.StartOfRun;
1049 return br.SizeOfRun;
1051 return 0;
1054 /*************************************************************************
1055 * RtlFindLongestRunClear [NTDLL.@]
1057 * Find the longest clear run in a bitmap.
1059 * PARAMS
1060 * lpBits [I] Bitmap pointer
1061 * pulStart [O] Destination for start of run
1063 * RETURNS
1064 * The length of the run found, or 0 if no run is found.
1066 ULONG WINAPI RtlFindLongestRunClear(PCRTL_BITMAP lpBits, PULONG pulStart)
1068 RTL_BITMAP_RUN br;
1070 TRACE("(%p,%p)\n", lpBits, pulStart);
1072 if (RtlFindClearRuns(lpBits, &br, 1, TRUE) == 1)
1074 if (pulStart)
1075 *pulStart = br.StartOfRun;
1076 return br.SizeOfRun;
1078 return 0;