Rusty Russell
6 years ago
9 changed files with 775 additions and 0 deletions
@ -0,0 +1 @@ |
|||||
|
../../licenses/LGPL-2.1 |
@ -0,0 +1,32 @@ |
|||||
|
#include "config.h" |
||||
|
#include <stdio.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
/** |
||||
|
* bitmap - bitmap handling |
||||
|
* |
||||
|
* This code handles manipulation of bitmaps, arbitrary length arrays |
||||
|
* of bits. |
||||
|
* |
||||
|
* License: LGPL (v2.1 or any later version) |
||||
|
* Author: David Gibson <david@gibson.dropbear.id.au> |
||||
|
*/ |
||||
|
int main(int argc, char *argv[]) |
||||
|
{ |
||||
|
/* Expect exactly one argument */ |
||||
|
if (argc != 2) |
||||
|
return 1; |
||||
|
|
||||
|
if (strcmp(argv[1], "depends") == 0) { |
||||
|
printf("ccan/endian\n"); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
if (strcmp(argv[1], "testdepends") == 0) { |
||||
|
printf("ccan/array_size\n"); |
||||
|
printf("ccan/foreach\n"); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
return 1; |
||||
|
} |
@ -0,0 +1,125 @@ |
|||||
|
/* Licensed under LGPLv2.1+ - see LICENSE file for details */ |
||||
|
|
||||
|
#include "config.h" |
||||
|
|
||||
|
#include <ccan/bitmap/bitmap.h> |
||||
|
|
||||
|
#include <assert.h> |
||||
|
|
||||
|
#define BIT_ALIGN_DOWN(n) ((n) & ~(BITMAP_WORD_BITS - 1)) |
||||
|
#define BIT_ALIGN_UP(n) BIT_ALIGN_DOWN((n) + BITMAP_WORD_BITS - 1) |
||||
|
|
||||
|
void bitmap_zero_range(bitmap *bitmap, unsigned long n, unsigned long m) |
||||
|
{ |
||||
|
unsigned long an = BIT_ALIGN_UP(n); |
||||
|
unsigned long am = BIT_ALIGN_DOWN(m); |
||||
|
bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS); |
||||
|
bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS)); |
||||
|
|
||||
|
assert(m >= n); |
||||
|
|
||||
|
if (am < an) { |
||||
|
BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask & tailmask); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (an > n) |
||||
|
BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask); |
||||
|
|
||||
|
if (am > an) |
||||
|
memset(&BITMAP_WORD(bitmap, an), 0, |
||||
|
(am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word)); |
||||
|
|
||||
|
if (m > am) |
||||
|
BITMAP_WORD(bitmap, m) &= ~bitmap_bswap(tailmask); |
||||
|
} |
||||
|
|
||||
|
void bitmap_fill_range(bitmap *bitmap, unsigned long n, unsigned long m) |
||||
|
{ |
||||
|
unsigned long an = BIT_ALIGN_UP(n); |
||||
|
unsigned long am = BIT_ALIGN_DOWN(m); |
||||
|
bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS); |
||||
|
bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS)); |
||||
|
|
||||
|
assert(m >= n); |
||||
|
|
||||
|
if (am < an) { |
||||
|
BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask & tailmask); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (an > n) |
||||
|
BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask); |
||||
|
|
||||
|
if (am > an) |
||||
|
memset(&BITMAP_WORD(bitmap, an), 0xff, |
||||
|
(am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word)); |
||||
|
|
||||
|
if (m > am) |
||||
|
BITMAP_WORD(bitmap, m) |= bitmap_bswap(tailmask); |
||||
|
} |
||||
|
|
||||
|
static int bitmap_clz(bitmap_word w) |
||||
|
{ |
||||
|
#if HAVE_BUILTIN_CLZL |
||||
|
return __builtin_clzl(w); |
||||
|
#else |
||||
|
int lz = 0; |
||||
|
bitmap_word mask = 1UL << (BITMAP_WORD_BITS - 1); |
||||
|
|
||||
|
while (!(w & mask)) { |
||||
|
lz++; |
||||
|
mask >>= 1; |
||||
|
} |
||||
|
|
||||
|
return lz; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
unsigned long bitmap_ffs(const bitmap *bitmap, |
||||
|
unsigned long n, unsigned long m) |
||||
|
{ |
||||
|
unsigned long an = BIT_ALIGN_UP(n); |
||||
|
unsigned long am = BIT_ALIGN_DOWN(m); |
||||
|
bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS); |
||||
|
bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS)); |
||||
|
|
||||
|
assert(m >= n); |
||||
|
|
||||
|
if (am < an) { |
||||
|
bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, n)); |
||||
|
|
||||
|
w &= (headmask & tailmask); |
||||
|
|
||||
|
return w ? am + bitmap_clz(w) : m; |
||||
|
} |
||||
|
|
||||
|
if (an > n) { |
||||
|
bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, n)); |
||||
|
|
||||
|
w &= headmask; |
||||
|
|
||||
|
if (w) |
||||
|
return BIT_ALIGN_DOWN(n) + bitmap_clz(w); |
||||
|
} |
||||
|
|
||||
|
while (an < am) { |
||||
|
bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, an)); |
||||
|
|
||||
|
if (w) |
||||
|
return an + bitmap_clz(w); |
||||
|
|
||||
|
an += BITMAP_WORD_BITS; |
||||
|
} |
||||
|
|
||||
|
if (m > am) { |
||||
|
bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, m)); |
||||
|
|
||||
|
w &= tailmask; |
||||
|
|
||||
|
if (w) |
||||
|
return am + bitmap_clz(w); |
||||
|
} |
||||
|
|
||||
|
return m; |
||||
|
} |
@ -0,0 +1,243 @@ |
|||||
|
/* Licensed under LGPLv2+ - see LICENSE file for details */ |
||||
|
#ifndef CCAN_BITMAP_H_ |
||||
|
#define CCAN_BITMAP_H_ |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
#include <limits.h> |
||||
|
|
||||
|
#include <ccan/endian/endian.h> |
||||
|
|
||||
|
typedef unsigned long bitmap_word; |
||||
|
|
||||
|
#define BITMAP_WORD_BITS (sizeof(bitmap_word) * CHAR_BIT) |
||||
|
#define BITMAP_NWORDS(_n) \ |
||||
|
(((_n) + BITMAP_WORD_BITS - 1) / BITMAP_WORD_BITS) |
||||
|
|
||||
|
/*
|
||||
|
* We wrap each word in a structure for type checking. |
||||
|
*/ |
||||
|
typedef struct { |
||||
|
bitmap_word w; |
||||
|
} bitmap; |
||||
|
|
||||
|
#define BITMAP_DECLARE(_name, _nbits) \ |
||||
|
bitmap (_name)[BITMAP_NWORDS(_nbits)] |
||||
|
|
||||
|
static inline size_t bitmap_sizeof(unsigned long nbits) |
||||
|
{ |
||||
|
return BITMAP_NWORDS(nbits) * sizeof(bitmap_word); |
||||
|
} |
||||
|
|
||||
|
static inline bitmap_word bitmap_bswap(bitmap_word w) |
||||
|
{ |
||||
|
if (BITMAP_WORD_BITS == 32) |
||||
|
return (ENDIAN_CAST bitmap_word)cpu_to_be32(w); |
||||
|
else if (BITMAP_WORD_BITS == 64) |
||||
|
return (ENDIAN_CAST bitmap_word)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 BITMAP_HEADWORDS(_nbits) \ |
||||
|
((_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, unsigned long n) |
||||
|
{ |
||||
|
BITMAP_WORD(bitmap, n) |= BITMAP_WORDBIT(n); |
||||
|
} |
||||
|
|
||||
|
static inline void bitmap_clear_bit(bitmap *bitmap, unsigned long n) |
||||
|
{ |
||||
|
BITMAP_WORD(bitmap, n) &= ~BITMAP_WORDBIT(n); |
||||
|
} |
||||
|
|
||||
|
static inline void bitmap_change_bit(bitmap *bitmap, unsigned long n) |
||||
|
{ |
||||
|
BITMAP_WORD(bitmap, n) ^= BITMAP_WORDBIT(n); |
||||
|
} |
||||
|
|
||||
|
static inline bool bitmap_test_bit(const bitmap *bitmap, unsigned long n) |
||||
|
{ |
||||
|
return !!(BITMAP_WORD(bitmap, n) & BITMAP_WORDBIT(n)); |
||||
|
} |
||||
|
|
||||
|
void bitmap_zero_range(bitmap *bitmap, unsigned long n, unsigned long m); |
||||
|
void bitmap_fill_range(bitmap *bitmap, unsigned long n, unsigned long m); |
||||
|
|
||||
|
static inline void bitmap_zero(bitmap *bitmap, unsigned long nbits) |
||||
|
{ |
||||
|
memset(bitmap, 0, bitmap_sizeof(nbits)); |
||||
|
} |
||||
|
|
||||
|
static inline void bitmap_fill(bitmap *bitmap, unsigned long nbits) |
||||
|
{ |
||||
|
memset(bitmap, 0xff, bitmap_sizeof(nbits)); |
||||
|
} |
||||
|
|
||||
|
static inline void bitmap_copy(bitmap *dst, const bitmap *src, |
||||
|
unsigned long nbits) |
||||
|
{ |
||||
|
memcpy(dst, src, bitmap_sizeof(nbits)); |
||||
|
} |
||||
|
|
||||
|
#define BITMAP_DEF_BINOP(_name, _op) \ |
||||
|
static inline void bitmap_##_name(bitmap *dst, bitmap *src1, bitmap *src2, \ |
||||
|
unsigned long nbits) \ |
||||
|
{ \ |
||||
|
unsigned long i = 0; \ |
||||
|
for (i = 0; i < BITMAP_NWORDS(nbits); i++) { \ |
||||
|
dst[i].w = src1[i].w _op src2[i].w; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
BITMAP_DEF_BINOP(and, &) |
||||
|
BITMAP_DEF_BINOP(or, |) |
||||
|
BITMAP_DEF_BINOP(xor, ^) |
||||
|
BITMAP_DEF_BINOP(andnot, & ~) |
||||
|
|
||||
|
#undef BITMAP_DEF_BINOP |
||||
|
|
||||
|
static inline void bitmap_complement(bitmap *dst, const bitmap *src, |
||||
|
unsigned long nbits) |
||||
|
{ |
||||
|
unsigned long i; |
||||
|
|
||||
|
for (i = 0; i < BITMAP_NWORDS(nbits); i++) |
||||
|
dst[i].w = ~src[i].w; |
||||
|
} |
||||
|
|
||||
|
static inline bool bitmap_equal(const bitmap *src1, const bitmap *src2, |
||||
|
unsigned long nbits) |
||||
|
{ |
||||
|
return (memcmp(src1, src2, BITMAP_HEADBYTES(nbits)) == 0) |
||||
|
&& (!BITMAP_HASTAIL(nbits) |
||||
|
|| (BITMAP_TAIL(src1, nbits) == BITMAP_TAIL(src2, nbits))); |
||||
|
} |
||||
|
|
||||
|
static inline bool bitmap_intersects(const bitmap *src1, const bitmap *src2, |
||||
|
unsigned long nbits) |
||||
|
{ |
||||
|
unsigned long i; |
||||
|
|
||||
|
for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) { |
||||
|
if (src1[i].w & src2[i].w) |
||||
|
return true; |
||||
|
} |
||||
|
if (BITMAP_HASTAIL(nbits) && |
||||
|
(BITMAP_TAIL(src1, nbits) & BITMAP_TAIL(src2, nbits))) |
||||
|
return true; |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
static inline bool bitmap_subset(const bitmap *src1, const bitmap *src2, |
||||
|
unsigned long nbits) |
||||
|
{ |
||||
|
unsigned long i; |
||||
|
|
||||
|
for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) { |
||||
|
if (src1[i].w & ~src2[i].w) |
||||
|
return false; |
||||
|
} |
||||
|
if (BITMAP_HASTAIL(nbits) && |
||||
|
(BITMAP_TAIL(src1, nbits) & ~BITMAP_TAIL(src2, nbits))) |
||||
|
return false; |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
static inline bool bitmap_full(const bitmap *bitmap, unsigned long nbits) |
||||
|
{ |
||||
|
unsigned long i; |
||||
|
|
||||
|
for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) { |
||||
|
if (bitmap[i].w != -1UL) |
||||
|
return false; |
||||
|
} |
||||
|
if (BITMAP_HASTAIL(nbits) && |
||||
|
(BITMAP_TAIL(bitmap, nbits) != BITMAP_TAILBITS(nbits))) |
||||
|
return false; |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
static inline bool bitmap_empty(const bitmap *bitmap, unsigned long nbits) |
||||
|
{ |
||||
|
unsigned long i; |
||||
|
|
||||
|
for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) { |
||||
|
if (bitmap[i].w != 0) |
||||
|
return false; |
||||
|
} |
||||
|
if (BITMAP_HASTAIL(nbits) && (BITMAP_TAIL(bitmap, nbits) != 0)) |
||||
|
return false; |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
unsigned long bitmap_ffs(const bitmap *bitmap, |
||||
|
unsigned long n, unsigned long m); |
||||
|
|
||||
|
/*
|
||||
|
* Allocation functions |
||||
|
*/ |
||||
|
static inline bitmap *bitmap_alloc(unsigned long nbits) |
||||
|
{ |
||||
|
return malloc(bitmap_sizeof(nbits)); |
||||
|
} |
||||
|
|
||||
|
static inline bitmap *bitmap_alloc0(unsigned long nbits) |
||||
|
{ |
||||
|
bitmap *bitmap; |
||||
|
|
||||
|
bitmap = bitmap_alloc(nbits); |
||||
|
if (bitmap) |
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
return bitmap; |
||||
|
} |
||||
|
|
||||
|
static inline bitmap *bitmap_alloc1(unsigned long nbits) |
||||
|
{ |
||||
|
bitmap *bitmap; |
||||
|
|
||||
|
bitmap = bitmap_alloc(nbits); |
||||
|
if (bitmap) |
||||
|
bitmap_fill(bitmap, nbits); |
||||
|
return bitmap; |
||||
|
} |
||||
|
|
||||
|
static inline bitmap *bitmap_realloc0(bitmap *bitmap, |
||||
|
unsigned long obits, unsigned long nbits) |
||||
|
{ |
||||
|
bitmap = realloc(bitmap, bitmap_sizeof(nbits)); |
||||
|
|
||||
|
if ((nbits > obits) && bitmap) |
||||
|
bitmap_zero_range(bitmap, obits, nbits); |
||||
|
|
||||
|
return bitmap; |
||||
|
} |
||||
|
|
||||
|
static inline bitmap *bitmap_realloc1(bitmap *bitmap, |
||||
|
unsigned long obits, unsigned long nbits) |
||||
|
{ |
||||
|
bitmap = realloc(bitmap, bitmap_sizeof(nbits)); |
||||
|
|
||||
|
if ((nbits > obits) && bitmap) |
||||
|
bitmap_fill_range(bitmap, obits, nbits); |
||||
|
|
||||
|
return bitmap; |
||||
|
} |
||||
|
|
||||
|
#endif /* CCAN_BITMAP_H_ */ |
@ -0,0 +1,101 @@ |
|||||
|
#include <ccan/bitmap/bitmap.h> |
||||
|
#include <ccan/tap/tap.h> |
||||
|
#include <ccan/array_size/array_size.h> |
||||
|
#include <ccan/foreach/foreach.h> |
||||
|
|
||||
|
#include <ccan/bitmap/bitmap.c> |
||||
|
|
||||
|
int bitmap_sizes[] = { |
||||
|
1, 2, 3, 4, 5, 6, 7, 8, |
||||
|
16, 17, 24, 32, 33, |
||||
|
64, 65, 127, 128, 129, |
||||
|
1023, 1024, 1025, |
||||
|
}; |
||||
|
#define NSIZES ARRAY_SIZE(bitmap_sizes) |
||||
|
#define NTESTS_BASE 4 |
||||
|
#define NTESTS_REALLOC 10 |
||||
|
|
||||
|
static void test_basic_alloc(int nbits) |
||||
|
{ |
||||
|
bitmap *bitmap; |
||||
|
|
||||
|
bitmap = bitmap_alloc0(nbits); |
||||
|
ok1(bitmap != NULL); |
||||
|
ok1(bitmap_empty(bitmap, nbits)); |
||||
|
|
||||
|
free(bitmap); |
||||
|
|
||||
|
bitmap = bitmap_alloc1(nbits); |
||||
|
ok1(bitmap != NULL); |
||||
|
ok1(bitmap_full(bitmap, nbits)); |
||||
|
|
||||
|
free(bitmap); |
||||
|
} |
||||
|
|
||||
|
static void test_realloc(int obits, int nbits) |
||||
|
{ |
||||
|
bitmap *bitmap; |
||||
|
int i; |
||||
|
bool wrong; |
||||
|
|
||||
|
bitmap = bitmap_alloc0(obits); |
||||
|
ok1(bitmap != NULL); |
||||
|
ok1(bitmap_empty(bitmap, obits)); |
||||
|
|
||||
|
bitmap = bitmap_realloc1(bitmap, obits, nbits); |
||||
|
ok1(bitmap != NULL); |
||||
|
if (obits < nbits) |
||||
|
ok1(bitmap_empty(bitmap, obits)); |
||||
|
else |
||||
|
ok1(bitmap_empty(bitmap, nbits)); |
||||
|
|
||||
|
wrong = false; |
||||
|
for (i = obits; i < nbits; i++) |
||||
|
wrong = wrong || !bitmap_test_bit(bitmap, i); |
||||
|
ok1(!wrong); |
||||
|
|
||||
|
free(bitmap); |
||||
|
|
||||
|
bitmap = bitmap_alloc1(obits); |
||||
|
ok1(bitmap != NULL); |
||||
|
ok1(bitmap_full(bitmap, obits)); |
||||
|
|
||||
|
bitmap = bitmap_realloc0(bitmap, obits, nbits); |
||||
|
ok1(bitmap != NULL); |
||||
|
if (obits < nbits) |
||||
|
ok1(bitmap_full(bitmap, obits)); |
||||
|
else |
||||
|
ok1(bitmap_full(bitmap, nbits)); |
||||
|
|
||||
|
wrong = false; |
||||
|
for (i = obits; i < nbits; i++) |
||||
|
wrong = wrong || bitmap_test_bit(bitmap, i); |
||||
|
ok1(!wrong); |
||||
|
|
||||
|
free(bitmap); |
||||
|
} |
||||
|
|
||||
|
int main(void) |
||||
|
{ |
||||
|
int i, j; |
||||
|
|
||||
|
/* This is how many tests you plan to run */ |
||||
|
plan_tests(NSIZES * NTESTS_BASE + NSIZES * NSIZES * NTESTS_REALLOC); |
||||
|
|
||||
|
for (i = 0; i < NSIZES; i++) { |
||||
|
diag("Testing %d-bit bitmap", bitmap_sizes[i]); |
||||
|
test_basic_alloc(bitmap_sizes[i]); |
||||
|
} |
||||
|
|
||||
|
for (i = 0; i < NSIZES; i++) { |
||||
|
for (j = 0; j < NSIZES; j++) { |
||||
|
diag("Testing %d-bit => %d-bit bitmap", |
||||
|
bitmap_sizes[i], bitmap_sizes[j]); |
||||
|
|
||||
|
test_realloc(bitmap_sizes[i], bitmap_sizes[j]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* This exits depending on whether all tests passed */ |
||||
|
return exit_status(); |
||||
|
} |
@ -0,0 +1,74 @@ |
|||||
|
#include <ccan/bitmap/bitmap.h> |
||||
|
#include <ccan/tap/tap.h> |
||||
|
#include <ccan/array_size/array_size.h> |
||||
|
#include <ccan/foreach/foreach.h> |
||||
|
|
||||
|
#include <ccan/bitmap/bitmap.c> |
||||
|
|
||||
|
int bitmap_sizes[] = { |
||||
|
1, 2, 3, 4, 5, 6, 7, 8, |
||||
|
16, 17, 24, 32, 33, |
||||
|
64, 65, 127, 128, 129, |
||||
|
1023, 1024, 1025, |
||||
|
}; |
||||
|
#define NSIZES ARRAY_SIZE(bitmap_sizes) |
||||
|
|
||||
|
#define ok_eq(a, b) \ |
||||
|
ok((a) == (b), "%s [%u] == %s [%u]", \ |
||||
|
#a, (unsigned)(a), #b, (unsigned)(b)) |
||||
|
|
||||
|
static void test_size(int nbits) |
||||
|
{ |
||||
|
BITMAP_DECLARE(bitmap, nbits); |
||||
|
int i; |
||||
|
|
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
ok_eq(bitmap_ffs(bitmap, 0, nbits), nbits); |
||||
|
|
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
bitmap_set_bit(bitmap, i); |
||||
|
|
||||
|
ok_eq(bitmap_ffs(bitmap, 0, nbits), i); |
||||
|
ok_eq(bitmap_ffs(bitmap, i, nbits), i); |
||||
|
ok_eq(bitmap_ffs(bitmap, i + 1, nbits), nbits); |
||||
|
|
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
bitmap_fill_range(bitmap, i, nbits); |
||||
|
|
||||
|
ok_eq(bitmap_ffs(bitmap, 0, nbits), i); |
||||
|
ok_eq(bitmap_ffs(bitmap, i, nbits), i); |
||||
|
ok_eq(bitmap_ffs(bitmap, i + 1, nbits), (i + 1)); |
||||
|
ok_eq(bitmap_ffs(bitmap, nbits - 1, nbits), (nbits - 1)); |
||||
|
|
||||
|
if (i > 0) { |
||||
|
ok_eq(bitmap_ffs(bitmap, 0, i), i); |
||||
|
ok_eq(bitmap_ffs(bitmap, 0, i - 1), (i - 1)); |
||||
|
} |
||||
|
|
||||
|
if (i > 0) { |
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
bitmap_fill_range(bitmap, 0, i); |
||||
|
|
||||
|
ok_eq(bitmap_ffs(bitmap, 0, nbits), 0); |
||||
|
ok_eq(bitmap_ffs(bitmap, i - 1, nbits), (i - 1)); |
||||
|
ok_eq(bitmap_ffs(bitmap, i, nbits), nbits); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int main(void) |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
/* Too complicated to work out the exact number */ |
||||
|
plan_no_plan(); |
||||
|
|
||||
|
for (i = 0; i < NSIZES; i++) { |
||||
|
diag("Testing %d-bit bitmap", bitmap_sizes[i]); |
||||
|
test_size(bitmap_sizes[i]); |
||||
|
} |
||||
|
|
||||
|
/* This exits depending on whether all tests passed */ |
||||
|
return exit_status(); |
||||
|
} |
@ -0,0 +1,77 @@ |
|||||
|
#include <ccan/bitmap/bitmap.h> |
||||
|
#include <ccan/tap/tap.h> |
||||
|
#include <ccan/array_size/array_size.h> |
||||
|
#include <ccan/foreach/foreach.h> |
||||
|
|
||||
|
#include <ccan/bitmap/bitmap.c> |
||||
|
|
||||
|
int bitmap_sizes[] = { |
||||
|
1, 2, 3, 4, 5, 6, 7, 8, |
||||
|
16, 24, 32, 64, 256, |
||||
|
/*
|
||||
|
* Don't put too big sizes in here, or it will take forever to |
||||
|
* run under valgrind (the test is O(n^3)). |
||||
|
*/ |
||||
|
}; |
||||
|
#define NSIZES ARRAY_SIZE(bitmap_sizes) |
||||
|
#define NTESTS 2 |
||||
|
|
||||
|
static void test_size(int nbits) |
||||
|
{ |
||||
|
BITMAP_DECLARE(bitmap, nbits); |
||||
|
uint32_t marker = 0xdeadbeef; |
||||
|
int i, j, k; |
||||
|
bool wrong; |
||||
|
|
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
for (j = i; j <= nbits; j++) { |
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
bitmap_fill_range(bitmap, i, j); |
||||
|
|
||||
|
wrong = false; |
||||
|
for (k = 0; k < nbits; k++) { |
||||
|
bool inrange = (k >= i) && (k < j); |
||||
|
wrong = wrong || (bitmap_test_bit(bitmap, k) != inrange); |
||||
|
} |
||||
|
ok1(!wrong); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
for (j = i; j <= nbits; j++) { |
||||
|
bitmap_fill(bitmap, nbits); |
||||
|
bitmap_zero_range(bitmap, i, j); |
||||
|
|
||||
|
wrong = false; |
||||
|
for (k = 0; k < nbits; k++) { |
||||
|
bool inrange = (k >= i) && (k < j); |
||||
|
wrong = wrong || (bitmap_test_bit(bitmap, k) == inrange); |
||||
|
} |
||||
|
ok1(!wrong); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ok1(marker == 0xdeadbeef); |
||||
|
} |
||||
|
|
||||
|
int main(void) |
||||
|
{ |
||||
|
int totaltests = 0; |
||||
|
int i; |
||||
|
|
||||
|
for (i = 0; i < NSIZES; i++) { |
||||
|
int size = bitmap_sizes[i]; |
||||
|
|
||||
|
/* Summing the arithmetic series gives: */ |
||||
|
totaltests += size*(size + 3) + 1; |
||||
|
} |
||||
|
plan_tests(totaltests); |
||||
|
|
||||
|
for (i = 0; i < NSIZES; i++) { |
||||
|
diag("Testing %d-bit bitmap", bitmap_sizes[i]); |
||||
|
test_size(bitmap_sizes[i]); |
||||
|
} |
||||
|
|
||||
|
/* This exits depending on whether all tests passed */ |
||||
|
return exit_status(); |
||||
|
} |
@ -0,0 +1,118 @@ |
|||||
|
#include <ccan/bitmap/bitmap.h> |
||||
|
#include <ccan/tap/tap.h> |
||||
|
#include <ccan/array_size/array_size.h> |
||||
|
#include <ccan/foreach/foreach.h> |
||||
|
|
||||
|
#include <ccan/bitmap/bitmap.c> |
||||
|
|
||||
|
int bitmap_sizes[] = { |
||||
|
1, 2, 3, 4, 5, 6, 7, 8, |
||||
|
16, 17, 24, 32, 33, |
||||
|
64, 65, 127, 128, 129, |
||||
|
1023, 1024, 1025, |
||||
|
}; |
||||
|
#define NSIZES ARRAY_SIZE(bitmap_sizes) |
||||
|
#define NTESTS 9 |
||||
|
|
||||
|
static void test_sizes(int nbits, bool dynalloc) |
||||
|
{ |
||||
|
BITMAP_DECLARE(sbitmap, nbits); |
||||
|
uint32_t marker; |
||||
|
bitmap *bitmap; |
||||
|
int i, j; |
||||
|
bool wrong; |
||||
|
|
||||
|
if (dynalloc) { |
||||
|
bitmap = bitmap_alloc(nbits); |
||||
|
ok1(bitmap != NULL); |
||||
|
} else { |
||||
|
bitmap = sbitmap; |
||||
|
marker = 0xdeadbeef; |
||||
|
} |
||||
|
|
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
wrong = false; |
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
wrong = wrong || bitmap_test_bit(bitmap, i); |
||||
|
} |
||||
|
ok1(!wrong); |
||||
|
|
||||
|
bitmap_fill(bitmap, nbits); |
||||
|
wrong = false; |
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
wrong = wrong || !bitmap_test_bit(bitmap, i); |
||||
|
} |
||||
|
ok1(!wrong); |
||||
|
|
||||
|
wrong = false; |
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
bitmap_set_bit(bitmap, i); |
||||
|
for (j = 0; j < nbits; j++) { |
||||
|
bool val = (i == j); |
||||
|
|
||||
|
wrong = wrong || (bitmap_test_bit(bitmap, j) != val); |
||||
|
} |
||||
|
} |
||||
|
ok1(!wrong); |
||||
|
|
||||
|
wrong = false; |
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
bitmap_fill(bitmap, nbits); |
||||
|
bitmap_clear_bit(bitmap, i); |
||||
|
for (j = 0; j < nbits; j++) { |
||||
|
bool val = !(i == j); |
||||
|
|
||||
|
wrong = wrong || (bitmap_test_bit(bitmap, j) != val); |
||||
|
} |
||||
|
} |
||||
|
ok1(!wrong); |
||||
|
|
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
ok1(bitmap_empty(bitmap, nbits)); |
||||
|
|
||||
|
wrong = false; |
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
bitmap_zero(bitmap, nbits); |
||||
|
bitmap_set_bit(bitmap, i); |
||||
|
wrong = wrong || bitmap_empty(bitmap, nbits); |
||||
|
} |
||||
|
ok1(!wrong); |
||||
|
|
||||
|
bitmap_fill(bitmap, nbits); |
||||
|
ok1(bitmap_full(bitmap, nbits)); |
||||
|
|
||||
|
wrong = false; |
||||
|
for (i = 0; i < nbits; i++) { |
||||
|
bitmap_fill(bitmap, nbits); |
||||
|
bitmap_clear_bit(bitmap, i); |
||||
|
wrong = wrong || bitmap_full(bitmap, nbits); |
||||
|
} |
||||
|
ok1(!wrong); |
||||
|
|
||||
|
if (dynalloc) { |
||||
|
free(bitmap); |
||||
|
} else { |
||||
|
ok1(marker == 0xdeadbeef); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int main(void) |
||||
|
{ |
||||
|
int i; |
||||
|
bool dynalloc; |
||||
|
|
||||
|
/* This is how many tests you plan to run */ |
||||
|
plan_tests(NSIZES * NTESTS * 2); |
||||
|
|
||||
|
for (i = 0; i < NSIZES; i++) { |
||||
|
foreach_int(dynalloc, false, true) { |
||||
|
diag("Testing %d-bit bitmap (%s allocation)", |
||||
|
bitmap_sizes[i], dynalloc ? "dynamic" : "static"); |
||||
|
test_sizes(bitmap_sizes[i], dynalloc); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* This exits depending on whether all tests passed */ |
||||
|
return exit_status(); |
||||
|
} |
Loading…
Reference in new issue