From 9171b225c7e57db40f949ac4449b37535c46ec94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 15 Apr 2025 10:27:38 +0000 Subject: Adjust comments and readability of stack and vector implementation --- arch/x86_64/include/arch/stl/stack.hpp | 67 ++++++------ arch/x86_64/include/arch/stl/vector.hpp | 174 ++++++++++++++++++-------------- 2 files changed, 136 insertions(+), 105 deletions(-) diff --git a/arch/x86_64/include/arch/stl/stack.hpp b/arch/x86_64/include/arch/stl/stack.hpp index c78a25e..9ecf0ca 100644 --- a/arch/x86_64/include/arch/stl/stack.hpp +++ b/arch/x86_64/include/arch/stl/stack.hpp @@ -4,9 +4,6 @@ #include "arch/exception_handling/panic.hpp" #include "arch/stl/vector.hpp" -#include -#include - namespace teachos::arch::stl { /** @@ -14,10 +11,18 @@ namespace teachos::arch::stl * custom memory management. * * @tparam T Element the stack instance should contain. + * @tparam Container Actual underlying container that should be wrapped to provide stack functionality. Requires + * access to pop_back(), push_back(), back(), size(), empty() and emplace_back() */ template> struct stack { + using container_type = Container; ///< Type of the underlying container used to implement stack-like interface. + using value_type = Container::value_type; ///< Type of the elements contained in the underlying container. + using size_type = Container::size_type; ///< Type of the size in the underlying container. + using reference = Container::reference; ///< Type of reference to the elements. + using const_reference = Container::const_reference; ///< Type of constant reference to the elements. + /** * @brief Default Constructor. */ @@ -27,11 +32,11 @@ namespace teachos::arch::stl * @brief Constructs data with the given amount of elements containg the given value or alterantively the default * constructed value. * - * @param capacity Amount of elements we want to create and set the given value for. + * @param n Amount of elements we want to create and set the given value for. * @param initial Inital value of all elements in the underlying data array. */ - explicit stack(std::size_t capacity, T initial = T{}) - : _container(capacity, initial) + explicit stack(size_type n, value_type initial = value_type{}) + : _container(n, initial) { // Nothing to do. } @@ -64,10 +69,10 @@ namespace teachos::arch::stl /** * @brief Copy constructor. * - * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all + * @note Allocates underlying data container with the same capacity as stack we are copying from and copies all * elements from it. * - * @param other Other instance of vector we want to copy the data from. + * @param other Other instance of stack we want to copy the data from. */ stack(stack const & other) : _container(other) @@ -97,7 +102,7 @@ namespace teachos::arch::stl * * @return Current amount of elements. */ - std::size_t size() const { return _container.size(); } + auto size() const -> size_type { return _container.size(); } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -105,7 +110,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T & top() { return _container.back(); } + auto top() -> reference { return _container.back(); } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -113,30 +118,25 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T const & top() const { return _container.back(); } + auto top() const -> const_reference { return _container.back(); } /** - * @brief Appends the given element value to the end of the container. The new element is initalized as a copy of - * value. + * @brief Appends the given element value to the end of the container. The element is assigned through the + * assignment operator of the template type. The value is forwarded to the constructor as + * std::forward(value), meaning it is either moved (rvalue) or copied (lvalue). * * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. + * Otherwise only the end() iterator is invalidated. Uses a forward reference for the actual value passed, which + * allows the template method to be used by both lvalue and rvalues and compile a different implementation. * * @param value The value of the element to append. */ - void push(T const & value) { _container.push_back(value); } - - /** - * @brief Appends the given element value to the end of the container. Value is moved into the new element. - * - * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, - * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. - * - * @param value The value of the element to append. - */ - void push(T && value) { _container.push_back(std::move(value)); } + template + auto push(U && value) -> void + { + _container.push_back(std::forward(value)); + } /** * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the @@ -144,24 +144,27 @@ namespace teachos::arch::stl * * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only - * the end() iterator is invalidated. + * the end() iterator is invalidated. Uses a forward reference for the actual value passed, which + * allows the template method to be used by both lvalue and rvalues and compile a different implementation. * * @tparam Args * @param args Arguments to forward to the constructor of the element - * @return T& + * @return value_type& */ template - auto emplace(Args &&... args) -> T & + auto emplace(Args &&... args) -> reference { _container.emplace_back(std::forward(args)...); } /** - * @brief Removes the last element of the container. Calling pop_back on an empty container results in halting the + * @brief Removes the last element of the container. + * + * @note Calling pop_back on an empty container results in halting the * further execution. Iterators and references to the last element are invalidated. The end() * iterator is also invalidated. */ - void pop() { _container.pop_back(); } + auto pop() -> void { _container.pop_back(); } /** * @brief Wheter there are currently any items this container or not. @@ -171,7 +174,7 @@ namespace teachos::arch::stl auto empty() const -> bool { return _container.empty(); } private: - Container _container = {}; ///< Underlying container used by the stack to actually save the data. + container_type _container = {}; ///< Underlying container used by the stack to actually save the data. }; } // namespace teachos::arch::stl diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index e14f2c9..c7d7853 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -2,9 +2,10 @@ #define TEACHOS_ARCH_X86_64_STL_VECTOR_HPP #include "arch/exception_handling/panic.hpp" +#include "arch/stl/container.hpp" +#include "arch/stl/contiguous_pointer_iterator.hpp" #include -#include namespace teachos::arch::stl { @@ -17,6 +18,13 @@ namespace teachos::arch::stl template struct vector { + using value_type = T; ///< Type of the elements contained in the container. + using size_type = std::size_t; ///< Type of the size in the container. + using reference = value_type &; ///< Type of reference to the elements. + using const_reference = value_type const &; ///< Type of constant reference to the elements. + using pointer = value_type *; ///< Type of pointer to the elements. + using const_pointer = value_type const *; ///< Type of constant pointer to the elements. + /** * @brief Default Constructor. */ @@ -26,15 +34,15 @@ namespace teachos::arch::stl * @brief Constructs data with the given amount of elements containg the given value or alterantively the default * constructed value. * - * @param capacity Amount of elements we want to create and set the given value for. + * @param n Amount of elements we want to create and set the given value for. * @param initial Inital value of all elements in the underlying data array. */ - explicit vector(std::size_t capacity, T initial = T{}) - : _size(capacity) - , _capacity(capacity) - , _data(new T[_capacity]{}) + explicit vector(size_type n, value_type initial = value_type{}) + : _size(n) + , _capacity(n) + , _data(new value_type[_capacity]{}) { - std::ranges::fill(begin(), end(), initial); + std::ranges::fill(*this, initial); } /** @@ -48,9 +56,10 @@ namespace teachos::arch::stl explicit vector(InputIterator first, InputIterator last) : _size(std::distance(first, last)) , _capacity(std::distance(first, last)) - , _data(new T[_capacity]{}) + , _data(new value_type[_capacity]{}) { - std::copy(first, last, _data); + stl::container container{first, last}; + std::ranges::copy(container, _data); } /** @@ -58,12 +67,12 @@ namespace teachos::arch::stl * * @param initalizer_list List we want to copy all elements from. */ - explicit vector(std::initializer_list initalizer_list) + explicit vector(std::initializer_list initalizer_list) : _size(initalizer_list.size()) , _capacity(initalizer_list.size()) - , _data(new T[_capacity]{}) + , _data(new value_type[_capacity]{}) { - std::copy(initalizer_list.begin(), initalizer_list.end(), _data); + std::ranges::copy(initalizer_list, _data); } /** @@ -74,13 +83,13 @@ namespace teachos::arch::stl * * @param other Other instance of vector we want to copy the data from. */ - vector(vector const & other) + vector(vector const & other) : _size(other._size) , _capacity(other._capacity) { delete[] _data; - _data = new T[_capacity]{}; - std::copy(other.begin(), other.end(), _data); + _data = new value_type[_capacity]{}; + std::ranges::copy(other, _data); } /** @@ -92,13 +101,13 @@ namespace teachos::arch::stl * @param other Other instance of vector we want to copy the data from. * @return Newly created copy. */ - vector & operator=(vector const & other) + vector & operator=(vector const & other) { delete[] _data; _size = other._size; _capacity = other._capacity; - _data = new T[_capacity]{}; - std::copy(other.begin(), other.end(), _data); + _data = new value_type[_capacity]{}; + std::ranges::copy(other, _data); return *this; } @@ -113,7 +122,7 @@ namespace teachos::arch::stl * * @return Current amount of elements. */ - std::size_t size() const { return _size; } + auto size() const -> size_type { return _size; } /** * @brief Amount of space the vector currently has, can be different than the size, because we allocate more than we @@ -121,7 +130,17 @@ namespace teachos::arch::stl * * @return Current amount of space the vector has for elements. */ - std::size_t capacity() const { return _capacity; } + auto capacity() const -> size_type { return _capacity; } + + /** + * @brief Array indexing operator. Allowing to access element at the given index. + * + * @note Does not do any bounds checks use at() for that. + * + * @param index Index we want to access elements at. + * @return Reference to the underlying element. + */ + auto operator[](size_type index) -> reference { return _data[index]; } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -131,7 +150,7 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - T & operator[](std::size_t index) { return _data[index]; } + auto operator[](size_type index) const -> const_reference { return _data[index]; } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -141,46 +160,44 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - T & at(std::size_t index) + auto at(size_type index) -> reference { - if (index >= _size) - { - exception_handling::panic("[Vector] Attempted to read element at invalid index"); - } + throw_if_out_of_range(index); return this->operator[](index); } /** - * @brief Appends the given element value to the end of the container. The new element is initalized as a copy of - * value. + * @brief Array indexing operator. Allowing to access element at the given index. * - * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, - * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. + * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. * - * @param value The value of the element to append. + * @param index Index we want to access elements at. + * @return Reference to the underlying element. */ - void push_back(T const & value) + auto at(size_type index) const -> const_reference { - increase_capacity_if_full(); - _data[_size] = value; - (void)_size++; + throw_if_out_of_range(index); + return this->operator[](index); } /** - * @brief Appends the given element value to the end of the container. Value is moved into the new element. + * @brief Appends the given element value to the end of the container. The element is assigned through the + * assignment operator of the template type. The value is forwarded to the constructor as + * std::forward(value), meaning it is either moved (rvalue) or copied (lvalue). * * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. + * Otherwise only the end() iterator is invalidated. Uses a forward reference for the actual value passed, which + * allows the template method to be used by both lvalue and rvalues and compile a different implementation. * * @param value The value of the element to append. */ - void push_back(T && value) + template + auto push_back(U && value) -> void { increase_capacity_if_full(); - _data[_size] = std::move(value); - _size++; + _data[_size] = std::forward(value); + (void)_size++; } /** @@ -189,17 +206,18 @@ namespace teachos::arch::stl * * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only - * the end() iterator is invalidated. + * the end() iterator is invalidated. Uses a forward reference for the actual value passed, which + * allows the template method to be used by both lvalue and rvalues and compile a different implementation. * * @tparam Args * @param args Arguments to forward to the constructor of the element - * @return T& + * @return value_type& */ template - auto emplace_back(Args &&... args) -> T & + auto emplace_back(Args &&... args) -> value_type & { increase_capacity_if_full(); - _data[_size] = T{std::forward(args)...}; + _data[_size] = value_type{std::forward(args)...}; auto const index = _size++; return _data[index]; } @@ -209,7 +227,7 @@ namespace teachos::arch::stl * further execution. Iterators and references to the last element are invalidated. The end() * iterator is also invalidated. */ - void pop_back() + auto pop_back() -> void { throw_if_empty(); (void)_size--; @@ -221,7 +239,7 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - T * begin() noexcept { return _data; } + auto begin() noexcept -> pointer { return _data; } /** * @brief Returns an iterator to the first element of the vector. @@ -229,7 +247,7 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - T const * begin() const noexcept { return _data; } + auto begin() const noexcept -> const_pointer { return _data; } /** * @brief Returns an iterator to the first element of the vector. @@ -237,7 +255,7 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - T const * cbegin() const noexcept { return begin(); } + auto cbegin() const noexcept -> const_pointer { return begin(); } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -245,7 +263,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - T * rbegin() noexcept { return _data + _size - 1; } + auto rbegin() noexcept -> pointer { return _data + _size - 1; } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -253,7 +271,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - T const * rbegin() const noexcept { return _data + _size - 1; } + auto rbegin() const noexcept -> const_pointer { return _data + _size - 1; } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -261,7 +279,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - T const * crbegin() const noexcept { return rbegin(); } + auto crbegin() const noexcept -> const_pointer { return rbegin(); } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -269,7 +287,7 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - T * end() noexcept { return _data + _size; } + auto end() noexcept -> pointer { return _data + _size; } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -277,7 +295,7 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - T const * end() const noexcept { return _data + _size; } + auto end() const noexcept -> const_pointer { return _data + _size; } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -285,7 +303,7 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - T const * cend() const noexcept { return end(); } + auto cend() const noexcept -> const_pointer { return end(); } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -294,7 +312,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - T * rend() noexcept { return _data + size - 1; } + auto rend() noexcept -> pointer { return _data + size - 1; } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -303,7 +321,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - T const * rend() const noexcept { return _data + size - 1; } + auto rend() const noexcept -> const_pointer { return _data + size - 1; } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -312,7 +330,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - T const * crend() const noexcept { return rbegin(); } + auto crend() const noexcept -> const_pointer { return rbegin(); } /** * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range @@ -322,7 +340,7 @@ namespace teachos::arch::stl * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal * to the address of the first element. */ - T * data() { return _data; } + auto data() -> pointer { return _data; } /** * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range @@ -332,7 +350,7 @@ namespace teachos::arch::stl * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal * to the address of the first element. */ - T const * data() const { return _data; } + auto data() const -> const_pointer { return _data; } /** * @brief Returns a reference to the first element in the container. Calling front on an empty container causes @@ -340,7 +358,7 @@ namespace teachos::arch::stl * * @return Reference to the first element. */ - T & front() + auto front() -> reference { throw_if_empty(); return *begin(); @@ -352,7 +370,7 @@ namespace teachos::arch::stl * * @return Reference to the first element. */ - T const & front() const + auto front() const -> const_reference { throw_if_empty(); return *begin(); @@ -364,7 +382,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T & back() + auto back() -> reference { throw_if_empty(); return *rbegin(); @@ -376,7 +394,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T const & back() const + auto back() const -> const_reference { throw_if_empty(); return *rbegin(); @@ -409,7 +427,7 @@ namespace teachos::arch::stl * * @param new_capacity New capacity of the vector, in number of elements */ - void reserve(std::size_t new_capacity) + auto reserve(size_type new_capacity) -> void { if (new_capacity <= _capacity) { @@ -417,8 +435,9 @@ namespace teachos::arch::stl } _capacity = new_capacity; - T * temp = new T[_capacity]{}; - std::copy(begin(), end(), temp); + value_type * temp = new value_type[_capacity]{}; + stl::container container{begin(), end()}; + std::ranges::copy(container, temp); delete[] _data; _data = temp; } @@ -429,7 +448,7 @@ namespace teachos::arch::stl * If reallocation occurs, all iterators (including the end() iterator) and all references to the elements are * invalidated. If no reallocation occurs, no iterators or references are invalidated. */ - void shrink_to_fit() + auto shrink_to_fit() -> void { if (_size == _capacity) { @@ -437,8 +456,9 @@ namespace teachos::arch::stl } _capacity = _size; - T * temp = new T[_capacity]{}; - std::copy(begin(), end(), temp); + value_type * temp = new value_type[_capacity]{}; + stl::container container{begin(), end()}; + std::copy(container, temp); delete[] _data; _data = temp; } @@ -462,6 +482,14 @@ namespace teachos::arch::stl } } + auto throw_if_out_of_range(size_type index) const -> void + { + if (index >= _size) + { + exception_handling::panic("[Vector] Attempted to read element at invalid index"); + } + } + /** * @brief Increases the internal capacity to 1 if it was previously 0 and to * 2 after that, meaning exponential * growth. This is done to decrease the amount of single allocations done and because a power of 2 in memory size is @@ -475,9 +503,9 @@ namespace teachos::arch::stl } } - std::size_t _size = {}; ///< Amount of elements in the underlying data container - std::size_t _capacity = {}; ///< Amount of space for elements in the underlying data container - T * _data = {}; ///< Pointer to the first element in the underlying data container + size_type _size = {}; ///< Amount of elements in the underlying data container + size_type _capacity = {}; ///< Amount of space for elements in the underlying data container + value_type * _data = {}; ///< Pointer to the first element in the underlying data container }; } // namespace teachos::arch::stl -- cgit v1.2.3