/*
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
namespace std
{
template >
class vector
{
public:
using value_type = T;
using allocator_type = Allocator;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using reference = value_type &;
using const_reference = const value_type &;
using pointer = typename std::allocator_traits::pointer;
using const_pointer = typename std::allocator_traits::const_pointer;
// using iterator = typename vector::iterator;
// using const_iterator = typename vector::const_iterator;
// using reverse_iterator = typename vector::reverse_iterator;
// using const_reverse_iterator = typename vector::const_reverse_iterator;
class iterator
{
public:
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T *;
using reference = T &;
using iterator_category = std::random_access_iterator_tag;
public:
pointer itrPtr;
public:
constexpr iterator() noexcept : itrPtr(nullptr) {}
constexpr iterator(pointer ptr) noexcept : itrPtr(ptr) {}
constexpr iterator(const iterator &other) noexcept : itrPtr(other.itrPtr) {}
constexpr iterator(iterator &&other) noexcept : itrPtr(other.itrPtr) {}
constexpr reference operator*() const { return *itrPtr; }
constexpr pointer operator->() const { return itrPtr; }
constexpr iterator &operator=(const iterator &other)
{
itrPtr = other.itrPtr;
return *this;
}
constexpr iterator &operator=(iterator &&other)
{
itrPtr = other.itrPtr;
return *this;
}
constexpr iterator &operator++()
{
itrPtr++;
return *this;
}
constexpr iterator operator++(int)
{
iterator temp = *this;
itrPtr++;
return temp;
}
constexpr iterator &operator--()
{
itrPtr--;
return *this;
}
constexpr iterator operator--(int)
{
iterator temp = *this;
itrPtr--;
return temp;
}
constexpr difference_type operator-(const iterator &other) const
{
return itrPtr - other.itrPtr;
}
constexpr iterator operator+(difference_type n) const
{
return iterator(itrPtr + n);
}
constexpr bool operator==(const iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const iterator &other) const { return itrPtr != other.itrPtr; }
};
class const_iterator
{
public:
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = const T *;
using reference = const T &;
using iterator_category = std::random_access_iterator_tag;
public:
pointer itrPtr;
public:
constexpr const_iterator() noexcept : itrPtr(nullptr) {}
constexpr const_iterator(pointer ptr) noexcept : itrPtr(ptr) {}
constexpr const_iterator(iterator it) noexcept : itrPtr(it.itrPtr) {}
constexpr const_iterator(const const_iterator &other) noexcept : itrPtr(other.itrPtr) {}
constexpr const_iterator(const_iterator &&other) noexcept : itrPtr(other.itrPtr) {}
constexpr reference operator*() const { return *itrPtr; }
constexpr pointer operator->() const { return itrPtr; }
constexpr const_iterator &operator=(const const_iterator &other)
{
itrPtr = other.itrPtr;
return *this;
}
constexpr const_iterator &operator=(const_iterator &&other)
{
itrPtr = other.itrPtr;
return *this;
}
constexpr const_iterator &operator++()
{
itrPtr++;
return *this;
}
constexpr const_iterator operator++(int)
{
const_iterator temp = *this;
itrPtr++;
return temp;
}
constexpr const_iterator &operator--()
{
itrPtr--;
return *this;
}
constexpr const_iterator operator--(int)
{
const_iterator temp = *this;
itrPtr--;
return temp;
}
constexpr difference_type operator-(const const_iterator &other) const
{
return itrPtr - other.itrPtr;
}
constexpr const_iterator operator+(difference_type n) const
{
return const_iterator(itrPtr + n);
}
constexpr bool operator==(const const_iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const const_iterator &other) const { return itrPtr != other.itrPtr; }
};
class reverse_iterator
{
public:
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T *;
using reference = T &;
using iterator_category = std::random_access_iterator_tag;
public:
pointer itrPtr;
public:
constexpr reverse_iterator() noexcept : itrPtr(nullptr) {}
constexpr reverse_iterator(pointer ptr) noexcept : itrPtr(ptr) {}
constexpr reverse_iterator(const reverse_iterator &other) noexcept : itrPtr(other.itrPtr) {}
constexpr reverse_iterator(reverse_iterator &&other) noexcept : itrPtr(other.itrPtr) {}
constexpr reference operator*() const { return *itrPtr; }
constexpr pointer operator->() const { return itrPtr; }
constexpr reverse_iterator &operator=(const reverse_iterator &other)
{
itrPtr = other.itrPtr;
return *this;
}
constexpr reverse_iterator &operator=(reverse_iterator &&other)
{
itrPtr = other.itrPtr;
return *this;
}
constexpr reverse_iterator &operator++()
{
itrPtr--;
return *this;
}
constexpr reverse_iterator operator++(int)
{
reverse_iterator temp = *this;
itrPtr--;
return temp;
}
constexpr reverse_iterator &operator--()
{
itrPtr++;
return *this;
}
constexpr reverse_iterator operator--(int)
{
reverse_iterator temp = *this;
itrPtr++;
return temp;
}
constexpr difference_type operator-(const reverse_iterator &other) const
{
return itrPtr - other.itrPtr;
}
constexpr reverse_iterator operator+(difference_type n) const
{
return reverse_iterator(itrPtr - n);
}
constexpr bool operator==(const reverse_iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const reverse_iterator &other) const { return itrPtr != other.itrPtr; }
constexpr bool operator==(const const_iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const const_iterator &other) const { return itrPtr != other.itrPtr; }
constexpr bool operator==(const iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const iterator &other) const { return itrPtr != other.itrPtr; }
};
class const_reverse_iterator
{
public:
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = const T *;
using reference = const T &;
using iterator_category = std::random_access_iterator_tag;
public:
pointer itrPtr;
public:
constexpr const_reverse_iterator() noexcept : itrPtr(nullptr) {}
constexpr const_reverse_iterator(pointer ptr) noexcept : itrPtr(ptr) {}
constexpr const_reverse_iterator(const const_reverse_iterator &other) noexcept : itrPtr(other.itrPtr) {}
constexpr const_reverse_iterator(const_reverse_iterator &&other) noexcept : itrPtr(other.itrPtr) {}
constexpr reference operator*() const { return *itrPtr; }
constexpr pointer operator->() const { return itrPtr; }
constexpr const_reverse_iterator &operator=(const const_reverse_iterator &other)
{
itrPtr = other.itrPtr;
return *this;
}
constexpr const_reverse_iterator &operator=(const_reverse_iterator &&other)
{
itrPtr = other.itrPtr;
return *this;
}
constexpr const_reverse_iterator &operator++()
{
itrPtr--;
return *this;
}
constexpr const_reverse_iterator operator++(int)
{
const_reverse_iterator temp = *this;
itrPtr--;
return temp;
}
constexpr const_reverse_iterator &operator--()
{
itrPtr++;
return *this;
}
constexpr const_reverse_iterator operator--(int)
{
const_reverse_iterator temp = *this;
itrPtr++;
return temp;
}
constexpr difference_type operator-(const const_reverse_iterator &other) const
{
return itrPtr - other.itrPtr;
}
constexpr const_reverse_iterator operator+(difference_type n) const
{
return const_reverse_iterator(itrPtr - n);
}
constexpr bool operator==(const const_reverse_iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const const_reverse_iterator &other) const { return itrPtr != other.itrPtr; }
constexpr bool operator==(const reverse_iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const reverse_iterator &other) const { return itrPtr != other.itrPtr; }
constexpr bool operator==(const const_iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const const_iterator &other) const { return itrPtr != other.itrPtr; }
constexpr bool operator==(const iterator &other) const { return itrPtr == other.itrPtr; }
constexpr bool operator!=(const iterator &other) const { return itrPtr != other.itrPtr; }
};
private:
allocator_type _alloc;
size_type _size;
size_type _capacity;
pointer _data;
public:
#pragma region Constructors
constexpr vector() noexcept(noexcept(Allocator()))
: _size(0),
_capacity(0),
_data(nullptr)
{
}
constexpr explicit vector(const Allocator &alloc) noexcept
: _alloc(alloc),
_size(0),
_capacity(0),
_data(nullptr)
{
}
constexpr vector(size_type count, const T &value, const Allocator &alloc = Allocator())
: _alloc(alloc),
_size(count),
_capacity(count),
_data(_alloc.allocate(count))
{
for (size_type i = 0; i < count; i++)
std::allocator_traits::construct(_alloc, _data + i, value);
}
constexpr explicit vector(size_type count, const Allocator &alloc = Allocator())
: _alloc(alloc),
_size(count),
_capacity(count),
_data(_alloc.allocate(count))
{
for (size_type i = 0; i < count; i++)
std::allocator_traits::construct(_alloc, _data + i);
}
/* FIXME: this conflicts with the above constructors */
// template
// constexpr vector(InputIt first, InputIt last, const Allocator &alloc = Allocator())
// {
// _alloc = alloc;
// _size = last - first;
// _capacity = last - first;
// _data = _alloc.allocate(_size);
// for (size_type i = 0; i < _size; i++)
// std::allocator_traits::construct(_alloc, _data + i, *(first + i));
// }
constexpr vector(const vector &other)
: _alloc(other._alloc),
_size(other._size),
_capacity(other._capacity),
_data(_alloc.allocate(_size))
{
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, _data + i, other._data[i]);
}
constexpr vector(const vector &other, const Allocator &alloc)
: _alloc(other._alloc),
_size(other._size),
_capacity(other._capacity),
_data(_alloc.allocate(_size))
{
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, _data + i, other._data[i]);
}
constexpr vector(vector &&other) noexcept
: _alloc(std::move(other._alloc)),
_size(other._size),
_capacity(other._capacity),
_data(other._data)
{
other._size = 0;
other._capacity = 0;
other._data = nullptr;
}
constexpr vector(vector &&other, const Allocator &alloc)
: _alloc(alloc),
_size(other._size),
_capacity(other._capacity),
_data(other._data)
{
other._size = 0;
other._capacity = 0;
other._data = nullptr;
}
constexpr vector(std::initializer_list init, const Allocator &alloc = Allocator())
: _alloc(alloc),
_size(init.size()),
_capacity(init.size()),
_data(_alloc.allocate(_size))
{
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, _data + i, *(init.begin() + i));
}
constexpr ~vector()
{
if (_capacity == 0 || _data == nullptr)
return;
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
_alloc.deallocate(_data, _size);
}
constexpr vector &operator=(const vector &other)
{
if (this == &other)
return *this;
if (_capacity != 0 && _data != nullptr)
{
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
_alloc.deallocate(_data, _size);
}
_size = other._size;
_capacity = other._capacity;
_data = _alloc.allocate(_size);
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, _data + i, other._data[i]);
return *this;
}
constexpr vector &operator=(vector &&other) /* noexcept(_alloc.propagate_on_container_move_assignment::value || _alloc.is_always_equal::value) */
{
if (this == &other)
return *this;
if (_capacity != 0 && _data != nullptr)
{
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
_alloc.deallocate(_data, _size);
}
_size = other._size;
_capacity = other._capacity;
_data = other._data;
other._size = 0;
other._capacity = 0;
other._data = nullptr;
return *this;
}
constexpr vector &operator=(std::initializer_list ilist)
{
_size = ilist.size();
_capacity = ilist.size();
_data = _alloc.allocate(_size);
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, _data + i, *(ilist.begin() + i));
return *this;
}
constexpr void assign(size_type count, const T &value)
{
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
if (_data != nullptr)
_alloc.deallocate(_data, _size);
_size = count;
_capacity = count;
_data = _alloc.allocate(_size);
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, _data + i, value);
}
template
constexpr void assign(InputIt first, InputIt last)
{
if (_capacity != 0 && _data != nullptr)
{
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
_alloc.deallocate(_data, _size);
}
_size = last - first;
_capacity = last - first;
_data = _alloc.allocate(_size);
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, _data + i, *(first + i));
}
constexpr void assign(std::initializer_list ilist)
{
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
if (_data != nullptr)
_alloc.deallocate(_data, _size);
_size = ilist.size();
_capacity = ilist.size();
_data = _alloc.allocate(_size);
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, _data + i, *(ilist.begin() + i));
}
constexpr allocator_type get_allocator() const noexcept
{
return _alloc;
}
#pragma endregion Constructors
#pragma region Element Access
reference at(size_type pos)
{
if (pos >= _size)
throw std::out_of_range("vector::at");
return _data[pos];
}
const_reference at(size_type pos) const
{
if (pos >= _size)
throw std::out_of_range("vector::at");
return _data[pos];
}
reference operator[](size_type pos)
{
return _data[pos];
}
const_reference operator[](size_type pos) const
{
return _data[pos];
}
reference front()
{
return _data[0];
}
const_reference front() const
{
return _data[0];
}
reference back()
{
return _data[_size - 1];
}
const_reference back() const
{
return _data[_size - 1];
}
constexpr T *data() noexcept
{
return _data;
}
constexpr const T *data() const
{
return _data;
}
#pragma endregion Element Access
#pragma region Iterators
constexpr iterator begin()
{
return iterator(_data);
}
constexpr const_iterator begin() const
{
return const_iterator(_data);
}
constexpr const_iterator cbegin() const noexcept
{
return const_iterator(_data);
}
constexpr iterator end() noexcept
{
return iterator(_data + _size);
}
constexpr const_iterator end() const noexcept
{
return const_iterator(_data + _size);
}
constexpr const_iterator cend() const noexcept
{
return const_iterator(_data + _size);
}
constexpr reverse_iterator rbegin()
{
return reverse_iterator(_data + _size - 1);
}
constexpr const_reverse_iterator rbegin() const
{
return const_reverse_iterator(_data + _size - 1);
}
constexpr const_reverse_iterator crbegin() const noexcept
{
return const_reverse_iterator(_data + _size - 1);
}
constexpr iterator rend() noexcept
{
return iterator(_data - 1);
}
constexpr const_iterator rend() const noexcept
{
return const_iterator(_data - 1);
}
constexpr const_iterator crend() const noexcept
{
return const_iterator(_data - 1);
}
#pragma endregion Iterators
#pragma region Capacity
[[nodiscard]] constexpr bool empty() const noexcept
{
return _size == 0; /* begin() == end() */
}
constexpr size_type size() const noexcept
{
return _size; /* std::distance(begin(), end()) */
}
constexpr size_type max_size() const noexcept
{
return std::numeric_limits::max();
}
constexpr void reserve(size_type new_cap)
{
if (new_cap <= _capacity)
return;
pointer new_data = _alloc.allocate(new_cap);
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, new_data + i, _data[i]);
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
if (_data != nullptr)
_alloc.deallocate(_data, _size);
_data = new_data;
_capacity = new_cap;
}
constexpr size_type capacity() const noexcept
{
return _capacity;
}
constexpr void shrink_to_fit()
{
if (_size >= _capacity)
return;
pointer new_data = _alloc.allocate(_size);
for (size_type i = 0; i < _size; i++)
std::allocator_traits::construct(_alloc, new_data + i, _data[i]);
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
if (_data != nullptr)
_alloc.deallocate(_data, _size);
_data = new_data;
_capacity = _size;
}
#pragma endregion Capacity
#pragma region Modifiers
constexpr void clear() noexcept
{
for (size_type i = 0; i < _size; i++)
_data[i].~value_type();
_size = 0;
}
constexpr iterator insert(const_iterator pos, const T &value)
{
size_type index = pos - begin();
if (_size == _capacity)
reserve(_capacity + (_capacity / 2) + 1);
for (size_type i = _size; i > index; i--)
_data[i] = _data[i - 1];
_data[index] = value;
_size++;
return iterator(_data + index);
}
constexpr iterator insert(const_iterator pos, size_type count, const T &value)
{
size_type index = pos - begin();
if (_size + count > _capacity)
reserve(_capacity + count);
for (size_type i = _size + count - 1; i > index + count - 1; i--)
_data[i] = _data[i - count];
for (size_type i = index; i < index + count; i++)
_data[i] = value;
_size += count;
return iterator(_data + index);
}
template
constexpr iterator insert(const_iterator pos, InputIt first, InputIt last)
{
size_type index = pos - begin();
size_type count = last - first;
if (_size + count > _capacity)
reserve(_capacity + count);
for (size_type i = _size + count - 1; i > index + count - 1; i--)
_data[i] = _data[i - count];
for (size_type i = index; i < index + count; i++)
_data[i] = *(first + i - index);
_size += count;
return iterator(_data + index);
}
constexpr iterator insert(const_iterator pos,
std::initializer_list ilist)
{
size_type index = pos - begin();
size_type count = ilist.size();
if (_size + count > _capacity)
reserve(_capacity + count);
for (size_type i = _size + count - 1; i > index + count - 1; i--)
_data[i] = _data[i - count];
for (size_type i = index; i < index + count; i++)
_data[i] = *(ilist.begin() + i - index);
_size += count;
return iterator(_data + index);
}
template
constexpr iterator emplace(const_iterator pos, Args &&...args)
{
size_type index = pos - begin();
if (_size == _capacity)
reserve(_capacity + (_capacity / 2) + 1);
for (size_type i = _size; i > index; i--)
_data[i] = _data[i - 1];
std::allocator_traits::construct(_alloc, _data + index, std::forward(args)...);
_size++;
return iterator(_data + index);
}
constexpr iterator erase(const_iterator pos)
{
size_type index = pos - cbegin();
for (size_type i = index; i < _size - 1; i++)
_data[i] = _data[i + 1];
_data[_size - 1].~value_type();
_size--;
return iterator(_data + index);
}
constexpr iterator erase(const_iterator first, const_iterator last)
{
size_type index = first - cbegin();
size_type count = last - first;
for (size_type i = index; i < _size - count; i++)
_data[i] = _data[i + count];
for (size_type i = _size - count; i < _size; i++)
_data[i].~value_type();
_size -= count;
return iterator(_data + index);
}
constexpr void push_back(const T &value)
{
if (_capacity == 0)
reserve(sizeof(T) * 2);
if (_size == _capacity)
reserve(_capacity + (_capacity / 2) + 1);
_data[_size] = value;
_size++;
}
constexpr void push_back(T &&value)
{
if (_capacity == 0)
reserve(sizeof(T) * 2);
if (_size == _capacity)
reserve(_capacity + (_capacity / 2) + 1);
_data[_size] = std::move(value);
_size++;
}
template
constexpr reference emplace_back(Args &&...args)
{
if (_size == _capacity)
reserve(_capacity + (_capacity / 2) + 1);
std::allocator_traits::construct(_alloc, _data + _size, std::forward(args)...);
_size++;
return _data[_size - 1];
}
constexpr void pop_back()
{
_data[_size - 1].~value_type();
_size--;
}
constexpr void resize(size_type count)
{
if (count > _size)
{
if (count > _capacity)
reserve(count);
for (size_type i = _size; i < count; i++)
std::allocator_traits::construct(_alloc, _data + i);
}
else
{
for (size_type i = count; i < _size; i++)
_data[i].~value_type();
}
_size = count;
}
constexpr void resize(size_type count, const value_type &value)
{
if (count > _size)
{
if (count > _capacity)
reserve(count);
for (size_type i = _size; i < count; i++)
std::allocator_traits::construct(_alloc, _data + i, value);
}
else
{
for (size_type i = count; i < _size; i++)
_data[i].~value_type();
}
_size = count;
}
constexpr void swap(vector &other) /* noexcept(_alloc.propagate_on_container_swap::value || _alloc.is_always_equal::value) */
{
size_type temp_size = _size;
size_type temp_capacity = _capacity;
pointer temp_data = _data;
_size = other._size;
_capacity = other._capacity;
_data = other._data;
other._size = temp_size;
other._capacity = temp_capacity;
other._data = temp_data;
}
#pragma endregion Modifiers
};
template
constexpr bool operator==(const std::vector &lhs, const std::vector &rhs)
{
if (lhs.size() != rhs.size())
return false;
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
template
constexpr auto operator<=>(const std::vector &lhs, const std::vector &rhs)
{
// return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), __synth_three_way);
auto it1 = lhs.begin();
auto it2 = rhs.begin();
while (it1 != lhs.end() && it2 != rhs.end())
{
if (*it1 < *it2)
return std::strong_ordering::less;
if (*it1 > *it2)
return std::strong_ordering::greater;
++it1;
++it2;
}
if (it1 == lhs.end() && it2 == rhs.end())
return std::strong_ordering::equal;
return (it1 == lhs.end()) ? std::strong_ordering::less : std::strong_ordering::greater;
}
template
constexpr void swap(std::vector &lhs, std::vector &rhs) noexcept(noexcept(noexcept(lhs.swap(rhs))))
{
lhs.swap(rhs);
}
template
constexpr std::vector::size_type erase(std::vector &c, const U &value)
{
auto it = std::remove(c.begin(), c.end(), value);
auto r = c.end() - it;
c.erase(it, c.end());
return r;
}
template
constexpr std::vector::size_type erase_if(std::vector &c, Pred pred)
{
auto it = std::remove_if(c.begin(), c.end(), pred);
auto r = c.end() - it;
c.erase(it, c.end());
return r;
}
}