util/set: Add a search_and_add function
[mesa.git] / src / util / set.c
index feef96d16eaf35ff4980821a57189091dbd9413a..2fd54a71a6f04a7fcb9d7c472d6421f957a8014d 100644 (file)
@@ -36,6 +36,7 @@
 #include <assert.h>
 #include <string.h>
 
+#include "hash_table.h"
 #include "macros.h"
 #include "ralloc.h"
 #include "set.h"
@@ -168,8 +169,6 @@ _mesa_set_destroy(struct set *ht, void (*delete_function)(struct set_entry *entr
       return;
 
    if (delete_function) {
-      struct set_entry *entry;
-
       set_foreach (ht, entry) {
          delete_function(entry);
       }
@@ -187,8 +186,6 @@ _mesa_set_destroy(struct set *ht, void (*delete_function)(struct set_entry *entr
 void
 _mesa_set_clear(struct set *set, void (*delete_function)(struct set_entry *entry))
 {
-   struct set_entry *entry;
-
    if (!set)
       return;
 
@@ -250,13 +247,13 @@ _mesa_set_search_pre_hashed(const struct set *set, uint32_t hash,
 }
 
 static struct set_entry *
-set_add(struct set *ht, uint32_t hash, const void *key);
+set_add(struct set *ht, uint32_t hash, const void *key, bool *replaced);
 
 static void
 set_rehash(struct set *ht, unsigned new_size_index)
 {
    struct set old_ht;
-   struct set_entry *table, *entry;
+   struct set_entry *table;
 
    if (new_size_index >= ARRAY_SIZE(hash_sizes))
       return;
@@ -277,7 +274,7 @@ set_rehash(struct set *ht, unsigned new_size_index)
    ht->deleted_entries = 0;
 
    set_foreach(&old_ht, entry) {
-      set_add(ht, entry->hash, entry->key);
+      set_add(ht, entry->hash, entry->key, NULL);
    }
 
    ralloc_free(old_ht.table);
@@ -290,7 +287,7 @@ set_rehash(struct set *ht, unsigned new_size_index)
  * so previously found hash_entries are no longer valid after this function.
  */
 static struct set_entry *
-set_add(struct set *ht, uint32_t hash, const void *key)
+set_add(struct set *ht, uint32_t hash, const void *key, bool *replaced)
 {
    uint32_t hash_address;
    struct set_entry *available_entry = NULL;
@@ -328,6 +325,8 @@ set_add(struct set *ht, uint32_t hash, const void *key)
           entry->hash == hash &&
           ht->key_equals_function(key, entry->key)) {
          entry->key = key;
+         if (replaced)
+            *replaced = true;
          return entry;
       }
 
@@ -342,6 +341,8 @@ set_add(struct set *ht, uint32_t hash, const void *key)
       available_entry->hash = hash;
       available_entry->key = key;
       ht->entries++;
+      if (replaced)
+         *replaced = false;
       return available_entry;
    }
 
@@ -355,7 +356,7 @@ struct set_entry *
 _mesa_set_add(struct set *set, const void *key)
 {
    assert(set->key_hash_function);
-   return set_add(set, set->key_hash_function(key), key);
+   return set_add(set, set->key_hash_function(key), key, NULL);
 }
 
 struct set_entry *
@@ -363,7 +364,23 @@ _mesa_set_add_pre_hashed(struct set *set, uint32_t hash, const void *key)
 {
    assert(set->key_hash_function == NULL ||
           hash == set->key_hash_function(key));
-   return set_add(set, hash, key);
+   return set_add(set, hash, key, NULL);
+}
+
+struct set_entry *
+_mesa_set_search_and_add(struct set *set, const void *key, bool *replaced)
+{
+   assert(set->key_hash_function);
+   return set_add(set, set->key_hash_function(key), key, replaced);
+}
+
+struct set_entry *
+_mesa_set_search_and_add_pre_hashed(struct set *set, uint32_t hash,
+                                    const void *key, bool *replaced)
+{
+   assert(set->key_hash_function == NULL ||
+          hash == set->key_hash_function(key));
+   return set_add(set, hash, key, replaced);
 }
 
 /**
@@ -441,3 +458,13 @@ _mesa_set_random_entry(struct set *ht,
 
    return NULL;
 }
+
+/**
+ * Helper to create a set with pointer keys.
+ */
+struct set *
+_mesa_pointer_set_create(void *mem_ctx)
+{
+   return _mesa_set_create(mem_ctx, _mesa_hash_pointer,
+                           _mesa_key_pointer_equal);
+}