[Bf-blender-cvs] [5bced60] temp-ghash-experiments: GHash: add intersection (with tests).
Bastien Montagne
noreply at git.blender.org
Tue Mar 3 09:02:04 CET 2015
Commit: 5bced60008282b52ad2fe12e8bf64dbc287630a2
Author: Bastien Montagne
Date: Mon Mar 2 16:03:05 2015 +0100
Branches: temp-ghash-experiments
https://developer.blender.org/rB5bced60008282b52ad2fe12e8bf64dbc287630a2
GHash: add intersection (with tests).
===================================================================
M source/blender/blenlib/BLI_ghash.h
M source/blender/blenlib/intern/BLI_ghash.c
===================================================================
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 32613a5..2a2b8a9 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -96,6 +96,11 @@ GHash *BLI_ghash_union_reversed(
GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
GHash *gh1, GHash *gh2, ...);
+GHash *BLI_ghash_intersection(
+ GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp,
+ GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
+ GHash *gh1, GHash *gh2, ...);
+
/* *** */
GHashIterator *BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
@@ -244,6 +249,7 @@ bool BLI_gset_issubset(GSet *gs1, GSet *gs2);
bool BLI_gset_issuperset(GSet *gs1, GSet *gs2);
GSet *BLI_gset_union(GSetKeyCopyFP keycopyfp, GSet *gs1, GSet *gs2, ...);
+GSet *BLI_gset_intersection(GSetKeyCopyFP keycopyfp, GSetKeyFreeFP keyfreefp, GSet *gs1, GSet *gs2, ...);
GSet *BLI_gset_ptr_new_ex(const char *info,
const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 25dffb6..69c0729 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -482,10 +482,10 @@ static GHash *ghash_union(
if (!gh1) {
gh1 = ghash_copy(ghn, entry_size, keycopyfp, valcopyfp);
- ghn = (GHash *)va_arg(arg, void *);
+ ghn = va_arg(arg, GHash *);
}
- for ( ; ghn; ghn = (GHash *)va_arg(arg, void *)) {
+ for ( ; ghn; ghn = va_arg(arg, GHash *)) {
unsigned int i;
for (i = 0; i < ghn->nbuckets; i++) {
@@ -522,6 +522,51 @@ static GHash *ghash_union(
return gh1;
}
+/**
+ * Remove all entries in \a gh1 which keys are not present in \a gh2 and all subsequent given GHash.
+ * If \a gh1 is NULL, a new GHash will be created first (avoids modifying \a gh1 in place).
+ */
+static GHash *ghash_intersection(
+ const unsigned int entry_size,
+ GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp,
+ GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
+ GHash *gh1, GHash *gh2, va_list arg)
+{
+ GHash *ghn = gh2;
+
+ BLI_assert(ghn);
+
+ if (!gh1) {
+ gh1 = ghash_copy(ghn, entry_size, keycopyfp, valcopyfp);
+ ghn = va_arg(arg, GHash *);
+ }
+
+ for ( ; ghn; ghn = va_arg(arg, GHash *)) {
+ unsigned int i;
+
+ for (i = 0; i < gh1->nbuckets; i++) {
+ Entry *e, *e_prev = NULL;
+
+ for (e = gh1->buckets[i]; e; e_prev = e, e = e->next) {
+ const unsigned int ghn_bucket_hash = ghash_bucket_hash(ghn, e->hash);
+
+ if (ghash_lookup_entry_ex(ghn, e->key, e->hash, ghn_bucket_hash) == NULL) {
+ Entry *e_next = e->next;
+
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+
+ if (e_prev) e_prev->next = e_next;
+ else gh1->buckets[i] = e_next;
+
+ ghash_expand_buckets(gh1, --gh1->nentries, false);
+ }
+ }
+ }
+ }
+
+ return gh1;
+}
/** \} */
@@ -887,6 +932,7 @@ bool BLI_ghash_issuperset(GHash *gh1, GHash *gh2)
/**
* Union, from left to right.
+ * Similar to python's \a PyDict_Merge(a, b, false).
* If \a gh1 is NULL, a new GHash is returned, otherwise \a gh1 is modified in place.
*/
GHash *BLI_ghash_union(GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp, GHash *gh1, GHash *gh2, ...)
@@ -903,7 +949,8 @@ GHash *BLI_ghash_union(GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp, GHash
/**
* Union, from right to left (less efficient, since it may have to allocate and then free key/val pairs).
- * If \a gh1 is NULL, a new GHash is returned, otherwise \a gh1 is modified in place.
+ * Similar to python's \a PyDict_Merge(a, b, true).
+ * If \a gh1 is NULL, a new GHash is returned, otherwise \a gh1 is modified in place and returned.
*/
GHash *BLI_ghash_union_reversed(
GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp,
@@ -920,6 +967,25 @@ GHash *BLI_ghash_union_reversed(
return gh_ret;
}
+/**
+ * Intersection (i.e. entries which keys exist in all gh1, gh2, ...).
+ * If \a gh1 is NULL, a new GHash is returned, otherwise \a gh1 is modified in place and returned.
+ */
+GHash *BLI_ghash_intersection(
+ GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp,
+ GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
+ GHash *gh1, GHash *gh2, ...)
+{
+ GHash *gh_ret;
+ va_list arg;
+
+ va_start(arg, gh2);
+ gh_ret = ghash_intersection(sizeof(Entry), keycopyfp, valcopyfp, keyfreefp, valfreefp, gh1, gh2, arg);
+ va_end(arg);
+
+ return gh_ret;
+}
+
/** \} */
@@ -1429,6 +1495,22 @@ GSet *BLI_gset_union(GSetKeyCopyFP keycopyfp, GSet *gs1, GSet *gs2, ...)
return gs_ret;
}
+/**
+ * Intersection (i.e. entries which keys exist in all gs1, gs2, ...).
+ * If \a gs1 is NULL, a new GSet is returned, otherwise \a gs1 is modified in place.
+ */
+GSet *BLI_gset_intersection(GSetKeyCopyFP keycopyfp, GSetKeyFreeFP keyfreefp, GSet *gs1, GSet *gs2, ...)
+{
+ GSet *gs_ret;
+ va_list arg;
+
+ va_start(arg, gs2);
+ gs_ret = (GSet *)ghash_intersection(GSET_ENTRY_SIZE, keycopyfp, NULL, keyfreefp, NULL, (GHash *)gs1, (GHash *)gs2, arg);
+ va_end(arg);
+
+ return gs_ret;
+}
+
/** \} */
More information about the Bf-blender-cvs
mailing list