#ifndef LIST_H #define LIST_H #include #include #include "utils/StringBuffer.h" template class List final { int length; int capacity; T* data; public: List() : length(0), capacity(0), data(nullptr) { } List(const List& other) : length(0), capacity(other.capacity), data(allocate(capacity)) { for(int i = 0; i < other.length; i++) { add(other[i]); } } List(List&& other) : List() { swap(other); } ~List() { clear(); delete[] reinterpret_cast(data); } List& operator=(List other) { swap(other); return *this; } T* begin() { return data; } T* end() { return data + length; } const T* begin() const { return data; } const T* end() const { return data + length; } void reserve(int n) { if(n <= capacity) { return; } List copy; copy.capacity = n; copy.data = allocate(n); for(int i = 0; i < length; i++) { copy.add(std::move(data[i])); } swap(copy); } void shrink() { if(length == capacity) { return; } List copy; copy.capacity = length; copy.data = allocate(length); for(int i = 0; i < length; i++) { copy.add(std::move(data[i])); } swap(copy); } void resize(int n, const T& t) { if(length < n) { reserve(n); for(int i = length; i < n; i++) { add(t); } } else if(length > n) { for(int i = n; i < length; i++) { data[i].~T(); } length = n; } } void resize(int n) { if(length < n) { reserve(n); for(int i = length; i < n; i++) { add(T()); } } else if(length > n) { for(int i = n; i < length; i++) { data[i].~T(); } length = n; } } template List& add(Args&&... args) { ensureCapacity(); new(data + length++) T(std::forward(args)...); return *this; } T& operator[](int index) { return data[index]; } const T& operator[](int index) const { return data[index]; } int getLength() const { return length; } int getCapacity() const { return capacity; } void clear() { for(int i = 0; i < length; i++) { data[i].~T(); } length = 0; } void removeBySwap(int index) { length--; if(index != length) { data[index] = std::move(data[length]); } data[length].~T(); } void remove(int index) { length--; for(int i = index; i < length; i++) { data[i] = std::move(data[i + 1]); } data[length].~T(); } template void toString(StringBuffer& s) const { s.append("["); for(int i = 0; i < length - 1; i++) { s.append(data[i]); s.append(", "); } if(length > 0) { s.append(data[length - 1]); } s.append("]"); } private: static T* allocate(int n) { return reinterpret_cast(new char[sizeof(T) * n]); } void swap(List& other) { std::swap(length, other.length); std::swap(capacity, other.capacity); std::swap(data, other.data); } void ensureCapacity() { if(length >= capacity) { reserve(capacity == 0 ? 8 : capacity * 2); } } }; #endif