/* This file is part of Mailfromd. Copyright (C) 2009-2019 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include /* FIXME: Ensure that sizeof(bitmask_bits_t)<=sizeof(void*) */ typedef unsigned bitmask_bits_t; struct bitmask { size_t bm_nset; /* Number of bits set */ size_t bm_size; /* Number of elements in bm_bits */ bitmask_bits_t *bm_bits; }; #define NBMBITS (sizeof(bitmask_bits_t) * 8) #define BIT_WORD(n) ((n) / NBMBITS) #define BIT_MASK(n) ((bitmask_bits_t)1 << ((n) % NBMBITS)) #define bitmask_zero(bm) \ do { \ memset((bm)->bm_bits, 0, \ (bm)->bm_size * sizeof(bitmask_bits_t)); \ (bm)->bm_nset = 0; \ } while (0) #define bitmask_init(bm) memset(bm, 0, sizeof((bm)[0])) #define bitmask_nset(bm) ((bm)->bm_nset) #define bitmask_max(bm) ((bm)->bm_nset * NBMBITS) #define __bitmask_expand(bm,n) \ do { \ size_t __n = n; \ (bm)->bm_bits = mu_realloc((bm)->bm_bits, \ (__n) * sizeof(bitmask_bits_t)); \ memset((bm)->bm_bits + (bm)->bm_size, 0, \ ((__n) - (bm)->bm_size) * sizeof(bitmask_bits_t)); \ (bm)->bm_size = __n; \ } while (0) #define bitmask_set(bm,n) \ do { \ unsigned num = BIT_WORD(n); \ if (num >= (bm)->bm_size) \ __bitmask_expand(bm, num+1); \ (bm)->bm_bits[num] |= BIT_MASK(n); \ (bm)->bm_nset++; \ } while (0) #define bitmask_isset(bm,n) \ ((BIT_WORD(n) < (bm)->bm_size) \ && (bm)->bm_bits[BIT_WORD(n)] & BIT_MASK(n)) #define bitmask_clr(bm,n) \ do { \ unsigned num = BIT_WORD(n); \ if (num < (bm)->bm_size) { \ (bm)->bm_bits[num] &= ~BIT_MASK(n); \ (bm)->bm_nset--; \ } \ } while (0) #define bitmask_merge(d,s) \ do { \ int __i; \ if ((s)->bm_size > (d)->bm_size) \ __bitmask_expand(d, (s)->bm_size); \ for (__i = 0; __i < (s)->bm_size; __i++) \ (d)->bm_bits[__i] |= (s)->bm_bits[__i]; \ (d)->bm_nset += (s)->bm_nset; \ } while (0)