minor api cleanup for ghash/edgehash

- use single inlined lookup function.
- move comments into source.
- pack iterator vars more efficiently.
This commit is contained in:
Campbell Barton 2013-08-18 01:00:52 +00:00
parent fbb446dff6
commit ee2d95f850
4 changed files with 120 additions and 94 deletions

@ -42,61 +42,21 @@ enum {
EdgeHash *BLI_edgehash_new(void); EdgeHash *BLI_edgehash_new(void);
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp); void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp);
/* Insert edge (v0,v1) into hash with given value, does
* not check for duplicates.
*/
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val); void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val);
/* Return value for given edge (v0,v1), or NULL if
* if key does not exist in hash. (If need exists
* to differentiate between key-value being NULL and
* lack of key then see BLI_edgehash_lookup_p().
*/
void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1); void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1);
/* Return pointer to value for given edge (v0,v1),
* or NULL if key does not exist in hash.
*/
void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1); void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1);
/* Return boolean true/false if edge (v0,v1) in hash. */
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1); bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1);
/* Return number of keys in hash. */
int BLI_edgehash_size(EdgeHash *eh); int BLI_edgehash_size(EdgeHash *eh);
/* Remove all edges from hash. */
void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp); void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp);
void BLI_edgehash_flag_set(EdgeHash *eh, unsigned short flag); void BLI_edgehash_flag_set(EdgeHash *eh, unsigned short flag);
void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned short flag); void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned short flag);
/***/
/**
* Create a new EdgeHashIterator. The hash table must not be mutated
* while the iterator is in use, and the iterator will step exactly
* BLI_edgehash_size(gh) times before becoming done.
*/
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh); EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh);
/* Free an EdgeHashIterator. */
void BLI_edgehashIterator_free(EdgeHashIterator *ehi); void BLI_edgehashIterator_free(EdgeHashIterator *ehi);
/* Retrieve the key from an iterator. */
void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r); void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r);
/* Retrieve the value from an iterator. */
void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi); void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi);
/* Set the value for an iterator. */
void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val); void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val);
/* Steps the iterator to the next index. */
void BLI_edgehashIterator_step(EdgeHashIterator *ehi); void BLI_edgehashIterator_step(EdgeHashIterator *ehi);
/* Determine if an iterator is done. */
bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi); bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi);
#endif #endif

@ -46,8 +46,8 @@ typedef struct GHash GHash;
typedef struct GHashIterator { typedef struct GHashIterator {
GHash *gh; GHash *gh;
unsigned int curBucket;
struct Entry *curEntry; struct Entry *curEntry;
unsigned int curBucket;
} GHashIterator; } GHashIterator;
enum { enum {
@ -60,6 +60,7 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info);
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_insert(GHash *gh, void *key, void *val); void BLI_ghash_insert(GHash *gh, void *key, void *val);
void *BLI_ghash_lookup(GHash *gh, const void *key); void *BLI_ghash_lookup(GHash *gh, const void *key);
void **BLI_ghash_lookup_p(GHash *gh, const void *key);
bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp);

@ -23,12 +23,13 @@
* Contributor(s): none yet. * Contributor(s): none yet.
* *
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
* A general (pointer -> pointer) hash table ADT
*/ */
/** \file blender/blenlib/intern/BLI_ghash.c /** \file blender/blenlib/intern/BLI_ghash.c
* \ingroup bli * \ingroup bli
* *
* A general (pointer -> pointer) hash table ADT
*
* \note edgehash.c is based on this, make sure they stay in sync. * \note edgehash.c is based on this, make sure they stay in sync.
*/ */
@ -138,19 +139,31 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val)
} }
} }
void *BLI_ghash_lookup(GHash *gh, const void *key) BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key)
{ {
const unsigned int hash = gh->hashfp(key) % gh->nbuckets; const unsigned int hash = gh->hashfp(key) % gh->nbuckets;
Entry *e; Entry *e;
for (e = gh->buckets[hash]; e; e = e->next) { for (e = gh->buckets[hash]; e; e = e->next) {
if (gh->cmpfp(key, e->key) == 0) { if (gh->cmpfp(key, e->key) == 0) {
return e->val; return e;
} }
} }
return NULL; return NULL;
} }
void *BLI_ghash_lookup(GHash *gh, const void *key)
{
Entry *e = ghash_lookup_entry(gh, key);
return e ? e->val : NULL;
}
void **BLI_ghash_lookup_p(GHash *gh, const void *key)
{
Entry *e = ghash_lookup_entry(gh, key);
return e ? &e->val : NULL;
}
bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{ {
unsigned int hash = gh->hashfp(key) % gh->nbuckets; unsigned int hash = gh->hashfp(key) % gh->nbuckets;
@ -179,33 +192,6 @@ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFr
return false; return false;
} }
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
unsigned int i;
if (keyfreefp || valfreefp) {
for (i = 0; i < gh->nbuckets; i++) {
Entry *e;
for (e = gh->buckets[i]; e; ) {
Entry *n = e->next;
if (keyfreefp) keyfreefp(e->key);
if (valfreefp) valfreefp(e->val);
e = n;
}
}
}
gh->cursize = 0;
gh->nentries = 0;
gh->nbuckets = hashsizes[gh->cursize];
MEM_freeN(gh->buckets);
gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
}
/* same as above but return the value, /* same as above but return the value,
* no free value argument since it will be returned */ * no free value argument since it will be returned */
void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
@ -238,14 +224,34 @@ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
bool BLI_ghash_haskey(GHash *gh, const void *key) bool BLI_ghash_haskey(GHash *gh, const void *key)
{ {
unsigned int hash = gh->hashfp(key) % gh->nbuckets; return (ghash_lookup_entry(gh, key) != NULL);
}
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
unsigned int i;
if (keyfreefp || valfreefp) {
for (i = 0; i < gh->nbuckets; i++) {
Entry *e; Entry *e;
for (e = gh->buckets[hash]; e; e = e->next) for (e = gh->buckets[i]; e; ) {
if (gh->cmpfp(key, e->key) == 0) Entry *n = e->next;
return true;
return false; if (keyfreefp) keyfreefp(e->key);
if (valfreefp) valfreefp(e->val);
e = n;
}
}
}
gh->cursize = 0;
gh->nentries = 0;
gh->nbuckets = hashsizes[gh->cursize];
MEM_freeN(gh->buckets);
gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
} }
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)

@ -18,12 +18,13 @@
* Contributor(s): Daniel Dunbar, Joseph Eagar * Contributor(s): Daniel Dunbar, Joseph Eagar
* *
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
* A general (pointer -> pointer) hash table ADT
*/ */
/** \file blender/blenlib/intern/edgehash.c /** \file blender/blenlib/intern/edgehash.c
* \ingroup bli * \ingroup bli
* *
* A general (pointer -> pointer) hash table ADT
*
* \note Based on 'BLI_ghash.c', make sure these stay in sync. * \note Based on 'BLI_ghash.c', make sure these stay in sync.
*/ */
@ -66,12 +67,11 @@ static const unsigned int _ehash_hashsizes[] = {
/***/ /***/
typedef struct EdgeEntry EdgeEntry; typedef struct EdgeEntry {
struct EdgeEntry { struct EdgeEntry *next;
EdgeEntry *next;
unsigned int v0, v1; unsigned int v0, v1;
void *val; void *val;
}; } EdgeEntry;
struct EdgeHash { struct EdgeHash {
EdgeEntry **buckets; EdgeEntry **buckets;
@ -80,7 +80,9 @@ struct EdgeHash {
unsigned short cursize, flag; unsigned short cursize, flag;
}; };
/***/
/* -------------------------------------------------------------------- */
/* EdgeHash API */
EdgeHash *BLI_edgehash_new(void) EdgeHash *BLI_edgehash_new(void)
{ {
@ -95,7 +97,10 @@ EdgeHash *BLI_edgehash_new(void)
return eh; return eh;
} }
/**
* Insert edge (\a v0, \a v1) into hash with given value, does
* not check for duplicates.
*/
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val) void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
{ {
unsigned int hash; unsigned int hash;
@ -138,7 +143,7 @@ void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *v
} }
} }
void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) BLI_INLINE EdgeEntry *edgehash_lookup_entry(EdgeHash *eh, unsigned int v0, unsigned int v1)
{ {
unsigned int hash; unsigned int hash;
EdgeEntry *e; EdgeEntry *e;
@ -146,30 +151,55 @@ void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1)
EDGE_ORD(v0, v1); /* ensure v0 is smaller */ EDGE_ORD(v0, v1); /* ensure v0 is smaller */
hash = EDGE_HASH(v0, v1) % eh->nbuckets; hash = EDGE_HASH(v0, v1) % eh->nbuckets;
for (e = eh->buckets[hash]; e; e = e->next) for (e = eh->buckets[hash]; e; e = e->next) {
if (v0 == e->v0 && v1 == e->v1) if (v0 == e->v0 && v1 == e->v1) {
return &e->val; return e;
}
}
return NULL; return NULL;
} }
/**
* Return pointer to value for given edge (\a v0, \a v1),
* or NULL if key does not exist in hash.
*/
void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1)
{
EdgeEntry *e = edgehash_lookup_entry(eh, v0, v1);
return e ? &e->val : NULL;
}
/**
* Return value for given edge (\a v0, \a v1), or NULL if
* if key does not exist in hash. (If need exists
* to differentiate between key-value being NULL and
* lack of key then see BLI_edgehash_lookup_p().
*/
void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1)
{ {
void **value_p = BLI_edgehash_lookup_p(eh, v0, v1); EdgeEntry *e = edgehash_lookup_entry(eh, v0, v1);
return e ? e->val : NULL;
return value_p ? *value_p : NULL;
} }
/**
* Return boolean true/false if edge (v0,v1) in hash.
*/
bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1) bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1)
{ {
return BLI_edgehash_lookup_p(eh, v0, v1) != NULL; return (edgehash_lookup_entry(eh, v0, v1) != NULL);
} }
/**
* Return number of keys in hash.
*/
int BLI_edgehash_size(EdgeHash *eh) int BLI_edgehash_size(EdgeHash *eh)
{ {
return (int)eh->nentries; return (int)eh->nentries;
} }
/**
* Remove all edges from hash.
*/
void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp)
{ {
unsigned int i; unsigned int i;
@ -212,7 +242,9 @@ void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned short flag)
eh->flag &= (unsigned short)~flag; eh->flag &= (unsigned short)~flag;
} }
/***/
/* -------------------------------------------------------------------- */
/* EdgeHash Iterator API */
struct EdgeHashIterator { struct EdgeHashIterator {
EdgeHash *eh; EdgeHash *eh;
@ -220,6 +252,12 @@ struct EdgeHashIterator {
EdgeEntry *curEntry; EdgeEntry *curEntry;
}; };
/**
* Create a new EdgeHashIterator. The hash table must not be mutated
* while the iterator is in use, and the iterator will step exactly
* BLI_edgehash_size(gh) times before becoming done.
*/
EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
{ {
EdgeHashIterator *ehi = MEM_mallocN(sizeof(*ehi), "eh iter"); EdgeHashIterator *ehi = MEM_mallocN(sizeof(*ehi), "eh iter");
@ -234,11 +272,18 @@ EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh)
} }
return ehi; return ehi;
} }
/**
* Free an EdgeHashIterator.
*/
void BLI_edgehashIterator_free(EdgeHashIterator *ehi) void BLI_edgehashIterator_free(EdgeHashIterator *ehi)
{ {
MEM_freeN(ehi); MEM_freeN(ehi);
} }
/**
* Retrieve the key from an iterator.
*/
void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r) void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r)
{ {
if (ehi->curEntry) { if (ehi->curEntry) {
@ -246,11 +291,18 @@ void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsi
*v1_r = ehi->curEntry->v1; *v1_r = ehi->curEntry->v1;
} }
} }
/**
* Retrieve the value from an iterator.
*/
void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi)
{ {
return ehi->curEntry ? ehi->curEntry->val : NULL; return ehi->curEntry ? ehi->curEntry->val : NULL;
} }
/**
* Set the value for an iterator.
*/
void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val)
{ {
if (ehi->curEntry) { if (ehi->curEntry) {
@ -258,6 +310,9 @@ void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val)
} }
} }
/**
* Steps the iterator to the next index.
*/
void BLI_edgehashIterator_step(EdgeHashIterator *ehi) void BLI_edgehashIterator_step(EdgeHashIterator *ehi)
{ {
if (ehi->curEntry) { if (ehi->curEntry) {
@ -272,6 +327,10 @@ void BLI_edgehashIterator_step(EdgeHashIterator *ehi)
} }
} }
} }
/**
* Determine if an iterator is done.
*/
bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi) bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi)
{ {
return (ehi->curEntry == NULL); return (ehi->curEntry == NULL);