diff --git a/include/QF/set.h b/include/QF/set.h index 52b1fae85..61bd865aa 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -57,6 +57,10 @@ typedef uint32_t set_bits_t; #define SET_ONE ((set_bits_t) 1) #define SET_TEST_MEMBER(s, x) \ ((s)->map[(x) / SET_BITS] & (SET_ONE << ((x) % SET_BITS))) +#define SET_STATIC_INIT(x, alloc) { \ + .size = SET_SIZE (x), \ + .map = alloc (SET_SIZE (x) / 8), \ +} /** Represent a set using a bitmap. @@ -129,9 +133,11 @@ set_t *set_new_r (set_pool_t *set_pool); \param size The number of elements for which space is to be allocated. \return The newly created, empty set. + \note \a size is the actual amount of elements, not the number of the + highest element (ie, for values 0..n, size is n + 1). */ -set_t *set_new_size (int size); -set_t *set_new_size_r (set_pool_t *set_pool, int size); +set_t *set_new_size (unsigned size); +set_t *set_new_size_r (set_pool_t *set_pool, unsigned size); /** Delete a set that is no longer needed. @@ -140,6 +146,18 @@ set_t *set_new_size_r (set_pool_t *set_pool, int size); void set_delete (set_t *set); void set_delete_r (set_pool_t *set_pool, set_t *set); +/** Pre-expand a set with space for the specified element + + Has no effect if the set is already large enough to hold the specified + element. + + \param set The set to be expanded + \param size The minimum number of elements representable by the set + \note \a size is the actual amount of elements, not the number of the + highest element (ie, for values 0..n, size is n + 1). +*/ +void set_expand (set_t *set, unsigned size); + /** Add an element to a set. It is not an error to add an element that is already a member of the set. diff --git a/libs/util/set.c b/libs/util/set.c index 6b15154e8..869fcc74e 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -111,16 +111,15 @@ set_delete (set_t *set) set_delete_r (&static_set_pool, set); } -static void -set_expand (set_t *set, unsigned x) +void +set_expand (set_t *set, unsigned size) { set_bits_t *map = set->map; - size_t size; - if (x <= set->size) + if (size <= set->size) return; - size = SET_SIZE (x); + size = SET_SIZE (size - 1); set->map = malloc (size / 8); memcpy (set->map, map, set->size / 8); memset (set->map + SET_WORDS (set), 0, (size - set->size) / 8); @@ -130,7 +129,7 @@ set_expand (set_t *set, unsigned x) } inline set_t * -set_new_size_r (set_pool_t *set_pool, int size) +set_new_size_r (set_pool_t *set_pool, unsigned size) { set_t *set; @@ -141,7 +140,7 @@ set_new_size_r (set_pool_t *set_pool, int size) } set_t * -set_new_size (int size) +set_new_size (unsigned size) { return set_new_size_r (&static_set_pool, size); } diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index 3d2b5e6d6..e1b93d137 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -109,6 +109,27 @@ make_not_55 (void) return set_invert (make_55 ()); } +static set_t * +expand_3xSIZEm1 (set_t *set, const set_t *x) +{ + set_expand (set, 3 * SIZE - 1); + return set; +} + +static set_t * +expand_3xSIZEp1 (set_t *set, const set_t *x) +{ + set_expand (set, 3 * SIZE + 1); + return set; +} + +static set_t * +expand_3xSIZE (set_t *set, const set_t *x) +{ + set_expand (set, 3 * SIZE); + return set; +} + struct { setup_func set1; setup_func set2; @@ -135,6 +156,11 @@ struct { {make_0_to_SIZEm1, make_everything, set_reverse_difference, check_size, SIZE, "{64 ...}" }, + {make_SIZE, 0, expand_3xSIZEm1, check_size, 3 * SIZE, + "{64}"}, + {make_SIZE, 0, expand_3xSIZE, check_size, 3 * SIZE, "{64}"}, + {make_SIZE, 0, expand_3xSIZEp1, check_size, + 3 * SIZE + SET_BITS, "{64}"}, {make_everything, make_empty, 0, set_is_subset, 1, 0}, {make_everything, make_empty, 0, set_is_equivalent, 0, 0}, {make_everything, make_empty, 0, set_is_intersecting, 0, 0},