/* 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; } }