add h_hashset_equal (set comparison)
This commit is contained in:
parent
976205f9da
commit
636f741d88
2 changed files with 53 additions and 0 deletions
|
|
@ -232,6 +232,7 @@ int h_hashtable_present(const HHashTable* ht, const void* key) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void h_hashtable_del(HHashTable* ht, const void* key) {
|
||||
HHashValue hashval = ht->hashFunc(key);
|
||||
#ifdef CONSISTENCY_CHECK
|
||||
|
|
@ -257,6 +258,7 @@ void h_hashtable_del(HHashTable* ht, const void* key) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void h_hashtable_free(HHashTable* ht) {
|
||||
for (size_t i = 0; i < ht->capacity; i++) {
|
||||
HHashTableEntry *hten, *hte = &ht->contents[i];
|
||||
|
|
@ -272,6 +274,56 @@ void h_hashtable_free(HHashTable* ht) {
|
|||
h_arena_free(ht->arena, ht->contents);
|
||||
}
|
||||
|
||||
// helper for hte_equal
|
||||
static bool hte_same_length(HHashTableEntry *xs, HHashTableEntry *ys) {
|
||||
for(; xs && ys; xs=xs->next, ys=ys->next) {
|
||||
// skip NULL keys (= element not present)
|
||||
if(xs->key == NULL) xs=xs->next;
|
||||
if(ys->key == NULL) ys=ys->next;
|
||||
}
|
||||
return (xs == ys); // both NULL
|
||||
}
|
||||
|
||||
// helper for hte_equal: are all elements of xs present in ys?
|
||||
static bool hte_subset(HEqualFunc eq, HHashTableEntry *xs, HHashTableEntry *ys)
|
||||
{
|
||||
for(; xs; xs=xs->next) {
|
||||
if(xs->key == NULL) continue; // element not present
|
||||
|
||||
HHashTableEntry *hte;
|
||||
for(hte=ys; hte; hte=hte->next) {
|
||||
if(hte->key == xs->key) break; // assume an element is equal to itself
|
||||
if(hte->hashval != xs->hashval) continue; // shortcut
|
||||
if(eq(hte->key, xs->key)) break;
|
||||
}
|
||||
if(hte == NULL) return false; // element not found
|
||||
}
|
||||
return true; // all found
|
||||
}
|
||||
|
||||
// compare two lists of HHashTableEntries
|
||||
static inline bool hte_equal(HEqualFunc eq, HHashTableEntry *xs, HHashTableEntry *ys) {
|
||||
return (hte_same_length(xs, ys) && hte_subset(eq, xs, ys));
|
||||
}
|
||||
|
||||
/* Set equality of HHashSets.
|
||||
* Obviously, 'a' and 'b' must use the same equality function.
|
||||
* Not strictly necessary, but we also assume the same hash function.
|
||||
*/
|
||||
bool h_hashset_equal(const HHashSet *a, const HHashSet *b) {
|
||||
if(a->capacity == b->capacity) {
|
||||
// iterate over the buckets in parallel
|
||||
for(size_t i=0; i < a->capacity; i++) {
|
||||
if(!hte_equal(a->equalFunc, &a->contents[i], &b->contents[i]))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
assert_message(0, "h_hashset_equal called on sets of different capacity");
|
||||
// TODO implement general case
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool h_eq_ptr(const void *p, const void *q) {
|
||||
return (p==q);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ typedef HHashTable HHashSet;
|
|||
#define h_hashset_empty(ht) h_hashtable_empty(ht)
|
||||
#define h_hashset_del(ht,el) h_hashtable_del(ht,el)
|
||||
#define h_hashset_free(ht) h_hashtable_free(ht)
|
||||
bool h_hashset_equal(const HHashSet *a, const HHashSet *b);
|
||||
|
||||
bool h_eq_ptr(const void *p, const void *q);
|
||||
HHashValue h_hash_ptr(const void *p);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue