]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/bitmap.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2015 Tom Gundersen
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
35 size_t bitmaps_allocated
;
38 /* Bitmaps are only meant to store relatively small numbers
39 * (corresponding to, say, an enum), so it is ok to limit
40 * the max entry. 64k should be plenty. */
41 #define BITMAPS_MAX_ENTRY 0xffff
43 /* This indicates that we reached the end of the bitmap */
44 #define BITMAP_END ((unsigned) -1)
46 #define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(uint64_t) * 8))
47 #define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8))
48 #define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem))
50 Bitmap
*bitmap_new(void) {
51 return new0(Bitmap
, 1);
54 Bitmap
*bitmap_copy(Bitmap
*b
) {
61 ret
->bitmaps
= newdup(uint64_t, b
->bitmaps
, b
->n_bitmaps
);
65 ret
->n_bitmaps
= ret
->bitmaps_allocated
= b
->n_bitmaps
;
69 void bitmap_free(Bitmap
*b
) {
77 int bitmap_ensure_allocated(Bitmap
**b
) {
94 int bitmap_set(Bitmap
*b
, unsigned n
) {
100 /* we refuse to allocate huge bitmaps */
101 if (n
> BITMAPS_MAX_ENTRY
)
104 offset
= BITMAP_NUM_TO_OFFSET(n
);
106 if (offset
>= b
->n_bitmaps
) {
107 if (!GREEDY_REALLOC0(b
->bitmaps
, b
->bitmaps_allocated
, offset
+ 1))
110 b
->n_bitmaps
= offset
+ 1;
113 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
115 b
->bitmaps
[offset
] |= bitmask
;
120 void bitmap_unset(Bitmap
*b
, unsigned n
) {
127 offset
= BITMAP_NUM_TO_OFFSET(n
);
129 if (offset
>= b
->n_bitmaps
)
132 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
134 b
->bitmaps
[offset
] &= ~bitmask
;
137 bool bitmap_isset(Bitmap
*b
, unsigned n
) {
144 offset
= BITMAP_NUM_TO_OFFSET(n
);
146 if (offset
>= b
->n_bitmaps
)
149 bitmask
= UINT64_C(1) << BITMAP_NUM_TO_REM(n
);
151 return !!(b
->bitmaps
[offset
] & bitmask
);
154 bool bitmap_isclear(Bitmap
*b
) {
160 for (i
= 0; i
< b
->n_bitmaps
; i
++)
161 if (b
->bitmaps
[i
] != 0)
167 void bitmap_clear(Bitmap
*b
) {
172 b
->bitmaps
= mfree(b
->bitmaps
);
174 b
->bitmaps_allocated
= 0;
177 bool bitmap_iterate(Bitmap
*b
, Iterator
*i
, unsigned *n
) {
179 unsigned offset
, rem
;
184 if (!b
|| i
->idx
== BITMAP_END
)
187 offset
= BITMAP_NUM_TO_OFFSET(i
->idx
);
188 rem
= BITMAP_NUM_TO_REM(i
->idx
);
189 bitmask
= UINT64_C(1) << rem
;
191 for (; offset
< b
->n_bitmaps
; offset
++) {
192 if (b
->bitmaps
[offset
]) {
193 for (; bitmask
; bitmask
<<= 1, rem
++) {
194 if (b
->bitmaps
[offset
] & bitmask
) {
195 *n
= BITMAP_OFFSET_TO_NUM(offset
, rem
);
212 bool bitmap_equal(Bitmap
*a
, Bitmap
*b
) {
213 size_t common_n_bitmaps
;
226 common_n_bitmaps
= MIN(a
->n_bitmaps
, b
->n_bitmaps
);
227 if (memcmp(a
->bitmaps
, b
->bitmaps
, sizeof(uint64_t) * common_n_bitmaps
) != 0)
230 c
= a
->n_bitmaps
> b
->n_bitmaps
? a
: b
;
231 for (i
= common_n_bitmaps
; i
< c
->n_bitmaps
; i
++)
232 if (c
->bitmaps
[i
] != 0)