mirror of https://github.com/JAJames/Jupiter.git
Browse Source
Added generic Hash_Table implementation Simplified and imrpoved Hash.h Replaced Hash.c with Hash.cpp DLList: * Added getHead(), getTail() SLList: * Added getHead(), getTail(), removeHead(), addHead(), erase(), eraseAndDelete(), copy and move assignment operators, move constructor * add() now appends rather than prependsrelease/0.19
Jessica James
8 years ago
12 changed files with 1114 additions and 195 deletions
@ -1,49 +0,0 @@ |
|||
/**
|
|||
* Copyright (C) 2015 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#include "Hash.h" |
|||
#include <openssl/sha.h> |
|||
|
|||
const uint32_t JUPITER_FNV_1_32_OFFSET_BASIS = 2166136261UL; |
|||
const uint64_t JUPITER_FNV_1_64_OFFSET_BASIS = 14695981039346656037ULL; |
|||
const uint32_t JUPITER_FNV_1_32_PRIME = 16777619UL; |
|||
const uint64_t JUPITER_FNV_1_64_PRIME = 1099511628211ULL; |
|||
|
|||
uint64_t Jupiter_fnv1(void *data, size_t length) |
|||
{ |
|||
uint8_t *ptr = (uint8_t *)data; |
|||
uint64_t hash = JUPITER_FNV_1_64_OFFSET_BASIS; |
|||
while (length-- != 0) |
|||
{ |
|||
hash = hash * JUPITER_FNV_1_64_PRIME; |
|||
hash = hash ^ *ptr++; |
|||
} |
|||
return hash; |
|||
} |
|||
|
|||
uint64_t Jupiter_fnv1a(void *data, size_t length) |
|||
{ |
|||
uint8_t *ptr = (uint8_t *)data; |
|||
uint64_t hash = JUPITER_FNV_1_64_OFFSET_BASIS; |
|||
while (length-- != 0) |
|||
{ |
|||
hash = hash ^ *ptr++; |
|||
hash = hash * JUPITER_FNV_1_64_PRIME; |
|||
} |
|||
return hash; |
|||
} |
@ -0,0 +1,83 @@ |
|||
/**
|
|||
* Copyright (C) 2015-2016 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#include "Hash.h" |
|||
|
|||
/** Constants */ |
|||
constexpr uint32_t JUPITER_FNV_1_32_OFFSET_BASIS = 2166136261UL; |
|||
constexpr uint64_t JUPITER_FNV_1_64_OFFSET_BASIS = 14695981039346656037ULL; |
|||
constexpr uint32_t JUPITER_FNV_1_32_PRIME = 16777619UL; |
|||
constexpr uint64_t JUPITER_FNV_1_64_PRIME = 1099511628211ULL; |
|||
|
|||
/** Fowler-Noll-Vo */ |
|||
|
|||
uint64_t Jupiter::fnv1(const uint8_t *data, const uint8_t *end) |
|||
{ |
|||
uint64_t hash = JUPITER_FNV_1_64_OFFSET_BASIS; |
|||
|
|||
while (data != end) |
|||
{ |
|||
hash = hash * JUPITER_FNV_1_64_PRIME; |
|||
hash = hash ^ *data; |
|||
++data; |
|||
} |
|||
|
|||
return hash; |
|||
} |
|||
|
|||
uint64_t Jupiter::fnv1a(const uint8_t *data, const uint8_t *end) |
|||
{ |
|||
uint64_t hash = JUPITER_FNV_1_64_OFFSET_BASIS; |
|||
|
|||
while (data != end) |
|||
{ |
|||
hash = hash ^ *data; |
|||
hash = hash * JUPITER_FNV_1_64_PRIME; |
|||
++data; |
|||
} |
|||
|
|||
return hash; |
|||
} |
|||
|
|||
uint32_t Jupiter::fnv1_32(const uint8_t *data, const uint8_t *end) |
|||
{ |
|||
uint32_t hash = JUPITER_FNV_1_32_OFFSET_BASIS; |
|||
|
|||
while (data != end) |
|||
{ |
|||
hash = hash * JUPITER_FNV_1_32_PRIME; |
|||
hash = hash ^ *data; |
|||
++data; |
|||
} |
|||
|
|||
return hash; |
|||
} |
|||
|
|||
uint32_t Jupiter::fnv1a_32(const uint8_t *data, const uint8_t *end) |
|||
{ |
|||
uint32_t hash = JUPITER_FNV_1_32_OFFSET_BASIS; |
|||
|
|||
while (data != end) |
|||
{ |
|||
hash = hash ^ *data; |
|||
hash = hash * JUPITER_FNV_1_32_PRIME; |
|||
++data; |
|||
} |
|||
|
|||
return hash; |
|||
} |
@ -0,0 +1,242 @@ |
|||
/**
|
|||
* Copyright (C) 2016 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined _HASH_TABLE_H_HEADER |
|||
#define _HASH_TABLE_H_HEADER |
|||
|
|||
/**
|
|||
* @file Hash_Table.h |
|||
* @brief Defines a generic hash table structure |
|||
*/ |
|||
|
|||
#include "String.h" |
|||
#include "SLList.h" |
|||
|
|||
namespace Jupiter |
|||
{ |
|||
template<typename T> inline size_t default_hash_function(const T &in); |
|||
|
|||
/**
|
|||
* @brief Provides a generic hash table structure |
|||
* |
|||
* @param KeyT Type the table will use for keys; must implement following: operator==, move constructor |
|||
* @param ValueT Type the table will use for values |
|||
* @param InKeyT Type the table will accept for keys (Default: KeyT) |
|||
* @param InValueT Type the table will accept for values (Default: KeyT) |
|||
* @param HashF Function to be used for generating hashes (Default: Fowler-Noll-Vo 1a) |
|||
*/ |
|||
template<typename KeyT, typename ValueT, typename InKeyT = KeyT, typename InValueT = ValueT, size_t(*HashF)(const InKeyT &) = Jupiter::default_hash_function<InKeyT>> class Hash_Table |
|||
{ |
|||
public: |
|||
/** Initial number of buckets to allocate; m_buckets_size is never less than INIT_SIZE. */ |
|||
static constexpr const size_t INIT_SIZE = 8; |
|||
|
|||
/**
|
|||
* @brief Container for table entries |
|||
*/ |
|||
struct Bucket |
|||
{ |
|||
/**
|
|||
* @brief An individual entry within the table, including its normal key and value. |
|||
*/ |
|||
struct Entry |
|||
{ |
|||
KeyT key; |
|||
ValueT value; |
|||
|
|||
Entry(const InKeyT &in_key, const InValueT &in_value); |
|||
}; |
|||
|
|||
/**
|
|||
* @brief Searches for an entry in the bucket and returns its value if it exists. |
|||
* |
|||
* @param in_key Key of the entry to search for |
|||
* @return Pointer to the value of the entry if it exists, nullptr otherwise |
|||
*/ |
|||
ValueT *get(const InKeyT &in_key) const; |
|||
|
|||
/**
|
|||
* @brief Sets the value for an entry in the bucket |
|||
* |
|||
* @param in_key Key of the entry to set |
|||
* @param in_value Value to set in the entry |
|||
* @return True if a new entry was added, false if an entry was overwritten |
|||
*/ |
|||
bool set(const InKeyT &in_key, const InValueT &in_value); |
|||
|
|||
/**
|
|||
* @brief Removes an entry from the bucket |
|||
* |
|||
* @param in_key Key of the entry to search for |
|||
* @return Value of the entry which was removed on success, nullptr otherwise |
|||
*/ |
|||
ValueT *remove(const InKeyT &in_key); |
|||
|
|||
/**
|
|||
* @brief Copy assignment operator |
|||
* |
|||
* @param in_bucket Bucket to copy entries from |
|||
* @return Reference to this bucket |
|||
*/ |
|||
Bucket &operator=(const Bucket &in_bucket); |
|||
|
|||
/**
|
|||
* @brief Move assignment operator |
|||
* |
|||
* @param in_bucket Bucket to move entries from |
|||
* @return Reference to this bucket |
|||
*/ |
|||
Bucket &operator=(Bucket &&in_bucket); |
|||
|
|||
/**
|
|||
* @brief Default constructor for the Bucket class |
|||
*/ |
|||
Bucket() = default; |
|||
|
|||
/**
|
|||
* @brief Copy constructor for the Bucket class |
|||
*/ |
|||
Bucket(const Bucket &in_bucket); |
|||
|
|||
/**
|
|||
* @brief Move constructor for the Bucket class |
|||
*/ |
|||
Bucket(Bucket &&in_bucket); |
|||
|
|||
/**
|
|||
* @brief Destructor for the Bucket class |
|||
*/ |
|||
~Bucket(); |
|||
|
|||
/** List of entries in the bucket */ |
|||
Jupiter::SLList<Entry> m_pairs; |
|||
}; |
|||
|
|||
/**
|
|||
* @brief Fetches the value of an entry based on its key |
|||
* |
|||
* @param in_key Key of the entry to search for |
|||
* @return Value of the entry if it exists, nullptr otherwise |
|||
*/ |
|||
ValueT *get(const InKeyT &in_key) const; |
|||
|
|||
/**
|
|||
* @brief Sets the value for an entry in the table |
|||
* |
|||
* @param in_key Key of the entry to set |
|||
* @param in_value Value of the entry to set |
|||
*/ |
|||
void set(const InKeyT &in_key, const InValueT &in_value); |
|||
|
|||
/**
|
|||
* @brief Removes an entry from the table and returns its value |
|||
* |
|||
* @param in_key Key of the entry to remove |
|||
* @return Value of the entry that was removed if it exists, nullptr otherwise |
|||
*/ |
|||
ValueT *remove(const InKeyT &in_key); |
|||
|
|||
/**
|
|||
* @brief Returns the number of entries in the table |
|||
* |
|||
* @return Number of entries in the table |
|||
*/ |
|||
size_t size() const; |
|||
|
|||
/**
|
|||
* @brief Erases the table's contents |
|||
*/ |
|||
void erase(); |
|||
|
|||
/**
|
|||
* @brief Shrinks the table's internal bucket pool to the current number of entries, not to be less than INIT_SIZE. |
|||
*/ |
|||
void shrink(); |
|||
|
|||
/**
|
|||
* @brief Copy assignment operator |
|||
* |
|||
* @param in_table Table to copy entries from |
|||
* @return Reference to this table |
|||
*/ |
|||
Hash_Table &operator=(const Hash_Table &in_table); |
|||
|
|||
/**
|
|||
* @brief Move assignment operator |
|||
* |
|||
* @param in_table Table to move entries from |
|||
* @return Reference to this table |
|||
*/ |
|||
Hash_Table &operator=(Hash_Table &&in_table); |
|||
|
|||
/**
|
|||
* @brief Default constructor for the Hash_Table class |
|||
*/ |
|||
Hash_Table(); |
|||
|
|||
/**
|
|||
* @brief Allocation constructor for the Hash_Table class |
|||
* |
|||
* @param in_buckets_size Number of buckets to initialize to |
|||
*/ |
|||
Hash_Table(size_t in_buckets_size); |
|||
|
|||
/**
|
|||
* @brief Copy constructor for the Hash_Table class |
|||
* |
|||
* @param in_table Table to copy entries from |
|||
*/ |
|||
Hash_Table(const Hash_Table &in_table); |
|||
|
|||
/**
|
|||
* @brief Move constructor for the Hash_Table class |
|||
* |
|||
* @param in_table Table to move entries from |
|||
*/ |
|||
Hash_Table(Hash_Table &&in_table); |
|||
|
|||
/**
|
|||
* @brief Destructor for the Hash_Table class |
|||
*/ |
|||
~Hash_Table(); |
|||
|
|||
private: |
|||
/**
|
|||
* @brief Doubles the size of m_buckets |
|||
*/ |
|||
void expand(); |
|||
|
|||
/**
|
|||
* @brief Copies entries from m_buckets to in_buckets; used when expanding or shrinking m_buckets. |
|||
* |
|||
* @param in_buckets Array of buckets to copy entries into |
|||
* @param in_buckets_size Number of buckets in in_buckets |
|||
*/ |
|||
void copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size); |
|||
|
|||
Bucket *m_buckets; /** Array of Buckets */ |
|||
size_t m_buckets_size; /** Number of buckets */ |
|||
size_t m_length = 0; /** Number of entries */ |
|||
}; |
|||
|
|||
typedef Hash_Table<Jupiter::StringS, Jupiter::StringS, Jupiter::ReadableString, Jupiter::ReadableString, Jupiter::default_hash_function<Jupiter::ReadableString>> HashTable; |
|||
} |
|||
|
|||
#include "Hash_Table_Imp.h" |
|||
|
|||
#endif // _HASH_TABLE_H_HEADER
|
@ -0,0 +1,317 @@ |
|||
/**
|
|||
* Copyright (C) 2016 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined _HASH_TABLE_IMP_H_HEADER |
|||
#define _HASH_TABLE_IMP_H_HEADER |
|||
|
|||
/**
|
|||
* @file Hash_Table_Imp.h |
|||
* @brief Provides the implementation for Hash_Table. |
|||
*/ |
|||
|
|||
#include "Hash_Table.h" |
|||
#include "Hash.h" |
|||
|
|||
/**
|
|||
* IMPLEMENTATION: |
|||
* Hash_Table |
|||
*/ |
|||
|
|||
template<typename T> inline size_t Jupiter::default_hash_function(const T &in) |
|||
{ |
|||
if (sizeof(size_t) >= sizeof(uint64_t)) |
|||
return static_cast<size_t>(Jupiter::fnv1a(in)); |
|||
|
|||
return static_cast<size_t>(Jupiter::fnv1a_32(in)); |
|||
} |
|||
|
|||
/** Hash_Table::Bucket::Entry */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Entry::Entry(const InKeyT &in_key, const InValueT &in_value) |
|||
{ |
|||
key = in_key; |
|||
value = in_value; |
|||
} |
|||
|
|||
/** Hash_Table::Bucket */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::get(const InKeyT &in_key) const |
|||
{ |
|||
for (Jupiter::SLList<Entry>::Node *node = m_pairs.getHead(); node != nullptr; node = node->next) |
|||
if (node->data->key == in_key) |
|||
return &node->data->value; |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::set(const InKeyT &in_key, const InValueT &in_value) |
|||
{ |
|||
for (Jupiter::SLList<Entry>::Node *node = m_pairs.getHead(); node != nullptr; node = node->next) |
|||
if (node->data->key == in_key) |
|||
{ |
|||
node->data->value = in_value; |
|||
return false; |
|||
} |
|||
|
|||
m_pairs.add(new Entry(in_key, in_value)); |
|||
return true; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::remove(const InKeyT &in_key) |
|||
{ |
|||
Jupiter::SLList<Entry>::Node *node = m_pairs.getHead(); |
|||
Entry *pair; |
|||
ValueT *result; |
|||
|
|||
// No nodes in the bucket
|
|||
if (node == nullptr) |
|||
return nullptr; |
|||
|
|||
// Check if the head is the desired node
|
|||
if (node->data->key == in_key) |
|||
{ |
|||
pair = m_pairs.removeHead(); |
|||
result = new ValueT(std::move(pair->value)); |
|||
delete pair; |
|||
|
|||
return result; |
|||
} |
|||
|
|||
// iterate through list
|
|||
while (node->next != nullptr) |
|||
{ |
|||
if (node->next->data->key == in_key) |
|||
{ |
|||
// The next node is the desired node
|
|||
pair = m_pairs.removeNext(node); |
|||
result = new ValueT(std::move(pair->value)); |
|||
delete pair; |
|||
|
|||
return result; |
|||
} |
|||
node = node->next; |
|||
} |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::operator=(const Bucket &in_bucket) |
|||
{ |
|||
m_pairs.eraseAndDelete(); |
|||
for (Jupiter::SLList<Entry>::Node *node = in_bucket.m_pairs.getHead(); node != nullptr; node = node->next) |
|||
m_pairs.add(new Entry(node->data->key, node->data->value)); |
|||
|
|||
return *this; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::operator=(Bucket &&in_bucket) |
|||
{ |
|||
m_pairs = std::move(in_bucket.m_pairs); |
|||
return *this; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Bucket(const Bucket &in_bucket) |
|||
{ |
|||
for (Jupiter::SLList<Entry>::Node *node = in_bucket.m_pairs.getHead(); node != nullptr; node = node->next) |
|||
m_pairs.add(new Entry(node->data->key, node->data->value)); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Bucket(Bucket &&in_bucket) |
|||
{ |
|||
m_pairs = std::move(in_bucket.m_pairs); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::~Bucket() |
|||
{ |
|||
m_pairs.eraseAndDelete(); |
|||
} |
|||
|
|||
/** Hash_Table */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::get(const InKeyT &in_key) const |
|||
{ |
|||
return m_buckets[HashF(in_key) % m_buckets_size].get(in_key); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::set(const InKeyT &in_key, const InValueT &in_value) |
|||
{ |
|||
if (m_buckets[HashF(in_key) % m_buckets_size].set(in_key, in_value)) |
|||
if (++m_length == m_buckets_size) |
|||
expand(); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::remove(const InKeyT &in_key) |
|||
{ |
|||
ValueT *value = m_buckets[HashF(in_key) % m_buckets_size].remove(in_key); |
|||
|
|||
if (value != nullptr) |
|||
--m_length; |
|||
|
|||
return value; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
size_t Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::size() const |
|||
{ |
|||
return m_length; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::erase() |
|||
{ |
|||
m_length = 0; |
|||
delete[] m_buckets; |
|||
|
|||
m_buckets_size = INIT_SIZE; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::shrink() |
|||
{ |
|||
size_t buckets_size = m_length < INIT_SIZE ? INIT_SIZE : m_length; |
|||
Bucket *buckets = new Bucket[buckets_size]; |
|||
|
|||
copy_to_buckets(buckets, buckets_size); |
|||
|
|||
delete[] m_buckets; |
|||
m_buckets = buckets; |
|||
m_buckets_size = buckets_size; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(const Hash_Table &in_table) |
|||
{ |
|||
// TODO: Optimize; can overwrite data instead of deleting and allocationg again if m_buckets_size > in.m_buckets_size
|
|||
delete[] m_buckets; |
|||
|
|||
m_length = in_table.m_length; |
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
|
|||
for (size_t index = 0; index != m_buckets_size; ++index) |
|||
m_buckets[index] = in_table.m_buckets[index]; |
|||
|
|||
return *this; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(Hash_Table &&in_table) |
|||
{ |
|||
// TODO: Optimize; can swap empty array instead of always deleting
|
|||
delete[] m_buckets; |
|||
|
|||
m_buckets = in_table.m_buckets; |
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_length = in_table.m_length; |
|||
|
|||
in_table.m_buckets = new Bucket[1]; |
|||
in_table.m_buckets_size = 1; |
|||
in_table.m_length = 0; |
|||
return *this; |
|||
} |
|||
|
|||
/** Constructors */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table() |
|||
{ |
|||
m_buckets_size = INIT_SIZE; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(size_t in_buckets_size) |
|||
{ |
|||
m_buckets_size = in_buckets_size; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(const Hash_Table &in_table) |
|||
{ |
|||
m_length = in_table.m_length; |
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
|
|||
for (size_t index = 0; index != m_buckets_size; ++index) |
|||
m_buckets[index] = in_table.m_buckets[index]; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(Hash_Table &&in_table) |
|||
{ |
|||
m_buckets = in_table.m_buckets; |
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_length = in_table.m_length; |
|||
|
|||
in_table.m_buckets = new Bucket[1]; |
|||
in_table.m_buckets_size = 1; |
|||
in_table.m_length = 0; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::~Hash_Table() |
|||
{ |
|||
delete[] m_buckets; |
|||
} |
|||
|
|||
/** Hash_Table/private */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::expand() |
|||
{ |
|||
size_t buckets_size = m_buckets_size * 2; |
|||
Bucket *buckets = new Bucket[buckets_size]; |
|||
|
|||
copy_to_buckets(buckets, buckets_size); |
|||
|
|||
delete[] m_buckets; |
|||
m_buckets = buckets; |
|||
m_buckets_size = buckets_size; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size) |
|||
{ |
|||
Jupiter::SLList<Bucket::Entry>::Node *node; |
|||
for (size_t index = 0; index != m_buckets_size; ++index) |
|||
{ |
|||
for (node = m_buckets[index].m_pairs.getHead(); node != nullptr; node = node->next) |
|||
in_buckets[HashF(node->data->key) % in_buckets_size].set(node->data->key, node->data->value); |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> |
|||
*/ |
|||
|
|||
#endif // _HASH_TABLE_IMP_H_HEADER
|
Binary file not shown.
Loading…
Reference in new issue