#ifndef VECTOR_H #define VECTOR_H #include #include #include "assert.h" #include "kmem.hpp" #include "string.h" class VectorTester; template class Vector { friend VectorTester; public: Vector() noexcept { _data = static_cast(kmalloc(_capacity * sizeof(T))); } explicit Vector(size_t n) noexcept { _capacity = n; _cur_size = n; _data = static_cast(kmalloc(_capacity * sizeof(T))); } Vector(std::initializer_list l) noexcept { _cur_size = l.size(); _capacity = _cur_size > 0 ? _cur_size : 2; _data = static_cast(kmalloc(_capacity * sizeof(T))); size_t i = 0; for (auto const &el: l) { new (_data + (i++)) T(el); } } Vector(Vector const &vec) noexcept { _cur_size = vec._cur_size; _capacity = _cur_size > 0 ? _cur_size : 2; _data = static_cast(kmalloc(_capacity * sizeof(T))); for (size_t i = 0; i < _cur_size; i++) new (_data + i) T(vec._data[i]); } Vector(Vector &&v) noexcept { _cur_size = v._cur_size; _capacity = v._capacity; _data = v._data; v._data = nullptr; } Vector &operator=(Vector vec) noexcept { std::swap(vec._data, _data); std::swap(vec._cur_size, _cur_size); std::swap(vec._capacity, _capacity); return *this; } ~Vector() noexcept { if (_data == nullptr) return; if constexpr (!std::is_trivially_destructible::value) for (size_t i = 0; i < _cur_size; i++) _data[i].~T(); kfree(_data); _data = nullptr; } template void emplace_back(Args &&...args) { if (_capacity == _cur_size) { _capacity *= 2; //Ugly hack to get around g++ warnings _data = (T *) krealloc(reinterpret_cast(_data), _capacity * sizeof(T)); assert(_data != nullptr); } new (_data + (_cur_size++)) T(std::forward(args)...); } void compact() { _data = (T *) krealloc(reinterpret_cast(_data), _cur_size * sizeof(T)); _capacity = _cur_size; } void erase(size_t idx) { if constexpr (!std::is_trivially_destructible::value) (_data + idx)->~T(); //Ugly hack to get around g++ warnings memmove(reinterpret_cast(_data + idx), reinterpret_cast(_data + idx + 1), sizeof(T) * (_cur_size - idx - 1)); _cur_size--; } T &operator[](size_t idx) { return _data[idx]; } T const &operator[](size_t idx) const { return _data[idx]; } bool operator==(Vector const &rhs) const { if (_cur_size != rhs._cur_size) return false; else for (size_t i = 0; i < _cur_size; i++) if (_data[i] != rhs._data[i]) return false; return true; } bool operator!=(Vector const &rhs) const { if (_cur_size != rhs._cur_size) return true; else for (size_t i = 0; i < _cur_size; i++) if (_data[i] != rhs._data[i]) return true; return false; } size_t size() const { return _cur_size; } bool empty() const { return _cur_size == 0; } T &back() { assert(size() != 0); return _data[size() - 1]; } const T &back() const { assert(size() != 0); return _data[size() - 1]; } Vector subvector(size_t start, size_t end) const { Vector out; if (start >= size()) return out; end = end > size() ? size() : end; for (size_t i = start; i < end; i++) { out.emplace_back(_data[i]); } return out; } void resize(size_t size) { if (size == _cur_size) return; if (size < _cur_size) { for (int i = size; i < _cur_size; i++) { if constexpr (!std::is_trivially_destructible::value) std::destroy_at(_data + i); } _cur_size = size; compact(); return; } if (size > _cur_size) { if (_capacity < size) { _capacity = size; _data = (T *) krealloc(reinterpret_cast(_data), _capacity * sizeof(T)); } for (int i = size; i < _cur_size; i++) { if constexpr (!std::is_trivially_constructible::value) new (_data + i) T(); else memset((char *) (_data + i), 0, sizeof(T)); } return; } } T *data() { return _data; } const T *data() const { return _data; } using iterator = T *; using const_iterator = const T *; iterator begin() { return _cur_size > 0 ? _data : end(); } iterator end() { return _data + _cur_size; } const_iterator begin() const { return _cur_size > 0 ? _data : end(); } const_iterator end() const { return _data + _cur_size; } const_iterator cbegin() const { return _cur_size > 0 ? _data : end(); } const_iterator cend() const { return _data + _cur_size; } private: size_t _capacity = 2; size_t _cur_size = 0; T *_data; }; #endif