Skip to content

Instantly share code, notes, and snippets.

@Venemo
Created May 11, 2015 22:03
Show Gist options
  • Save Venemo/9c4d83130c6294b958c5 to your computer and use it in GitHub Desktop.
Save Venemo/9c4d83130c6294b958c5 to your computer and use it in GitHub Desktop.
/**
* 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