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