1 /* This file is part of Mailfromd. 2 Copyright (C) 2009-2021 Sergey Poznyakoff 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include <stdlib.h> 18 19 /* FIXME: Ensure that sizeof(bitmask_bits_t)<=sizeof(void*) */ 20 typedef unsigned bitmask_bits_t; 21 22 struct bitmask 23 { 24 size_t bm_nset; /* Number of bits set */ 25 size_t bm_size; /* Number of elements in bm_bits */ 26 bitmask_bits_t *bm_bits; 27 }; 28 29 #define NBMBITS (sizeof(bitmask_bits_t) * 8) 30 31 #define BIT_WORD(n) ((n) / NBMBITS) 32 #define BIT_MASK(n) ((bitmask_bits_t)1 << ((n) % NBMBITS)) 33 34 #define bitmask_zero(bm) \ 35 do { \ 36 memset((bm)->bm_bits, 0, \ 37 (bm)->bm_size * sizeof(bitmask_bits_t)); \ 38 (bm)->bm_nset = 0; \ 39 } while (0) 40 41 #define bitmask_init(bm) memset(bm, 0, sizeof((bm)[0])) 42 #define bitmask_nset(bm) ((bm)->bm_nset) 43 #define bitmask_max(bm) ((bm)->bm_nset * NBMBITS) 44 45 #define __bitmask_expand(bm,n) \ 46 do { \ 47 size_t __n = n; \ 48 (bm)->bm_bits = mu_realloc((bm)->bm_bits, \ 49 (__n) * sizeof(bitmask_bits_t)); \ 50 memset((bm)->bm_bits + (bm)->bm_size, 0, \ 51 ((__n) - (bm)->bm_size) * sizeof(bitmask_bits_t)); \ 52 (bm)->bm_size = __n; \ 53 } while (0) 54 55 #define bitmask_set(bm,n) \ 56 do { \ 57 unsigned num = BIT_WORD(n); \ 58 if (num >= (bm)->bm_size) \ 59 __bitmask_expand(bm, num+1); \ 60 (bm)->bm_bits[num] |= BIT_MASK(n); \ 61 (bm)->bm_nset++; \ 62 } while (0) 63 64 #define bitmask_isset(bm,n) \ 65 ((BIT_WORD(n) < (bm)->bm_size) \ 66 && (bm)->bm_bits[BIT_WORD(n)] & BIT_MASK(n)) 67 68 #define bitmask_clr(bm,n) \ 69 do { \ 70 unsigned num = BIT_WORD(n); \ 71 if (num < (bm)->bm_size) { \ 72 (bm)->bm_bits[num] &= ~BIT_MASK(n); \ 73 (bm)->bm_nset--; \ 74 } \ 75 } while (0) 76 77 #define bitmask_merge(d,s) \ 78 do { \ 79 int __i; \ 80 if ((s)->bm_size > (d)->bm_size) \ 81 __bitmask_expand(d, (s)->bm_size); \ 82 for (__i = 0; __i < (s)->bm_size; __i++) \ 83 (d)->bm_bits[__i] |= (s)->bm_bits[__i]; \ 84 (d)->bm_nset += (s)->bm_nset; \ 85 } while (0) 86