bitmap: Add functions to set/clear ranges of bits
[ccan] / ccan / bitmap / bitmap.c
1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2
3 #include "config.h"
4
5 #include <ccan/bitmap/bitmap.h>
6
7 #include <assert.h>
8
9 #define BIT_ALIGN_DOWN(n)       ((n) & ~(BITMAP_WORD_BITS - 1))
10 #define BIT_ALIGN_UP(n)         BIT_ALIGN_DOWN((n) + BITMAP_WORD_BITS - 1)
11
12 void bitmap_zero_range(bitmap *bitmap, unsigned long n, unsigned long m)
13 {
14         unsigned long an = BIT_ALIGN_UP(n);
15         unsigned long am = BIT_ALIGN_DOWN(m);
16         bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS);
17         bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS));
18
19         assert(m >= n);
20
21         if (am < an) {
22                 BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask & tailmask);
23                 return;
24         }
25
26         if (an > n)
27                 BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask);
28
29         if (am > an)
30                 memset(&BITMAP_WORD(bitmap, an), 0,
31                        (am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word));
32
33         if (m > am)
34                 BITMAP_WORD(bitmap, m) &= ~bitmap_bswap(tailmask);
35 }
36
37 void bitmap_fill_range(bitmap *bitmap, unsigned long n, unsigned long m)
38 {
39         unsigned long an = BIT_ALIGN_UP(n);
40         unsigned long am = BIT_ALIGN_DOWN(m);
41         bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS);
42         bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS));
43
44         assert(m >= n);
45
46         if (am < an) {
47                 BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask & tailmask);
48                 return;
49         }
50
51         if (an > n)
52                 BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask);
53
54         if (am > an)
55                 memset(&BITMAP_WORD(bitmap, an), 0xff,
56                        (am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word));
57
58         if (m > am)
59                 BITMAP_WORD(bitmap, m) |= bitmap_bswap(tailmask);
60 }