Browse Source

Removed Jupiter.lib binary file

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 prepends
release/0.19
Jessica James 8 years ago
parent
commit
ae3294c72b
  1. 99
      Jupiter/DLList.h
  2. 49
      Jupiter/Hash.c
  3. 83
      Jupiter/Hash.cpp
  4. 98
      Jupiter/Hash.h
  5. 242
      Jupiter/Hash_Table.h
  6. 317
      Jupiter/Hash_Table_Imp.h
  7. 4
      Jupiter/Jupiter.vcxproj
  8. 21
      Jupiter/Jupiter.vcxproj.filters
  9. 358
      Jupiter/SLList.h
  10. 1
      Jupiter/String_Imp.h
  11. BIN
      Release/Jupiter.lib
  12. 37
      Tester/Test.cpp

99
Jupiter/DLList.h

@ -46,13 +46,27 @@ namespace Jupiter
T *data; T *data;
}; };
/*
* @brief Returns the head of the list
*
* @return Head of the list
*/
Node *getHead() const;
/*
* @brief Returns the tail of the list
*
* @return Tail of the list
*/
Node *getTail() const;
/** /**
* @brief Returns the n'th Node in the list. * @brief Returns the Node at the specified index in the list.
* *
* @param n Index of the node to return. * @param index Index of the node to return.
* @return n'th Node in the list. * @return Node at specified index in the list.
*/ */
Node *getNode(size_t n) const; Node *getNode(size_t index) const;
/** /**
* @brief Gets the data at a specified index. * @brief Gets the data at a specified index.
@ -87,7 +101,7 @@ namespace Jupiter
void add(T *data, size_t index); void add(T *data, size_t index);
/** /**
* @brief Adds data to the end of the list. * @brief Adds data to the tail of the list.
* *
* @param data Data to add to the list. * @param data Data to add to the list.
*/ */
@ -96,7 +110,7 @@ namespace Jupiter
/** /**
* @brief Default constructor for the DLList class. * @brief Default constructor for the DLList class.
*/ */
DLList(); DLList() = default;
/** /**
* @brief Copy constructor for the DLList class. * @brief Copy constructor for the DLList class.
@ -111,42 +125,35 @@ namespace Jupiter
/** Private members */ /** Private members */
private: private:
Node *head; Node *m_head = nullptr;
Node *end; Node *m_tail = nullptr;
}; };
} }
// Implementation // Implementation
template<typename T> Jupiter::DLList<T>::DLList()
{
Jupiter::DLList<T>::head = nullptr;
Jupiter::DLList<T>::end = nullptr;
Jupiter::List<T>::length = 0;
}
template<typename T> Jupiter::DLList<T>::DLList(const Jupiter::DLList<T> &source) template<typename T> Jupiter::DLList<T>::DLList(const Jupiter::DLList<T> &source)
{ {
Jupiter::List<T>::length = source.length; Jupiter::List<T>::length = source.length;
if (Jupiter::List<T>::length == 0) if (Jupiter::List<T>::length == 0)
{ {
Jupiter::DLList<T>::head = nullptr; m_head = nullptr;
Jupiter::DLList<T>::end = nullptr; m_tail = nullptr;
} }
else if (Jupiter::List<T>::length == 1) else if (Jupiter::List<T>::length == 1)
{ {
Jupiter::DLList<T>::Node *n = new Jupiter::DLList<T>::Node; Jupiter::DLList<T>::Node *n = new Jupiter::DLList<T>::Node;
n->data = source.getNode(0)->data; n->data = source.getNode(0)->data;
Jupiter::DLList<T>::head = n; m_head = n;
Jupiter::DLList<T>::end = n; m_tail = n;
} }
else else
{ {
Jupiter::DLList<T>::Node *sourceNode = source.getNode(0); Jupiter::DLList<T>::Node *sourceNode = source.getNode(0);
Jupiter::DLList<T>::Node *n = new Jupiter::DLList<T>::Node; Jupiter::DLList<T>::Node *n = new Jupiter::DLList<T>::Node;
n->data = sourceNode->data; n->data = sourceNode->data;
Jupiter::DLList<T>::head = n; m_head = n;
sourceNode = sourceNode->next; sourceNode = sourceNode->next;
while (sourceNode->next != nullptr) while (sourceNode->next != nullptr)
@ -161,14 +168,14 @@ template<typename T> Jupiter::DLList<T>::DLList(const Jupiter::DLList<T> &source
n = n->next; n = n->next;
n->data = sourceNode->data; n->data = sourceNode->data;
Jupiter::DLList<T>::end = n; m_tail = n;
} }
} }
template<typename T> Jupiter::DLList<T>::~DLList() template<typename T> Jupiter::DLList<T>::~DLList()
{ {
Jupiter::DLList<T>::Node *p; Jupiter::DLList<T>::Node *p;
Jupiter::DLList<T>::Node *c = Jupiter::DLList<T>::head; Jupiter::DLList<T>::Node *c = m_head;
while (c != nullptr) while (c != nullptr)
{ {
p = c; p = c;
@ -177,16 +184,26 @@ template<typename T> Jupiter::DLList<T>::~DLList()
} }
} }
template<typename T> typename Jupiter::DLList<T>::Node *Jupiter::DLList<T>::getHead() const
{
return m_head;
}
template<typename T> typename Jupiter::DLList<T>::Node *Jupiter::DLList<T>::getTail() const
{
return m_tail;
}
template<typename T> typename Jupiter::DLList<T>::Node *Jupiter::DLList<T>::getNode(size_t index) const template<typename T> typename Jupiter::DLList<T>::Node *Jupiter::DLList<T>::getNode(size_t index) const
{ {
Jupiter::DLList<T>::Node *r; Jupiter::DLList<T>::Node *r;
if (index * 2 < Jupiter::List<T>::length) if (index * 2 < Jupiter::List<T>::length)
{ {
r = Jupiter::DLList<T>::head; r = m_head;
for (size_t i = 0; i < index; i++) r = r->next; for (size_t i = 0; i < index; i++) r = r->next;
return r; return r;
} }
r = Jupiter::DLList<T>::end; r = m_tail;
for (size_t i = Jupiter::List<T>::length - 1; i > index; i--) r = r->previous; for (size_t i = Jupiter::List<T>::length - 1; i > index; i--) r = r->previous;
return r; return r;
} }
@ -203,16 +220,16 @@ template<typename T> T *Jupiter::DLList<T>::remove(size_t index)
template<typename T> T *Jupiter::DLList<T>::remove(Node *data) template<typename T> T *Jupiter::DLList<T>::remove(Node *data)
{ {
if (Jupiter::DLList<T>::head == data) if (m_head == data)
{ {
Jupiter::DLList<T>::head = data->next; m_head = data->next;
if (data->next != nullptr) data->next->previous = data->previous; if (data->next != nullptr) data->next->previous = data->previous;
else Jupiter::DLList<T>::end = nullptr; else m_tail = nullptr;
} }
else if (Jupiter::DLList<T>::end == data) else if (m_tail == data)
{ {
Jupiter::DLList<T>::end = data->previous; m_tail = data->previous;
Jupiter::DLList<T>::end->next = nullptr; m_tail->next = nullptr;
} }
else else
{ {
@ -231,16 +248,16 @@ template<typename T> void Jupiter::DLList<T>::add(T *data, size_t index)
node->data = data; node->data = data;
if (index == 0) if (index == 0)
{ {
node->next = Jupiter::DLList<T>::head; node->next = m_head;
Jupiter::DLList<T>::head->previous = node; m_head->previous = node;
Jupiter::DLList<T>::head = node; m_head = node;
node->previous = nullptr; node->previous = nullptr;
} }
else if (index == Jupiter::List<T>::length) else if (index == Jupiter::List<T>::length)
{ {
node->previous = Jupiter::DLList<T>::end; node->previous = m_tail;
Jupiter::DLList<T>::end->next = node; m_tail->next = node;
Jupiter::DLList<T>::end = node; m_tail = node;
node->next = nullptr; node->next = nullptr;
} }
else else
@ -261,15 +278,15 @@ template<typename T> void Jupiter::DLList<T>::add(T *data)
n->next = nullptr; n->next = nullptr;
if (Jupiter::List<T>::length == 0) if (Jupiter::List<T>::length == 0)
{ {
Jupiter::DLList<T>::head = n; m_head = n;
Jupiter::DLList<T>::end = n; m_tail = n;
n->previous = nullptr; n->previous = nullptr;
} }
else else
{ {
n->previous = Jupiter::DLList<T>::end; n->previous = m_tail;
Jupiter::DLList<T>::end->next = n; m_tail->next = n;
Jupiter::DLList<T>::end = n; m_tail = n;
} }
Jupiter::List<T>::length++; Jupiter::List<T>::length++;
} }

49
Jupiter/Hash.c

@ -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;
}

83
Jupiter/Hash.cpp

@ -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;
}

98
Jupiter/Hash.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2015 Jessica James. * Copyright (C) 2015-2016 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -24,53 +24,121 @@
* @brief Defines some hashing algorithms. * @brief Defines some hashing algorithms.
*/ */
#include "Jupiter.h"
#if defined __cplusplus
#include <cstdint> #include <cstdint>
#include "Jupiter.h"
#include "Readable_String.h"
namespace Jupiter namespace Jupiter
{ {
/** Sums */
template<typename T = char, typename R = uint64_t> inline R calcsum(const T *in_data, size_t in_length);
template<typename T = char, typename R = uint64_t> inline R calcsum(const Jupiter::Readable_String<T> &str);
/** Fowler-Noll-Vo hash algorithms */ /** Fowler-Noll-Vo hash algorithms */
template<typename T> inline uint64_t fnv1(const T &data);
template<typename T = char> inline uint64_t fnv1(const T *str, size_t length); template<typename T = char> inline uint64_t fnv1(const T *str, size_t length);
template<typename T = char> inline uint64_t fnv1(const Jupiter::Readable_String<T> &str); template<typename T = char> inline uint64_t fnv1(const Jupiter::Readable_String<T> &str);
template<typename T> inline uint32_t fnv1_32(const T &data);
template<typename T = char> inline uint32_t fnv1_32(const T *str, size_t length);
template<typename T = char> inline uint32_t fnv1_32(const Jupiter::Readable_String<T> &str);
template<typename T> inline uint64_t fnv1a(const T &data);
template<typename T = char> inline uint64_t fnv1a(const T *str, size_t length); template<typename T = char> inline uint64_t fnv1a(const T *str, size_t length);
template<typename T = char> inline uint64_t fnv1a(const Jupiter::Readable_String<T> &str); template<typename T = char> inline uint64_t fnv1a(const Jupiter::Readable_String<T> &str);
template<typename T> inline uint32_t fnv1a_32(const T &data);
template<typename T = char> inline uint32_t fnv1a_32(const T *str, size_t length);
template<typename T = char> inline uint32_t fnv1a_32(const Jupiter::Readable_String<T> &str);
JUPITER_API uint64_t fnv1(const uint8_t *data, const uint8_t *end);
JUPITER_API uint64_t fnv1a(const uint8_t *data, const uint8_t *end);
JUPITER_API uint32_t fnv1_32(const uint8_t *data, const uint8_t *end);
JUPITER_API uint32_t fnv1a_32(const uint8_t *data, const uint8_t *end);
} }
extern "C" /** Calcsum implementation */
template<typename T, typename R> inline R Jupiter::calcsum(const T *in_data, size_t in_length)
{ {
#else const uint8_t *itr = reinterpret_cast<const uint8_t *>(in_data);
#include <stdint.h> const uint8_t *end = reinterpret_cast<const uint8_t *>(in_data + in_length);
#endif // __cplusplus R sum = 0;
JUPITER_API uint64_t Jupiter_fnv1(void *data, size_t length); while (itr != end)
JUPITER_API uint64_t Jupiter_fnv1a(void *data, size_t length); {
sum += *itr;
++itr;
}
#if defined __cplusplus return sum;
}
template<typename T, typename R> inline R Jupiter::calcsum(const Jupiter::Readable_String<T> &str)
{
return Jupiter::calcsum<T, R>(str.ptr(), str.size());
} }
/** fnv1 implementation */ /** fnv1 implementation */
template<typename T> inline uint64_t Jupiter::fnv1(const T &data)
{
return Jupiter::fnv1(&data, &data + 1);
}
template<typename T> inline uint64_t Jupiter::fnv1(const T *data, size_t length) template<typename T> inline uint64_t Jupiter::fnv1(const T *data, size_t length)
{ {
return Jupiter_fnv1(data, length * sizeof(T)); return Jupiter::fnv1(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length));
} }
template<typename T> inline uint64_t Jupiter::fnv1(const Jupiter::Readable_String<T> &data) template<typename T> inline uint64_t Jupiter::fnv1(const Jupiter::Readable_String<T> &data)
{ {
return Jupiter_fnv1(data.ptr(), data.size() * sizeof(T)); return Jupiter::fnv1(reinterpret_cast<const uint8_t *>(data.ptr()), reinterpret_cast<const uint8_t *>(data.ptr() + data.size()));
}
template<typename T> inline uint32_t Jupiter::fnv1_32(const T &data)
{
return Jupiter::fnv1_32(&data, &data + 1);
}
template<typename T> inline uint32_t Jupiter::fnv1_32(const T *data, size_t length)
{
return Jupiter::fnv1_32(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length));
}
template<typename T> inline uint32_t Jupiter::fnv1_32(const Jupiter::Readable_String<T> &data)
{
return Jupiter::fnv1_32(reinterpret_cast<const uint8_t *>(data.ptr()), reinterpret_cast<const uint8_t *>(data.ptr() + data.size()));
}
template<typename T> inline uint64_t Jupiter::fnv1a(const T &data)
{
return Jupiter::fnv1a(reinterpret_cast<const uint8_t *>(&data), reinterpret_cast<const uint8_t *>(&data + 1));
} }
template<typename T> inline uint64_t Jupiter::fnv1a(const T *data, size_t length) template<typename T> inline uint64_t Jupiter::fnv1a(const T *data, size_t length)
{ {
return Jupiter_fnv1a(data, length * sizeof(T)); return Jupiter::fnv1a(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length));
} }
template<typename T> inline uint64_t Jupiter::fnv1a(const Jupiter::Readable_String<T> &data) template<typename T> inline uint64_t Jupiter::fnv1a(const Jupiter::Readable_String<T> &data)
{ {
return Jupiter_fnv1a(data.ptr(), data.size() * sizeof(T)); return Jupiter::fnv1a(data.ptr(), data.size());
} }
#endif // __cplusplus template<typename T> inline uint32_t Jupiter::fnv1a_32(const T &data)
{
return Jupiter::fnv1a_32(reinterpret_cast<const uint8_t *>(&data), reinterpret_cast<const uint8_t *>(&data + 1));
}
template<typename T> inline uint32_t Jupiter::fnv1a_32(const T *data, size_t length)
{
return Jupiter::fnv1a_32(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length));
}
template<typename T> inline uint32_t Jupiter::fnv1a_32(const Jupiter::Readable_String<T> &data)
{
return Jupiter::fnv1a_32(data.ptr(), data.size());
}
#endif // _HASH_H_HEADER #endif // _HASH_H_HEADER

242
Jupiter/Hash_Table.h

@ -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

317
Jupiter/Hash_Table_Imp.h

@ -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

4
Jupiter/Jupiter.vcxproj

@ -182,7 +182,7 @@
<ClCompile Include="File.cpp" /> <ClCompile Include="File.cpp" />
<ClCompile Include="Functions.c" /> <ClCompile Include="Functions.c" />
<ClCompile Include="GenericCommand.cpp" /> <ClCompile Include="GenericCommand.cpp" />
<ClCompile Include="Hash.c" /> <ClCompile Include="Hash.cpp" />
<ClCompile Include="HTTP_Server.cpp" /> <ClCompile Include="HTTP_Server.cpp" />
<ClCompile Include="INIFile.cpp" /> <ClCompile Include="INIFile.cpp" />
<ClCompile Include="IRC_Client.cpp" /> <ClCompile Include="IRC_Client.cpp" />
@ -210,6 +210,8 @@
<ClInclude Include="File.h" /> <ClInclude Include="File.h" />
<ClInclude Include="GenericCommand.h" /> <ClInclude Include="GenericCommand.h" />
<ClInclude Include="Hash.h" /> <ClInclude Include="Hash.h" />
<ClInclude Include="Hash_Table.h" />
<ClInclude Include="Hash_Table_Imp.h" />
<ClInclude Include="HTTP.h" /> <ClInclude Include="HTTP.h" />
<ClInclude Include="HTTP_QueryString.h" /> <ClInclude Include="HTTP_QueryString.h" />
<ClInclude Include="HTTP_Server.h" /> <ClInclude Include="HTTP_Server.h" />

21
Jupiter/Jupiter.vcxproj.filters

@ -55,6 +55,9 @@
<Filter Include="Source Files\HTTP"> <Filter Include="Source Files\HTTP">
<UniqueIdentifier>{7a4d818a-481e-467c-a3e3-d6d0e7dde244}</UniqueIdentifier> <UniqueIdentifier>{7a4d818a-481e-467c-a3e3-d6d0e7dde244}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Header Files\Hash">
<UniqueIdentifier>{7db21243-8b23-4dd2-9888-0bdd3c5a1edd}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Functions.c"> <ClCompile Include="Functions.c">
@ -105,9 +108,6 @@
<ClCompile Include="IRC_Client.cpp"> <ClCompile Include="IRC_Client.cpp">
<Filter>Source Files\IRC</Filter> <Filter>Source Files\IRC</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Hash.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DataBuffer.cpp"> <ClCompile Include="DataBuffer.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -123,6 +123,9 @@
<ClCompile Include="Command.cpp"> <ClCompile Include="Command.cpp">
<Filter>Source Files\Object Extensions</Filter> <Filter>Source Files\Object Extensions</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Hash.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Functions.h"> <ClInclude Include="Functions.h">
@ -233,9 +236,6 @@
<ClInclude Include="Reference_String_Imp.h"> <ClInclude Include="Reference_String_Imp.h">
<Filter>Header Files\Strings</Filter> <Filter>Header Files\Strings</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Hash.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Database.h"> <ClInclude Include="Database.h">
<Filter>Header Files\Files</Filter> <Filter>Header Files\Files</Filter>
</ClInclude> </ClInclude>
@ -260,6 +260,15 @@
<ClInclude Include="Command.h"> <ClInclude Include="Command.h">
<Filter>Header Files\Object Extensions</Filter> <Filter>Header Files\Object Extensions</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Hash.h">
<Filter>Header Files\Hash</Filter>
</ClInclude>
<ClInclude Include="Hash_Table.h">
<Filter>Header Files\Hash</Filter>
</ClInclude>
<ClInclude Include="Hash_Table_Imp.h">
<Filter>Header Files\Hash</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="Jupiter.rc"> <ResourceCompile Include="Jupiter.rc">

358
Jupiter/SLList.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2013-2015 Jessica James. * Copyright (C) 2013-2016 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -45,13 +45,27 @@ namespace Jupiter
T *data = nullptr; T *data = nullptr;
}; };
/*
* @brief Returns the head of the list
*
* @return Head of the list
*/
Node *getHead() const;
/*
* @brief Returns the tail of the list
*
* @return Tail of the list
*/
Node *getTail() const;
/** /**
* @brief Returns the n'th Node in the list. * @brief Returns the Node at the specified index in the list.
* *
* @param n Index of the node to return. * @param index Index of the node to return.
* @return n'th Node in the list. * @return Node at specified index in the list.
*/ */
Node *getNode(size_t n) const; Node *getNode(size_t index) const;
/** /**
* @brief Gets the data at a specified index. * @brief Gets the data at a specified index.
@ -61,6 +75,13 @@ namespace Jupiter
*/ */
T *get(size_t index) const; T *get(size_t index) const;
/**
* @brief Removes the head of the list
*
* @return Value that was stored in the head of the list
*/
T *removeHead();
/** /**
* @brief Removes the n'th Node in the list, and returns its contents. * @brief Removes the n'th Node in the list, and returns its contents.
* *
@ -78,29 +99,58 @@ namespace Jupiter
T *removeNext(Node *data); T *removeNext(Node *data);
/** /**
* @brief Adds data to the list at a specified index. * @brief Adds data to the end of the list.
* *
* @param data Data to add to the list. * @param data Data to add to the list.
* @param index Position in the list to add the data to. */
void add(T *data);
/**
* @brief Inserts data to the specified index in the list.
*
* @param data Data to insert into the list.
* @param index Position in the list to insert data to.
*/ */
void add(T *data, size_t index); void add(T *data, size_t index);
/** /**
* @brief Adds data to the front of the list. * @brief Inserts data to the head of the list.
* *
* @param data Data to add to the list. * @param data Data to insert into the list.
*/ */
void add(T *data); void addHead(T *data);
/**
* @breif Erases all entries in the list
*/
void erase();
/**
* @breif Erases and deletes all entries in the list
*/
void eraseAndDelete();
SLList &operator=(const SLList &in_list);
SLList &operator=(SLList &&in_list);
/** /**
* @brief Default constructor for the SLList class. * @brief Default constructor for the SLList class.
*/ */
SLList(); SLList() = default;
/** /**
* @brief Copy constructor for the SLList class. * @brief Copy constructor for the SLList class.
*
* @param in_list List to copy data from
*/ */
SLList(const SLList<T> &); SLList(const SLList<T> &in_list);
/**
* @brief Move constructor for the SLList class
*
* @param in_list List to move data from
*/
SLList(SLList<T> &&in_list);
/** /**
* @brief Destructor for the SLList class. * @brief Destructor for the SLList class.
@ -110,105 +160,200 @@ namespace Jupiter
/** Private members */ /** Private members */
private: private:
Node *head; void copy_from_internal(const SLList<T> &in_list);
Node *m_head = nullptr;
Node *m_tail = nullptr;
}; };
} }
// Implementation // Implementation
template<typename T> Jupiter::SLList<T>::SLList() template<typename T> typename Jupiter::SLList<T>::Node *Jupiter::SLList<T>::getHead() const
{ {
Jupiter::SLList<T>::head = new Jupiter::SLList<T>::Node(); return m_head;
Jupiter::List<T>::length = 0;
} }
template<typename T> Jupiter::SLList<T>::SLList(const Jupiter::SLList<T> &source) template<typename T> typename Jupiter::SLList<T>::Node *Jupiter::SLList<T>::getTail() const
{ {
Jupiter::SLList<T>::head = new Jupiter::SLList<T>::Node(); return m_tail;
Jupiter::SLList<T>::Node *sourceNode = source.head; }
head->data = sourceNode->data; template<typename T> typename Jupiter::SLList<T>::Node *Jupiter::SLList<T>::getNode(size_t in_index) const
sourceNode = sourceNode->next; {
if (in_index == Jupiter::SLList<T>::length)
return m_tail;
Jupiter::SLList<T>::Node *n = Jupiter::SLList<T>::head; Jupiter::SLList<T>::Node *node = m_head;
while (sourceNode != nullptr) while (in_index != 0)
{ {
n->next = new Jupiter::SLList<T>::Node(); node = node->next;
n = n->next; --in_index;
n->data = sourceNode->data;
sourceNode = sourceNode->next;
} }
Jupiter::List<T>::length = source.length;
return node;
} }
template<typename T> Jupiter::SLList<T>::~SLList() template<typename T> T *Jupiter::SLList<T>::get(size_t in_index) const
{ {
Jupiter::SLList<T>::Node *p; return Jupiter::SLList<T>::getNode(in_index)->data;
Jupiter::SLList<T>::Node *c = head;
do
{
p = c;
c = c->next;
delete p;
} while (c != nullptr);
} }
template<typename T> typename Jupiter::SLList<T>::Node *Jupiter::SLList<T>::getNode(size_t index) const template<typename T> T *Jupiter::SLList<T>::removeHead()
{ {
Jupiter::SLList<T>::Node *t = head->next; if (m_head == nullptr)
for (size_t i = 0; i != index; i++) t = t->next; return nullptr;
return t;
T *result = m_head->data;
Jupiter::SLList<T>::Node *node = m_head;
m_head = m_head->next;
delete node;
--Jupiter::List<T>::length;
return result;
} }
template<typename T> T *Jupiter::SLList<T>::get(size_t index) const template<typename T> T *Jupiter::SLList<T>::remove(size_t in_index)
{ {
return Jupiter::SLList<T>::getNode(index)->data; if (in_index == 0)
return Jupiter::SLList<T>::removeHead();
Jupiter::SLList<T>::Node *node = m_head;
while (in_index != 1)
{
node = node->next;
--in_index;
}
Jupiter::SLList<T>::Node *tmp = node->next;
T *result = tmp->data;
node->next = tmp->next;
delete tmp;
--Jupiter::List<T>::length;
return result;
} }
template<typename T> T *Jupiter::SLList<T>::remove(size_t index) template<typename T> T *Jupiter::SLList<T>::removeNext(Node *in_data)
{ {
Jupiter::SLList<T>::Node *t = head; Jupiter::SLList<T>::Node *node = in_data->next;
for (size_t i = 0; i != index; i++)
t = t->next; if (node == nullptr)
Jupiter::SLList<T>::Node *t2 = t->next; return nullptr;
t->next = t2->next;
T *r = t2->data; T *result = node->data;
delete t2;
in_data->next = node->next;
delete node;
--Jupiter::List<T>::length; --Jupiter::List<T>::length;
return r;
return result;
}
template<typename T> void Jupiter::SLList<T>::add(T *data)
{
Jupiter::SLList<T>::Node *node = new Jupiter::SLList<T>::Node();
node->data = data;
if (m_head == nullptr)
m_head = node;
else
m_tail->next = node;
m_tail = node;
++Jupiter::List<T>::length;
}
template<typename T> void Jupiter::SLList<T>::add(T *in_data, size_t in_index)
{
if (in_index == 0)
{
Jupiter::SLList<T>::addHead(in_data);
return;
}
if (in_index >= Jupiter::List<T>::length)
{
Jupiter::SLList<T>::add(in_data);
return;
}
Jupiter::SLList<T>::Node *node = new Jupiter::SLList<T>::Node();
node->data = in_data;
Jupiter::SLList<T>::Node *itr = m_head;
while (in_index != 1)
{
itr = itr->next;
--in_index;
}
node->next = itr->next;
itr->next = node;
++Jupiter::List<T>::length;
} }
template<typename T> T *Jupiter::SLList<T>::removeNext(Node *data) template<typename T> void Jupiter::SLList<T>::addHead(T *data)
{ {
Jupiter::SLList<T>::Node *t = data->next; Jupiter::SLList<T>::Node *node = new Jupiter::SLList<T>::Node();
if (t == nullptr) return nullptr; node->data = data;
T *r = t->data; node->next = m_head;
data->next = t->next; m_head = node;
delete t;
Jupiter::List<T>::length--; if (m_tail == nullptr)
return r; m_tail = node;
++Jupiter::List<T>::length;
} }
template<typename T> void Jupiter::SLList<T>::add(T *data, size_t index) template<typename T> void Jupiter::SLList<T>::erase()
{ {
Jupiter::SLList<T>::Node *n = new Jupiter::SLList<T>::Node(); Jupiter::SLList<T>::Node *node = m_head;
n->data = data;
Jupiter::SLList<T>::Node *t = Jupiter::SLList<T>::head; if (node == nullptr)
for (size_t i = 0; i < index; i++) t = t->next; return;
n->next = t->next;
t->next = n; Jupiter::SLList<T>::Node *tmp;
Jupiter::List<T>::length++;
do
{
tmp = node;
node = node->next;
delete tmp;
} while (node != nullptr);
m_head = nullptr;
m_tail = nullptr;
Jupiter::List<T>::length = 0;
} }
template<typename T> void Jupiter::SLList<T>::add(T *data) template<typename T> void Jupiter::SLList<T>::eraseAndDelete()
{ {
Jupiter::SLList<T>::Node *n = new Jupiter::SLList<T>::Node(); Jupiter::SLList<T>::Node *node = m_head;
n->data = data;
n->next = Jupiter::SLList<T>::head->next; if (node == nullptr)
Jupiter::SLList<T>::head->next = n; return;
Jupiter::List<T>::length++;
Jupiter::SLList<T>::Node *tmp;
do
{
tmp = node;
node = node->next;
delete tmp->data;
delete tmp;
} while (node != nullptr);
m_head = nullptr;
m_tail = nullptr;
Jupiter::List<T>::length = 0;
} }
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::SLList> template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::SLList>
@ -216,7 +361,7 @@ template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::SLLis
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::SLList<Y> *data) template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::SLList<Y> *data)
{ {
buffer->push<size_t>(data->size()); buffer->push<size_t>(data->size());
Jupiter::SLList<Y>::Node *head = data->getNode(0); Jupiter::SLList<Y>::Node *head = data->getHead();
while (head != nullptr) while (head != nullptr)
buffer->push<Y>(*head++->data); buffer->push<Y>(*head++->data);
}; };
@ -232,4 +377,65 @@ template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::SLLis
} }
}; };
template<typename T> Jupiter::SLList<T> &Jupiter::SLList<T>::operator=(const SLList &in_list)
{
Jupiter::SLList<T>::erase();
Jupiter::SLList<T>::copy_from_internal(in_list);
return *this;
}
template<typename T> Jupiter::SLList<T> &Jupiter::SLList<T>::operator=(SLList &&in_list)
{
m_head = in_list.m_head;
m_tail = in_list.m_tail;
return *this;
}
template<typename T> Jupiter::SLList<T>::SLList(const Jupiter::SLList<T> &in_list)
{
Jupiter::SLList<T>::copy_from_internal(in_list);
}
template<typename T> Jupiter::SLList<T>::SLList(Jupiter::SLList<T> &&in_list)
{
m_head = in_list.m_head;
m_tail = in_list.m_tail;
in_list.m_head = nullptr;
in_list.m_tail = nullptr;
}
template<typename T> Jupiter::SLList<T>::~SLList()
{
Jupiter::SLList<T>::erase();
}
/** Internal */
template<typename T> void Jupiter::SLList<T>::copy_from_internal(const SLList<T> &in_list)
{
Jupiter::SLList<T>::Node *source_node = in_list.m_head;
if (source_node == nullptr)
return;
Jupiter::SLList<T>::Node *node = new Jupiter::SLList<T>::Node();
node->data = source_node->data;
source_node = source_node->next;
while (source_node != nullptr)
{
node->next = new Jupiter::SLList<T>::Node();
node = node->next;
node->data = source_node->data;
source_node = source_node->next;
}
m_tail = node;
Jupiter::List<T>::length = in_list.length;
}
#endif // _SLLIST_H_HEADER #endif // _SLLIST_H_HEADER

1
Jupiter/String_Imp.h

@ -22,7 +22,6 @@
/** /**
* @file String_Imp.h * @file String_Imp.h
* @brief Provides the implementations for String_Strict and String_Loose. * @brief Provides the implementations for String_Strict and String_Loose.
* Note: Modification of this file is not supported in any way.
*/ */
#include "String.h" #include "String.h"

BIN
Release/Jupiter.lib

Binary file not shown.

37
Tester/Test.cpp

@ -1,6 +1,7 @@
#include <chrono> #include <chrono>
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <thread>
#include "Jupiter/Functions.h" #include "Jupiter/Functions.h"
#include "Jupiter/CString.h" #include "Jupiter/CString.h"
#include "Jupiter/String.h" #include "Jupiter/String.h"
@ -9,6 +10,11 @@
#include "Jupiter/InvalidIndex.h" #include "Jupiter/InvalidIndex.h"
#include "Jupiter/Reference_String.h" #include "Jupiter/Reference_String.h"
#include "Jupiter/DataBuffer.h" #include "Jupiter/DataBuffer.h"
#include "Jupiter/HTTP.h"
#include "Jupiter/HTTP_Server.h"
#include "Jupiter/HTTP_QueryString.h"
#include "Jupiter/Hash.h"
#include "Jupiter/Hash_Table.h"
using namespace Jupiter; using namespace Jupiter;
using namespace Jupiter::literals; using namespace Jupiter::literals;
@ -18,16 +24,35 @@ unsigned int totalTests = 0;
void test(bool expr) void test(bool expr)
{ {
totalTests++; ++totalTests;
if (expr) goodTests++; if (expr)
else printf("Test number %u failed!" ENDL, totalTests); ++goodTests;
else
printf("Test number %u failed!" ENDL, totalTests);
}
Jupiter::StringS randstr(size_t length)
{
StringS str;
while (length != 0)
{
str += ' ' + rand() % ('z' - ' ');
--length;
}
return str;
} }
int main() int main()
{ {
if (goodTests == totalTests) printf("All %u tests succeeded." ENDL, totalTests); if (goodTests == totalTests)
else printf("ERROR: Only %u/%u tests succeeded. %u tests failed." ENDL, goodTests, totalTests, totalTests - goodTests); printf("All %u tests succeeded." ENDL, totalTests);
else
printf("ERROR: Only %u/%u tests succeeded. %u tests failed." ENDL, goodTests, totalTests, totalTests - goodTests);
puts("Press any key to continue..."); puts("Press any key to continue...");
fgetc(stdin); fgetc(stdin);
return 0; return 0;
} }

Loading…
Cancel
Save