mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
[util] Expose set_expand and fix an out-by-one bug
Having set_expand exposed is useful for loading data into a set. However, it turns out there was a bug in its size calculation in that when the requested set size was a multiple of SET_BITS (and greater than the current set size), the new set size one be SET_BITS larger than requested. There's now some tests for this :)
This commit is contained in:
parent
7995f59a90
commit
03921c03c5
3 changed files with 52 additions and 9 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
|
Loading…
Reference in a new issue