/* This file is part of Fennix Kernel. Fennix Kernel is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fennix Kernel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Fennix Kernel. If not, see . */ #pragma once #include #include #include #include #include #include #include #include // #define DEBUG_VECTOR_MESSAGES 1 #ifdef DEBUG_VECTOR_MESSAGES #define vDebug(m, ...) debug("%#lx: " m, this, ##__VA_ARGS__) #else #define vDebug(m, ...) #endif namespace std { template class vector { private: NewLock(lock); std::atomic_size_t VectorSize = 0; std::atomic_size_t VectorCapacity = 0; T *VectorBuffer = nullptr; public: typedef T *iterator; typedef const T *const_iterator; vector() { vDebug("( empty init )"); } vector(size_t Size) : VectorSize(Size), VectorCapacity(Size), VectorBuffer(new T[Size]) { vDebug("( init w/size: %lld )", Size); } vector(size_t Size, const T &Initial) : VectorSize(Size), VectorCapacity(Size), VectorBuffer(new T[Size]) { vDebug("( init w/size: %lld, initial vector: %llx )", Size, Initial); assert(Size > 0); SmartLock(this->lock); for (size_t i = 0; i < Size; i++) VectorBuffer[i] = Initial; } vector(const vector &v) : VectorSize(v.VectorSize.load()), VectorCapacity(v.VectorCapacity.load()), VectorBuffer(nullptr) { vDebug("( vector copy: %#lx )", &v); if (!v.VectorBuffer || VectorSize.load() <= 0) return; SmartLock(this->lock); VectorBuffer = new T[VectorSize.load()]; std::copy(v.VectorBuffer, v.VectorBuffer + VectorSize.load(), VectorBuffer); } ~vector() { vDebug("( deinit )"); VectorSize.store(0); VectorCapacity.store(0); SmartLock(this->lock); if (VectorBuffer != nullptr) { delete[] VectorBuffer; VectorBuffer = nullptr; } } void erase(iterator Position) { vDebug("Erasing element at position %lld (v. size: %lld)", Position - this->VectorBuffer, this->VectorSize.load()); if (Position == this->end()) { warn("%#lx: Cannot erase element at end of vector (not found if std::find is used)", this); return; } assert(Position <= this->end()); assert(Position >= this->VectorBuffer); assert(Position < this->VectorBuffer + this->VectorSize.load()); SmartLock(this->lock); size_t index = Position - this->VectorBuffer; if (std::is_trivially_copyable::value) { this->VectorBuffer[index] = T(); vDebug("%#lx is trivially copyable", &this->VectorBuffer[index]); } else { this->VectorBuffer[index].~T(); vDebug("%#lx is not trivially copyable", &this->VectorBuffer[index]); } for (size_t i = index; i < this->VectorSize.load() - 1; ++i) { this->VectorBuffer[i] = std::move(this->VectorBuffer[i + 1]); } this->VectorSize--; } T &next(size_t Position) { SmartLock(this->lock); if (Position + 1 < this->VectorSize.load()) return this->VectorBuffer[Position + 1]; warn("%#lx: next( %lld ) is null (requested by %#lx)", this, Position, __builtin_return_address(0)); return {}; } T &prev(size_t Position) { SmartLock(this->lock); if (Position > 0) return this->VectorBuffer[Position - 1]; warn("%#lx: prev( %lld ) is null (requested by %#lx)", this, Position, __builtin_return_address(0)); return {}; } T &next(const T &Value) { SmartLock(this->lock); for (size_t i = 0; i < this->VectorSize.load(); i++) { if (std::equal_to()(this->VectorBuffer[i], Value)) { if (i + 1 < this->VectorSize.load()) return this->VectorBuffer[i + 1]; else break; } } warn("%#lx: next( %#lx ) is null (requested by %#lx)", this, Value, __builtin_return_address(0)); return {}; } T &prev(const T &Value) { SmartLock(this->lock); for (size_t i = 0; i < this->VectorSize.load(); i++) { if (std::equal_to()(this->VectorBuffer[i], Value)) { if (i > 0) return this->VectorBuffer[i - 1]; else break; } } warn("%#lx: prev( %#lx ) is null (requested by %#lx)", this, Value, __builtin_return_address(0)); return {}; } void push_back(const T &Value) { vDebug("push_back( %#lx )", Value); if (this->VectorSize.load() >= this->VectorCapacity.load()) { size_t newCapacity = this->VectorCapacity.load() == 0 ? 1 : this->VectorCapacity.load() * 2; reserve(newCapacity); } SmartLock(this->lock); this->VectorBuffer[this->VectorSize++] = Value; } template void emplace_back(Args &&...args) { vDebug("emplace_back( %#lx )", args...); if (this->VectorSize.load() >= this->VectorCapacity.load()) { size_t newCapacity = this->VectorCapacity.load() == 0 ? 1 : this->VectorCapacity.load() * 2; reserve(newCapacity); } SmartLock(this->lock); this->VectorBuffer[this->VectorSize++] = T(std::forward(args)...); } void reverse() { if (this->VectorSize.load() <= 1) return; SmartLock(this->lock); for (size_t i = 0, j = this->VectorSize.load() - 1; i < j; i++, j--) { T &elem1 = this->VectorBuffer[i]; T &elem2 = this->VectorBuffer[j]; std::swap(elem1, elem2); } } void reserve(size_t Capacity) { assert(!(Capacity <= VectorCapacity.load())); SmartLock(this->lock); T *NewBuffer = new T[Capacity]; size_t Size = std::min(Capacity, this->VectorSize.load()); for (size_t i = 0; i < Size; i++) NewBuffer[i] = std::move(this->VectorBuffer[i]); vDebug("reserve( %lld )->Buffer:~%#lx", Capacity, this->VectorBuffer); delete[] this->VectorBuffer; this->VectorBuffer = NewBuffer; this->VectorCapacity.store(Capacity); } void resize(size_t Size) { reserve(Size); this->VectorSize.store(Size); } void resize(size_t count, const T &value) { reserve(count); for (size_t i = this->VectorSize.load(); i < count; i++) this->VectorBuffer[i] = value; this->VectorSize.store(count); } void clear() { this->VectorCapacity.store(0); this->VectorSize.store(0); SmartLock(this->lock); if (VectorBuffer != nullptr) { delete[] this->VectorBuffer; this->VectorBuffer = nullptr; } } T &operator[](size_t Index) { SmartLock(this->lock); if (Index >= this->VectorSize.load() || !this->VectorBuffer) { warn("%#lx: operator[]( %lld ) is null (requested by %#lx)", this, Index, __builtin_return_address(0)); static T null_elem{}; return null_elem; } return this->VectorBuffer[Index]; } vector &operator=(const vector &v) { SmartLock(this->lock); if (this == &v) return *this; delete[] this->VectorBuffer; this->VectorSize.store(v.VectorSize.load()); this->VectorCapacity.store(v.VectorCapacity.load()); vDebug("operator=( )->Size:%lld", this->VectorSize.load()); this->VectorBuffer = new T[this->VectorSize.load()]; for (size_t i = 0; i < this->VectorSize.load(); i++) this->VectorBuffer[i] = v.VectorBuffer[i]; return *this; } void pop_back() { this->VectorSize--; } T &front() { SmartLock(this->lock); return this->VectorBuffer[0]; } T &back() { SmartLock(this->lock); return this->VectorBuffer[this->VectorSize.load() - 1]; } T *data() { SmartLock(this->lock); return this->VectorBuffer; } bool empty() const { return this->VectorSize.load() == 0; } size_t capacity() const { return this->VectorCapacity.load(); } size_t size() const { return this->VectorSize.load(); } iterator begin() { SmartLock(this->lock); return this->VectorBuffer; } iterator end() { SmartLock(this->lock); return this->VectorBuffer + size(); } const_iterator begin() const { SmartLock(this->lock); return this->VectorBuffer; } const_iterator end() const { SmartLock(this->lock); return this->VectorBuffer + size(); } }; }