diff options
Diffstat (limited to 'euler/include/std')
-rw-r--r-- | euler/include/std/allocator.hpp | 30 | ||||
-rw-r--r-- | euler/include/std/string.hpp | 80 | ||||
-rw-r--r-- | euler/include/std/vector.hpp | 191 |
3 files changed, 301 insertions, 0 deletions
diff --git a/euler/include/std/allocator.hpp b/euler/include/std/allocator.hpp new file mode 100644 index 0000000..32ba005 --- /dev/null +++ b/euler/include/std/allocator.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include <euler/heap.hpp> + +namespace std { + + template <class T> + struct allocator { + + using value_type = T; + + constexpr allocator() noexcept {} + constexpr allocator(const allocator &other) noexcept {} + + template <class U> + constexpr allocator(const allocator<U> &other) noexcept {} + + constexpr ~allocator() {} + + constexpr T *allocate(size_t n) { + return (T *)euler::heap::get_block(n * sizeof(T)); + } + + constexpr void deallocate(T *p, size_t n) { + euler::heap::return_block(p, n * sizeof(T)); + } + + }; + +} diff --git a/euler/include/std/string.hpp b/euler/include/std/string.hpp new file mode 100644 index 0000000..7ccdbc2 --- /dev/null +++ b/euler/include/std/string.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include <cstddef> +#include <vector> + +namespace std { + + class string { + + std::vector<char> characters; + + public: + constexpr string() : characters({'\0'}) {} + + constexpr string(const string &other) + : characters(other.characters) {} + + constexpr string(string &&other) noexcept + : characters(std::move(other.characters)) { + other.characters.push_back('\0'); + } + + constexpr string(const char *s) { + size_t count = 0; + while (s[count] != '\0') + ++count; + characters.resize(count + 1); + for (size_t i = 0; i <= count; ++i) + characters[i] = s[i]; + } + + constexpr ~string() {} + + constexpr string &operator =(const string &str) { + characters = str.characters; + return *this; + } + + constexpr string &operator =(string &&str) noexcept { + characters = std::move(str.characters); + str.characters.push_back('\0'); + return *this; + } + + constexpr size_t size() const noexcept { + return characters.size() - 1; + } + + constexpr void resize(size_t count) { + if (count < characters.size() - 1) { + characters.resize(count + 1); + characters[count] = '\0'; + } + else if (count > characters.size() - 1) + characters.resize(count + 1); + } + + constexpr void clear() noexcept { + resize(0); + } + + constexpr const char *data() const noexcept { + return characters.data(); + } + + constexpr char *data() noexcept { + return characters.data(); + } + + constexpr char &operator[](size_t pos) { + return characters[pos]; + } + + constexpr const char &operator[](size_t pos) const { + return characters[pos]; + } + + }; + +} diff --git a/euler/include/std/vector.hpp b/euler/include/std/vector.hpp new file mode 100644 index 0000000..a1ac21d --- /dev/null +++ b/euler/include/std/vector.hpp @@ -0,0 +1,191 @@ +#pragma once + +#include <memory> + +namespace std { + + template <class T, class Allocator = std::allocator<T>> + class vector { + + public: + using size_type = size_t; + using value_type = T; + using reference = value_type &; + using const_reference = const value_type &; + + private: + Allocator _alloc; + size_type _capacity; + size_type _size; + T *_data; + + constexpr void expand_capacity_to(size_type at_least) { + + size_type new_capacity = _capacity == 0 ? 1 : _capacity; + while (new_capacity < at_least) + new_capacity *= 2; + if (new_capacity == _capacity) + return; + + T *new_data = _alloc.allocate(new_capacity); + for (size_type i = 0; i < _size; ++i) { + std::construct_at(new_data + i, std::move(_data[i])); + std::destroy_at(_data + i); + } + if (_capacity > 0) + _alloc.deallocate(_data, _capacity); + + _capacity = new_capacity; + _data = new_data; + + } + + public: + constexpr vector() noexcept(noexcept(Allocator())) + : _alloc(), _capacity(0), _size(0), _data(0) {} + + constexpr vector(const vector &other) + : _alloc(), _capacity(other._size), _size(other._size), + _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i, other._data[i]); + } + + constexpr vector(vector &&other) noexcept + : _alloc(std::move(other._alloc)), _capacity(other._capacity), + _size(other._size), _data(other._data) { + other._capacity = 0; + other._size = 0; + } + + constexpr vector( + std::initializer_list<T> init, const Allocator &alloc = Allocator()) + : _alloc(alloc), _capacity(init.size()), + _size(init.size()), _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i, init.begin()[i]); + } + + explicit vector(size_type count) + : _alloc(), _capacity(count), _size(count), + _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i); + } + + constexpr ~vector() { + if (_capacity > 0) { + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + _alloc.deallocate(_data, _capacity); + } + } + + constexpr vector &operator =(const vector &other) { + + if (&other == this) + return *this; + + expand_capacity_to(other._size); + + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + + for (size_type i = 0; i < other._size; ++i) { + std::construct_at(_data + i, std::move(other._data[i])); + std::destroy_at(other._data + i); + } + + _size = other._size; + return *this; + + } + + constexpr vector &operator =(vector &&other) + noexcept( + std::allocator_traits<Allocator>:: + propagate_on_container_move_assignment::value || + std::allocator_traits<Allocator>:: + is_always_equal::value) { + + if (&other == this) + return *this; + + if (_capacity > 0) { + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + _alloc.deallocate(_data, _capacity); + } + + _alloc = std::move(other._alloc); + _capacity = other._capacity; + _size = other._size; + _data = other._data; + + other._capacity = 0; + other._size = 0; + + return *this; + + } + + constexpr size_type size() const noexcept { + return _size; + } + + constexpr T *data() noexcept { + return _data; + } + + constexpr const T *data() const noexcept { + return _data; + } + + constexpr reference operator[](size_type pos) { + return _data[pos]; + } + + constexpr const_reference operator[](size_type pos) const { + return _data[pos]; + } + + constexpr reference back() { + return _data[_size - 1]; + } + + constexpr const_reference back() const { + return _data[_size - 1]; + } + + constexpr void resize(size_type count) { + + if (count < _size) { + for (size_type i = count; i < _size; ++i) + std::destroy_at(_data + i); + _size = count; + } + + else if (count > _size) { + expand_capacity_to(count); + for (size_type i = _size; i < count; ++i) + std::construct_at(_data + i); + _size = count; + } + + } + + constexpr void push_back(const T &value) { + expand_capacity_to(_size + 1); + std::construct_at(_data + _size, value); + ++_size; + } + + constexpr void push_back(T &&value) { + expand_capacity_to(_size + 1); + std::construct_at(_data + _size, std::move(value)); + ++_size; + } + + }; + +} |