mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-31 12:00:38 +00:00
Remove hashset
This commit is contained in:
parent
46752af74b
commit
b47e3ebccf
2 changed files with 0 additions and 186 deletions
46
gmqcc.h
46
gmqcc.h
|
@ -380,14 +380,6 @@ typedef struct hash_table_t {
|
|||
struct hash_node_t **table;
|
||||
} hash_table_t, *ht;
|
||||
|
||||
typedef struct hash_set_t {
|
||||
size_t bits;
|
||||
size_t mask;
|
||||
size_t capacity;
|
||||
size_t *items;
|
||||
size_t total;
|
||||
} hash_set_t, *hs;
|
||||
|
||||
/*
|
||||
* hashtable implementation:
|
||||
*
|
||||
|
@ -430,44 +422,6 @@ void util_htrm (hash_table_t *ht, const char *key, void (*cb)(void*));
|
|||
void *util_htget (hash_table_t *ht, const char *key);
|
||||
void *util_htgeth(hash_table_t *ht, const char *key, size_t hash);
|
||||
|
||||
/*
|
||||
* hashset implementation:
|
||||
* This was designed for pointers: you manage the life of the object yourself
|
||||
* if you do use this for non-pointers please be warned that the object may not
|
||||
* be valid if the duration of it exceeds (i.e on stack). So you need to allocate
|
||||
* yourself, or put those in global scope to ensure duration is for the whole
|
||||
* runtime.
|
||||
*
|
||||
* util_hsnew() -- to make a new hashset
|
||||
* util_hsadd(set, key) -- to add something in the set
|
||||
* util_hshas(set, key) -- to check if something is in the set
|
||||
* util_hsrem(set, key) -- to remove something in the set
|
||||
* util_hsdel(set) -- to delete the set
|
||||
*
|
||||
* example of use:
|
||||
*
|
||||
* hs foo = util_hsnew();
|
||||
* char *bar = "hello blub\n";
|
||||
* char *baz = "hello dale\n";
|
||||
*
|
||||
* util_hsadd(foo, bar);
|
||||
* util_hsadd(foo, baz);
|
||||
* util_hsrem(foo, baz);
|
||||
*
|
||||
* printf("bar %d | baz %d\n",
|
||||
* util_hshas(foo, bar),
|
||||
* util_hshad(foo, baz)
|
||||
* );
|
||||
*
|
||||
* util_hsdel(foo);
|
||||
*/
|
||||
|
||||
hash_set_t *util_hsnew(void);
|
||||
int util_hsadd(hash_set_t *, void *);
|
||||
int util_hshas(hash_set_t *, void *);
|
||||
int util_hsrem(hash_set_t *, void *);
|
||||
void util_hsdel(hash_set_t *);
|
||||
|
||||
/*===================================================================*/
|
||||
/*============================ file.c ===============================*/
|
||||
/*===================================================================*/
|
||||
|
|
140
util.c
140
util.c
|
@ -670,146 +670,6 @@ void util_htdel(hash_table_t *ht) {
|
|||
util_htrem(ht, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* A basic implementation of a hash-set. Unlike a hashtable, a hash
|
||||
* set doesn't maintain key-value pairs. It simply maintains a key
|
||||
* that can be set, removed, and checked for.
|
||||
*
|
||||
* See EXPOSED interface comment below
|
||||
*/
|
||||
#define GMQCC_HASHSET_PRIME0 0x0049
|
||||
#define GMQCC_HASHSET_PRIME1 0x1391
|
||||
|
||||
static int util_hsput(hash_set_t *set, void *item) {
|
||||
size_t hash = (size_t)item; /* shouldn't drop the bits */
|
||||
size_t iter;
|
||||
|
||||
/* a == 0 || a == 1 */
|
||||
if (hash >> 1)
|
||||
return -1;
|
||||
|
||||
iter = set->mask & (GMQCC_HASHSET_PRIME0 * hash);
|
||||
|
||||
/* while (set->items[iter] != 0 && set->items[iter] != 1) */
|
||||
while (!(set->items[iter] >> 1)) {
|
||||
if (set->items[iter] == hash)
|
||||
return 0;
|
||||
|
||||
iter = set->mask & (iter + GMQCC_HASHSET_PRIME1);
|
||||
}
|
||||
|
||||
set->total ++;
|
||||
set->items[iter] = hash;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void util_hsupdate(hash_set_t *set) {
|
||||
size_t *old;
|
||||
size_t end;
|
||||
size_t itr;
|
||||
|
||||
/* time to rehash? */
|
||||
if ((float)set->total >= (size_t)((double)set->capacity * 0.85)) {
|
||||
old = set->items;
|
||||
end = set->capacity;
|
||||
|
||||
set->bits ++;
|
||||
set->capacity = (size_t)(1 << set->bits);
|
||||
set->mask = set->capacity - 1;
|
||||
set->items = (size_t*)mem_a(set->capacity * sizeof(size_t));
|
||||
set->total = 0;
|
||||
|
||||
/*assert(set->items);*/
|
||||
|
||||
/*
|
||||
* this shouldn't be slow? if so unroll it a little perhaps
|
||||
* (shouldn't be though)
|
||||
*/
|
||||
for (itr = 0; itr < end; itr++)
|
||||
util_hsput(set, (void*)old[itr]);
|
||||
|
||||
mem_d(old);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* EXPOSED interface: all of these functions are exposed to the outside
|
||||
* for use. The stuff above is static because it's the "internal" mechanics
|
||||
* for syncronizing the set for updating, and putting data into the set.
|
||||
*/
|
||||
int util_hsadd(hash_set_t *set, void *item) {
|
||||
int run = util_hsput(set, item); /* inlined */
|
||||
util_hsupdate(set);
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
/* remove item in set */
|
||||
int util_hsrem(hash_set_t *set, void *item) {
|
||||
size_t hash = (size_t)item;
|
||||
size_t iter = set->mask & (GMQCC_HASHSET_PRIME0 * hash);
|
||||
|
||||
while (set->items[iter]) {
|
||||
if (set->items[iter] == hash) {
|
||||
set->items[iter] = 1;
|
||||
set->total --;
|
||||
|
||||
return 1;
|
||||
}
|
||||
iter = set->mask & (iter + GMQCC_HASHSET_PRIME1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if item is set */
|
||||
int util_hshas(hash_set_t *set, void *item) {
|
||||
size_t hash = (size_t)item;
|
||||
size_t iter = set->mask & (GMQCC_HASHSET_PRIME0 * hash);
|
||||
|
||||
while (set->items[iter]) {
|
||||
if (set->items[iter] == hash)
|
||||
return 1;
|
||||
|
||||
iter = set->mask & (iter + GMQCC_HASHSET_PRIME1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
hash_set_t *util_hsnew(void) {
|
||||
hash_set_t *set;
|
||||
|
||||
if (!(set = (hash_set_t*)mem_a(sizeof(hash_set_t))))
|
||||
return NULL;
|
||||
|
||||
set->bits = 3;
|
||||
set->total = 0;
|
||||
set->capacity = (size_t)(1 << set->bits);
|
||||
set->mask = set->capacity - 1;
|
||||
set->items = (size_t*)mem_a(set->capacity * sizeof(size_t));
|
||||
|
||||
if (!set->items) {
|
||||
util_hsdel(set);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
void util_hsdel(hash_set_t *set) {
|
||||
if (!set) return;
|
||||
|
||||
if (set->items)
|
||||
mem_d(set->items);
|
||||
|
||||
mem_d(set);
|
||||
}
|
||||
#undef GMQCC_HASHSET_PRIME0
|
||||
#undef GMQCC_HASHSET_PRIME1
|
||||
|
||||
|
||||
/*
|
||||
* Portable implementation of vasprintf/asprintf. Assumes vsnprintf
|
||||
* exists, otherwise compiler error.
|
||||
|
|
Loading…
Reference in a new issue