|
|
@@ -13,8 +13,8 @@
|
|
|
#include "array.h"
|
|
|
#include "container_types.h"
|
|
|
|
|
|
-namespace crown {
|
|
|
-
|
|
|
+namespace crown
|
|
|
+{
|
|
|
/// The hash function stores its data in a "list-in-an-array" where
|
|
|
/// indices are used instead of pointers.
|
|
|
///
|
|
|
@@ -25,29 +25,29 @@ namespace crown {
|
|
|
namespace hash
|
|
|
{
|
|
|
/// Returns true if the specified key exists in the hash.
|
|
|
- template<typename T> bool has(const Hash<T> &h, uint64_t key);
|
|
|
+ template<typename T> bool has(const Hash<T>& h, uint64_t key);
|
|
|
|
|
|
/// Returns the value stored for the specified key, or deffault if the key
|
|
|
/// does not exist in the hash.
|
|
|
- template<typename T> const T &get(const Hash<T> &h, uint64_t key, const T &deffault);
|
|
|
+ template<typename T> const T& get(const Hash<T>& h, uint64_t key, const T& deffault);
|
|
|
|
|
|
/// Sets the value for the key.
|
|
|
- template<typename T> void set(Hash<T> &h, uint64_t key, const T &value);
|
|
|
+ template<typename T> void set(Hash<T>& h, uint64_t key, const T& value);
|
|
|
|
|
|
/// Removes the key from the hash if it exists.
|
|
|
- template<typename T> void remove(Hash<T> &h, uint64_t key);
|
|
|
+ template<typename T> void remove(Hash<T>& h, uint64_t key);
|
|
|
|
|
|
/// Resizes the hash lookup table to the specified size.
|
|
|
/// (The table will grow automatically when 70 % full.)
|
|
|
- template<typename T> void reserve(Hash<T> &h, uint32_t size);
|
|
|
+ template<typename T> void reserve(Hash<T>& h, uint32_t size);
|
|
|
|
|
|
/// Remove all elements from the hash.
|
|
|
- template<typename T> void clear(Hash<T> &h);
|
|
|
+ template<typename T> void clear(Hash<T>& h);
|
|
|
|
|
|
/// Returns a pointer to the first entry in the hash table, can be used to
|
|
|
/// efficiently iterate over the elements (in random order).
|
|
|
- template<typename T> const typename Hash<T>::Entry *begin(const Hash<T> &h);
|
|
|
- template<typename T> const typename Hash<T>::Entry *end(const Hash<T> &h);
|
|
|
+ template<typename T> const typename Hash<T>::Entry* begin(const Hash<T>& h);
|
|
|
+ template<typename T> const typename Hash<T>::Entry* end(const Hash<T>& h);
|
|
|
}
|
|
|
|
|
|
/// Functions to manipulate Hash as a multi-hash.
|
|
|
@@ -56,26 +56,26 @@ namespace crown {
|
|
|
namespace multi_hash
|
|
|
{
|
|
|
/// Finds the first entry with the specified key.
|
|
|
- template<typename T> const typename Hash<T>::Entry *find_first(const Hash<T> &h, uint64_t key);
|
|
|
+ template<typename T> const typename Hash<T>::Entry* find_first(const Hash<T>& h, uint64_t key);
|
|
|
|
|
|
/// Finds the next entry with the same key as e.
|
|
|
- template<typename T> const typename Hash<T>::Entry *find_next(const Hash<T> &h, const typename Hash<T>::Entry *e);
|
|
|
+ template<typename T> const typename Hash<T>::Entry* find_next(const Hash<T>& h, const typename Hash<T>::Entry* e);
|
|
|
|
|
|
/// Returns the number of entries with the key.
|
|
|
- template<typename T> uint32_t count(const Hash<T> &h, uint64_t key);
|
|
|
+ template<typename T> uint32_t count(const Hash<T>& h, uint64_t key);
|
|
|
|
|
|
/// Returns all the entries with the specified key.
|
|
|
/// Use a TempAllocator for the array to avoid allocating memory.
|
|
|
- template<typename T> void get(const Hash<T> &h, uint64_t key, Array<T> &items);
|
|
|
+ template<typename T> void get(const Hash<T>& h, uint64_t key, Array<T> &items);
|
|
|
|
|
|
/// Inserts the value as an aditional value for the key.
|
|
|
- template<typename T> void insert(Hash<T> &h, uint64_t key, const T &value);
|
|
|
+ template<typename T> void insert(Hash<T>& h, uint64_t key, const T& value);
|
|
|
|
|
|
/// Removes the specified entry.
|
|
|
- template<typename T> void remove(Hash<T> &h, const typename Hash<T>::Entry *e);
|
|
|
+ template<typename T> void remove(Hash<T>& h, const typename Hash<T>::Entry* e);
|
|
|
|
|
|
/// Removes all entries with the specified key.
|
|
|
- template<typename T> void remove_all(Hash<T> &h, uint64_t key);
|
|
|
+ template<typename T> void remove_all(Hash<T>& h, uint64_t key);
|
|
|
}
|
|
|
|
|
|
namespace hash_internal
|
|
|
@@ -89,7 +89,7 @@ namespace crown {
|
|
|
uint32_t data_i;
|
|
|
};
|
|
|
|
|
|
- template<typename T> uint32_t add_entry(Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> uint32_t add_entry(Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
typename Hash<T>::Entry e;
|
|
|
e.key = key;
|
|
|
@@ -99,7 +99,7 @@ namespace crown {
|
|
|
return ei;
|
|
|
}
|
|
|
|
|
|
- template<typename T> FindResult find(const Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> FindResult find(const Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
FindResult fr;
|
|
|
fr.hash_i = END_OF_LIST;
|
|
|
@@ -120,7 +120,7 @@ namespace crown {
|
|
|
return fr;
|
|
|
}
|
|
|
|
|
|
- template<typename T> FindResult find(const Hash<T> &h, const typename Hash<T>::Entry *e)
|
|
|
+ template<typename T> FindResult find(const Hash<T>& h, const typename Hash<T>::Entry* e)
|
|
|
{
|
|
|
FindResult fr;
|
|
|
fr.hash_i = END_OF_LIST;
|
|
|
@@ -141,7 +141,7 @@ namespace crown {
|
|
|
return fr;
|
|
|
}
|
|
|
|
|
|
- template<typename T> void erase(Hash<T> &h, const FindResult &fr)
|
|
|
+ template<typename T> void erase(Hash<T>& h, const FindResult &fr)
|
|
|
{
|
|
|
if (fr.data_prev == END_OF_LIST)
|
|
|
h._hash[fr.hash_i] = h._data[fr.data_i].next;
|
|
|
@@ -162,12 +162,12 @@ namespace crown {
|
|
|
h._hash[last.hash_i] = fr.data_i;
|
|
|
}
|
|
|
|
|
|
- template<typename T> uint32_t find_or_fail(const Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> uint32_t find_or_fail(const Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
return find(h, key).data_i;
|
|
|
}
|
|
|
|
|
|
- template<typename T> uint32_t find_or_make(Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> uint32_t find_or_make(Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
const FindResult fr = find(h, key);
|
|
|
if (fr.data_i != END_OF_LIST)
|
|
|
@@ -181,7 +181,7 @@ namespace crown {
|
|
|
return i;
|
|
|
}
|
|
|
|
|
|
- template<typename T> uint32_t make(Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> uint32_t make(Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
const FindResult fr = find(h, key);
|
|
|
const uint32_t i = add_entry(h, key);
|
|
|
@@ -195,14 +195,14 @@ namespace crown {
|
|
|
return i;
|
|
|
}
|
|
|
|
|
|
- template<typename T> void find_and_erase(Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> void find_and_erase(Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
const FindResult fr = find(h, key);
|
|
|
if (fr.data_i != END_OF_LIST)
|
|
|
erase(h, fr);
|
|
|
}
|
|
|
|
|
|
- template<typename T> void rehash(Hash<T> &h, uint32_t new_size)
|
|
|
+ template<typename T> void rehash(Hash<T>& h, uint32_t new_size)
|
|
|
{
|
|
|
Hash<T> nh(*h._hash._allocator);
|
|
|
array::resize(nh._hash, new_size);
|
|
|
@@ -220,13 +220,13 @@ namespace crown {
|
|
|
memcpy(&nh, &empty, sizeof(Hash<T>));
|
|
|
}
|
|
|
|
|
|
- template<typename T> bool full(const Hash<T> &h)
|
|
|
+ template<typename T> bool full(const Hash<T>& h)
|
|
|
{
|
|
|
const float max_load_factor = 0.7f;
|
|
|
return array::size(h._data) >= array::size(h._hash) * max_load_factor;
|
|
|
}
|
|
|
|
|
|
- template<typename T> void grow(Hash<T> &h)
|
|
|
+ template<typename T> void grow(Hash<T>& h)
|
|
|
{
|
|
|
const uint32_t new_size = array::size(h._data) * 2 + 10;
|
|
|
rehash(h, new_size);
|
|
|
@@ -235,18 +235,18 @@ namespace crown {
|
|
|
|
|
|
namespace hash
|
|
|
{
|
|
|
- template<typename T> bool has(const Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> bool has(const Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
return hash_internal::find_or_fail(h, key) != hash_internal::END_OF_LIST;
|
|
|
}
|
|
|
|
|
|
- template<typename T> const T &get(const Hash<T> &h, uint64_t key, const T &deffault)
|
|
|
+ template<typename T> const T& get(const Hash<T>& h, uint64_t key, const T& deffault)
|
|
|
{
|
|
|
const uint32_t i = hash_internal::find_or_fail(h, key);
|
|
|
return i == hash_internal::END_OF_LIST ? deffault : h._data[i].value;
|
|
|
}
|
|
|
|
|
|
- template<typename T> void set(Hash<T> &h, uint64_t key, const T &value)
|
|
|
+ template<typename T> void set(Hash<T>& h, uint64_t key, const T& value)
|
|
|
{
|
|
|
if (array::size(h._hash) == 0)
|
|
|
hash_internal::grow(h);
|
|
|
@@ -257,28 +257,28 @@ namespace crown {
|
|
|
hash_internal::grow(h);
|
|
|
}
|
|
|
|
|
|
- template<typename T> void remove(Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> void remove(Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
hash_internal::find_and_erase(h, key);
|
|
|
}
|
|
|
|
|
|
- template<typename T> void reserve(Hash<T> &h, uint32_t size)
|
|
|
+ template<typename T> void reserve(Hash<T>& h, uint32_t size)
|
|
|
{
|
|
|
hash_internal::rehash(h, size);
|
|
|
}
|
|
|
|
|
|
- template<typename T> void clear(Hash<T> &h)
|
|
|
+ template<typename T> void clear(Hash<T>& h)
|
|
|
{
|
|
|
array::clear(h._data);
|
|
|
array::clear(h._hash);
|
|
|
}
|
|
|
|
|
|
- template<typename T> const typename Hash<T>::Entry *begin(const Hash<T> &h)
|
|
|
+ template<typename T> const typename Hash<T>::Entry* begin(const Hash<T>& h)
|
|
|
{
|
|
|
return array::begin(h._data);
|
|
|
}
|
|
|
|
|
|
- template<typename T> const typename Hash<T>::Entry *end(const Hash<T> &h)
|
|
|
+ template<typename T> const typename Hash<T>::Entry* end(const Hash<T>& h)
|
|
|
{
|
|
|
return array::end(h._data);
|
|
|
}
|
|
|
@@ -286,13 +286,13 @@ namespace crown {
|
|
|
|
|
|
namespace multi_hash
|
|
|
{
|
|
|
- template<typename T> const typename Hash<T>::Entry *find_first(const Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> const typename Hash<T>::Entry* find_first(const Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
const uint32_t i = hash_internal::find_or_fail(h, key);
|
|
|
return i == hash_internal::END_OF_LIST ? 0 : &h._data[i];
|
|
|
}
|
|
|
|
|
|
- template<typename T> const typename Hash<T>::Entry *find_next(const Hash<T> &h, const typename Hash<T>::Entry *e)
|
|
|
+ template<typename T> const typename Hash<T>::Entry* find_next(const Hash<T>& h, const typename Hash<T>::Entry* e)
|
|
|
{
|
|
|
uint32_t i = e->next;
|
|
|
while (i != hash_internal::END_OF_LIST) {
|
|
|
@@ -303,10 +303,10 @@ namespace crown {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- template<typename T> uint32_t count(const Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> uint32_t count(const Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
uint32_t i = 0;
|
|
|
- const typename Hash<T>::Entry *e = find_first(h, key);
|
|
|
+ const typename Hash<T>::Entry* e = find_first(h, key);
|
|
|
while (e) {
|
|
|
++i;
|
|
|
e = find_next(h, e);
|
|
|
@@ -314,16 +314,16 @@ namespace crown {
|
|
|
return i;
|
|
|
}
|
|
|
|
|
|
- template<typename T> void get(const Hash<T> &h, uint64_t key, Array<T> &items)
|
|
|
+ template<typename T> void get(const Hash<T>& h, uint64_t key, Array<T> &items)
|
|
|
{
|
|
|
- const typename Hash<T>::Entry *e = find_first(h, key);
|
|
|
+ const typename Hash<T>::Entry* e = find_first(h, key);
|
|
|
while (e) {
|
|
|
array::push_back(items, e->value);
|
|
|
e = find_next(h, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- template<typename T> void insert(Hash<T> &h, uint64_t key, const T &value)
|
|
|
+ template<typename T> void insert(Hash<T>& h, uint64_t key, const T& value)
|
|
|
{
|
|
|
if (array::size(h._hash) == 0)
|
|
|
hash_internal::grow(h);
|
|
|
@@ -334,14 +334,14 @@ namespace crown {
|
|
|
hash_internal::grow(h);
|
|
|
}
|
|
|
|
|
|
- template<typename T> void remove(Hash<T> &h, const typename Hash<T>::Entry *e)
|
|
|
+ template<typename T> void remove(Hash<T>& h, const typename Hash<T>::Entry* e)
|
|
|
{
|
|
|
const hash_internal::FindResult fr = hash_internal::find(h, e);
|
|
|
if (fr.data_i != hash_internal::END_OF_LIST)
|
|
|
hash_internal::erase(h, fr);
|
|
|
}
|
|
|
|
|
|
- template<typename T> void remove_all(Hash<T> &h, uint64_t key)
|
|
|
+ template<typename T> void remove_all(Hash<T>& h, uint64_t key)
|
|
|
{
|
|
|
while (hash::has(h, key))
|
|
|
hash::remove(h, key);
|