Commit e0b9db61 authored by David Gibson's avatar David Gibson

bitmap: Rework to assume always multiple of words storage length

Handling bitmaps which extend some odd number of bits, and assuring they
don't clobber partially overlapped variables is not worth the bother.

Also avoid namespace pollution.
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent 4b284149
...@@ -17,6 +17,7 @@ int main(int argc, char *argv[]) ...@@ -17,6 +17,7 @@ int main(int argc, char *argv[])
return 1; return 1;
if (strcmp(argv[1], "depends") == 0) { if (strcmp(argv[1], "depends") == 0) {
printf("ccan/endian\n");
return 0; return 0;
} }
......
...@@ -7,10 +7,13 @@ ...@@ -7,10 +7,13 @@
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <ccan/endian/endian.h>
typedef unsigned long bitmap_word; typedef unsigned long bitmap_word;
#define BITMAP_WORD_BITS (sizeof(bitmap_word) * CHAR_BIT) #define BITMAP_WORD_BITS (sizeof(bitmap_word) * CHAR_BIT)
#define BITMAP_NWORDS(_n) (((_n) + BITMAP_WORD_BITS - 1) / BITMAP_WORD_BITS) #define BITMAP_NWORDS(_n) \
(((_n) + BITMAP_WORD_BITS - 1) / BITMAP_WORD_BITS)
/* /*
* We wrap each word in a structure for type checking. * We wrap each word in a structure for type checking.
...@@ -29,198 +32,154 @@ static inline bitmap *bitmap_alloc(int nbits) ...@@ -29,198 +32,154 @@ static inline bitmap *bitmap_alloc(int nbits)
return malloc(bitmap_sizeof(nbits)); return malloc(bitmap_sizeof(nbits));
} }
#define BYTE(_bm, _n) (((unsigned char *)(_bm))[(_n) / CHAR_BIT]) static inline bitmap_word bitmap_bswap(bitmap_word w)
#define BIT(_n) (0x80 >> ((_n) % 8)) {
#define WORD(_bm, _n) ((_bm)[(_n) / BITMAP_WORD_BITS].w) if (BITMAP_WORD_BITS == 32)
return cpu_to_be32(w);
else if (BITMAP_WORD_BITS == 64)
return cpu_to_be64(w);
}
#define BITMAP_WORD(_bm, _n) ((_bm)[(_n) / BITMAP_WORD_BITS].w)
#define BITMAP_WORDBIT(_n) \
(bitmap_bswap(1UL << (BITMAP_WORD_BITS - ((_n) % BITMAP_WORD_BITS) - 1)))
#define BYTES(_nbits) ((_nbits) / 8) #define BITMAP_HEADWORDS(_nbits) \
#define BITS(_nbits) ((~(0xff >> ((_nbits) % 8))) & 0xff) ((_nbits) / BITMAP_WORD_BITS)
#define BITMAP_HEADBYTES(_nbits) \
(BITMAP_HEADWORDS(_nbits) * sizeof(bitmap_word))
#define BITMAP_TAILWORD(_bm, _nbits) \
((_bm)[BITMAP_HEADWORDS(_nbits)].w)
#define BITMAP_HASTAIL(_nbits) (((_nbits) % BITMAP_WORD_BITS) != 0)
#define BITMAP_TAILBITS(_nbits) \
(bitmap_bswap(~(-1UL >> ((_nbits) % BITMAP_WORD_BITS))))
#define BITMAP_TAIL(_bm, _nbits) \
(BITMAP_TAILWORD(_bm, _nbits) & BITMAP_TAILBITS(_nbits))
static inline void bitmap_set_bit(bitmap *bitmap, int n) static inline void bitmap_set_bit(bitmap *bitmap, int n)
{ {
BYTE(bitmap, n) |= BIT(n); BITMAP_WORD(bitmap, n) |= BITMAP_WORDBIT(n);
} }
static inline void bitmap_clear_bit(bitmap *bitmap, int n) static inline void bitmap_clear_bit(bitmap *bitmap, int n)
{ {
BYTE(bitmap, n) &= ~BIT(n); BITMAP_WORD(bitmap, n) &= ~BITMAP_WORDBIT(n);
} }
static inline void bitmap_change_bit(bitmap *bitmap, int n) static inline void bitmap_change_bit(bitmap *bitmap, int n)
{ {
BYTE(bitmap, n) ^= BIT(n); BITMAP_WORD(bitmap, n) ^= BITMAP_WORDBIT(n);
} }
static inline bool bitmap_test_bit(bitmap *bitmap, int n) static inline bool bitmap_test_bit(bitmap *bitmap, int n)
{ {
return !!(BYTE(bitmap, n) & BIT(n)); return !!(BITMAP_WORD(bitmap, n) & BITMAP_WORDBIT(n));
} }
static inline void bitmap_zero(bitmap *bitmap, int nbits) static inline void bitmap_zero(bitmap *bitmap, int nbits)
{ {
memset(bitmap, 0, BYTES(nbits)); memset(bitmap, 0, bitmap_sizeof(nbits));
if (BITS(nbits))
BYTE(bitmap, nbits) &= ~BITS(nbits);
} }
static inline void bitmap_fill(bitmap *bitmap, int nbits) static inline void bitmap_fill(bitmap *bitmap, int nbits)
{ {
memset(bitmap, 0xff, BYTES(nbits)); memset(bitmap, 0xff, bitmap_sizeof(nbits));
if (BITS(nbits))
BYTE(bitmap, nbits) |= BITS(nbits);
} }
static inline void bitmap_copy(bitmap *dst, bitmap *src, int nbits) static inline void bitmap_copy(bitmap *dst, bitmap *src, int nbits)
{ {
memcpy(dst, src, BYTES(nbits)); memcpy(dst, src, bitmap_sizeof(nbits));
if (BITS(nbits)) {
BYTE(dst, nbits) &= ~BITS(nbits);
BYTE(dst, nbits) |= BYTE(src, nbits) & BITS(nbits);
}
} }
#define DEF_BINOP(_name, _op) \ #define BITMAP_DEF_BINOP(_name, _op) \
static inline void bitmap_##_name(bitmap *dst, bitmap *src1, bitmap *src2, \ static inline void bitmap_##_name(bitmap *dst, bitmap *src1, bitmap *src2, \
int nbits) \ int nbits) \
{ \ { \
int n = 0; \ int i = 0; \
while ((nbits - n) >= BITMAP_WORD_BITS) { \ for (i = 0; i < BITMAP_NWORDS(nbits); i++) { \
WORD(dst, n) = WORD(src1, n) _op WORD(src2, n); \ dst[i].w = src1[i].w _op src2[i].w; \
n += BITMAP_WORD_BITS; \
} \
while ((nbits - n) >= 8) { \
BYTE(dst, n) = BYTE(src1, n) _op BYTE(src2, n); \
n += 8; \
} \
if (BITS(nbits)) { \
BYTE(dst, nbits) &= ~BITS(nbits); \
BYTE(dst, nbits) |= (BYTE(src1, nbits) _op BYTE(src2, nbits)) \
& BITS(nbits); \
} \ } \
} }
DEF_BINOP(and, &) BITMAP_DEF_BINOP(and, &)
DEF_BINOP(or, |) BITMAP_DEF_BINOP(or, |)
DEF_BINOP(xor, ^) BITMAP_DEF_BINOP(xor, ^)
DEF_BINOP(andnot, & ~) BITMAP_DEF_BINOP(andnot, & ~)
#undef DEF_BINOP #undef BITMAP_DEF_BINOP
static inline void bitmap_complement(bitmap *dst, bitmap *src, int nbits) static inline void bitmap_complement(bitmap *dst, bitmap *src, int nbits)
{ {
int n = 0; int i;
while ((nbits - n) >= BITMAP_WORD_BITS) { for (i = 0; i < BITMAP_NWORDS(nbits); i++)
WORD(dst, n) = ~WORD(src, n); dst[i].w = ~src[i].w;
n += BITMAP_WORD_BITS;
}
while ((nbits - n) >= 8) {
BYTE(dst, n) = ~BYTE(src, n);
n += 8;
}
if (BITS(nbits)) {
BYTE(dst, nbits) &= ~BITS(nbits);
BYTE(dst, nbits) |= ~BYTE(src, nbits) & BITS(nbits);
}
} }
static inline bool bitmap_equal(bitmap *src1, bitmap *src2, int nbits) static inline bool bitmap_equal(bitmap *src1, bitmap *src2, int nbits)
{ {
if (memcmp(src1, src2, BYTES(nbits)) != 0) return (memcmp(src1, src2, BITMAP_HEADBYTES(nbits)) == 0)
return false; && (!BITMAP_HASTAIL(nbits)
if ((BYTE(src1, nbits) & BITS(nbits)) || (BITMAP_TAIL(src1, nbits) == BITMAP_TAIL(src2, nbits)));
!= (BYTE(src2, nbits) & BITS(nbits)))
return false;
return true;
} }
static inline bool bitmap_intersects(bitmap *src1, bitmap *src2, int nbits) static inline bool bitmap_intersects(bitmap *src1, bitmap *src2, int nbits)
{ {
int n = 0; int i;
while ((nbits - n) >= BITMAP_WORD_BITS) { for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) {
if (WORD(src1, n) & WORD(src2, n)) if (src1[i].w & src2[i].w)
return true;
n += BITMAP_WORD_BITS;
}
while ((nbits - n) >= 8) {
if (BYTE(src1, n) & BYTE(src2, n))
return true; return true;
n += 8;
} }
if (BITS(nbits) & BYTE(src1, nbits) & BYTE(src2, nbits)) { if (BITMAP_HASTAIL(nbits) &&
(BITMAP_TAIL(src1, nbits) & BITMAP_TAIL(src2, nbits)))
return true; return true;
}
return false; return false;
} }
static inline bool bitmap_subset(bitmap *src1, bitmap *src2, int nbits) static inline bool bitmap_subset(bitmap *src1, bitmap *src2, int nbits)
{ {
int n = 0; int i;
while ((nbits - n) >= BITMAP_WORD_BITS) { for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) {
if (WORD(src1, n) & ~WORD(src2, n)) if (src1[i].w & ~src2[i].w)
return false;
n += BITMAP_WORD_BITS;
}
while ((nbits - n) >= 8) {
if (BYTE(src1, n) & ~BYTE(src2, n))
return false; return false;
n += 8;
} }
if (BITS(nbits) & (BYTE(src1, nbits) & ~BYTE(src2, nbits))) { if (BITMAP_HASTAIL(nbits) &&
(BITMAP_TAIL(src1, nbits) & ~BITMAP_TAIL(src2, nbits)))
return false; return false;
}
return true; return true;
} }
static inline bool bitmap_full(bitmap *bitmap, int nbits) static inline bool bitmap_full(bitmap *bitmap, int nbits)
{ {
int n = 0; int i;
while ((nbits - n) >= BITMAP_WORD_BITS) { for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) {
if (WORD(bitmap, n) != -1UL) if (bitmap[i].w != -1UL)
return false;
n += BITMAP_WORD_BITS;
}
while ((nbits - n) >= 8) {
if (BYTE(bitmap, n) != 0xff)
return false; return false;
n += 8;
} }
if (BITS(nbits) if (BITMAP_HASTAIL(nbits) &&
&& ((BITS(nbits) & BYTE(bitmap, nbits)) != BITS(nbits))) { (BITMAP_TAIL(bitmap, nbits) != BITMAP_TAILBITS(nbits)))
return false; return false;
}
return true; return true;
} }
static inline bool bitmap_empty(bitmap *bitmap, int nbits) static inline bool bitmap_empty(bitmap *bitmap, int nbits)
{ {
int n = 0; int i;
while ((nbits - n) >= BITMAP_WORD_BITS) { for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) {
if (WORD(bitmap, n)) if (bitmap[i].w != 0)
return false;
n += BITMAP_WORD_BITS;
}
while ((nbits - n) >= 8) {
if (BYTE(bitmap, n))
return false; return false;
n += 8;
} }
if (BITS(nbits) && ((BITS(nbits) & BYTE(bitmap, nbits)))) { if (BITMAP_HASTAIL(nbits) && (BITMAP_TAIL(bitmap, nbits) != 0))
return false; return false;
}
return true; return true;
} }
#undef BYTE
#undef WORD
#undef BIT
#undef BYTES
#undef BITS
#endif /* CCAN_BITMAP_H_ */ #endif /* CCAN_BITMAP_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment