From 833738f7023324172dbb0922fe1be9ad9cc88330 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 14 Jul 2025 20:35:38 +0000 Subject: libs: rename kstd headers to be more STL like --- libs/kstd/CMakeLists.txt | 9 +- libs/kstd/include/kstd/memory | 7 + libs/kstd/include/kstd/memory.hpp | 7 - libs/kstd/include/kstd/mutex | 60 ++++ libs/kstd/include/kstd/mutex.hpp | 60 ---- libs/kstd/include/kstd/stack | 213 ++++++++++++++ libs/kstd/include/kstd/stack.hpp | 213 -------------- libs/kstd/include/kstd/vector | 596 ++++++++++++++++++++++++++++++++++++++ libs/kstd/include/kstd/vector.hpp | 596 -------------------------------------- libs/kstd/src/mutex.cpp | 2 +- 10 files changed, 885 insertions(+), 878 deletions(-) create mode 100644 libs/kstd/include/kstd/memory delete mode 100644 libs/kstd/include/kstd/memory.hpp create mode 100644 libs/kstd/include/kstd/mutex delete mode 100644 libs/kstd/include/kstd/mutex.hpp create mode 100644 libs/kstd/include/kstd/stack delete mode 100644 libs/kstd/include/kstd/stack.hpp create mode 100644 libs/kstd/include/kstd/vector delete mode 100644 libs/kstd/include/kstd/vector.hpp (limited to 'libs') diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt index a29fac8..b0abaaf 100644 --- a/libs/kstd/CMakeLists.txt +++ b/libs/kstd/CMakeLists.txt @@ -9,7 +9,14 @@ target_sources("kstd" PUBLIC FILE_SET HEADERS BASE_DIRS "include" FILES - "include/kstd/mutex.hpp" + "include/kstd/bits/os.hpp" + "include/kstd/bits/shared_ptr.hpp" + "include/kstd/bits/unique_ptr.hpp" + + "include/kstd/memory" + "include/kstd/mutex" + "include/kstd/stack" + "include/kstd/vector" ) target_include_directories("kstd" PUBLIC diff --git a/libs/kstd/include/kstd/memory b/libs/kstd/include/kstd/memory new file mode 100644 index 0000000..cab2fba --- /dev/null +++ b/libs/kstd/include/kstd/memory @@ -0,0 +1,7 @@ +#ifndef KSTD_SHARED_POINTER_HPP +#define KSTD_SHARED_POINTER_HPP + +#include "kstd/bits/shared_ptr.hpp" // IWYU pragma: export +#include "kstd/bits/unique_ptr.hpp" // IWYU pragma: export + +#endif \ No newline at end of file diff --git a/libs/kstd/include/kstd/memory.hpp b/libs/kstd/include/kstd/memory.hpp deleted file mode 100644 index cab2fba..0000000 --- a/libs/kstd/include/kstd/memory.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef KSTD_SHARED_POINTER_HPP -#define KSTD_SHARED_POINTER_HPP - -#include "kstd/bits/shared_ptr.hpp" // IWYU pragma: export -#include "kstd/bits/unique_ptr.hpp" // IWYU pragma: export - -#endif \ No newline at end of file diff --git a/libs/kstd/include/kstd/mutex b/libs/kstd/include/kstd/mutex new file mode 100644 index 0000000..cf8549f --- /dev/null +++ b/libs/kstd/include/kstd/mutex @@ -0,0 +1,60 @@ +#ifndef KSTD_MUTEX_HPP +#define KSTD_MUTEX_HPP + +#include + +namespace kstd +{ + /** + * @brief Custom mutex implementation, that simply wraps an atomic boolean to keep track if the mutex is already in + * use by another thread or not. + */ + struct mutex + { + /** + * @brief Defaulted constructor. + */ + mutex() = default; + + /** + * @brief Defaulted destructor. + */ + ~mutex() = default; + + /** + * @brief Deleted copy constructor. + */ + mutex(const mutex &) = delete; + + /** + * @brief Deleted assignment operator. + */ + mutex & operator=(const mutex &) = delete; + + /** + * @brief Lock the mutex (blocks for as long as it is not available). + */ + [[gnu::section(".stl_text")]] + auto lock() -> void; + + /** + * @brief Try to lock the mutex (non-blocking). + * + * @return True if lock has been acquired and false otherwise. + */ + [[gnu::section(".stl_text")]] + auto try_lock() -> bool; + + /** + * @brief Unlock the mutex. + */ + [[gnu::section(".stl_text")]] + auto unlock() -> void; + + private: + std::atomic locked = {false}; // Atomic boolean to track if mutex is locked or not. + }; + +} // namespace kstd + +#endif \ No newline at end of file diff --git a/libs/kstd/include/kstd/mutex.hpp b/libs/kstd/include/kstd/mutex.hpp deleted file mode 100644 index cf8549f..0000000 --- a/libs/kstd/include/kstd/mutex.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef KSTD_MUTEX_HPP -#define KSTD_MUTEX_HPP - -#include - -namespace kstd -{ - /** - * @brief Custom mutex implementation, that simply wraps an atomic boolean to keep track if the mutex is already in - * use by another thread or not. - */ - struct mutex - { - /** - * @brief Defaulted constructor. - */ - mutex() = default; - - /** - * @brief Defaulted destructor. - */ - ~mutex() = default; - - /** - * @brief Deleted copy constructor. - */ - mutex(const mutex &) = delete; - - /** - * @brief Deleted assignment operator. - */ - mutex & operator=(const mutex &) = delete; - - /** - * @brief Lock the mutex (blocks for as long as it is not available). - */ - [[gnu::section(".stl_text")]] - auto lock() -> void; - - /** - * @brief Try to lock the mutex (non-blocking). - * - * @return True if lock has been acquired and false otherwise. - */ - [[gnu::section(".stl_text")]] - auto try_lock() -> bool; - - /** - * @brief Unlock the mutex. - */ - [[gnu::section(".stl_text")]] - auto unlock() -> void; - - private: - std::atomic locked = {false}; // Atomic boolean to track if mutex is locked or not. - }; - -} // namespace kstd - -#endif \ No newline at end of file diff --git a/libs/kstd/include/kstd/stack b/libs/kstd/include/kstd/stack new file mode 100644 index 0000000..8c702cf --- /dev/null +++ b/libs/kstd/include/kstd/stack @@ -0,0 +1,213 @@ +#ifndef KSTD_STACK_HPP +#define KSTD_STACK_HPP + +#include "kstd/vector.hpp" + +#include + +namespace kstd +{ + /** + * @brief Custom stack implementation mirroring the std::stack to allow for the usage of STL functionality with our + * 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. + */ + stack() = default; + + /** + * @brief Constructs data with the given amount of elements containg the given value or alterantively the default + * constructed value. + * + * @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. + */ + [[gnu::section(".stl_text")]] + explicit stack(size_type n, value_type initial = value_type{}) + : _container(n, initial) + { + // Nothing to do. + } + + /** + * @brief Constructs data by copying all element from the given exclusive range. + * + * @tparam InputIterator Template that should have atleast input iterator characteristics. + * @param first Input iterator to the first element in the range we want to copy from. + * @param last Input iterator to one past the last element in the range we want to copy from. + */ + template + [[gnu::section(".stl_text")]] + explicit stack(InputIterator first, InputIterator last) + : _container(first, last) + { + // Nothing to do. + } + + /** + * @brief Construct data by copying all elements from the initializer list. + * + * @param initalizer_list List we want to copy all elements from. + */ + [[gnu::section(".stl_text")]] + explicit stack(std::initializer_list initalizer_list) + : _container(initalizer_list) + { + // Nothing to do. + } + + /** + * @brief Copy constructor. + * + * @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 stack we want to copy the data from. + */ + [[gnu::section(".stl_text")]] + stack(stack const & other) + : _container(other) + { + // Nothing to do. + } + + /** + * @brief Copy assignment operator. + * + * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all + * elements from it. + * + * @param other Other instance of vector we want to copy the data from. + * @return Newly created copy. + */ + [[gnu::section(".stl_text")]] + stack & operator=(stack const & other) + { + _container = other; + } + + /** + * @brief Destructor. + */ + ~stack() = default; + + /** + * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If + * that is the case the capacity is increased automatically. + * + * @return Current amount of elements. + */ + [[gnu::section(".stl_text")]] + 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 + * undefined behavior. + * + * @return Reference to the last element. + */ + [[gnu::section(".stl_text")]] + auto top() -> reference + { + return _container.back(); + } + + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + [[gnu::section(".stl_text")]] + auto top() const -> const_reference + { + return _container.back(); + } + + /** + * @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. 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. + */ + template + [[gnu::section(".stl_text")]] + 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 + * template type. The arguments args... are forwarded to the constructor as std::forward(args).... + * + * 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. 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 value_type& + */ + template + [[gnu::section(".stl_text")]] + auto emplace(Args &&... args) -> reference + { + _container.emplace_back(std::forward(args)...); + } + + /** + * @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. + */ + [[gnu::section(".stl_text")]] + auto pop() -> void + { + _container.pop_back(); + } + + /** + * @brief Wheter there are currently any items this container or not. + * + * @return True if there are no elements, false if there are. + */ + [[gnu::section(".stl_text")]] + auto empty() const -> bool + { + return _container.empty(); + } + + private: + container_type _container = {}; ///< Underlying container used by the stack to actually save the data. + }; + +} // namespace kstd + +#endif diff --git a/libs/kstd/include/kstd/stack.hpp b/libs/kstd/include/kstd/stack.hpp deleted file mode 100644 index 8c702cf..0000000 --- a/libs/kstd/include/kstd/stack.hpp +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef KSTD_STACK_HPP -#define KSTD_STACK_HPP - -#include "kstd/vector.hpp" - -#include - -namespace kstd -{ - /** - * @brief Custom stack implementation mirroring the std::stack to allow for the usage of STL functionality with our - * 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. - */ - stack() = default; - - /** - * @brief Constructs data with the given amount of elements containg the given value or alterantively the default - * constructed value. - * - * @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. - */ - [[gnu::section(".stl_text")]] - explicit stack(size_type n, value_type initial = value_type{}) - : _container(n, initial) - { - // Nothing to do. - } - - /** - * @brief Constructs data by copying all element from the given exclusive range. - * - * @tparam InputIterator Template that should have atleast input iterator characteristics. - * @param first Input iterator to the first element in the range we want to copy from. - * @param last Input iterator to one past the last element in the range we want to copy from. - */ - template - [[gnu::section(".stl_text")]] - explicit stack(InputIterator first, InputIterator last) - : _container(first, last) - { - // Nothing to do. - } - - /** - * @brief Construct data by copying all elements from the initializer list. - * - * @param initalizer_list List we want to copy all elements from. - */ - [[gnu::section(".stl_text")]] - explicit stack(std::initializer_list initalizer_list) - : _container(initalizer_list) - { - // Nothing to do. - } - - /** - * @brief Copy constructor. - * - * @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 stack we want to copy the data from. - */ - [[gnu::section(".stl_text")]] - stack(stack const & other) - : _container(other) - { - // Nothing to do. - } - - /** - * @brief Copy assignment operator. - * - * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all - * elements from it. - * - * @param other Other instance of vector we want to copy the data from. - * @return Newly created copy. - */ - [[gnu::section(".stl_text")]] - stack & operator=(stack const & other) - { - _container = other; - } - - /** - * @brief Destructor. - */ - ~stack() = default; - - /** - * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If - * that is the case the capacity is increased automatically. - * - * @return Current amount of elements. - */ - [[gnu::section(".stl_text")]] - 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 - * undefined behavior. - * - * @return Reference to the last element. - */ - [[gnu::section(".stl_text")]] - auto top() -> reference - { - return _container.back(); - } - - /** - * @brief Returns a reference to the last element in the container. Calling back on an empty container causes - * undefined behavior. - * - * @return Reference to the last element. - */ - [[gnu::section(".stl_text")]] - auto top() const -> const_reference - { - return _container.back(); - } - - /** - * @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. 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. - */ - template - [[gnu::section(".stl_text")]] - 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 - * template type. The arguments args... are forwarded to the constructor as std::forward(args).... - * - * 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. 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 value_type& - */ - template - [[gnu::section(".stl_text")]] - auto emplace(Args &&... args) -> reference - { - _container.emplace_back(std::forward(args)...); - } - - /** - * @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. - */ - [[gnu::section(".stl_text")]] - auto pop() -> void - { - _container.pop_back(); - } - - /** - * @brief Wheter there are currently any items this container or not. - * - * @return True if there are no elements, false if there are. - */ - [[gnu::section(".stl_text")]] - auto empty() const -> bool - { - return _container.empty(); - } - - private: - container_type _container = {}; ///< Underlying container used by the stack to actually save the data. - }; - -} // namespace kstd - -#endif diff --git a/libs/kstd/include/kstd/vector b/libs/kstd/include/kstd/vector new file mode 100644 index 0000000..1009e81 --- /dev/null +++ b/libs/kstd/include/kstd/vector @@ -0,0 +1,596 @@ +#ifndef KSTD_VECTOR_HPP +#define KSTD_VECTOR_HPP + +#include "bits/os.hpp" + +#include + +namespace kstd +{ + /** + * @brief Custom vector implementation mirroring the std::vector to allow for the usage of STL functionality with our + * custom memory management. + * + * @tparam T Element the vector instance should contain. + */ + 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. + */ + vector() = default; + + /** + * @brief Constructs data with the given amount of elements containg the given value or alterantively the default + * constructed value. + * + * @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(size_type n, value_type initial = value_type{}) + : _size(n) + , _capacity(n) + , _data(new value_type[_capacity]{}) + { + std::ranges::fill(*this, initial); + } + + /** + * @brief Constructs data by copying all element from the given exclusive range. + * + * @tparam InputIterator Template that should have atleast input iterator characteristics. + * @param first Input iterator to the first element in the range we want to copy from. + * @param last Input iterator to one past the last element in the range we want to copy from. + */ + template + explicit vector(InputIterator first, InputIterator last) + : _size(std::distance(first, last)) + , _capacity(std::distance(first, last)) + , _data(new value_type[_capacity]{}) + { + std::ranges::copy(first, last, _data); + } + + /** + * @brief Construct data by copying all elements from the initializer list. + * + * @param initalizer_list List we want to copy all elements from. + */ + explicit vector(std::initializer_list initalizer_list) + : _size(initalizer_list.size()) + , _capacity(initalizer_list.size()) + , _data(new value_type[_capacity]{}) + { + std::ranges::copy(initalizer_list, _data); + } + + /** + * @brief Copy constructor. + * + * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all + * elements from it. + * + * @param other Other instance of vector we want to copy the data from. + */ + vector(vector const & other) + : _size(other._size) + , _capacity(other._capacity) + { + delete[] _data; + _data = new value_type[_capacity]{}; + std::ranges::copy(other, _data); + } + + /** + * @brief Copy assignment operator. + * + * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all + * elements from it. + * + * @param other Other instance of vector we want to copy the data from. + * @return Newly created copy. + */ + [[gnu::section(".stl_text")]] + vector & operator=(vector const & other) + { + delete[] _data; + _size = other._size; + _capacity = other._capacity; + _data = new value_type[_capacity]{}; + std::ranges::copy(other, _data); + return *this; + } + + /** + * @brief Destructor. + */ + ~vector() { delete[] _data; } + + /** + * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If + * that is the case the capacity is increased automatically. + * + * @return Current amount of elements. + */ + [[gnu::section(".stl_text")]] + 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 + * exactly require to decrease the amount of allocations and deallocation to improve speed. + * + * @return Current amount of space the vector has for elements. + */ + [[gnu::section(".stl_text")]] + 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. + */ + [[gnu::section(".stl_text")]] + auto operator[](size_type index) -> reference + { + return _data[index]; + } + + /** + * @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. + */ + [[gnu::section(".stl_text")]] + auto operator[](size_type index) const -> const_reference + { + return _data[index]; + } + + /** + * @brief Array indexing operator. Allowing to access element at the given index. + * + * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. + * + * @param index Index we want to access elements at. + * @return Reference to the underlying element. + */ + [[gnu::section(".stl_text")]] + auto at(size_type index) -> reference + { + throw_if_out_of_range(index); + return this->operator[](index); + } + + /** + * @brief Array indexing operator. Allowing to access element at the given index. + * + * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. + * + * @param index Index we want to access elements at. + * @return Reference to the underlying element. + */ + [[gnu::section(".stl_text")]] + auto at(size_type index) const -> const_reference + { + throw_if_out_of_range(index); + return this->operator[](index); + } + + /** + * @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. 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. + */ + template + [[gnu::section(".stl_text")]] + auto push_back(U && value) -> void + { + increase_capacity_if_full(); + _data[_size] = std::forward(value); + (void)_size++; + } + + /** + * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the + * template type. The arguments args... are forwarded to the constructor as std::forward(args).... + * + * 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. 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 value_type& + */ + template + [[gnu::section(".stl_text")]] + auto emplace_back(Args &&... args) -> value_type & + { + increase_capacity_if_full(); + _data[_size] = value_type{std::forward(args)...}; + auto const index = _size++; + return _data[index]; + } + + /** + * @brief Removes the last element of the container. 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. + */ + [[gnu::section(".stl_text")]] + auto pop_back() -> void + { + throw_if_empty(); + (void)_size--; + } + + /** + * @brief Returns an iterator to the first element of the vector. + * If the vector is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + [[gnu::section(".stl_text")]] + auto begin() noexcept -> pointer + { + return _data; + } + + /** + * @brief Returns an iterator to the first element of the vector. + * If the vector is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + [[gnu::section(".stl_text")]] + auto begin() const noexcept -> const_pointer + { + return _data; + } + + /** + * @brief Returns an iterator to the first element of the vector. + * If the vector is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + [[gnu::section(".stl_text")]] + 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 + * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + [[gnu::section(".stl_text")]] + 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 + * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + [[gnu::section(".stl_text")]] + 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 + * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + [[gnu::section(".stl_text")]] + 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 + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + [[gnu::section(".stl_text")]] + 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 + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + [[gnu::section(".stl_text")]] + 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 + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + [[gnu::section(".stl_text")]] + 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 + * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + [[gnu::section(".stl_text")]] + 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 + * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + [[gnu::section(".stl_text")]] + 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 + * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + [[gnu::section(".stl_text")]] + 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 + * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable + * in that case). + * + * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal + * to the address of the first element. + */ + [[gnu::section(".stl_text")]] + auto data() -> pointer + { + return _data; + } + + /** + * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range + * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable + * in that case). + * + * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal + * to the address of the first element. + */ + [[gnu::section(".stl_text")]] + 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 + * undefined behavior. + * + * @return Reference to the first element. + */ + [[gnu::section(".stl_text")]] + auto front() -> reference + { + throw_if_empty(); + return *begin(); + } + + /** + * @brief Returns a reference to the first element in the container. Calling front on an empty container causes + * undefined behavior. + * + * @return Reference to the first element. + */ + [[gnu::section(".stl_text")]] + auto front() const -> const_reference + { + throw_if_empty(); + return *begin(); + } + + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + [[gnu::section(".stl_text")]] + auto back() -> reference + { + throw_if_empty(); + return *rbegin(); + } + + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + [[gnu::section(".stl_text")]] + auto back() const -> const_reference + { + throw_if_empty(); + return *rbegin(); + } + + /** + * @brief Increase the capacity of the vector (the total number of elements that the vector can hold without + * requiring reallocation) to a value that's greater or equal to new_cap. If new_cap is greater than the current + * capacity(), new storage is allocated, otherwise the function does nothing. + * + * reserve() does not change the size of the vector. + * + * If new_cap is greater than capacity(), all iterators (including the end() iterator) and all references to the + * elements are invalidated. Otherwise, no iterators or references are invalidated. + * + * After a call to reserve(), insertions will not trigger reallocation unless the insertion would make the size of + * the vector greater than the value of capacity(). + * + * @note Correctly using reserve() can prevent unnecessary reallocations, but inappropriate uses of reserve() (for + * instance, calling it before every push_back() call) may actually increase the number of reallocations (by causing + * the capacity to grow linearly rather than exponentially) and result in increased computational complexity and + * decreased performance. For example, a function that receives an arbitrary vector by reference and appends + * elements to it should usually not call reserve() on the vector, since it does not know of the vector's usage + * characteristics. + * + * When inserting a range, the range version of insert() is generally preferable as it preserves the correct + * capacity growth behavior, unlike reserve() followed by a series of push_back()s. + * + * reserve() cannot be used to reduce the capacity of the container; to that end shrink_to_fit() is provided. + * + * @param new_capacity New capacity of the vector, in number of elements + */ + [[gnu::section(".stl_text")]] + auto reserve(size_type new_capacity) -> void + { + if (new_capacity <= _capacity) + { + return; + } + + _capacity = new_capacity; + value_type * temp = new value_type[_capacity]{}; + std::ranges::copy(begin(), end(), temp); + delete[] _data; + _data = temp; + } + + /** + * @brief Requests the removal of unused capacity. Meaning it requests to reduce capacity() to size(). + * + * 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. + */ + [[gnu::section(".stl_text")]] + auto shrink_to_fit() -> void + { + if (_size == _capacity) + { + return; + } + + _capacity = _size; + value_type * temp = new value_type[_capacity]{}; + std::ranges::copy(begin(), end(), temp); + delete[] _data; + _data = temp; + } + + /** + * @brief Wheter there are currently any items this container or not. + * + * @return True if there are no elements, false if there are. + */ + [[gnu::section(".stl_text")]] + auto empty() const -> bool + { + return _size <= 0; + } + + private: + /** + * @brief Halts the execution of the application if the data container is currently empty. + */ + auto throw_if_empty() const -> void + { + if (empty()) + { + os::panic("[Vector] Attempted to access element of currently empty vector"); + } + } + + auto throw_if_out_of_range(size_type index) const -> void + { + if (index >= _size) + { + os::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 + * normally perferable for the cache. + */ + auto increase_capacity_if_full() -> void + { + if (_size == _capacity) + { + reserve(_capacity == 0U ? 1U : _capacity * 2U); + } + } + + 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 kstd + +#endif diff --git a/libs/kstd/include/kstd/vector.hpp b/libs/kstd/include/kstd/vector.hpp deleted file mode 100644 index 1009e81..0000000 --- a/libs/kstd/include/kstd/vector.hpp +++ /dev/null @@ -1,596 +0,0 @@ -#ifndef KSTD_VECTOR_HPP -#define KSTD_VECTOR_HPP - -#include "bits/os.hpp" - -#include - -namespace kstd -{ - /** - * @brief Custom vector implementation mirroring the std::vector to allow for the usage of STL functionality with our - * custom memory management. - * - * @tparam T Element the vector instance should contain. - */ - 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. - */ - vector() = default; - - /** - * @brief Constructs data with the given amount of elements containg the given value or alterantively the default - * constructed value. - * - * @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(size_type n, value_type initial = value_type{}) - : _size(n) - , _capacity(n) - , _data(new value_type[_capacity]{}) - { - std::ranges::fill(*this, initial); - } - - /** - * @brief Constructs data by copying all element from the given exclusive range. - * - * @tparam InputIterator Template that should have atleast input iterator characteristics. - * @param first Input iterator to the first element in the range we want to copy from. - * @param last Input iterator to one past the last element in the range we want to copy from. - */ - template - explicit vector(InputIterator first, InputIterator last) - : _size(std::distance(first, last)) - , _capacity(std::distance(first, last)) - , _data(new value_type[_capacity]{}) - { - std::ranges::copy(first, last, _data); - } - - /** - * @brief Construct data by copying all elements from the initializer list. - * - * @param initalizer_list List we want to copy all elements from. - */ - explicit vector(std::initializer_list initalizer_list) - : _size(initalizer_list.size()) - , _capacity(initalizer_list.size()) - , _data(new value_type[_capacity]{}) - { - std::ranges::copy(initalizer_list, _data); - } - - /** - * @brief Copy constructor. - * - * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all - * elements from it. - * - * @param other Other instance of vector we want to copy the data from. - */ - vector(vector const & other) - : _size(other._size) - , _capacity(other._capacity) - { - delete[] _data; - _data = new value_type[_capacity]{}; - std::ranges::copy(other, _data); - } - - /** - * @brief Copy assignment operator. - * - * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all - * elements from it. - * - * @param other Other instance of vector we want to copy the data from. - * @return Newly created copy. - */ - [[gnu::section(".stl_text")]] - vector & operator=(vector const & other) - { - delete[] _data; - _size = other._size; - _capacity = other._capacity; - _data = new value_type[_capacity]{}; - std::ranges::copy(other, _data); - return *this; - } - - /** - * @brief Destructor. - */ - ~vector() { delete[] _data; } - - /** - * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If - * that is the case the capacity is increased automatically. - * - * @return Current amount of elements. - */ - [[gnu::section(".stl_text")]] - 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 - * exactly require to decrease the amount of allocations and deallocation to improve speed. - * - * @return Current amount of space the vector has for elements. - */ - [[gnu::section(".stl_text")]] - 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. - */ - [[gnu::section(".stl_text")]] - auto operator[](size_type index) -> reference - { - return _data[index]; - } - - /** - * @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. - */ - [[gnu::section(".stl_text")]] - auto operator[](size_type index) const -> const_reference - { - return _data[index]; - } - - /** - * @brief Array indexing operator. Allowing to access element at the given index. - * - * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. - * - * @param index Index we want to access elements at. - * @return Reference to the underlying element. - */ - [[gnu::section(".stl_text")]] - auto at(size_type index) -> reference - { - throw_if_out_of_range(index); - return this->operator[](index); - } - - /** - * @brief Array indexing operator. Allowing to access element at the given index. - * - * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. - * - * @param index Index we want to access elements at. - * @return Reference to the underlying element. - */ - [[gnu::section(".stl_text")]] - auto at(size_type index) const -> const_reference - { - throw_if_out_of_range(index); - return this->operator[](index); - } - - /** - * @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. 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. - */ - template - [[gnu::section(".stl_text")]] - auto push_back(U && value) -> void - { - increase_capacity_if_full(); - _data[_size] = std::forward(value); - (void)_size++; - } - - /** - * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the - * template type. The arguments args... are forwarded to the constructor as std::forward(args).... - * - * 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. 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 value_type& - */ - template - [[gnu::section(".stl_text")]] - auto emplace_back(Args &&... args) -> value_type & - { - increase_capacity_if_full(); - _data[_size] = value_type{std::forward(args)...}; - auto const index = _size++; - return _data[index]; - } - - /** - * @brief Removes the last element of the container. 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. - */ - [[gnu::section(".stl_text")]] - auto pop_back() -> void - { - throw_if_empty(); - (void)_size--; - } - - /** - * @brief Returns an iterator to the first element of the vector. - * If the vector is empty, the returned iterator will be equal to end(). - * - * @return Iterator to the first element. - */ - [[gnu::section(".stl_text")]] - auto begin() noexcept -> pointer - { - return _data; - } - - /** - * @brief Returns an iterator to the first element of the vector. - * If the vector is empty, the returned iterator will be equal to end(). - * - * @return Iterator to the first element. - */ - [[gnu::section(".stl_text")]] - auto begin() const noexcept -> const_pointer - { - return _data; - } - - /** - * @brief Returns an iterator to the first element of the vector. - * If the vector is empty, the returned iterator will be equal to end(). - * - * @return Iterator to the first element. - */ - [[gnu::section(".stl_text")]] - 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 - * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). - * - * @return Reverse iterator to the first element. - */ - [[gnu::section(".stl_text")]] - 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 - * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). - * - * @return Reverse iterator to the first element. - */ - [[gnu::section(".stl_text")]] - 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 - * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). - * - * @return Reverse iterator to the first element. - */ - [[gnu::section(".stl_text")]] - 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 - * placeholder, attempting to access it results in undefined behavior. - * - * @return Iterator to the element following the last element. - */ - [[gnu::section(".stl_text")]] - 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 - * placeholder, attempting to access it results in undefined behavior. - * - * @return Iterator to the element following the last element. - */ - [[gnu::section(".stl_text")]] - 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 - * placeholder, attempting to access it results in undefined behavior. - * - * @return Iterator to the element following the last element. - */ - [[gnu::section(".stl_text")]] - 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 - * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Reverse iterator to the element following the last element. - */ - [[gnu::section(".stl_text")]] - 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 - * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Reverse iterator to the element following the last element. - */ - [[gnu::section(".stl_text")]] - 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 - * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Reverse iterator to the element following the last element. - */ - [[gnu::section(".stl_text")]] - 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 - * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable - * in that case). - * - * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal - * to the address of the first element. - */ - [[gnu::section(".stl_text")]] - auto data() -> pointer - { - return _data; - } - - /** - * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range - * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable - * in that case). - * - * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal - * to the address of the first element. - */ - [[gnu::section(".stl_text")]] - 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 - * undefined behavior. - * - * @return Reference to the first element. - */ - [[gnu::section(".stl_text")]] - auto front() -> reference - { - throw_if_empty(); - return *begin(); - } - - /** - * @brief Returns a reference to the first element in the container. Calling front on an empty container causes - * undefined behavior. - * - * @return Reference to the first element. - */ - [[gnu::section(".stl_text")]] - auto front() const -> const_reference - { - throw_if_empty(); - return *begin(); - } - - /** - * @brief Returns a reference to the last element in the container. Calling back on an empty container causes - * undefined behavior. - * - * @return Reference to the last element. - */ - [[gnu::section(".stl_text")]] - auto back() -> reference - { - throw_if_empty(); - return *rbegin(); - } - - /** - * @brief Returns a reference to the last element in the container. Calling back on an empty container causes - * undefined behavior. - * - * @return Reference to the last element. - */ - [[gnu::section(".stl_text")]] - auto back() const -> const_reference - { - throw_if_empty(); - return *rbegin(); - } - - /** - * @brief Increase the capacity of the vector (the total number of elements that the vector can hold without - * requiring reallocation) to a value that's greater or equal to new_cap. If new_cap is greater than the current - * capacity(), new storage is allocated, otherwise the function does nothing. - * - * reserve() does not change the size of the vector. - * - * If new_cap is greater than capacity(), all iterators (including the end() iterator) and all references to the - * elements are invalidated. Otherwise, no iterators or references are invalidated. - * - * After a call to reserve(), insertions will not trigger reallocation unless the insertion would make the size of - * the vector greater than the value of capacity(). - * - * @note Correctly using reserve() can prevent unnecessary reallocations, but inappropriate uses of reserve() (for - * instance, calling it before every push_back() call) may actually increase the number of reallocations (by causing - * the capacity to grow linearly rather than exponentially) and result in increased computational complexity and - * decreased performance. For example, a function that receives an arbitrary vector by reference and appends - * elements to it should usually not call reserve() on the vector, since it does not know of the vector's usage - * characteristics. - * - * When inserting a range, the range version of insert() is generally preferable as it preserves the correct - * capacity growth behavior, unlike reserve() followed by a series of push_back()s. - * - * reserve() cannot be used to reduce the capacity of the container; to that end shrink_to_fit() is provided. - * - * @param new_capacity New capacity of the vector, in number of elements - */ - [[gnu::section(".stl_text")]] - auto reserve(size_type new_capacity) -> void - { - if (new_capacity <= _capacity) - { - return; - } - - _capacity = new_capacity; - value_type * temp = new value_type[_capacity]{}; - std::ranges::copy(begin(), end(), temp); - delete[] _data; - _data = temp; - } - - /** - * @brief Requests the removal of unused capacity. Meaning it requests to reduce capacity() to size(). - * - * 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. - */ - [[gnu::section(".stl_text")]] - auto shrink_to_fit() -> void - { - if (_size == _capacity) - { - return; - } - - _capacity = _size; - value_type * temp = new value_type[_capacity]{}; - std::ranges::copy(begin(), end(), temp); - delete[] _data; - _data = temp; - } - - /** - * @brief Wheter there are currently any items this container or not. - * - * @return True if there are no elements, false if there are. - */ - [[gnu::section(".stl_text")]] - auto empty() const -> bool - { - return _size <= 0; - } - - private: - /** - * @brief Halts the execution of the application if the data container is currently empty. - */ - auto throw_if_empty() const -> void - { - if (empty()) - { - os::panic("[Vector] Attempted to access element of currently empty vector"); - } - } - - auto throw_if_out_of_range(size_type index) const -> void - { - if (index >= _size) - { - os::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 - * normally perferable for the cache. - */ - auto increase_capacity_if_full() -> void - { - if (_size == _capacity) - { - reserve(_capacity == 0U ? 1U : _capacity * 2U); - } - } - - 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 kstd - -#endif diff --git a/libs/kstd/src/mutex.cpp b/libs/kstd/src/mutex.cpp index cfb1c84..137ebc0 100644 --- a/libs/kstd/src/mutex.cpp +++ b/libs/kstd/src/mutex.cpp @@ -1,4 +1,4 @@ -#include "kstd/mutex.hpp" +#include "kstd/mutex" namespace kstd { -- cgit v1.2.3