]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/bitmap.c
7c985a0956f93247b5f813699221792f0be38ea8
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
7 #include "memory-util.h"
9 /* Bitmaps are only meant to store relatively small numbers
10 * (corresponding to, say, an enum), so it is ok to limit
11 * the max entry. 64k should be plenty. */
12 #define BITMAPS_MAX_ENTRY 0xffff
14 /* This indicates that we reached the end of the bitmap */
15 #define BITMAP_END (UINT_MAX)
17 #define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(uint64_t) * 8))
18 #define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8))
19 #define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem))
21 Bitmap
* bitmap_new(void) {
22 return new0(Bitmap
, 1);
25 Bitmap
* bitmap_copy(Bitmap
*b
) {
32 ret
->bitmaps
= newdup(uint64_t, b
->bitmaps
, b
->n_bitmaps
);
36 ret
->n_bitmaps
= b
->n_bitmaps
;
40 Bitmap
* bitmap_free(Bitmap
*b
) {
48 int bitmap_ensure_allocated(Bitmap
**b
) {
65 int bitmap_set(Bitmap
*b
, unsigned n
) {
71 /* we refuse to allocate huge bitmaps */
72 if (n
> BITMAPS_MAX_ENTRY
)
75 offset
= BITMAP_NUM_TO_OFFSET(n
);
77 if (offset
>= b
->n_bitmaps
) {
78 if (!GREEDY_REALLOC0(b
->bitmaps
, offset
+ 1))
81 b
->n_bitmaps
= offset
+ 1;
84 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
86 b
->bitmaps
[offset
] |= bitmask
;
91 void bitmap_unset(Bitmap
*b
, unsigned n
) {
98 offset
= BITMAP_NUM_TO_OFFSET(n
);
100 if (offset
>= b
->n_bitmaps
)
103 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
105 b
->bitmaps
[offset
] &= ~bitmask
;
108 bool bitmap_isset(const Bitmap
*b
, unsigned n
) {
115 offset
= BITMAP_NUM_TO_OFFSET(n
);
117 if (offset
>= b
->n_bitmaps
)
120 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
122 return !!(b
->bitmaps
[offset
] & bitmask
);
125 bool bitmap_isclear(const Bitmap
*b
) {
130 FOREACH_ARRAY(i
, b
->bitmaps
, b
->n_bitmaps
)
137 void bitmap_clear(Bitmap
*b
) {
141 b
->bitmaps
= mfree(b
->bitmaps
);
145 bool bitmap_iterate(const Bitmap
*b
, Iterator
*i
, unsigned *n
) {
147 unsigned offset
, rem
;
152 if (!b
|| i
->idx
== BITMAP_END
)
155 offset
= BITMAP_NUM_TO_OFFSET(i
->idx
);
156 rem
= BITMAP_NUM_TO_REM(i
->idx
);
157 bitmask
= UINT64_C(1) << rem
;
159 for (; offset
< b
->n_bitmaps
; offset
++) {
160 if (b
->bitmaps
[offset
]) {
161 for (; bitmask
; bitmask
<<= 1, rem
++) {
162 if (b
->bitmaps
[offset
] & bitmask
) {
163 *n
= BITMAP_OFFSET_TO_NUM(offset
, rem
);
180 bool bitmap_equal(const Bitmap
*a
, const Bitmap
*b
) {
181 size_t common_n_bitmaps
;
193 common_n_bitmaps
= MIN(a
->n_bitmaps
, b
->n_bitmaps
);
194 if (memcmp_safe(a
->bitmaps
, b
->bitmaps
, sizeof(uint64_t) * common_n_bitmaps
) != 0)
197 c
= a
->n_bitmaps
> b
->n_bitmaps
? a
: b
;
198 for (unsigned i
= common_n_bitmaps
; i
< c
->n_bitmaps
; i
++)
199 if (c
->bitmaps
[i
] != 0)