Created
May 11, 2015 22:03
-
-
Save Venemo/9c4d83130c6294b958c5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Collection that stores the number of elements and the actual elements | |
* in a contiguous chunk of memory, making it ideal for a number of use cases. | |
*/ | |
template<typename T> | |
class Array final { | |
private: | |
bool ownsData; | |
void *data; | |
public: | |
/** | |
* Initializes an Array. | |
*/ | |
explicit Array() { | |
this->data = new std::uint8_t[sizeof(std::uint32_t) / sizeof(std::uint8_t)]; | |
this->ownsData = true; | |
*reinterpret_cast<std::uint32_t*>(data) = 0; | |
} | |
/** | |
* Destroys the Array. | |
*/ | |
~Array() { | |
if (this->ownsData) { | |
// Delete data if we owned it | |
delete [] reinterpret_cast<std::uint8_t*>(this->data); | |
} | |
} | |
/** | |
* Gets the number of items in the Array. | |
*/ | |
inline std::uint32_t count() const { | |
return *reinterpret_cast<std::uint32_t*>(data); | |
} | |
/** | |
* Gets the item at the given position. | |
*/ | |
inline T operator[](std::uint32_t i) const { | |
if (i >= this->count()) { | |
throw std::out_of_range("You are out of range of the Array"); | |
} | |
return *(reinterpret_cast<T*>(reinterpret_cast<std::uint32_t*>(data) + 1) + i); | |
} | |
/** | |
* Tells whether the Array contains an item or not. | |
*/ | |
inline bool contains(const T &t) const { | |
for (std::uint32_t x = 0; x < this->count(); x++) { | |
if (this->operator[](x) == t) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* Removes an item from the Array. | |
*/ | |
inline void remove(const T &t) { | |
for (std::uint32_t x = 0; x < this->count(); x++) { | |
if (this->operator[](x) == t) { | |
this->removeAt(x); | |
} | |
} | |
} | |
/** | |
* Removes the item at the given position. | |
*/ | |
inline void removeAt(std::uint32_t i) { | |
if (i >= this->count()) { | |
throw std::out_of_range("You are out of range of the Array"); | |
} | |
// Get new count | |
auto nc = this->count() - 1; | |
// Allocate new buffer | |
auto *buf = new std::uint8_t[(sizeof(T) * nc + sizeof(std::uint32_t)) / sizeof(std::uint8_t)]; | |
// Set new count | |
*reinterpret_cast<std::uint32_t*>(buf) = nc; | |
// Copy old data | |
std::uint32_t x; | |
for (x = 0; x < i; x++) { | |
*(reinterpret_cast<T*>(reinterpret_cast<std::uint32_t*>(buf) + 1) + x) = *(reinterpret_cast<T*>(reinterpret_cast<std::uint32_t*>(this->data) + 1) + x); | |
} | |
for (; x < nc; x++) { | |
*(reinterpret_cast<T*>(reinterpret_cast<std::uint32_t*>(buf) + 1) + x) = *(reinterpret_cast<T*>(reinterpret_cast<std::uint32_t*>(this->data) + 1) + x + 1); | |
} | |
// Set ownership and new data | |
if (this->ownsData) { | |
// Delete data if we owned it | |
delete [] reinterpret_cast<std::uint8_t*>(this->data); | |
} | |
this->data = buf; | |
this->ownsData = true; | |
} | |
/** | |
* Adds an item to the Array. | |
*/ | |
inline void append(T t) { | |
auto nc = this->count() + 1; | |
// Allocate new buffer | |
auto *buf = new std::uint8_t[(sizeof(T) * nc + sizeof(std::uint32_t)) / sizeof(std::uint8_t)]; | |
// Set new count | |
*reinterpret_cast<std::uint32_t*>(buf) = nc; | |
// Copy old data | |
std::uint32_t x; | |
for (x = 0; x < nc - 1; x++) { | |
*(reinterpret_cast<T*>(reinterpret_cast<std::uint32_t*>(buf) + 1) + x) = *(reinterpret_cast<T*>(reinterpret_cast<std::uint32_t*>(this->data) + 1) + x); | |
} | |
// Append new data | |
*(reinterpret_cast<T*>(reinterpret_cast<std::uint32_t*>(buf) + 1) + x) = t; | |
// Set ownership and new data | |
if (this->ownsData) { | |
// Delete data if we owned it | |
delete [] reinterpret_cast<std::uint8_t*>(this->data); | |
} | |
this->data = buf; | |
this->ownsData = true; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment