From ee2d95f8507a46a8ac025582c1b6188ff9468046 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 18 Aug 2013 01:00:52 +0000 Subject: [PATCH] minor api cleanup for ghash/edgehash - use single inlined lookup function. - move comments into source. - pack iterator vars more efficiently. --- source/blender/blenlib/BLI_edgehash.h | 40 ---------- source/blender/blenlib/BLI_ghash.h | 3 +- source/blender/blenlib/intern/BLI_ghash.c | 78 ++++++++++--------- source/blender/blenlib/intern/edgehash.c | 93 ++++++++++++++++++----- 4 files changed, 120 insertions(+), 94 deletions(-) diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h index 5d945bb9efc..094a10eb25f 100644 --- a/source/blender/blenlib/BLI_edgehash.h +++ b/source/blender/blenlib/BLI_edgehash.h @@ -42,61 +42,21 @@ enum { EdgeHash *BLI_edgehash_new(void); 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); - -/* 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); - -/* 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); - -/* Return boolean true/false if edge (v0,v1) in hash. */ bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1); - -/* Return number of keys in hash. */ int BLI_edgehash_size(EdgeHash *eh); - -/* Remove all edges from hash. */ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp); - void BLI_edgehash_flag_set(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); - -/* Free an EdgeHashIterator. */ 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); - -/* Retrieve the value from an iterator. */ void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi); - -/* Set the value for an iterator. */ void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val); - -/* Steps the iterator to the next index. */ void BLI_edgehashIterator_step(EdgeHashIterator *ehi); - -/* Determine if an iterator is done. */ bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi); #endif diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index d914c32664d..235afb7c8fe 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -46,8 +46,8 @@ typedef struct GHash GHash; typedef struct GHashIterator { GHash *gh; - unsigned int curBucket; struct Entry *curEntry; + unsigned int curBucket; } GHashIterator; 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_insert(GHash *gh, void *key, void *val); 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); void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 50d52a299a7..da886e59c21 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -23,12 +23,13 @@ * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** - * A general (pointer -> pointer) hash table ADT */ /** \file blender/blenlib/intern/BLI_ghash.c * \ingroup bli * + * A general (pointer -> pointer) hash table ADT + * * \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; Entry *e; for (e = gh->buckets[hash]; e; e = e->next) { if (gh->cmpfp(key, e->key) == 0) { - return e->val; + return e; } } 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) { 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; } -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, * no free value argument since it will be returned */ 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) { - unsigned int hash = gh->hashfp(key) % gh->nbuckets; - Entry *e; + return (ghash_lookup_entry(gh, key) != NULL); +} - for (e = gh->buckets[hash]; e; e = e->next) - if (gh->cmpfp(key, e->key) == 0) - return true; +void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +{ + unsigned int i; - return false; + 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"); } void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index d3ce9bb4857..cad6271aa68 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -18,12 +18,13 @@ * Contributor(s): Daniel Dunbar, Joseph Eagar * * ***** END GPL LICENSE BLOCK ***** - * A general (pointer -> pointer) hash table ADT */ /** \file blender/blenlib/intern/edgehash.c * \ingroup bli * + * A general (pointer -> pointer) hash table ADT + * * \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; -struct EdgeEntry { - EdgeEntry *next; +typedef struct EdgeEntry { + struct EdgeEntry *next; unsigned int v0, v1; void *val; -}; +} EdgeEntry; struct EdgeHash { EdgeEntry **buckets; @@ -80,7 +80,9 @@ struct EdgeHash { unsigned short cursize, flag; }; -/***/ + +/* -------------------------------------------------------------------- */ +/* EdgeHash API */ EdgeHash *BLI_edgehash_new(void) { @@ -95,7 +97,10 @@ EdgeHash *BLI_edgehash_new(void) 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) { 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; 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 */ hash = EDGE_HASH(v0, v1) % eh->nbuckets; - for (e = eh->buckets[hash]; e; e = e->next) - if (v0 == e->v0 && v1 == e->v1) - return &e->val; - + for (e = eh->buckets[hash]; e; e = e->next) { + if (v0 == e->v0 && v1 == e->v1) { + return e; + } + } 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 **value_p = BLI_edgehash_lookup_p(eh, v0, v1); - - return value_p ? *value_p : NULL; + EdgeEntry *e = edgehash_lookup_entry(eh, v0, v1); + return e ? e->val : NULL; } +/** + * Return boolean true/false if edge (v0,v1) in hash. + */ 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) { return (int)eh->nentries; } +/** + * Remove all edges from hash. + */ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) { unsigned int i; @@ -212,7 +242,9 @@ void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned short flag) eh->flag &= (unsigned short)~flag; } -/***/ + +/* -------------------------------------------------------------------- */ +/* EdgeHash Iterator API */ struct EdgeHashIterator { EdgeHash *eh; @@ -220,6 +252,12 @@ struct EdgeHashIterator { 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 *ehi = MEM_mallocN(sizeof(*ehi), "eh iter"); @@ -234,11 +272,18 @@ EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) } return ehi; } + +/** + * Free an EdgeHashIterator. + */ void BLI_edgehashIterator_free(EdgeHashIterator *ehi) { MEM_freeN(ehi); } +/** + * Retrieve the key from an iterator. + */ void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r) { if (ehi->curEntry) { @@ -246,11 +291,18 @@ void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsi *v1_r = ehi->curEntry->v1; } } + +/** + * Retrieve the value from an iterator. + */ void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) { return ehi->curEntry ? ehi->curEntry->val : NULL; } +/** + * Set the value for an iterator. + */ void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) { 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) { 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) { return (ehi->curEntry == NULL);