]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/bitmap.c
2 This file is part of systemd.
4 Copyright 2015 Tom Gundersen
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 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 License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "alloc-util.h"
34 size_t bitmaps_allocated
;
37 /* Bitmaps are only meant to store relatively small numbers
38 * (corresponding to, say, an enum), so it is ok to limit
39 * the max entry. 64k should be plenty. */
40 #define BITMAPS_MAX_ENTRY 0xffff
42 /* This indicates that we reached the end of the bitmap */
43 #define BITMAP_END ((unsigned) -1)
45 #define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(uint64_t) * 8))
46 #define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8))
47 #define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem))
49 Bitmap
*bitmap_new(void) {
50 return new0(Bitmap
, 1);
53 void bitmap_free(Bitmap
*b
) {
61 int bitmap_ensure_allocated(Bitmap
**b
) {
78 int bitmap_set(Bitmap
*b
, unsigned n
) {
84 /* we refuse to allocate huge bitmaps */
85 if (n
> BITMAPS_MAX_ENTRY
)
88 offset
= BITMAP_NUM_TO_OFFSET(n
);
90 if (offset
>= b
->n_bitmaps
) {
91 if (!GREEDY_REALLOC0(b
->bitmaps
, b
->bitmaps_allocated
, offset
+ 1))
94 b
->n_bitmaps
= offset
+ 1;
97 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
99 b
->bitmaps
[offset
] |= bitmask
;
104 void bitmap_unset(Bitmap
*b
, unsigned n
) {
111 offset
= BITMAP_NUM_TO_OFFSET(n
);
113 if (offset
>= b
->n_bitmaps
)
116 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
118 b
->bitmaps
[offset
] &= ~bitmask
;
121 bool bitmap_isset(Bitmap
*b
, unsigned n
) {
128 offset
= BITMAP_NUM_TO_OFFSET(n
);
130 if (offset
>= b
->n_bitmaps
)
133 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
135 return !!(b
->bitmaps
[offset
] & bitmask
);
138 bool bitmap_isclear(Bitmap
*b
) {
144 for (i
= 0; i
< b
->n_bitmaps
; i
++)
145 if (b
->bitmaps
[i
] != 0)
151 void bitmap_clear(Bitmap
*b
) {
156 b
->bitmaps
= mfree(b
->bitmaps
);
158 b
->bitmaps_allocated
= 0;
161 bool bitmap_iterate(Bitmap
*b
, Iterator
*i
, unsigned *n
) {
163 unsigned offset
, rem
;
168 if (!b
|| i
->idx
== BITMAP_END
)
171 offset
= BITMAP_NUM_TO_OFFSET(i
->idx
);
172 rem
= BITMAP_NUM_TO_REM(i
->idx
);
173 bitmask
= UINT64_C(1) << rem
;
175 for (; offset
< b
->n_bitmaps
; offset
++) {
176 if (b
->bitmaps
[offset
]) {
177 for (; bitmask
; bitmask
<<= 1, rem
++) {
178 if (b
->bitmaps
[offset
] & bitmask
) {
179 *n
= BITMAP_OFFSET_TO_NUM(offset
, rem
);
196 bool bitmap_equal(Bitmap
*a
, Bitmap
*b
) {
197 size_t common_n_bitmaps
;
210 common_n_bitmaps
= MIN(a
->n_bitmaps
, b
->n_bitmaps
);
211 if (memcmp(a
->bitmaps
, b
->bitmaps
, sizeof(uint64_t) * common_n_bitmaps
) != 0)
214 c
= a
->n_bitmaps
> b
->n_bitmaps
? a
: b
;
215 for (i
= common_n_bitmaps
; i
< c
->n_bitmaps
; i
++)
216 if (c
->bitmaps
[i
] != 0)