mirror of
https://github.com/momo5502/hypervisor.git
synced 2025-04-19 21:52:55 +00:00
Finish vector
This commit is contained in:
parent
4cd7e711f7
commit
d778a3190a
@ -2,194 +2,227 @@
|
|||||||
#include "type_traits.hpp"
|
#include "type_traits.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
#include "exception.hpp"
|
#include "exception.hpp"
|
||||||
|
#include "finally.hpp"
|
||||||
|
|
||||||
template <typename T>
|
namespace utils
|
||||||
class vector
|
|
||||||
{
|
{
|
||||||
public:
|
template <typename T>
|
||||||
using type = T;
|
class vector
|
||||||
|
|
||||||
vector() = default;
|
|
||||||
|
|
||||||
~vector()
|
|
||||||
{
|
{
|
||||||
this->clear();
|
public:
|
||||||
}
|
using type = T;
|
||||||
|
|
||||||
vector(const vector& obj)
|
vector() = default;
|
||||||
: vector()
|
|
||||||
{
|
|
||||||
this->operator=(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
vector(vector&& obj) noexcept
|
~vector()
|
||||||
: vector()
|
|
||||||
{
|
|
||||||
this->operator=(std::move(obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
vector& operator=(const vector& obj)
|
|
||||||
{
|
|
||||||
if (this != &obj)
|
|
||||||
{
|
{
|
||||||
this->clear();
|
this->clear();
|
||||||
this->reserve(obj.size_);
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < obj.size_; ++i)
|
vector(const vector& obj)
|
||||||
|
: vector()
|
||||||
|
{
|
||||||
|
this->operator=(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector(vector&& obj) noexcept
|
||||||
|
: vector()
|
||||||
|
{
|
||||||
|
this->operator=(std::move(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
vector& operator=(const vector& obj)
|
||||||
|
{
|
||||||
|
if (this != &obj)
|
||||||
{
|
{
|
||||||
this->push_back(obj.at(i));
|
this->clear();
|
||||||
|
this->reserve(obj.size_);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < obj.size_; ++i)
|
||||||
|
{
|
||||||
|
this->push_back(obj.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector& operator=(vector&& obj) noexcept
|
||||||
|
{
|
||||||
|
if (this != &obj)
|
||||||
|
{
|
||||||
|
this->clear();
|
||||||
|
|
||||||
|
this->storage_ = obj.storage_;
|
||||||
|
this->capacity_ = obj.capacity_;
|
||||||
|
this->size_ = obj.size_;
|
||||||
|
|
||||||
|
obj.storage_ = nullptr;
|
||||||
|
obj.capacity_ = 0;
|
||||||
|
obj.size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(size_t capacity)
|
||||||
|
{
|
||||||
|
if (this->capacity_ >= capacity)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* old_mem = this->storage_;
|
||||||
|
auto* old_data = this->data();
|
||||||
|
|
||||||
|
this->storage_ = allocate_memory_for_capacity(capacity);
|
||||||
|
this->capacity_ = capacity;
|
||||||
|
|
||||||
|
auto _ = utils::finally([&old_mem]
|
||||||
|
{
|
||||||
|
free_memory(old_mem);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto* data = this->data();
|
||||||
|
for (size_t i = 0; i < this->size_; ++i)
|
||||||
|
{
|
||||||
|
new(data + i) T(std::move(old_data[i]));
|
||||||
|
old_data[i].~T();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
T& push_back(T obj)
|
||||||
}
|
|
||||||
|
|
||||||
vector& operator=(vector&& obj) noexcept
|
|
||||||
{
|
|
||||||
if (this != &obj)
|
|
||||||
{
|
{
|
||||||
this->clear();
|
if (this->size_ + 1 > this->capacity_)
|
||||||
|
{
|
||||||
|
this->reserve(max(this->capacity_, 5) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
this->storage_ = obj.storage_;
|
auto* data = this->data() + this->size_++;
|
||||||
this->capacity_ = obj.capacity_;
|
new(data) T(std::move(obj));
|
||||||
this->size_ = obj.size_;
|
|
||||||
|
|
||||||
obj.storage_ = nullptr;
|
return *data;
|
||||||
obj.capacity_ = 0;
|
|
||||||
obj.size_ = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
T& operator[](const size_t index)
|
||||||
}
|
|
||||||
|
|
||||||
void reserve(size_t capacity)
|
|
||||||
{
|
|
||||||
if (this->capacity_ >= capacity)
|
|
||||||
{
|
{
|
||||||
return;
|
return this->at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* old_mem = this->storage_;
|
const T& operator[](const size_t index) const
|
||||||
auto* old_data = this->data();
|
|
||||||
|
|
||||||
this->storage_ = allocate_memory_for_capacity(capacity);
|
|
||||||
this->capacity_ = capacity;
|
|
||||||
|
|
||||||
auto _ = finally([&old_mem]
|
|
||||||
{
|
{
|
||||||
free_memory(old_mem);
|
return this->at(index);
|
||||||
});
|
|
||||||
|
|
||||||
auto* data = this->data();
|
|
||||||
for (size_t i = 0; i < this->size_; ++i)
|
|
||||||
{
|
|
||||||
new(data + i) T(std::move(old_data[i]));
|
|
||||||
old_data[i]->~T();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T& push_back(T obj)
|
|
||||||
{
|
|
||||||
if (this->size_ + 1 > this->capacity_)
|
|
||||||
{
|
|
||||||
this->reserve(max(this->capacity_, 5) * 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* data = this->data() + this->size_++;
|
T& at(const size_t index)
|
||||||
new(data) T(std::move(obj));
|
|
||||||
|
|
||||||
return *data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
T& at(size_t index)
|
|
||||||
{
|
|
||||||
if (index >= this->size_)
|
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Out of bounds access");
|
if (index >= this->size_)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Out of bounds access");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->data()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->data()[index];
|
const T& at(const size_t index) const
|
||||||
}
|
|
||||||
|
|
||||||
const T& at(size_t index) const
|
|
||||||
{
|
|
||||||
if (index >= this->size_)
|
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Out of bounds access");
|
if (index >= this->size_)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Out of bounds access");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->data()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->data()[index];
|
void clear()
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
auto* data = this->data();
|
|
||||||
for (size_t i = 0; i < this->size_; ++i)
|
|
||||||
{
|
{
|
||||||
data[i]->~T();
|
auto* data = this->data();
|
||||||
|
for (size_t i = 0; i < this->size_; ++i)
|
||||||
|
{
|
||||||
|
data[i].~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
free_memory(this->storage_);
|
||||||
|
this->storage_ = nullptr;
|
||||||
|
this->capacity_ = 0;
|
||||||
|
this->size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_memory(this->storage_);
|
[[nodiscard]] size_t capacity() const
|
||||||
this->storage_ = nullptr;
|
|
||||||
this->capacity_ = nullptr;
|
|
||||||
this->size_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t capacity() const
|
|
||||||
{
|
|
||||||
return this->capacity_;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const
|
|
||||||
{
|
|
||||||
return this->size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* data()
|
|
||||||
{
|
|
||||||
if (!this->storage_)
|
|
||||||
{
|
{
|
||||||
return nullptr;
|
return this->capacity_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<T*>(align_pointer(this->storage_));
|
[[nodiscard]] size_t size() const
|
||||||
}
|
|
||||||
|
|
||||||
const T* data() const
|
|
||||||
{
|
|
||||||
if (!this->storage_)
|
|
||||||
{
|
{
|
||||||
return nullptr;
|
return this->size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<const T*>(align_pointer(this->storage_));
|
T* data()
|
||||||
}
|
{
|
||||||
|
if (!this->storage_)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
return static_cast<T*>(align_pointer(this->storage_));
|
||||||
void* storage_{nullptr};
|
}
|
||||||
size_t capacity_{0};
|
|
||||||
size_t size_{0};
|
|
||||||
|
|
||||||
static void* allocate_memory_for_capacity(const size_t capacity)
|
const T* data() const
|
||||||
{
|
{
|
||||||
constexpr auto alignment = alignof(T);
|
if (!this->storage_)
|
||||||
auto* memory = memory::allocate_non_paged_memory(capacity * sizeof(T) + alignment);
|
{
|
||||||
return memory;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_memory(void* memory)
|
return static_cast<const T*>(align_pointer(this->storage_));
|
||||||
{
|
}
|
||||||
memory::free_non_paged_memory(memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U>
|
T* begin()
|
||||||
static U* align_pointer(U* pointer)
|
{
|
||||||
{
|
return this->data();
|
||||||
const auto align_bits = alignof(T) - 1;
|
}
|
||||||
auto ptr = static_cast<intptr_t>(pointer);
|
|
||||||
ptr = (ptr + align_bits) & (~align_bits);
|
|
||||||
|
|
||||||
return static_cast<U*>(ptr);
|
const T* begin() const
|
||||||
}
|
{
|
||||||
};
|
return this->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
T* end()
|
||||||
|
{
|
||||||
|
return this->data() + this->size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* end() const
|
||||||
|
{
|
||||||
|
return this->data() + this->size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* storage_{nullptr};
|
||||||
|
size_t capacity_{0};
|
||||||
|
size_t size_{0};
|
||||||
|
|
||||||
|
static void* allocate_memory_for_capacity(const size_t capacity)
|
||||||
|
{
|
||||||
|
constexpr auto alignment = alignof(T);
|
||||||
|
auto* memory = memory::allocate_non_paged_memory(capacity * sizeof(T) + alignment);
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_memory(void* memory)
|
||||||
|
{
|
||||||
|
memory::free_non_paged_memory(memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
static U* align_pointer(U* pointer)
|
||||||
|
{
|
||||||
|
const auto align_bits = alignof(T) - 1;
|
||||||
|
auto ptr = reinterpret_cast<intptr_t>(pointer);
|
||||||
|
ptr = (ptr + align_bits) & (~align_bits);
|
||||||
|
|
||||||
|
return reinterpret_cast<U*>(ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user