mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-27 15:04:33 +00:00
385 lines
8.2 KiB
Plaintext
385 lines
8.2 KiB
Plaintext
/*
|
|
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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <types.h>
|
|
|
|
#include <type_trails>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include <assert.h>
|
|
#include <lock.hpp>
|
|
#include <cstring>
|
|
#include <utility>
|
|
|
|
// #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 T>
|
|
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<T> &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<T>::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<T>()(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<T>()(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 <class... Args>
|
|
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>(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 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<T> &operator=(const vector<T> &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=( <vector> )->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();
|
|
}
|
|
};
|
|
}
|