util/set: add a clone function
[mesa.git] / src / util / set.c
index 99abefd0632cdac1100cd994c59cab513543c91e..b2aa5ba13d58e928e48e2f9e49cf407e8c1e89fe 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <stdlib.h>
 #include <assert.h>
+#include <string.h>
 
 #include "macros.h"
 #include "ralloc.h"
@@ -45,8 +46,8 @@
  * free to avoid exponential performance degradation as the hash table fills
  */
 
-uint32_t deleted_key_value;
-const void *deleted_key = &deleted_key_value;
+static const uint32_t deleted_key_value;
+static const void *deleted_key = &deleted_key_value;
 
 static const struct {
    uint32_t max_entries, size, rehash;
@@ -132,6 +133,28 @@ _mesa_set_create(void *mem_ctx,
    return ht;
 }
 
+struct set *
+_mesa_set_clone(struct set *set, void *dst_mem_ctx)
+{
+   struct set *clone;
+
+   clone = ralloc(dst_mem_ctx, struct set);
+   if (clone == NULL)
+      return NULL;
+
+   memcpy(clone, set, sizeof(struct set));
+
+   clone->table = ralloc_array(clone, struct set_entry, clone->size);
+   if (clone->table == NULL) {
+      ralloc_free(clone);
+      return NULL;
+   }
+
+   memcpy(clone->table, set->table, clone->size * sizeof(struct set_entry));
+
+   return clone;
+}
+
 /**
  * Frees the given set.
  *
@@ -155,6 +178,29 @@ _mesa_set_destroy(struct set *ht, void (*delete_function)(struct set_entry *entr
    ralloc_free(ht);
 }
 
+/**
+ * Clears all values from the given set.
+ *
+ * If delete_function is passed, it gets called on each entry present before
+ * the set is cleared.
+ */
+void
+_mesa_set_clear(struct set *set, void (*delete_function)(struct set_entry *entry))
+{
+   struct set_entry *entry;
+
+   if (!set)
+      return;
+
+   set_foreach (set, entry) {
+      if (delete_function)
+         delete_function(entry);
+      entry->key = deleted_key;
+   }
+
+   set->entries = set->deleted_entries = 0;
+}
+
 /**
  * Finds a set entry with the given key and hash of that key.
  *
@@ -230,12 +276,8 @@ set_rehash(struct set *ht, unsigned new_size_index)
    ht->entries = 0;
    ht->deleted_entries = 0;
 
-   for (entry = old_ht.table;
-        entry != old_ht.table + old_ht.size;
-        entry++) {
-      if (entry_is_present(entry)) {
-         set_add(ht, entry->hash, entry->key);
-      }
+   set_foreach(&old_ht, entry) {
+      set_add(ht, entry->hash, entry->key);
    }
 
    ralloc_free(old_ht.table);