X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fprogram%2Fhash_table.h;h=e95fc4982ec861b404b02218c96df78f1277b42b;hb=5a74e17ab0f5ec864c18bc74f951e18d3ecc136f;hp=7b302f5dbeee0e23f4228cbc59e42ccda0e3678e;hpb=ca12aefdacd22fb42e3f1d3852db4c12de886554;p=mesa.git diff --git a/src/mesa/program/hash_table.h b/src/mesa/program/hash_table.h index 7b302f5dbee..e95fc4982ec 100644 --- a/src/mesa/program/hash_table.h +++ b/src/mesa/program/hash_table.h @@ -32,6 +32,17 @@ #define HASH_TABLE_H #include +#include +#include +#include +#include +#include + +struct string_to_uint_map; + +#ifdef __cplusplus +extern "C" { +#endif struct hash_table; @@ -86,10 +97,42 @@ extern void *hash_table_find(struct hash_table *ht, const void *key); /** * Add an element to a hash table + * + * \warning + * If \c key is already in the hash table, it will be added again. Future + * calls to \c hash_table_find and \c hash_table_remove will return or remove, + * repsectively, the most recently added instance of \c key. + * + * \warning + * The value passed by \c key is kept in the hash table and is used by later + * calls to \c hash_table_find. + * + * \sa hash_table_replace */ extern void hash_table_insert(struct hash_table *ht, void *data, const void *key); +/** + * Add an element to a hash table with replacement + * + * \return + * 1 if it did replace the the value (in which case the old key is kept), 0 if + * it did not replace the value (in which case the new key is kept). + * + * \warning + * If \c key is already in the hash table, \c data will \b replace the most + * recently inserted \c data (see the warning in \c hash_table_insert) for + * that key. + * + * \sa hash_table_insert + */ +extern bool hash_table_replace(struct hash_table *ht, void *data, + const void *key); + +/** + * Remove a specific element from a hash table. + */ +extern void hash_table_remove(struct hash_table *ht, const void *key); /** * Compute hash value of a string @@ -114,4 +157,132 @@ extern unsigned hash_table_string_hash(const void *key); */ #define hash_table_string_compare ((hash_compare_func_t) strcmp) + +/** + * Compute hash value of a pointer + * + * \param key Pointer to be used as a hash key + * + * \note + * The memory pointed to by \c key is \b never accessed. The value of \c key + * itself is used as the hash key + * + * \sa hash_table_pointer_compare + */ +unsigned +hash_table_pointer_hash(const void *key); + + +/** + * Compare two pointers used as keys + * + * \sa hash_table_pointer_hash + */ +int +hash_table_pointer_compare(const void *key1, const void *key2); + +void +hash_table_call_foreach(struct hash_table *ht, + void (*callback)(const void *key, + void *data, + void *closure), + void *closure); + +struct string_to_uint_map * +string_to_uint_map_ctor(); + +void +string_to_uint_map_dtor(struct string_to_uint_map *); + + +#ifdef __cplusplus +} + +/** + * Map from a string (name) to an unsigned integer value + * + * \note + * Because of the way this class interacts with the \c hash_table + * implementation, values of \c UINT_MAX cannot be stored in the map. + */ +struct string_to_uint_map { +public: + string_to_uint_map() + { + this->ht = hash_table_ctor(0, hash_table_string_hash, + hash_table_string_compare); + } + + ~string_to_uint_map() + { + hash_table_call_foreach(this->ht, delete_key, NULL); + hash_table_dtor(this->ht); + } + + /** + * Remove all mappings from this map. + */ + void clear() + { + hash_table_call_foreach(this->ht, delete_key, NULL); + hash_table_clear(this->ht); + } + + /** + * Get the value associated with a particular key + * + * \return + * If \c key is found in the map, \c true is returned. Otherwise \c false + * is returned. + * + * \note + * If \c key is not found in the table, \c value is not modified. + */ + bool get(unsigned &value, const char *key) + { + const intptr_t v = + (intptr_t) hash_table_find(this->ht, (const void *) key); + + if (v == 0) + return false; + + value = (unsigned)(v - 1); + return true; + } + + void put(unsigned value, const char *key) + { + /* The low-level hash table structure returns NULL if key is not in the + * hash table. However, users of this map might want to store zero as a + * valid value in the table. Bias the value by +1 so that a + * user-specified zero is stored as 1. This enables ::get to tell the + * difference between a user-specified zero (returned as 1 by + * hash_table_find) and the key not in the table (returned as 0 by + * hash_table_find). + * + * The net effect is that we can't store UINT_MAX in the table. This is + * because UINT_MAX+1 = 0. + */ + assert(value != UINT_MAX); + char *dup_key = strdup(key); + bool result = hash_table_replace(this->ht, + (void *) (intptr_t) (value + 1), + dup_key); + if (result) + free(dup_key); + } + +private: + static void delete_key(const void *key, void *data, void *closure) + { + (void) data; + (void) closure; + + free((char *)key); + } + + struct hash_table *ht; +}; + +#endif /* __cplusplus */ #endif /* HASH_TABLE_H */