diff options
Diffstat (limited to 'libs/kstd')
| -rw-r--r-- | libs/kstd/CMakeLists.txt | 40 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/asm_ptr | 77 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/bits/os.hpp | 34 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/bits/shared_ptr.hpp | 269 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/bits/unique_ptr.hpp | 206 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/ext/bitfield_enum | 65 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/memory | 7 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/mutex | 71 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/stack | 201 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/vector | 599 | ||||
| -rw-r--r-- | libs/kstd/kstd.dox | 14 | ||||
| -rw-r--r-- | libs/kstd/src/bits/os.cpp | 10 | ||||
| -rw-r--r-- | libs/kstd/src/libc/stdlib.cpp | 19 | ||||
| -rw-r--r-- | libs/kstd/src/libc/string.cpp | 32 | ||||
| -rw-r--r-- | libs/kstd/src/mutex.cpp | 24 |
15 files changed, 1668 insertions, 0 deletions
diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt new file mode 100644 index 0000000..d83e704 --- /dev/null +++ b/libs/kstd/CMakeLists.txt @@ -0,0 +1,40 @@ +add_library("kstd" STATIC) +add_library("libs::kstd" ALIAS "kstd") + +set(KSTD_LIBC_SYMBOLS + "abort" + "strlen" + "memcmp" +) + +target_sources("kstd" PRIVATE + "src/bits/os.cpp" + "src/libc/stdlib.cpp" + "src/libc/string.cpp" + "src/mutex.cpp" +) + +target_sources("kstd" PUBLIC + FILE_SET HEADERS + BASE_DIRS "include" + FILES + "include/kstd/bits/os.hpp" + "include/kstd/bits/shared_ptr.hpp" + "include/kstd/bits/unique_ptr.hpp" + + "include/kstd/ext/bitfield_enum" + + "include/kstd/asm_ptr" + "include/kstd/memory" + "include/kstd/mutex" + "include/kstd/stack" + "include/kstd/vector" +) + +target_include_directories("kstd" PUBLIC + "include" +) + +list(TRANSFORM KSTD_LIBC_SYMBOLS PREPEND "-Wl,--undefined=") + +target_link_options("kstd" INTERFACE ${KSTD_LIBC_SYMBOLS})
\ No newline at end of file diff --git a/libs/kstd/include/kstd/asm_ptr b/libs/kstd/include/kstd/asm_ptr new file mode 100644 index 0000000..e8636c3 --- /dev/null +++ b/libs/kstd/include/kstd/asm_ptr @@ -0,0 +1,77 @@ +#ifndef KSTD_ASM_POINTER_HPP +#define KSTD_ASM_POINTER_HPP + +#include <bit> + +namespace kstd +{ + + /** + * @brief A pointer that is defined in some assembly source file. + * + * @tparam Type The type of the pointer + */ + template<typename Type> + struct asm_ptr + { + using value_type = Type; + using pointer = value_type *; + using const_pointer = value_type const *; + using reference = value_type &; + using const_reference = value_type const &; + + asm_ptr() = delete; + asm_ptr(asm_ptr const &) = delete; + asm_ptr(asm_ptr &&) = delete; + ~asm_ptr() = delete; + + constexpr auto operator=(asm_ptr const &) = delete; + constexpr auto operator=(asm_ptr &&) = delete; + + auto get() const noexcept -> pointer + { + return m_ptr; + } + + constexpr auto operator+(std::ptrdiff_t offset) const noexcept -> pointer + { + return std::bit_cast<pointer>(m_ptr) + offset; + } + + constexpr auto operator*() noexcept -> reference + { + return *(std::bit_cast<pointer>(m_ptr)); + } + + constexpr auto operator*() const noexcept -> const_reference + { + return *(std::bit_cast<const_pointer>(m_ptr)); + } + + constexpr auto operator[](std::ptrdiff_t offset) noexcept -> reference + { + return *(*this + offset); + } + + constexpr auto operator[](std::ptrdiff_t offset) const noexcept -> const_reference + { + return *(*this + offset); + } + + constexpr auto operator->() noexcept -> pointer + { + return m_ptr; + } + + constexpr auto operator->() const noexcept -> const_pointer + { + return m_ptr; + } + + private: + pointer m_ptr; + }; + +} // namespace kstd + +#endif
\ No newline at end of file diff --git a/libs/kstd/include/kstd/bits/os.hpp b/libs/kstd/include/kstd/bits/os.hpp new file mode 100644 index 0000000..0474f16 --- /dev/null +++ b/libs/kstd/include/kstd/bits/os.hpp @@ -0,0 +1,34 @@ +#ifndef KSTD_OS_HPP +#define KSTD_OS_HPP + +#include <source_location> +#include <string_view> + +namespace kstd::os +{ + /** + * @brief Handle an unrecoverable library error. + * + * The operating system kernel may choose to implement this function in order to try to perform additional cleanup + * before terminating execution. If the kernel does not implement this function, the default implementation will be + * chosen. This default implementation doest nothing. + */ + [[noreturn]] + auto abort() -> void; + + /** + * @brief Terminate execution of the operating system. + * + * The operating system must implement this function. This function must terminate the execution of the operating + * system kernel as is. It may choose to restart the kernel or to halt execution entirely. The implementation must + * guarantee that execution never return from this function. + * + * @param message A message describing the reason for termination of execution. + * @param where The source code location at which the panic was triggered. In general, no argument shall be provided + * for this parameter, thus implicitly capturing the location at which the call originates. + */ + [[noreturn]] + auto panic(std::string_view message, std::source_location where = std::source_location::current()) -> void; +} // namespace kstd::os + +#endif
\ No newline at end of file diff --git a/libs/kstd/include/kstd/bits/shared_ptr.hpp b/libs/kstd/include/kstd/bits/shared_ptr.hpp new file mode 100644 index 0000000..4bcf499 --- /dev/null +++ b/libs/kstd/include/kstd/bits/shared_ptr.hpp @@ -0,0 +1,269 @@ +#ifndef KSTD_BITS_SHARED_PTR_HPP +#define KSTD_BITS_SHARED_PTR_HPP + +#include <atomic> + +namespace kstd +{ + /** + * @brief Shared_pointer is a smart pointer that retains shared ownership of an object through a pointer. Several + * shared_ptr objects may own the same object. The object is destroyed and its memory deallocated when either of + * the following happens: the last remaining shared_ptr owning the object is destroyed; the last remaining + * shared_ptr owning the object is assigned another pointer via operator= or reset(). A + * shared_ptr can share ownership of an object while storing a pointer to another object. This feature can be used + * to point to member objects while owning the object they belong to. The stored pointer is the one accessed by get(), + * the dereference and the comparison operators. The managed pointer is the one passed to the deleter when use count + * reaches zero. + * + * @tparam T The type of the managed object. + */ + template<typename T> + struct shared_ptr + { + /** + * @brief Constructor. + * + * @param pointer A pointer to an object to manage (default is nullptr). + */ + [[gnu::section(".stl_text")]] + explicit shared_ptr(T * pointer = nullptr) + : pointer(pointer) + , ref_count(new std::atomic<std::size_t>(pointer != nullptr ? 1 : 0)) + { + // Nothing to do. + } + + /** + * @brief Copy constructor. + * + * @param other The shared_ptr to copy from. + */ + [[gnu::section(".stl_text")]] + shared_ptr(shared_ptr const & other) + : pointer(other.pointer) + , ref_count(other.ref_count) + { + if (pointer != nullptr) + { + ++(*ref_count); + } + } + + /** + * @brief Move constructor. + * + * @param other The shared_ptr to move from. + */ + [[gnu::section(".stl_text")]] + shared_ptr(shared_ptr && other) noexcept + : pointer(other.pointer) + , ref_count(other.ref_count) + { + other.pointer = nullptr; + other.ref_count = nullptr; + } + + /** + * @brief Copy assignment operator. Replaces the managed object with the one managed by r. Shares ownership of the + * object managed by r. If r manages no object, *this manages no object too. Equivalent to + * shared_ptr<T>(r).swap(*this). + * + * @param other Another smart pointer to share the ownership with. + * @return Reference to this shared pointer. + */ + [[gnu::section(".stl_text")]] + shared_ptr & operator=(shared_ptr const & other) + { + if (this != &other) + { + cleanup(); + pointer = other.pointer; + ref_count = other.ref_count; + + if (pointer != nullptr) + { + ++(*ref_count); + } + } + + return *this; + } + + /** + * @brief Move assignment operator. Move-assigns a shared_ptr from r. After the assignment, *this contains a copy of + * the previous state of r, and r is empty. Equivalent to shared_ptr<T>(std::move(r)).swap(*this). + * + * @param other Another smart pointer to acquire the ownership from. + * @return Reference to this shared pointer. + */ + [[gnu::section(".stl_text")]] + shared_ptr & operator=(shared_ptr && other) noexcept + { + if (this != &other) + { + cleanup(); + pointer = other.pointer; + ref_count = other.ref_count; + other.pointer = nullptr; + other.ref_count = nullptr; + } + + return *this; + } + + /** + * @brief Destructor. Cleans up resources if necessary. + */ + [[gnu::section(".stl_text")]] + ~shared_ptr() + { + cleanup(); + } + + /** + * @brief Replaces the managed object. + * + * @param ptr Pointer to a new object to manage (default = nullptr). + */ + [[gnu::section(".stl_text")]] + void reset(T * ptr = nullptr) + { + cleanup(); + pointer = ptr; + ref_count = new std::atomic<std::size_t>(ptr != nullptr ? 1 : 0); + } + + /** + * @brief Exchanges the stored pointer values and the ownerships of *this and r. Reference counts, if any, are not + * adjusted. + * + * @param other The shared_ptr to swap with. + */ + [[gnu::section(".stl_text")]] + void swap(shared_ptr & other) + { + std::swap(pointer, other.pointer); + std::swap(ref_count, other.ref_count); + } + + /** + * @brief Dereference operator. If get() is a null pointer, the behavior is undefined. + * + * @return Returns the object owned by *this, equivalent to *get(). + */ + [[gnu::section(".stl_text")]] + auto operator*() const -> T & + { + return *pointer; + } + + /** + * @brief Member access operator. + * + * @return Returns a pointer to the object owned by *this, i.e. get(). + */ + [[gnu::section(".stl_text")]] + auto operator->() const -> T * + { + return pointer; + } + + /** + * @brief Returns a pointer to the managed object or nullptr if no object is owned. + * + * @return Pointer to the managed object or nullptr if no object is owned. + */ + [[gnu::section(".stl_text")]] + auto get() const -> T * + { + return pointer; + } + + /** + * @brief Returns the number of different shared_ptr instances (*this included) managing the current object. If + * there is no managed object, 0 is returned. + * + * @note Common use cases include comparison with 0. If use_count returns zero, the shared pointer is empty + * and manages no objects (whether or not its stored pointer is nullptr). Comparison with 1. If use_count returns 1, + * there are no other owners. + * + * @return The number of Shared_pointer instances managing the current object or 0 if there is no managed + * object. + */ + [[gnu::section(".stl_text")]] + auto use_count() const -> std::size_t + { + if (pointer != nullptr) + { + return *ref_count; + } + + return 0; + } + + /** + * @brief Checks whether *this owns an object, i.e. whether get() != nullptr. + * + * @return true if *this owns an object, false otherwise. + */ + [[gnu::section(".stl_text")]] + explicit operator bool() const + { + return pointer != nullptr; + } + + /** + * @brief Defaulted three-way comparator operator. + */ + [[gnu::section(".stl_text")]] + auto operator<=>(shared_ptr const & other) const = default; + + private: + /** + * @brief Releases ownership and deletes the object if this was the last reference to the owned managed object. + */ + [[gnu::section(".stl_text")]] + auto cleanup() -> void + { + if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0) + { + delete pointer; + delete ref_count; + } + } + + T * pointer; ///< The managed object. + std::atomic<std::size_t> * ref_count; ///< Reference count. + }; + + /** + * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls + * lhs.swap(rhs). + * + * @tparam T Type of the managed object. + * @param lhs, rhs Smart pointers whose contents to swap. + */ + template<typename T> + auto swap(shared_ptr<T> & lhs, shared_ptr<T> & rhs) -> void + { + lhs.swap(rhs); + } + + /** + * @brief Constructs an object of type T and wraps it in a shared_ptr. Constructs a non-array type T. The + * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is + * not an array type. The function is equivalent to: shared_ptr<T>(new T(std::forward<Args>(args)...)). + * + * @tparam T Type of the managed object. + * @tparam Args Argument types for T's constructor. + * @param args List of arguments with which an instance of T will be constructed. + * @returns Shared_pointer of an instance of type T. + */ + template<typename T, typename... Args> + auto make_shared(Args &&... args) -> shared_ptr<T> + { + return shared_ptr<T>(new T(std::forward<Args>(args)...)); + } +} // namespace kstd + +#endif
\ No newline at end of file diff --git a/libs/kstd/include/kstd/bits/unique_ptr.hpp b/libs/kstd/include/kstd/bits/unique_ptr.hpp new file mode 100644 index 0000000..5f54848 --- /dev/null +++ b/libs/kstd/include/kstd/bits/unique_ptr.hpp @@ -0,0 +1,206 @@ +#ifndef KSTD_BITS_UNIQUE_POINTER_HPP +#define KSTD_BITS_UNIQUE_POINTER_HPP + +#include <utility> + +namespace kstd +{ + /** + * @brief Unique_pointer is a smart pointer that owns (is responsible for) and manages another object via a pointer + * and subsequently disposes of that object when the unique_ptr goes out of scope. + * + * @tparam T Type of the managed object. + */ + template<typename T> + struct unique_ptr + { + /** + * @brief Constructor. + * + * @param ptr A pointer to an object to manage (default is nullptr). + */ + [[gnu::section(".stl_text")]] + explicit unique_ptr(T * ptr = nullptr) + : pointer(ptr) + { + // Nothing to do. + } + + /** + * @brief Destructor that deletes the managed object. + */ + [[gnu::section(".stl_text")]] + ~unique_ptr() + { + delete pointer; + } + + /** + * @brief Deleted copy constructor to enforce unique ownership. + */ + unique_ptr(unique_ptr const &) = delete; + + /** + * @brief Deleted copy assignment operator to enforce unique ownership. + */ + auto operator=(unique_ptr const &) -> unique_ptr & = delete; + + /** + * @brief Move constructor. + * + * @param other Unique pointer to move from. + */ + [[gnu::section(".stl_text")]] + unique_ptr(unique_ptr && other) noexcept + : pointer(other.pointer) + { + other.pointer = nullptr; + } + + /** + * @brief Move assignment operator. Transfers ownership from other to *this as if by calling reset(r.release()). + * + * @param other Smart pointer from which ownership will be transferred. + * @return Reference to this unique pointer. + */ + [[gnu::section(".stl_text")]] + auto operator=(unique_ptr && other) noexcept -> unique_ptr & + { + if (this != &other) + { + delete pointer; + pointer = other.pointer; + other.pointer = nullptr; + } + return *this; + } + + /** + * @brief Dereference operator. If get() is a null pointer, the behavior is undefined. + * + * @return Returns the object owned by *this, equivalent to *get(). + */ + [[gnu::section(".stl_text")]] + auto operator*() const -> T & + { + return *pointer; + } + + /** + * @brief Member access operator. + * + * @return Returns a pointer to the object owned by *this, i.e. get(). + */ + [[gnu::section(".stl_text")]] + auto operator->() const -> T * + { + return pointer; + } + + /** + * @brief Returns a pointer to the managed object or nullptr if no object is owned. + * + * @return Pointer to the managed object or nullptr if no object is owned. + */ + [[gnu::section(".stl_text")]] + auto get() const -> T * + { + return pointer; + } + + /** + * @brief Checks whether *this owns an object, i.e. whether get() != nullptr. + * + * @return true if *this owns an object, false otherwise. + */ + [[gnu::section(".stl_text")]] + explicit operator bool() const noexcept + { + return pointer != nullptr; + } + + /** + * @brief Releases the ownership of the managed object, if any. + * get() returns nullptr after the call. + * The caller is responsible for cleaning up the object (e.g. by use of get_deleter()). + * + * @return Pointer to the managed object or nullptr if there was no managed object, i.e. the value which would be + * returned by get() before the call. + */ + [[gnu::section(".stl_text")]] + auto release() -> T * + { + T * temp = pointer; + pointer = nullptr; + return temp; + } + + /** + * @brief Replaces the managed object. + * + * @note A test for self-reset, i.e. whether ptr points to an object already managed by *this, is not performed, + * except where provided as a compiler extension or as a debugging assert. Note that code such as + * p.reset(p.release()) does not involve self-reset, only code like p.reset(p.get()) does. + * + * @param ptr Pointer to a new object to manage (default = nullptr). + */ + [[gnu::section(".stl_text")]] + auto reset(T * ptr = nullptr) -> void + { + delete pointer; + pointer = ptr; + } + + /** + * @brief Swaps the managed objects and associated deleters of *this and another unique_ptr object other. + * + * @param other Another unique_ptr object to swap the managed object and the deleter with. + */ + [[gnu::section(".stl_text")]] + auto swap(unique_ptr & other) -> void + { + using std::swap; + swap(pointer, other.pointer); + } + + /** + * @brief Defaulted three-way comparator operator. + */ + [[gnu::section(".stl_text")]] + auto operator<=>(unique_ptr const & other) const = default; + + private: + T * pointer; ///< The managed pointer. + }; + + /** + * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls + * lhs.swap(rhs). + * + * @tparam T Type of the managed object. + * @param lhs, rhs Smart pointers whose contents to swap. + */ + template<typename T> + auto swap(unique_ptr<T> & lhs, unique_ptr<T> & rhs) -> void + { + lhs.swap(rhs); + } + + /** + * @brief Constructs an object of type T and wraps it in a unique_ptr. Constructs a non-array type T. The + * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is + * not an array type. The function is equivalent to: unique_ptr<T>(new T(std::forward<Args>(args)...)). + * + * @tparam T Type of the managed object. + * @tparam Args Argument types for T's constructor. + * @param args List of arguments with which an instance of T will be constructed. + * @returns Unique_pointer of an instance of type T. + */ + template<typename T, typename... Args> + auto make_unique(Args &&... args) -> unique_ptr<T> + { + return unique_ptr<T>(new T(std::forward<Args>(args)...)); + } +} // namespace kstd + +#endif
\ No newline at end of file diff --git a/libs/kstd/include/kstd/ext/bitfield_enum b/libs/kstd/include/kstd/ext/bitfield_enum new file mode 100644 index 0000000..80fe9d2 --- /dev/null +++ b/libs/kstd/include/kstd/ext/bitfield_enum @@ -0,0 +1,65 @@ +#ifndef KSTD_EXT_BITFIELD_ENUM_HPP +#define KSTD_EXT_BITFIELD_ENUM_HPP + +#include <bit> +#include <type_traits> +#include <utility> + +namespace kstd::ext +{ + + template<typename EnumType> + requires std::is_enum_v<EnumType> + struct is_bitfield_enum : std::false_type + { + }; + + //! @concept Specifies that an enum is to be used to define bits in a bitfield. + template<typename EnumType> + concept bitfield_enum = is_bitfield_enum<EnumType>::value; + +}; // namespace kstd::ext + +template<kstd::ext::bitfield_enum EnumType> +constexpr auto operator|(EnumType lhs, EnumType rhs) -> EnumType +{ + return std::bit_cast<EnumType>(std::to_underlying(lhs) | std::to_underlying(rhs)); +} + +template<kstd::ext::bitfield_enum EnumType> +constexpr auto operator|=(EnumType & lhs, EnumType rhs) -> EnumType & +{ + return lhs = lhs | rhs; +} + +template<kstd::ext::bitfield_enum EnumType> +constexpr auto operator&(EnumType lhs, EnumType rhs) -> EnumType +{ + return std::bit_cast<EnumType>(std::to_underlying(lhs) & std::to_underlying(rhs)); +} + +template<kstd::ext::bitfield_enum EnumType> +constexpr auto operator&=(EnumType & lhs, EnumType rhs) -> EnumType & +{ + return lhs = lhs & rhs; +} + +template<kstd::ext::bitfield_enum EnumType> +constexpr auto operator^(EnumType lhs, EnumType rhs) -> EnumType +{ + return std::bit_cast<EnumType>(std::to_underlying(lhs) ^ std::to_underlying(rhs)); +} + +template<kstd::ext::bitfield_enum EnumType> +constexpr auto operator^=(EnumType & lhs, EnumType rhs) -> EnumType & +{ + return lhs = lhs ^ rhs; +} + +template<kstd::ext::bitfield_enum EnumType> +constexpr auto operator~(EnumType lhs) -> EnumType +{ + return std::bit_cast<EnumType>(~std::to_underlying(lhs)); +} + +#endif
\ No newline at end of file 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/mutex b/libs/kstd/include/kstd/mutex new file mode 100644 index 0000000..6ae3adf --- /dev/null +++ b/libs/kstd/include/kstd/mutex @@ -0,0 +1,71 @@ +#ifndef KSTD_MUTEX_HPP +#define KSTD_MUTEX_HPP + +#include <atomic> + +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(mutex const &) = delete; + + /** + * @brief Deleted move constructor. + * + */ + mutex(mutex &&) = delete; + + /** + * @brief Deleted copy assignment operator. + */ + auto operator=(mutex const &) -> mutex & = delete; + + /** + * @brief Deleted move assignment operator. + */ + auto operator=(mutex &&) -> 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<bool> 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..8cd208a --- /dev/null +++ b/libs/kstd/include/kstd/stack @@ -0,0 +1,201 @@ +#ifndef KSTD_STACK_HPP +#define KSTD_STACK_HPP + +#include "kstd/vector" +#include <utility> + +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<typename T, typename Container = kstd::vector<T>> + 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; + + stack(stack const &) = delete; + stack(stack &&) = delete; + auto operator=(stack const &) -> stack & = delete; + auto operator=(stack &&) -> stack & = delete; + /** + * @brief Constructs data with the given amount of elements containing the given value or alternatively 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<typename InputIterator> + [[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 elements List we want to copy all elements from. + */ + [[gnu::section(".stl_text")]] + explicit stack(std::initializer_list<T> elements) + : _container(elements) + { + // 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<T> const & other) + : _container(other) + { + // Nothing to do. + } + + /** + * @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<U>(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<class U> + [[gnu::section(".stl_text")]] + auto push(U && value) -> void + { + _container.push_back(std::forward<U>(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>(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<class... Args> + [[gnu::section(".stl_text")]] + auto emplace(Args &&... args) -> reference + { + _container.emplace_back(std::forward<Args>(args)...); + } + + /** + * @brief Removes the last element of the containe |
