Skip to content

Instantly share code, notes, and snippets.

@Rycieos
Created January 25, 2016 18:24
Show Gist options
  • Save Rycieos/c3f4fbc73acbd396cd40 to your computer and use it in GitHub Desktop.
Save Rycieos/c3f4fbc73acbd396cd40 to your computer and use it in GitHub Desktop.
template<typename Item>
class Array {
private:
unsigned int first_, last_, capacity_, size_;
Item* myArray;
public:
/*!
* Array constructor method.
* @param size The maximum capacity of the Array.
*/
// This is a standard constructor, simply creates a basic array
// Note that the reason for this Array class instead of using a
// normal List or Vector is that this needs to be static and fast to
// handle the large amounts of video objects being strung through it
// thousands of times per second. This design prevents hangs from
// dynamic size increases.
Array(unsigned int size) {
capacity_ = size;
myArray = new Item[size];
myArray[0] = nullptr;
first_ = last_ = size_ = 0;
}
/*!
* Array destructor method.
* Frees up memory allocated to an Array instance.
*/
virtual ~Array() {
clear();
delete[] myArray;
}
/*!
* Empties the internal array and resets it, deleting contained objects.
*/
// This is the complicated part. Since the first and last locations are arbitrary,
// we need to loop from the first to the last, but we might need to wrap around.
// We could simply clear the entire array from the actual start to the end, but if
// the whole array is not full, that is a large waste of time.
void clear() {
if (first_ > last_) { // Check if the array wraps around
for (; first_ < capacity_; first_++) { // Delete from first to the end (but only if it wraps around)
delete myArray[first_];
myArray[first_] = nullptr; // We do not need to do this pointer reset, but it adds almost no time and is safer
}
first_ = 0; // Move first to the beginning
}
for (; first_ <= last_; first_++) { // Delete from first to last (if it wrapped around, first is now 0, the beginning)
delete myArray[first_];
myArray[first_] = nullptr;
}
first_ = last_ = size_ = 0; // Reset all vars
}
/*!
* Empties the internal array but does not delete the objects it contains.
* \note This method doesn't delete the shapes inside of it; it only moves pointers around.
* \warning <b>This will result in a memory leak if the objects are not pointed to anywhere else!</b>
*/
// This method is needed if the contents of this Array are dumpped into some other storage, meaning that
// the objects cannot be deleted. It is rarely used, but the design called for a way to drop the pointers of the Array.
// It would be easier to delete the array object and create a new one, but this clear loop is almost always faster, and
// if we did not care about clearing the
void shallowClear() {
if (first_ > last_) { // If the array wraps around...
for (; first_ < capacity_; first_++) // Delete from first to the end
myArray[first_] = nullptr;
first_ = 0; // Move first to the beginning
}
for (; first_ <= last_; first_++) // Delete from first to last
myArray[first_] = nullptr;
first_ = last_ = size_ = 0; // Reset all vars
}
/*!
* Returns the item at index index.
* @param index The index of the item in the internal array.
* @note This is the read version of the subscript operator.
* @eturn The item at index index.
*/
// I will only comment on the first of these, since they do the same thing/
// This is where the boundry checking happens, to prevent reading outside real data.
// Note that although the user is requesting an Item at an index, the index given is not
// the same in the underlying array. This is where the shifting comes into play.
// Also note that since the array is designed to wrap around, most often the user is not
// going to use this [] operator and will just use push(), pop(), first(), and last(), making this
// Array much like a list.
const Item& operator[](unsigned int index) const {
if (size_ == 0)
throw std::out_of_range("Array::operator[](): array is empty");
else if (index >= size_)
throw std::out_of_range("Array::operator[](): index is larger than number of items in array");
else
return myArray[(first_ + index) % capacity_]; // Wrap around for the underlying array
}
/*!
* Returns the item at index index.
* @param index The index of the item in the internal array.
* @note This is the write version of the subscript operator.
* @eturn The item at index index.
*/
Item& operator[](unsigned int index) {
if (size_ == 0) {
throw std::out_of_range("Array::operator[](): array is empty");
} else if (index >= size_) {
throw std::out_of_range("Array::operator[](): index is larger than number of items in array");
} else {
return myArray[(first_ + index) % capacity_]; // Wrap around for the underlying array
}
}
/*! Returns the number of items in the internal array. */
unsigned int size() const {
return size_;
}
/*! Returns the maximum amount of items the internal array can store. */
unsigned int capacity() const {
return capacity_;
}
/*! Returns true if the internal array contains no items, false otherwise. */
bool isEmpty() const {
return (size_ == 0);
}
/*!
* Adds the item to the end of the internal array.
* @note If the internal array is full, push() will remove the oldest item.
* @param item The item to add.
* @return The same item.
*/
// This is the complicated part of the Array. Since the array can wrap around the
// true pysical end of the memory array, we need to handle that as well as the case
// of a full array. This is done with some careful logic using our first_, last_, and capacity_
// variables.
Item push(Item item) {
if (myArray[first_] != nullptr) // If the array has items (the first item is not null)
(last_ + 1) == capacity_ ? last_ = 0 : last_++; // Increment last (the index of our new item) (handle wrap around)
if (last_ == first_ && myArray[first_] != nullptr) { // If the array is out of room (ie. if our new last index == our first)
// (but also double check to make sure the array is not empty)
delete myArray[first_]; // Delete the first element
(first_ + 1) == capacity_ ? first_ = 0 : first_++; // Increment first (the index of the deleted item) (handle wrap around)
} else
size_++; // Otherwise (we were not out of room), we added an item (so size goes up)
return myArray[last_] = item; // Actually add the item (now that our indexes are fixed)
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment