]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/bitmap.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2015 Tom Gundersen
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 long long unsigned *bitmaps
;
29 size_t bitmaps_allocated
;
32 /* Bitmaps are only meant to store relatively small numbers
33 * (corresponding to, say, an enum), so it is ok to limit
34 * the max entry. 64k should be plenty. */
35 #define BITMAPS_MAX_ENTRY 0xffff
37 /* This indicates that we reached the end of the bitmap */
38 #define BITMAP_END ((unsigned) -1)
40 #define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(long long unsigned) * 8))
41 #define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(long long unsigned) * 8))
42 #define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(long long unsigned) * 8 + (rem))
44 Bitmap
*bitmap_new(void) {
45 return new0(Bitmap
, 1);
48 void bitmap_free(Bitmap
*b
) {
56 int bitmap_ensure_allocated(Bitmap
**b
) {
71 int bitmap_set(Bitmap
*b
, unsigned n
) {
72 long long unsigned bitmask
;
77 /* we refuse to allocate huge bitmaps */
78 if (n
> BITMAPS_MAX_ENTRY
)
81 offset
= BITMAP_NUM_TO_OFFSET(n
);
83 if (offset
>= b
->n_bitmaps
) {
84 if (!GREEDY_REALLOC0(b
->bitmaps
, b
->bitmaps_allocated
, offset
+ 1))
87 b
->n_bitmaps
= offset
+ 1;
90 bitmask
= 1ULL << BITMAP_NUM_TO_REM(n
);
92 b
->bitmaps
[offset
] |= bitmask
;
97 void bitmap_unset(Bitmap
*b
, unsigned n
) {
98 long long unsigned bitmask
;
103 offset
= BITMAP_NUM_TO_OFFSET(n
);
105 if (offset
>= b
->n_bitmaps
)
108 bitmask
= 1ULL << BITMAP_NUM_TO_REM(n
);
110 b
->bitmaps
[offset
] &= ~bitmask
;
113 bool bitmap_isset(Bitmap
*b
, unsigned n
) {
114 long long unsigned bitmask
;
117 if (!b
|| !b
->bitmaps
)
120 offset
= BITMAP_NUM_TO_OFFSET(n
);
122 if (offset
>= b
->n_bitmaps
)
125 bitmask
= 1ULL << BITMAP_NUM_TO_REM(n
);
127 return !!(b
->bitmaps
[offset
] & bitmask
);
130 bool bitmap_isclear(Bitmap
*b
) {
135 for (i
= 0; i
< b
->n_bitmaps
; i
++)
142 void bitmap_clear(Bitmap
*b
) {
147 for (i
= 0; i
< b
->n_bitmaps
; i
++)
151 bool bitmap_iterate(Bitmap
*b
, Iterator
*i
, unsigned *n
) {
152 long long unsigned bitmask
;
153 unsigned offset
, rem
;
155 if (!b
|| i
->idx
== BITMAP_END
)
158 offset
= BITMAP_NUM_TO_OFFSET(i
->idx
);
159 rem
= BITMAP_NUM_TO_REM(i
->idx
);
160 bitmask
= 1ULL << rem
;
162 for (; offset
< b
->n_bitmaps
; offset
++) {
163 if (b
->bitmaps
[offset
]) {
164 for (; bitmask
; bitmask
<<= 1, rem
++) {
165 if (b
->bitmaps
[offset
] & bitmask
) {
166 *n
= BITMAP_OFFSET_TO_NUM(offset
, rem
);
183 bool bitmap_equal(Bitmap
*a
, Bitmap
*b
) {
192 if (a
->n_bitmaps
!= b
->n_bitmaps
)
195 for (i
= 0; i
< a
->n_bitmaps
; i
++)
196 if (a
->bitmaps
[i
] != b
->bitmaps
[i
])