aboutsummaryrefslogtreecommitdiff
path: root/libs/kstd/include
diff options
context:
space:
mode:
Diffstat (limited to 'libs/kstd/include')
-rw-r--r--libs/kstd/include/kstd/allocator64
-rw-r--r--libs/kstd/include/kstd/asm_ptr78
-rw-r--r--libs/kstd/include/kstd/bits/concepts.hpp15
-rw-r--r--libs/kstd/include/kstd/bits/flat_map.hpp186
-rw-r--r--libs/kstd/include/kstd/bits/format/arg.hpp75
-rw-r--r--libs/kstd/include/kstd/bits/format/args.hpp160
-rw-r--r--libs/kstd/include/kstd/bits/format/context.hpp65
-rw-r--r--libs/kstd/include/kstd/bits/format/error.hpp24
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter.hpp92
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/bool.hpp83
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/byte.hpp23
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/char.hpp94
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/cstring.hpp29
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/integral.hpp204
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/ordering.hpp111
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/pointer.hpp42
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/range.hpp32
-rw-r--r--libs/kstd/include/kstd/bits/format/formatter/string_view.hpp41
-rw-r--r--libs/kstd/include/kstd/bits/format/fwd.hpp23
-rw-r--r--libs/kstd/include/kstd/bits/format/output_buffer.hpp32
-rw-r--r--libs/kstd/include/kstd/bits/format/parse_context.hpp109
-rw-r--r--libs/kstd/include/kstd/bits/format/specifiers.hpp205
-rw-r--r--libs/kstd/include/kstd/bits/format/string.hpp148
-rw-r--r--libs/kstd/include/kstd/bits/format/vformat.hpp99
-rw-r--r--libs/kstd/include/kstd/bits/observer_ptr.hpp163
-rw-r--r--libs/kstd/include/kstd/bits/print_sink.hpp17
-rw-r--r--libs/kstd/include/kstd/bits/shared_ptr.hpp648
-rw-r--r--libs/kstd/include/kstd/bits/unique_ptr.hpp199
-rw-r--r--libs/kstd/include/kstd/cstring21
-rw-r--r--libs/kstd/include/kstd/ext/bitfield_enum65
-rw-r--r--libs/kstd/include/kstd/flat_map365
-rw-r--r--libs/kstd/include/kstd/format22
-rw-r--r--libs/kstd/include/kstd/memory8
-rw-r--r--libs/kstd/include/kstd/mutex101
-rw-r--r--libs/kstd/include/kstd/os/error.hpp34
-rw-r--r--libs/kstd/include/kstd/os/print.hpp14
-rw-r--r--libs/kstd/include/kstd/print69
-rw-r--r--libs/kstd/include/kstd/ranges21
-rw-r--r--libs/kstd/include/kstd/stack192
-rw-r--r--libs/kstd/include/kstd/string380
-rw-r--r--libs/kstd/include/kstd/units149
-rw-r--r--libs/kstd/include/kstd/vector1154
42 files changed, 0 insertions, 5656 deletions
diff --git a/libs/kstd/include/kstd/allocator b/libs/kstd/include/kstd/allocator
deleted file mode 100644
index 0de0e10..0000000
--- a/libs/kstd/include/kstd/allocator
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef KSTD_ALLOCATOR_HPP
-#define KSTD_ALLOCATOR_HPP
-
-#include <cstddef>
-#include <new>
-#include <type_traits>
-
-#if __has_builtin(__builtin_operator_new) >= 201'802L
-#define KSTD_OPERATOR_NEW __builtin_operator_new
-#define KSTD_OPERATOR_DELETE __builtin_operator_delete
-#else
-#define KSTD_OPERATOR_NEW ::operator new
-#define KSTD_OPERATOR_DELETE ::operator delete
-#endif
-
-namespace kstd
-{
-
- template<typename T>
- struct allocator
- {
- using value_type = T;
- using size_type = std::size_t;
- using difference_type = std::ptrdiff_t;
- using propagate_on_container_move_assignment = std::true_type;
- using is_always_equal = std::true_type;
-
- constexpr allocator() noexcept = default;
-
- template<typename U>
- constexpr allocator(allocator<U> const &) noexcept
- {}
-
- constexpr auto allocate(std::size_t n) -> T *
- {
- if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
- {
- return static_cast<T *>(KSTD_OPERATOR_NEW(n * sizeof(T), std::align_val_t{alignof(T)}));
- }
- return static_cast<T *>(KSTD_OPERATOR_NEW(n * sizeof(T)));
- }
-
- constexpr void deallocate(T * p, std::size_t n) noexcept
- {
- if (alignof(T) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
- {
- KSTD_OPERATOR_DELETE(p, n * sizeof(T), std::align_val_t{alignof(T)});
- }
- KSTD_OPERATOR_DELETE(p, n * sizeof(T));
- }
- };
-
- template<typename T, typename U>
- constexpr auto operator==(allocator<T> const &, allocator<U> const &) noexcept -> bool
- {
- return true;
- }
-
-} // namespace kstd
-
-#undef KSTD_OPERATOR_NEW
-#undef KSTD_OPERATOR_DELETE
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/asm_ptr b/libs/kstd/include/kstd/asm_ptr
deleted file mode 100644
index c06a8b5..0000000
--- a/libs/kstd/include/kstd/asm_ptr
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef KSTD_ASM_POINTER_HPP
-#define KSTD_ASM_POINTER_HPP
-
-#include <bit>
-#include <cstddef>
-
-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/concepts.hpp b/libs/kstd/include/kstd/bits/concepts.hpp
deleted file mode 100644
index 74c25cb..0000000
--- a/libs/kstd/include/kstd/bits/concepts.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef KSTD_BITS_CONCEPTS_HPP
-#define KSTD_BITS_CONCEPTS_HPP
-
-#include <concepts>
-#include <ranges>
-namespace kstd::bits
-{
-
- template<typename RangeType, typename ValueType>
- concept container_compatible_range =
- std::ranges::input_range<RangeType> && std::convertible_to<std::ranges::range_reference_t<RangeType>, ValueType>;
-
-}
-
-#endif
diff --git a/libs/kstd/include/kstd/bits/flat_map.hpp b/libs/kstd/include/kstd/bits/flat_map.hpp
deleted file mode 100644
index fe46203..0000000
--- a/libs/kstd/include/kstd/bits/flat_map.hpp
+++ /dev/null
@@ -1,186 +0,0 @@
-#ifndef KSTD_BITS_FLAT_MAP_HPP
-#define KSTD_BITS_FLAT_MAP_HPP
-
-#include <concepts>
-#include <cstddef>
-#include <iterator>
-#include <memory>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-
-namespace kstd::bits
-{
-
- template<typename KeyType, typename MappedType>
- struct flat_map_reference
- {
- using key_type = KeyType;
- using mapped_type = MappedType;
-
- constexpr flat_map_reference(key_type const & key, mapped_type & mapped)
- : first{key}
- , second{mapped}
- {}
-
- constexpr auto operator=(flat_map_reference const & other) const -> flat_map_reference const &
- {
- second = other.second;
- return *this;
- }
-
- constexpr auto operator=(flat_map_reference && other) const -> flat_map_reference const &
- {
- second = std::move(other.second);
- return *this;
- }
-
- template<typename TupleLikeType>
- requires(std::tuple_size_v<std::remove_cvref_t<TupleLikeType>> == 2)
- constexpr auto operator=(TupleLikeType && tuple) const -> flat_map_reference const &
- {
- second = std::forward<TupleLikeType>(tuple).second;
- return *this;
- }
-
- template<std::size_t Index>
- requires(Index >= 0 && Index <= 1)
- [[nodiscard]] constexpr auto get() const noexcept -> decltype(auto)
- {
- if constexpr (Index == 0)
- {
- return (first);
- }
- else
- {
- return (second);
- }
- }
-
- key_type const & first; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members)
- mapped_type & second; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members)
- };
-
- template<typename Reference>
- struct flat_map_pointer
- {
- Reference reference;
-
- [[nodiscard]] constexpr auto operator->() noexcept -> Reference *
- {
- return std::addressof(reference);
- }
-
- [[nodiscard]] constexpr auto operator->() const noexcept -> Reference const *
- {
- return std::addressof(reference);
- }
- };
-
- template<typename KeyType, typename MappedType, typename KeyIterator, typename MappedIterator>
- struct flat_map_iterator
- {
- using iterator_category = std::random_access_iterator_tag;
- using value_type = std::pair<KeyType, MappedType>;
- using difference_type = std::ptrdiff_t;
- using reference = flat_map_reference<KeyType, MappedType>;
- using pointer = flat_map_pointer<reference>;
-
- constexpr flat_map_iterator() = default;
-
- constexpr flat_map_iterator(KeyIterator key_iterator, MappedIterator mapped_iterator)
- : m_key_iterator{key_iterator}
- , m_mapped_iterator{mapped_iterator}
- {}
-
- template<typename OtherMappedType, typename OtherKeyIterator, typename OtherMappedIterator>
- requires(std::convertible_to<OtherKeyIterator, KeyIterator> &&
- std::convertible_to<OtherMappedIterator, MappedIterator>)
- constexpr flat_map_iterator(
- flat_map_iterator<KeyType, OtherMappedType, OtherKeyIterator, OtherMappedIterator> const & other) noexcept
- : m_key_iterator{other.m_key_iterator}
- , m_mapped_iterator{other.m_mapped_iterator}
- {}
-
- [[nodiscard]] auto key_iterator() const noexcept -> KeyIterator
- {
- return m_key_iterator;
- }
-
- [[nodiscard]] constexpr auto operator*() const noexcept -> reference
- {
- return {*m_key_iterator, *m_mapped_iterator};
- }
-
- [[nodiscard]] constexpr auto operator->() const noexcept -> pointer
- {
- return {
- {*m_key_iterator, *m_mapped_iterator}
- };
- }
-
- constexpr auto operator++() noexcept -> flat_map_iterator &
- {
- ++m_key_iterator;
- ++m_mapped_iterator;
- return *this;
- }
-
- constexpr auto operator++(int) noexcept -> flat_map_iterator
- {
- auto copy = *this;
- ++(*this);
- return copy;
- }
-
- constexpr auto operator--() noexcept -> flat_map_iterator &
- {
- --m_key_iterator;
- --m_mapped_iterator;
- return *this;
- }
-
- constexpr auto operator--(int) noexcept -> flat_map_iterator
- {
- auto copy = *this;
- --(*this);
- return copy;
- }
-
- [[nodiscard]] constexpr auto operator+(difference_type offset) const noexcept -> flat_map_iterator
- {
- return {m_key_iterator + offset, m_mapped_iterator + offset};
- }
-
- [[nodiscard]] constexpr auto operator-(flat_map_iterator const & other) const noexcept -> difference_type
- {
- return m_key_iterator - other.m_key_iterator;
- }
-
- [[nodiscard]] constexpr auto operator<=>(flat_map_iterator const & other) const noexcept = default;
-
- private:
- KeyIterator m_key_iterator{};
- MappedIterator m_mapped_iterator{};
- };
-
-} // namespace kstd::bits
-
-template<typename K, typename M>
-struct std::tuple_size<kstd::bits::flat_map_reference<K, M>> : std::integral_constant<std::size_t, 2>
-{
-};
-
-template<typename K, typename M>
-struct std::tuple_element<0, kstd::bits::flat_map_reference<K, M>>
-{
- using type = K const &;
-};
-
-template<typename K, typename M>
-struct std::tuple_element<1, kstd::bits::flat_map_reference<K, M>>
-{
- using type = M &;
-};
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/arg.hpp b/libs/kstd/include/kstd/bits/format/arg.hpp
deleted file mode 100644
index e65b26f..0000000
--- a/libs/kstd/include/kstd/bits/format/arg.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_ARG_HPP
-#define KSTD_BITS_FORMAT_ARG_HPP
-
-// IWYU pragma: private, include <kstd/format>
-
-#include <kstd/bits/format/error.hpp>
-#include <kstd/bits/format/fwd.hpp>
-
-#include <cstddef>
-#include <cstdint>
-#include <string_view>
-
-namespace kstd
-{
-
- namespace bits::format
- {
- enum struct arg_type : std::uint8_t
- {
- none,
- boolean,
- character,
- integer,
- unsigned_integer,
- string_view,
- c_string,
- pointer,
- user_defined,
- };
- } // namespace bits::format
-
- struct format_arg
- {
- bits::format::arg_type type{};
- union
- {
- bool boolean;
- char character;
- std::int64_t integer;
- std::uint64_t unsigned_integer;
- std::string_view string_view;
- char const * c_string;
- void const * pointer;
- struct
- {
- void const * pointer;
- auto (*format)(void const * value, format_parse_context & parse_context, format_context & context) -> void;
- } user_defined;
- } value{};
- };
-
- namespace bits::format
- {
- constexpr auto extrat_dynamic_width(format_arg const & arg) -> std::size_t
- {
- if (arg.type == arg_type::unsigned_integer)
- {
- return static_cast<std::size_t>(arg.value.unsigned_integer);
- }
- else if (arg.type == arg_type::integer)
- {
- if (arg.value.integer < 0)
- {
- error("Dynamic width cannont be negative.");
- }
- return static_cast<std::size_t>(arg.value.integer);
- }
- error("Dynamic width argument is not an integral value.");
- return 0;
- }
- } // namespace bits::format
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/args.hpp b/libs/kstd/include/kstd/bits/format/args.hpp
deleted file mode 100644
index e8e3114..0000000
--- a/libs/kstd/include/kstd/bits/format/args.hpp
+++ /dev/null
@@ -1,160 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_ARGS_HPP
-#define KSTD_BITS_FORMAT_ARGS_HPP
-
-// IWYU pragma: private, include <kstd/format>
-
-#include <kstd/bits/format/arg.hpp>
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/fwd.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-
-#include <array>
-#include <concepts>
-#include <cstddef>
-#include <cstdint>
-#include <span>
-#include <string_view>
-#include <type_traits>
-
-namespace kstd
-{
-
- namespace bits::format
- {
-
- template<typename ValueType>
- auto format_trampoline(void const * value_pointer, format_parse_context & parse_context, format_context & context)
- -> void
- {
- auto typed_value_pointer = static_cast<ValueType const *>(value_pointer);
- auto fmt = formatter<std::remove_cvref_t<ValueType>>{};
- auto const it = fmt.parse(parse_context);
- parse_context.advance_to(it);
- fmt.format(*typed_value_pointer, context);
- }
-
- template<typename ValueType>
- constexpr auto determine_arg_type() -> arg_type
- {
- using decay_type = std::remove_cvref_t<ValueType>;
- if constexpr (std::same_as<decay_type, bool>)
- {
- return arg_type::boolean;
- }
- else if constexpr (std::same_as<decay_type, char>)
- {
- return arg_type::character;
- }
- else if constexpr (std::integral<decay_type> && std::is_signed_v<decay_type>)
- {
- return arg_type::integer;
- }
- else if constexpr (std::integral<decay_type> && std::is_unsigned_v<decay_type>)
- {
- return arg_type::unsigned_integer;
- }
- else if constexpr (std::same_as<decay_type, std::string_view>)
- {
- return arg_type::string_view;
- }
- else if constexpr (std::same_as<std::decay_t<decay_type>, char *> ||
- std::same_as<std::decay_t<decay_type>, char const *>)
- {
- return arg_type::c_string;
- }
- else if constexpr (std::is_pointer_v<decay_type> || std::same_as<decay_type, std::nullptr_t>)
- {
- if constexpr (std::same_as<decay_type, char *> || std::same_as<decay_type, char const *>)
- {
- return arg_type::user_defined;
- }
- else
- {
- return arg_type::pointer;
- }
- }
- else
- {
- return arg_type::user_defined;
- }
- }
-
- template<typename ValueType>
- constexpr auto make_single_arg(ValueType const & value) -> format_arg
- {
- auto result = format_arg{};
- constexpr auto type = determine_arg_type<ValueType>();
- result.type = type;
-
- if constexpr (type == arg_type::boolean)
- {
- result.value.boolean = value;
- }
- else if constexpr (type == arg_type::character)
- {
- result.value.character = value;
- }
- else if constexpr (type == arg_type::integer)
- {
- result.value.integer = static_cast<std::int64_t>(value);
- }
- else if constexpr (type == arg_type::unsigned_integer)
- {
- result.value.unsigned_integer = static_cast<std::uint64_t>(value);
- }
- else if constexpr (type == arg_type::string_view)
- {
- result.value.string_view = value;
- }
- else if constexpr (type == arg_type::c_string)
- {
- result.value.c_string = value;
- }
- else if constexpr (type == arg_type::pointer)
- {
- if constexpr (std::same_as<std::remove_cvref_t<ValueType>, std::nullptr_t>)
- {
- result.value.pointer = nullptr;
- }
- else
- {
- result.value.pointer = static_cast<void const *>(value);
- }
- }
- else
- {
- result.value.user_defined.pointer = &value;
- result.value.user_defined.format = format_trampoline<ValueType>;
- }
- return result;
- }
-
- } // namespace bits::format
-
- using format_args = std::span<format_arg const>;
-
- template<std::size_t Count>
- struct format_arg_store
- {
- std::array<format_arg, Count> args{};
- };
-
- template<typename... Arguments>
- [[nodiscard]] auto make_format_args(Arguments const &... args) noexcept -> format_arg_store<sizeof...(Arguments)>
- {
- using namespace bits::format;
-
- if constexpr (sizeof...(Arguments) == 0)
- {
- return format_arg_store<0>{};
- }
- else
- {
- return format_arg_store<sizeof...(Arguments)>{
- std::array<format_arg, sizeof...(Arguments)>{make_single_arg(args)...}};
- }
- }
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/context.hpp b/libs/kstd/include/kstd/bits/format/context.hpp
deleted file mode 100644
index c166ba9..0000000
--- a/libs/kstd/include/kstd/bits/format/context.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_CONTEXT_HPP
-#define KSTD_BITS_FORMAT_CONTEXT_HPP
-
-// IWYU pragma: private, include <kstd/format>
-
-#include <kstd/bits/format/arg.hpp>
-#include <kstd/bits/format/output_buffer.hpp>
-#include <kstd/os/error.hpp>
-
-#include <concepts>
-#include <cstddef>
-#include <span>
-#include <string_view>
-
-namespace kstd
-{
-
- namespace bits::format
- {
- template<typename T>
- constexpr auto inline is_width_v = std::integral<T> && //
- !std::same_as<bool, T> && //
- !std::same_as<char, T> && //
- !std::same_as<wchar_t, T> && //
- !std::same_as<char8_t, T> && //
- !std::same_as<char16_t, T> && //
- !std::same_as<char32_t, T>;
- }
-
- struct format_context
- {
- using format_args = std::span<format_arg const>;
- format_args args{};
-
- format_context(bits::format::output_buffer & buffer, format_args args)
- : args{args}
- , m_buffer{&buffer}
- {}
-
- [[nodiscard]] auto arg(std::size_t const id) const -> format_arg const &
- {
- if (id >= args.size())
- {
- kstd::os::panic("[kstd:format] argument index out of range!");
- }
- return args[id];
- }
-
- constexpr auto push(std::string_view string) -> void
- {
- m_buffer->push(string);
- }
-
- constexpr auto push(char character) -> void
- {
- m_buffer->push(character);
- }
-
- private:
- bits::format::output_buffer * m_buffer;
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/error.hpp b/libs/kstd/include/kstd/bits/format/error.hpp
deleted file mode 100644
index c0cb53d..0000000
--- a/libs/kstd/include/kstd/bits/format/error.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_ERROR_HPP
-#define KSTD_BITS_FORMAT_ERROR_HPP
-
-#include <kstd/os/error.hpp>
-
-namespace kstd::bits::format
-{
-
- constexpr auto error(char const * message) -> void
- {
- if consteval
- {
- extern void compile_time_format_error_triggered(char const *);
- compile_time_format_error_triggered(message);
- }
- else
- {
- kstd::os::panic("Error while formatting a string.");
- }
- }
-
-} // namespace kstd::bits::format
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter.hpp b/libs/kstd/include/kstd/bits/format/formatter.hpp
deleted file mode 100644
index eb28829..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter.hpp
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef KSTD_BITS_FORMATTER_HPP
-#define KSTD_BITS_FORMATTER_HPP
-
-// IWYU pragma: private, include <kstd/format>
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/error.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-
-#include <algorithm>
-#include <iterator>
-#include <string_view>
-
-namespace kstd
-{
-
- template<typename>
- struct formatter
- {
- formatter() = delete;
- formatter(formatter const &) = delete;
- auto operator=(formatter const &) -> formatter & = delete;
- };
-
- template<typename ValueType>
- struct range_formatter
- {
- constexpr auto set_separator(std::string_view sep) -> void
- {
- m_separator = sep;
- }
-
- constexpr auto set_brackets(std::string_view opening, std::string_view closing)
- {
- m_prefix = opening;
- m_suffix = closing;
- }
-
- constexpr auto parse(format_parse_context & context)
- {
- auto it = context.begin();
- auto const end = context.end();
-
- if (it != end && *it == 'n')
- {
- set_brackets("", "");
- std::advance(it, 1);
- }
-
- if (it != end && *it == ':')
- {
- std::advance(it, 1);
- context.advance_to(it);
- it = m_inner_formatter.parse(context);
- }
-
- if (it != end && *it != '}')
- {
- bits::format::error("Invalid formate specifier for range");
- }
-
- return it;
- }
-
- template<typename Range>
- auto format(Range const & range, format_context & context)
- {
- context.push(m_prefix);
-
- auto is_first = true;
- std::ranges::for_each(range, [&](auto const & element) {
- if (!is_first)
- {
- context.push(m_separator);
- }
- m_inner_formatter.format(element, context);
- is_first = false;
- });
-
- context.push(m_suffix);
- }
-
- private:
- kstd::formatter<ValueType> m_inner_formatter{};
- std::string_view m_separator{", "};
- std::string_view m_prefix{"["};
- std::string_view m_suffix{"]"};
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/bool.hpp b/libs/kstd/include/kstd/bits/format/formatter/bool.hpp
deleted file mode 100644
index cc8d190..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/bool.hpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_BOOL_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_BOOL_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/error.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-#include <kstd/bits/format/specifiers.hpp>
-
-#include <iterator>
-#include <string_view>
-
-namespace kstd
-{
-
- template<>
- struct formatter<bool>
- {
- bits::format::specifiers specifiers{};
-
- constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator
- {
- specifiers = bits::format::parse_format_specifiers(context);
-
- auto it = context.begin();
- auto const end = context.end();
-
- if (it != end && *it != '}')
- {
- if (*it == 's')
- {
- specifiers.type = *it;
- std::advance(it, 1);
- }
- else
- {
- bits::format::error("Invalid type specifier for bool.");
- }
- }
-
- if (it != end && *it != '}')
- {
- bits::format::error("Missing terminating '}' in format string.");
- }
-
- return it;
- }
-
- auto format(bool value, format_context & context) const -> void
- {
- auto const text = value ? std::string_view{"true"} : std::string_view{"false"};
- auto final_width = 0uz;
-
- if (specifiers.mode == bits::format::width_mode::static_value)
- {
- final_width = specifiers.width_value;
- }
- else if (specifiers.mode == bits::format::width_mode::dynamic_argument_id)
- {
- auto const & arg = context.arg(specifiers.width_value);
- final_width = bits::format::extrat_dynamic_width(arg);
- }
-
- auto padding = bits::format::calculate_format_padding(final_width, text.size(), specifiers.align,
- bits::format::alignment::left);
-
- for (auto i = 0uz; i < padding.left; ++i)
- {
- context.push(specifiers.fill);
- }
-
- context.push(text);
-
- for (auto i = 0uz; i < padding.right; ++i)
- {
- context.push(specifiers.fill);
- }
- }
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/byte.hpp b/libs/kstd/include/kstd/bits/format/formatter/byte.hpp
deleted file mode 100644
index cc8aece..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/byte.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_BYTE_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_BYTE_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/formatter/integral.hpp>
-
-#include <cstddef>
-
-namespace kstd
-{
-
- template<>
- struct formatter<std::byte> : formatter<int>
- {
- auto format(std::byte value, format_context & context) const -> void
- {
- formatter<int>::format(static_cast<int>(value), context);
- }
- };
-
-} // namespace kstd
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/char.hpp b/libs/kstd/include/kstd/bits/format/formatter/char.hpp
deleted file mode 100644
index 92489a1..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/char.hpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_CHAR_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_CHAR_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/error.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/formatter/integral.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-#include <kstd/bits/format/specifiers.hpp>
-
-#include <iterator>
-
-namespace kstd
-{
-
- template<>
- struct formatter<char> : formatter<unsigned char>
- {
- bits::format::specifiers specifiers{};
-
- constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator
- {
- specifiers = bits::format::parse_format_specifiers(context);
-
- auto it = context.begin();
- auto const end = context.end();
-
- if (specifiers.alternative_form || specifiers.zero_pad || specifiers.sign != bits::format::sign_mode::none)
- {
- bits::format::error("Invalid format specifiers for 'char'");
- }
-
- if (it != end && *it != '}')
- {
- if (*it == 'c' || *it == 'b' || *it == 'B' || *it == 'd' || *it == 'o' || *it == 'x' || *it == 'X')
- {
- specifiers.type = *it;
- std::advance(it, 1);
- }
- else
- {
- bits::format::error("Invalid type specifier for char.");
- }
- }
-
- if (it != end && *it != '}')
- {
- bits::format::error("Missing terminating '}' in format string.");
- }
-
- return it;
- }
-
- auto format(char value, format_context & context) const -> void
- {
- if (specifiers.type == '\0' || specifiers.type == 'c')
- {
- auto final_width = 0uz;
-
- if (specifiers.mode == bits::format::width_mode::static_value)
- {
- final_width = specifiers.width_value;
- }
- else if (specifiers.mode == bits::format::width_mode::dynamic_argument_id)
- {
- auto const & arg = context.arg(specifiers.width_value);
- final_width = bits::format::extrat_dynamic_width(arg);
- }
-
- auto padding =
- bits::format::calculate_format_padding(final_width, 1, specifiers.align, bits::format::alignment::left);
-
- for (auto i = 0uz; i < padding.left; ++i)
- {
- context.push(specifiers.fill);
- }
-
- context.push(value);
-
- for (auto i = 0uz; i < padding.right; ++i)
- {
- context.push(specifiers.fill);
- }
- }
- else
- {
- formatter<unsigned char>::format(static_cast<unsigned char>(value), context);
- }
- }
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/cstring.hpp b/libs/kstd/include/kstd/bits/format/formatter/cstring.hpp
deleted file mode 100644
index 553c8ca..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/cstring.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_CSTRING_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_CSTRING_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/formatter/string_view.hpp>
-
-#include <string_view>
-
-namespace kstd
-{
-
- template<>
- struct formatter<char const *> : formatter<std::string_view>
- {
- auto format(char const * string, format_context & context) const -> void
- {
- formatter<std::string_view>::format(string ? std::string_view{string} : "(null)", context);
- }
- };
-
- template<>
- struct formatter<char *> : formatter<char const *>
- {
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/integral.hpp b/libs/kstd/include/kstd/bits/format/formatter/integral.hpp
deleted file mode 100644
index d17dc95..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/integral.hpp
+++ /dev/null
@@ -1,204 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_INTEGRAL_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_INTEGRAL_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/error.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-#include <kstd/bits/format/specifiers.hpp>
-
-#include <array>
-#include <concepts>
-#include <cstddef>
-#include <iterator>
-#include <string_view>
-#include <type_traits>
-#include <utility>
-
-namespace kstd
-{
-
- template<std::integral T>
- struct formatter<T>
- {
- bits::format::specifiers specifiers{};
-
- constexpr auto static maximum_digits = 80;
-
- enum struct base
- {
- bin = 2,
- oct = 8,
- dec = 10,
- hex = 16,
- };
-
- constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator
- {
- specifiers = bits::format::parse_format_specifiers(context);
-
- auto it = context.begin();
- auto const end = context.end();
-
- if (it != end && *it != '}')
- {
- if (*it == 'b' || *it == 'B' || *it == 'd' || *it == 'o' || *it == 'x' || *it == 'X' || *it == 'p')
- {
- specifiers.type = *it;
- std::advance(it, 1);
- }
- else
- {
- bits::format::error("Invalid type specifier for integral type.");
- }
- }
-
- if (it != end && *it != '}')
- {
- bits::format::error("Missing terminating '}' in format string.");
- }
-
- return it;
- }
-
- auto format(T value, format_context & context) const -> void
- {
- auto final_width = 0uz;
- if (specifiers.mode == bits::format::width_mode::static_value)
- {
- final_width = specifiers.width_value;
- }
- else if (specifiers.mode == bits::format::width_mode::dynamic_argument_id)
- {
- auto const & arg = context.arg(specifiers.width_value);
- final_width = bits::format::extrat_dynamic_width(arg);
- }
-
- using unsigned_T = std::make_unsigned_t<T>;
- auto absolute_value = static_cast<unsigned_T>(value);
- auto is_negative = false;
-
- if constexpr (std::is_signed_v<T>)
- {
- if (value < 0)
- {
- is_negative = true;
- absolute_value = 0 - static_cast<unsigned_T>(value);
- }
- }
-
- auto const base = [type = specifiers.type] -> auto {
- switch (type)
- {
- case 'x':
- case 'X':
- case 'p':
- return base::hex;
- case 'b':
- case 'B':
- return base::bin;
- case 'o':
- return base::oct;
- default:
- return base::dec;
- }
- }();
-
- auto buffer = std::array<char, maximum_digits>{};
- auto digits = (specifiers.type == 'X') ? "0123456789ABCDEF" : "0123456789abcdef";
- auto current = buffer.rbegin();
-
- if (absolute_value == 0)
- {
- *current = '0';
- std::advance(current, 1);
- }
- else
- {
- while (absolute_value != 0)
- {
- *current = digits[absolute_value % std::to_underlying(base)];
- std::advance(current, 1);
- absolute_value /= std::to_underlying(base);
- }
- }
-
- auto content_length = static_cast<std::size_t>(std::distance(buffer.rbegin(), current));
- auto prefix = std::array<char, 2>{'0', '\0'};
- auto prefix_length = 0uz;
- if (specifiers.alternative_form)
- {
- switch (base)
- {
- case base::bin:
- prefix[1] = specifiers.type == 'B' ? 'B' : 'b';
- prefix_length = 2;
- break;
- case base::oct:
- prefix_length = 1;
- break;
- case base::hex:
- prefix[1] = specifiers.type == 'X' ? 'X' : 'x';
- prefix_length = 2;
- break;
- default:
- break;
- }
- }
-
- auto sign_character = '\0';
- if (is_negative)
- {
- sign_character = '-';
- }
- else if (specifiers.sign == bits::format::sign_mode::plus)
- {
- sign_character = '+';
- }
- else if (specifiers.sign == bits::format::sign_mode::space)
- {
- sign_character = ' ';
- }
-
- auto const total_length = content_length + prefix_length + (sign_character != '\0');
- auto const padding = bits::format::calculate_format_padding(final_width, total_length, specifiers.align,
- bits::format::alignment::right);
- auto const effective_zero_pad = specifiers.zero_pad && (specifiers.align == bits::format::alignment::none);
-
- if (!effective_zero_pad)
- {
- for (auto i = 0uz; i < padding.left; ++i)
- {
- context.push(specifiers.fill);
- }
- }
-
- if (sign_character != '\0')
- {
- context.push(sign_character);
- }
- if (prefix_length > 0)
- {
- context.push(std::string_view{prefix.data(), prefix_length});
- }
-
- if (effective_zero_pad)
- {
- for (auto i = 0uz; i < padding.left; ++i)
- {
- context.push('0');
- }
- }
-
- context.push(std::string_view{current.base(), content_length});
-
- for (auto i = 0uz; i < padding.right; ++i)
- {
- context.push(specifiers.fill);
- }
- }
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/ordering.hpp b/libs/kstd/include/kstd/bits/format/formatter/ordering.hpp
deleted file mode 100644
index 7832226..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/ordering.hpp
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_ORDERING_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_ORDERING_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-#include <kstd/bits/format/specifiers.hpp>
-
-#include <compare>
-
-namespace kstd
-{
-
- template<>
- struct formatter<std::strong_ordering>
- {
- bits::format::specifiers specifiers{};
-
- constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator
- {
- specifiers = bits::format::parse_format_specifiers(context);
- return context.begin();
- }
-
- auto format(std::strong_ordering value, format_context & context) const -> void
- {
- if (value == std::strong_ordering::equal)
- {
- return context.push(specifiers.alternative_form ? "==" : "equal");
- }
- else if (value == std::strong_ordering::equivalent)
- {
- return context.push(specifiers.alternative_form ? "==" : "equivalent");
- }
- else if (value == std::strong_ordering::greater)
- {
- return context.push(specifiers.alternative_form ? ">" : "greater");
- }
- else if (value == std::strong_ordering::less)
- {
- return context.push(specifiers.alternative_form ? "<" : "less");
- }
- kstd::os::panic("[kstd:format] Invalid strong ordering value!");
- }
- };
-
- template<>
- struct formatter<std::weak_ordering>
- {
- bits::format::specifiers specifiers{};
-
- constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator
- {
- specifiers = bits::format::parse_format_specifiers(context);
- return context.begin();
- }
-
- auto format(std::weak_ordering value, format_context & context) const -> void
- {
- if (value == std::weak_ordering::equivalent)
- {
- return context.push(specifiers.alternative_form ? "==" : "equivalent");
- }
- else if (value == std::weak_ordering::greater)
- {
- return context.push(specifiers.alternative_form ? ">" : "greater");
- }
- else if (value == std::weak_ordering::less)
- {
- return context.push(specifiers.alternative_form ? "<" : "less");
- }
- kstd::os::panic("[kstd:format] Invalid weak ordering value!");
- }
- };
-
- template<>
- struct formatter<std::partial_ordering>
- {
- bits::format::specifiers specifiers{};
-
- constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator
- {
- specifiers = bits::format::parse_format_specifiers(context);
- return context.begin();
- }
-
- auto format(std::partial_ordering value, format_context & context) const -> void
- {
- if (value == std::partial_ordering::equivalent)
- {
- return context.push(specifiers.alternative_form ? "==" : "equivalent");
- }
- else if (value == std::partial_ordering::greater)
- {
- return context.push(specifiers.alternative_form ? ">" : "greater");
- }
- else if (value == std::partial_ordering::less)
- {
- return context.push(specifiers.alternative_form ? "<" : "less");
- }
- else if (value == std::partial_ordering::unordered)
- {
- return context.push(specifiers.alternative_form ? "<=>" : "unordered");
- }
- kstd::os::panic("[kstd:format] Invalid partial ordering value!");
- }
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/pointer.hpp b/libs/kstd/include/kstd/bits/format/formatter/pointer.hpp
deleted file mode 100644
index 15f9a5b..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/pointer.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_POINTER_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_POINTER_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/formatter/integral.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-#include <kstd/bits/format/specifiers.hpp>
-
-#include <bit>
-#include <cstdint>
-
-namespace kstd
-{
-
- template<typename T>
- struct formatter<T const *> : formatter<std::uintptr_t>
- {
- constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator
- {
- auto result = formatter<std::uintptr_t>::parse(context);
- if (!this->specifiers.type)
- {
- this->specifiers.type = 'p';
- this->specifiers.alternative_form = true;
- }
- return result;
- }
-
- auto format(T const * pointer, format_context & context) const -> void
- {
- formatter<std::uintptr_t>::format(std::bit_cast<std::uintptr_t>(pointer), context);
- }
- };
-
- template<typename T>
- struct formatter<T *> : formatter<T const *>
- {
- };
-
-} // namespace kstd
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/range.hpp b/libs/kstd/include/kstd/bits/format/formatter/range.hpp
deleted file mode 100644
index 05af06f..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/range.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_RANGE_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_RANGE_HPP
-
-#include <kstd/bits/format/formatter.hpp>
-
-#include <concepts>
-#include <ranges>
-#include <string_view>
-#include <type_traits>
-
-namespace kstd
-{
- namespace bits::format
- {
- template<typename T>
- concept iterable = requires(T const & t) {
- t.begin();
- t.end();
- };
-
- template<typename T>
- concept formattable_range = iterable<T> && !std::same_as<std::remove_cvref_t<T>, std::string_view> &&
- !std::same_as<std::decay_t<T>, char *> && !std::same_as<std::decay_t<T>, char const *>;
- } // namespace bits::format
-
- template<bits::format::formattable_range Range>
- struct formatter<Range> : range_formatter<std::ranges::range_value_t<Range>>
- {
- };
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/formatter/string_view.hpp b/libs/kstd/include/kstd/bits/format/formatter/string_view.hpp
deleted file mode 100644
index 7d74579..0000000
--- a/libs/kstd/include/kstd/bits/format/formatter/string_view.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FORMATTER_STRING_VIEW_HPP
-#define KSTD_BITS_FORMAT_FORMATTER_STRING_VIEW_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/error.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-
-#include <string_view>
-
-namespace kstd
-{
-
- template<>
- struct formatter<std::string_view>
- {
- constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator
- {
- auto it = context.begin();
-
- if (it != context.end() && *it == 's')
- {
- ++it;
- }
-
- if (it != context.end() && *it != '}')
- {
- bits::format::error("Invalid specifier for string_view.");
- }
- return it;
- }
-
- auto format(std::string_view const & string, format_context & context) const -> void
- {
- context.push(string);
- }
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/fwd.hpp b/libs/kstd/include/kstd/bits/format/fwd.hpp
deleted file mode 100644
index 6caedae..0000000
--- a/libs/kstd/include/kstd/bits/format/fwd.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_FWD_HPP
-#define KSTD_BITS_FORMAT_FWD_HPP
-
-// IWYU pragma: private
-
-#include <cstddef>
-
-namespace kstd
-{
-
- struct format_parse_context;
- struct format_context;
- struct format_arg;
-
- template<typename>
- struct formatter;
-
- template<std::size_t>
- struct format_arg_store;
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/output_buffer.hpp b/libs/kstd/include/kstd/bits/format/output_buffer.hpp
deleted file mode 100644
index fd7a2b4..0000000
--- a/libs/kstd/include/kstd/bits/format/output_buffer.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_OUTPUT_BUFFER_HPP
-#define KSTD_BITS_FORMAT_OUTPUT_BUFFER_HPP
-
-// IWYU pragma: private, include <kstd/format>
-
-#include <string_view>
-
-namespace kstd::bits::format
-{
-
- //! An abstract interface for formatted output buffers.
- //!
- //! This interface is intended to be use for functions dealing with string formatting, like the print and the format
- //! family.
- struct output_buffer
- {
- virtual ~output_buffer() = default;
-
- //! Push a text segment into the buffer.
- //!
- //! @param text The text segment to push.
- virtual auto push(std::string_view text) -> void = 0;
-
- //! Push a single character into the buffer.
- //!
- //! @param character The character to push into the buffer.
- virtual auto push(char character) -> void = 0;
- };
-
-} // namespace kstd::bits::format
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/parse_context.hpp b/libs/kstd/include/kstd/bits/format/parse_context.hpp
deleted file mode 100644
index cab8d72..0000000
--- a/libs/kstd/include/kstd/bits/format/parse_context.hpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_PARSE_CONTEXT_HPP
-#define KSTD_BITS_FORMAT_PARSE_CONTEXT_HPP
-
-// IWYU pragma: private, include <kstd/format>
-
-#include <kstd/bits/format/error.hpp>
-
-#include <cstddef>
-#include <string_view>
-
-namespace kstd
-{
-
- struct format_parse_context
- {
- using iterator = std::string_view::const_iterator;
-
- constexpr format_parse_context(std::string_view format, std::size_t argument_count,
- bool const * is_integral = nullptr)
- : m_current{format.begin()}
- , m_end{format.end()}
- , m_argument_count{argument_count}
- , m_is_integral{is_integral}
- {}
-
- [[nodiscard]] constexpr auto begin() const -> iterator
- {
- return m_current;
- }
-
- [[nodiscard]] constexpr auto end() const -> iterator
- {
- return m_end;
- }
-
- constexpr auto advance_to(iterator position) -> void
- {
- m_current = position;
- }
-
- constexpr auto next_arg_id() -> std::size_t
- {
- if (m_mode == index_mode::manual)
- {
- bits::format::error("Cannot mix automatic and manual indexing.");
- }
-
- m_mode = index_mode::automatic;
-
- if (m_next_argument_id >= m_argument_count)
- {
- bits::format::error("Argument index out of bounds.");
- }
- return m_next_argument_id++;
- }
-
- constexpr auto check_arg_id(std::size_t index) -> void
- {
- if (m_mode == index_mode::automatic)
- {
- bits::format::error("Cannot mix automatic and manual indexing.");
- }
-
- m_mode = index_mode::manual;
-
- if (index >= m_argument_count)
- {
- bits::format::error("Argument index out of bounds.");
- }
- }
-
- constexpr auto check_dynamic_width_id(std::size_t id) -> void
- {
- check_arg_id(id);
- if (m_is_integral && !m_is_integral[id])
- {
- bits::format::error("Dynamic width argument must be an integral object.");
- }
- }
-
- constexpr auto next_dynamic_width_id() -> std::size_t
- {
- auto const id = next_arg_id();
- if (m_is_integral && !m_is_integral[id])
- {
- bits::format::error("Dynamic width argument must be an integral object.");
- }
- return id;
- }
-
- private:
- enum class index_mode
- {
- unknown,
- automatic,
- manual,
- };
-
- iterator m_current{};
- iterator m_end{};
- index_mode m_mode{};
- std::size_t m_next_argument_id{};
- std::size_t m_argument_count{};
- bool const * m_is_integral{};
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/specifiers.hpp b/libs/kstd/include/kstd/bits/format/specifiers.hpp
deleted file mode 100644
index 211c95d..0000000
--- a/libs/kstd/include/kstd/bits/format/specifiers.hpp
+++ /dev/null
@@ -1,205 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_SPECS_HPP
-#define KSTD_BITS_FORMAT_SPECS_HPP
-
-// IWYU pragma: private
-
-#include <kstd/bits/format/error.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-
-#include <cstddef>
-#include <cstdint>
-#include <iterator>
-
-namespace kstd::bits::format
-{
- enum struct alignment : std::uint8_t
- {
- none,
- left,
- right,
- center,
- };
-
- enum struct sign_mode : std::uint8_t
- {
- none,
- plus,
- minus,
- space,
- };
-
- enum struct width_mode : std::uint8_t
- {
- none,
- static_value,
- dynamic_argument_id
- };
-
- struct specifiers
- {
- char fill{' '};
- alignment align{};
- sign_mode sign{};
- bool alternative_form{};
- bool zero_pad{};
-
- width_mode mode{};
- std::size_t width_value{};
- char type{};
- };
-
- struct padding
- {
- std::size_t left{};
- std::size_t right{};
- };
-
- constexpr auto parse_format_specifiers(format_parse_context & context) -> specifiers
- {
- auto specs = specifiers{};
- auto it = context.begin();
- auto const end = context.end();
-
- if (it != end && *it == '}')
- {
- return specs;
- }
-
- if (std::next(it) != end && ((*std::next(it)) == '<' || (*std::next(it)) == '>' || (*std::next(it)) == '^'))
- {
- specs.fill = *it;
- switch (*std::next(it))
- {
- case '<':
- specs.align = alignment::left;
- break;
- case '>':
- specs.align = alignment::right;
- break;
- case '^':
- default:
- specs.align = alignment::center;
- break;
- }
- std::advance(it, 2);
- }
- else if (*it == '<' || *it == '>' || *it == '^')
- {
- switch (*it)
- {
- case '<':
- specs.align = alignment::left;
- break;
- case '>':
- specs.align = alignment::right;
- break;
- case '^':
- default:
- specs.align = alignment::center;
- break;
- }
- std::advance(it, 1);
- }
-
- if (it != end && (*it == '+' || *it == '-' || *it == ' '))
- {
- switch (*it)
- {
- case '+':
- specs.sign = sign_mode::plus;
- break;
- case '-':
- specs.sign = sign_mode::minus;
- break;
- case ' ':
- default:
- specs.sign = sign_mode::space;
- break;
- }
- std::advance(it, 1);
- }
-
- if (it != end && *it == '#')
- {
- specs.alternative_form = true;
- std::advance(it, 1);
- }
-
- if (it != end && *it == '0')
- {
- specs.zero_pad = true;
- std::advance(it, 1);
- }
-
- if (it != end && *it == '{')
- {
- specs.mode = width_mode::dynamic_argument_id;
- std::advance(it, 1);
- auto argument_id = 0uz;
-
- if (it != end && *it >= '0' && *it <= '9')
- {
- while (it != end && *it >= '0' && *it <= '9')
- {
- argument_id = argument_id * 10 + static_cast<std::size_t>(*it - '0');
- std::advance(it, 1);
- }
- context.check_dynamic_width_id(argument_id);
- }
- else
- {
- argument_id = context.next_dynamic_width_id();
- }
-
- if (it == end || *it != '}')
- {
- error("Expected '}' for dynamic width.");
- }
- std::advance(it, 1);
- specs.width_value = argument_id;
- }
- else if (it != end && *it >= '0' && *it <= '9')
- {
- specs.mode = width_mode::static_value;
- while (it != end && *it >= '0' && *it <= '9')
- {
- specs.width_value = specs.width_value * 10 + static_cast<std::size_t>(*it - '0');
- std::advance(it, 1);
- }
- }
-
- context.advance_to(it);
- return specs;
- }
-
- constexpr auto calculate_format_padding(std::size_t target_width, std::size_t content_length,
- alignment requested_alignment, alignment default_alignment) -> padding
- {
- if (target_width <= content_length)
- {
- return {};
- }
-
- auto total_padding = target_width - content_length;
- auto effective_alignment = (requested_alignment == alignment::none) ? default_alignment : requested_alignment;
-
- switch (effective_alignment)
- {
- case alignment::center:
- {
- auto left = total_padding / 2;
- auto right = total_padding - left;
- return {left, right};
- }
- case alignment::left:
- return {0, total_padding};
- case alignment::right:
- default:
- return {total_padding, 0};
- break;
- }
- }
-
-} // namespace kstd::bits::format
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/string.hpp b/libs/kstd/include/kstd/bits/format/string.hpp
deleted file mode 100644
index e7e4088..0000000
--- a/libs/kstd/include/kstd/bits/format/string.hpp
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_STRING_HPP
-#define KSTD_BITS_FORMAT_STRING_HPP
-
-// IWYU pragma: private, include <kstd/format>
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/error.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/parse_context.hpp>
-
-#include <array>
-#include <cstddef>
-#include <string_view>
-#include <type_traits>
-
-namespace kstd
-{
-
- namespace bits::format
- {
- template<typename... Args>
- constexpr auto validate_argument(std::size_t target_index, format_parse_context & context) -> void
- {
- auto found = false;
- auto current_index = 0uz;
-
- (..., [&] {
- if (current_index == target_index && !found)
- {
- using decay_type = std::remove_cvref_t<Args>;
- static_assert(std::is_default_constructible_v<formatter<decay_type>>, "Missing formatter specialization.");
- auto fmt = formatter<decay_type>{};
-
- auto it = fmt.parse(context);
- context.advance_to(it);
- found = true;
- }
- ++current_index;
- }());
-
- if (!found)
- {
- error("Argument index out of bounds.");
- }
- }
-
- template<typename... Args>
- constexpr auto validate_dynamic_width(std::size_t target_index) -> void
- {
- auto is_valid_integer = false;
- auto current_index = 0uz;
-
- (..., [&] {
- if (current_index == target_index)
- {
- using decay_type = std::remove_cvref_t<Args>;
- if constexpr (std::is_integral_v<decay_type>)
- {
- is_valid_integer = true;
- }
- }
- ++current_index;
- }());
-
- if (!is_valid_integer)
- {
- error("Dynamic width argument must be an integral object.");
- }
- }
- } // namespace bits::format
-
- template<typename... Args>
- struct format_string
- {
- template<std::size_t Size>
- consteval format_string(char const (&str)[Size]) noexcept(false) // NOLINT
- : str_view{str}
- {
- using namespace bits::format;
-
- auto const is_width_compatible =
- std::array<bool, (sizeof...(Args) > 0 ? sizeof...(Args) : 1)>{is_width_v<std::remove_cvref_t<Args>>...};
- auto context = format_parse_context{str_view, sizeof...(Args), is_width_compatible.data()};
- auto it = context.begin();
-
- while (it != context.end())
- {
- if (*it == '{')
- {
- ++it;
- if (it != context.end() && *it == '{')
- {
- ++it;
- context.advance_to(it);
- continue;
- }
-
- context.advance_to(it);
- auto argument_id = 0uz;
-
- if (it != context.end() && *it >= '0' && *it <= '9')
- {
- while (it != context.end() && *it >= '0' && *it <= '9')
- {
- argument_id = argument_id * 10 + static_cast<std::size_t>(*it - '0');
- ++it;
- }
- context.check_arg_id(argument_id);
- context.advance_to(it);
- }
- else
- {
- argument_id = context.next_arg_id();
- }
-
- if (it != context.end() && *it == ':')
- {
- ++it;
- context.advance_to(it);
- }
-
- validate_argument<Args...>(argument_id, context);
-
- it = context.begin();
- if (it == context.end() || *it != '}')
- {
- bits::format::error("Missing closing '}' in format string.");
- }
- }
- else if (*it == '}')
- {
- ++it;
- if (it != context.end() && *it == '}')
- {
- bits::format::error("Unescaped '}' in format string.");
- }
- }
- ++it;
- context.advance_to(it);
- }
- }
-
- std::string_view str_view;
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/format/vformat.hpp b/libs/kstd/include/kstd/bits/format/vformat.hpp
deleted file mode 100644
index 994fae5..0000000
--- a/libs/kstd/include/kstd/bits/format/vformat.hpp
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef KSTD_BITS_FORMAT_VFORMAT_HPP
-#define KSTD_BITS_FORMAT_VFORMAT_HPP
-
-// IWYU pragma: private, include <kstd/format>
-
-#include <kstd/bits/format/args.hpp>
-#include <kstd/bits/format/output_buffer.hpp>
-#include <kstd/bits/format/string.hpp>
-#include <kstd/string>
-
-#include <algorithm>
-#include <iterator>
-#include <string_view>
-#include <type_traits>
-
-namespace kstd
-{
-
- namespace bits::format
- {
- //! Format a string with the given arguments into the given buffer.
- //!
- //! External implementations of `vprint` may call this function.
- //!
- //! @param buffer The buffer to format into.
- //! @param format The format string to use.
- //! @param args The arguments for the format string.
- auto vformat_to(output_buffer & buffer, std::string_view format, format_args args) -> void;
-
- struct string_writer : output_buffer
- {
- auto push(std::string_view text) -> void override;
- auto push(char character) -> void override;
-
- auto release() -> string &&;
-
- private:
- string m_result{};
- };
-
- template<std::output_iterator<char> Output>
- struct iterator_writer : output_buffer
- {
- explicit iterator_writer(Output iterator)
- : m_output{iterator}
- {}
-
- [[nodiscard]] auto iterator() const -> Output
- {
- return m_output;
- }
-
- auto push(std::string_view text) -> void override
- {
- m_output = std::ranges::copy(text, m_output).out;
- }
-
- auto push(char character) -> void override
- {
- *m_output++ = character;
- }
-
- private:
- Output m_output{};
- };
-
- } // namespace bits::format
-
- //! Format a given string with the provided arguments.
- //!
- //! @param format The format string.
- //! @param args The arguments for the format string.
- //! @return A new string containing the result of the format operation.
- template<typename... ArgumentTypes>
- auto format(format_string<std::type_identity_t<ArgumentTypes>...> format, ArgumentTypes &&... args) -> string
- {
- auto buffer = bits::format::string_writer{};
- bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
- return buffer.release();
- }
-
- //! Format a given string with the provided arguments.
- //!
- //! @param iterator The iterator to write to.
- //! @param format The format string.
- //! @param args The arguments for the format string.
- //! @return An iterator past the last element written.
- template<std::output_iterator<char> Output, typename... ArgumentTypes>
- auto format_to(Output iterator, format_string<std::type_identity_t<ArgumentTypes>...> format,
- ArgumentTypes &&... args) -> Output
- {
- auto buffer = bits::format::iterator_writer{iterator};
- bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
- return buffer.iterator();
- }
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/observer_ptr.hpp b/libs/kstd/include/kstd/bits/observer_ptr.hpp
deleted file mode 100644
index 2593d7a..0000000
--- a/libs/kstd/include/kstd/bits/observer_ptr.hpp
+++ /dev/null
@@ -1,163 +0,0 @@
-#ifndef KSTD_OBSERVER_PTR_HPP
-#define KSTD_OBSERVER_PTR_HPP
-
-// IWYU pragma: private, include <kstd/memory>
-
-#include <kstd/os/error.hpp>
-
-#include <compare>
-#include <concepts>
-#include <cstddef>
-#include <type_traits>
-#include <utility>
-
-namespace kstd
-{
-
- template<typename ElementType>
- struct observer_ptr
- {
- //! The type of the element being pointed to.
- using element_type = ElementType;
-
- //! Construct an empty observer pointer.
- constexpr observer_ptr() noexcept = default;
-
- //! Construct an empty observer pointer from a null pointer.
- constexpr observer_ptr(std::nullptr_t) noexcept {}
-
- //! Construct an observer pointer from a raw pointer.
- constexpr explicit observer_ptr(element_type * pointer)
- : m_ptr{pointer}
- {}
-
- //! Construct an observer pointer from another observer pointer.
- template<typename OtherElementType>
- requires std::convertible_to<OtherElementType *, ElementType *>
- constexpr observer_ptr(observer_ptr<OtherElementType> other) noexcept
- : m_ptr{other.get()}
- {}
-
- //! Copy construct an observer pointer.
- constexpr observer_ptr(observer_ptr const & other) noexcept = default;
-
- //! Move construct an observer pointer.
- constexpr observer_ptr(observer_ptr && other) noexcept = default;
-
- //! Copy assign an observer pointer.
- constexpr auto operator=(observer_ptr const & other) noexcept -> observer_ptr & = default;
-
- //! Move assign an observer pointer.
- constexpr auto operator=(observer_ptr && other) noexcept -> observer_ptr & = default;
-
- //! Stop watching the the watched object.
- //!
- //! @return The currently watched object, or nullptr if no object is being watched.
- [[nodiscard]] constexpr auto release() noexcept -> element_type *
- {
- return std::exchange(m_ptr, nullptr);
- }
-
- //! Reset the observer pointer.
- //!
- //! @param pointer The new object to watch.
- constexpr auto reset(element_type * pointer = nullptr) noexcept -> void
- {
- m_ptr = pointer;
- }
-
- //! Swap the observer pointer with another observer pointer.
- //!
- //! @param other The other observer pointer to swap with.
- constexpr auto swap(observer_ptr & other) noexcept -> void
- {
- std::swap(m_ptr, other.m_ptr);
- }
-
- //! Get the currently watched object.
- //!
- //! @return The currently watched object, or nullptr if no object is being watched.
- [[nodiscard]] constexpr auto get() const noexcept -> element_type *
- {
- return m_ptr;
- }
-
- //! Check if the observer pointer is watching an object.
- //!
- //! @return True if the observer pointer is watching an object, false otherwise.
- [[nodiscard]] constexpr explicit operator bool() const noexcept
- {
- return m_ptr != nullptr;
- }
-
- //! Get the currently watched object.
- //!
- //! @return A reference to the currently watched object.
- [[nodiscard]] constexpr auto operator*() const -> std::add_lvalue_reference_t<element_type>
- {
- throw_on_null();
- return *m_ptr;
- }
-
- //! Get the currently watched object.
- //!
- //! @return A pointer to the currently watched object.
- [[nodiscard]] constexpr auto operator->() const -> element_type *
- {
- throw_on_null();
- return m_ptr;
- }
-
- //! Convert the observer pointer to a raw pointer.
- //!
- //! @return A pointer to the currently watched object.
- constexpr explicit operator element_type *() const noexcept
- {
- return m_ptr;
- }
-
- //! Compare the observer pointer with another observer pointer.
- //!>
- //! @param other The other observer pointer to compare with.
- //! @return The result of the comparison.
- constexpr auto operator<=>(observer_ptr const & other) const noexcept -> std::strong_ordering = default;
-
- private:
- //! Throw an exception if the observer pointer is null.
- //!
- //! @throws std::runtime_error if the observer pointer is null.
- constexpr auto throw_on_null() const -> void
- {
- if (m_ptr == nullptr)
- {
- os::panic("[kstd:observer_ptr] Dereferencing a null observer pointer");
- }
- }
-
- //! The raw pointer to the watched object.
- ElementType * m_ptr{};
- };
-
- //! Swap two observer pointers.
- //!
- //! @param lhs The first observer pointer to swap.
- //! @param rhs The second observer pointer to swap.
- template<typename ElementType>
- constexpr auto swap(observer_ptr<ElementType> & lhs, observer_ptr<ElementType> & rhs) noexcept -> void
- {
- lhs.swap(rhs);
- }
-
- //! Create an observer pointer from a raw pointer.
- //!
- //! @param pointer The raw pointer to create an observer pointer from.
- //! @return An observer pointer to the given raw pointer.
- template<typename ElementType>
- constexpr auto make_observer(ElementType * pointer) noexcept -> observer_ptr<ElementType>
- {
- return observer_ptr<ElementType>{pointer};
- }
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/bits/print_sink.hpp b/libs/kstd/include/kstd/bits/print_sink.hpp
deleted file mode 100644
index af765e0..0000000
--- a/libs/kstd/include/kstd/bits/print_sink.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef KSTD_BITS_PRINT_SINK_HPP
-#define KSTD_BITS_PRINT_SINK_HPP
-
-// IWYU pragma: private, include <kstd/print>
-
-namespace kstd
-{
-
- enum struct print_sink
- {
- stdout,
- stderr,
- };
-
-} // namespace kstd
-
-#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
deleted file mode 100644
index 8930095..0000000
--- a/libs/kstd/include/kstd/bits/shared_ptr.hpp
+++ /dev/null
@@ -1,648 +0,0 @@
-#ifndef KSTD_BITS_SHARED_PTR_HPP
-#define KSTD_BITS_SHARED_PTR_HPP
-
-#include <atomic>
-#include <cstddef>
-#include <type_traits>
-#include <utility>
-
-// IWYU pragma: private, include <kstd/memory>
-
-namespace kstd
-{
- /**
- * @brief Control block for shared_ptr and weak_ptr. This control block contains the reference counts for shared
- * ownership and weak ownership. The shared_count tracks the number of shared_ptr instances that own the managed
- * object, while the weak_count tracks the number of weak_ptr instances that reference the managed object.
- * The weak_count is needed to determine when it is safe to delete the shared_control_block itself
- */
- struct shared_control_block
- {
- std::atomic<std::size_t> shared_count;
- std::atomic<std::size_t> weak_count;
-
- explicit shared_control_block(std::size_t shared = 1, std::size_t weak = 0)
- : shared_count(shared)
- , weak_count(weak)
- {}
- };
-
- template<typename T>
- struct shared_ptr;
-
- /**
- * @brief weak_ptr is a smart pointer that holds a non-owning weak reference to an object that is managed by
- * shared_ptr. It must be converted to shared_ptr in to be able to access the referenced object. A weak_ptr is created
- * as a copy of a shared_ptr, or as a copy of another weak_ptr. A weak_ptr is typically used to break circular
- * references between shared_ptr to avoid memory leaks. A weak_ptr does not contribute to the reference count of the
- * object, and it does not manage the lifetime of the object. If the object managed by shared_ptr is destroyed, the
- * weak_ptr becomes expired and cannot be used to access the object anymore.
- */
- template<typename T>
- struct weak_ptr
- {
- template<typename U>
- friend struct shared_ptr;
-
- /**
- * @brief Constructs a null weak_ptr.
- */
- weak_ptr() noexcept
- : pointer(nullptr)
- , control(nullptr)
- {}
-
- template<typename U>
- requires(std::is_convertible_v<U *, T *>)
- weak_ptr(shared_ptr<U> const & other)
- : pointer(other.pointer)
- , control(other.control)
- {
- if (control != nullptr)
- {
- ++(control->weak_count);
- }
- }
-
- /**
- * @brief Copy constructor. Constructs a weak_ptr which shares ownership of the object managed by other.
- */
- weak_ptr(weak_ptr const & other)
- : pointer(other.pointer)
- , control(other.control)
- {
- if (control != nullptr)
- {
- ++(control->weak_count);
- }
- }
-
- /**
- * @brief Move constructor. Constructs a weak_ptr which takes ownership of the object managed by other.
- */
- weak_ptr(weak_ptr && other) noexcept
- : pointer(other.pointer)
- , control(other.control)
- {
- other.pointer = nullptr;
- other.control = nullptr;
- }
-
- /**
- * @brief Assignment operator. Assigns the weak_ptr to another weak_ptr.
- */
- auto operator=(weak_ptr const & other) -> weak_ptr &
- {
- if (this != &other)
- {
- cleanup();
- pointer = other.pointer;
- control = other.control;
- if (control != nullptr)
- {
- ++(control->weak_count);
- }
- }
-
- return *this;
- }
-
- /**
- * @brief Move assignment operator. Move-assigns a weak_ptr from other.
- */
- auto operator=(weak_ptr && other) noexcept -> weak_ptr &
- {
- if (this != &other)
- {
- cleanup();
- pointer = other.pointer;
- control = other.control;
- other.pointer = nullptr;
- other.control = nullptr;
- }
-
- return *this;
- }
-
- /**
- * @brief Destructor. Cleans up resources if necessary.
- */
- ~weak_ptr()
- {
- cleanup();
- }
-
- /**
- * @brief Returns a shared_ptr that shares ownership of the managed object if the managed object still exists, or an
- * empty shared_ptr otherwise.
- */
- [[nodiscard]] auto lock() const -> shared_ptr<T>
- {
- return shared_ptr<T>(*this);
- }
-
- private:
- auto cleanup() -> void
- {
- if (control != nullptr)
- {
- if (--(control->weak_count) == 0 && control->shared_count == 0)
- {
- delete control;
- }
- }
- }
-
- T * pointer;
- shared_control_block * control;
- };
-
- /**
- * @brief enable_shared_from_this is a base class that allows an object that is currently managed by a shared_ptr to
- * create additional shared_ptr instances that share ownership of the same object. This is usefl when you want to
- * create shared_ptr instances in a member function of the object.
- *
- * @tparam T The type of the managed object.
- */
- template<typename T>
- struct enable_shared_from_this
- {
- template<typename U>
- friend struct shared_ptr;
-
- friend T;
-
- public:
- /**
- * @brief Returns a shared_ptr that shares ownership of *this.
- */
- auto shared_from_this() -> shared_ptr<T>
- {
- return shared_ptr<T>(weak_this);
- }
-
- /**
- * @brief Returns a shared_ptr that shares ownership of *this.
- */
- auto shared_from_this() const -> shared_ptr<T const>
- {
- return shared_ptr<T const>(weak_this);
- }
-
- private:
- enable_shared_from_this() = default;
- enable_shared_from_this(enable_shared_from_this const &) = default;
- auto operator=(enable_shared_from_this const &) -> enable_shared_from_this & = default;
- ~enable_shared_from_this() = default;
-
- void internal_assign_ptr(shared_ptr<T> const & ptr) const
- {
- weak_this = ptr;
- }
-
- mutable weak_ptr<T> weak_this{}; ///< Weak pointer to the object, used for shared_from_this functionality.
- };
-
- /**
- * @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
- {
- template<typename U>
- friend struct shared_ptr;
-
- template<typename U>
- friend struct weak_ptr;
-
- /**
- * @brief Construct an empty shared_ptr.
- */
- shared_ptr() noexcept
- : pointer(nullptr)
- , control(nullptr)
- {}
-
- /**
- * @brief Construct an empty shared_ptr from nullptr.
- */
- shared_ptr(std::nullptr_t) noexcept
- : pointer(nullptr)
- , control(nullptr)
- {}
-
- /**
- * @brief Constructor.
- *
- * @param pointer A pointer to an object to manage (default is nullptr).
- */
- template<typename U>
- requires(std::is_convertible_v<U *, T *>)
- explicit shared_ptr(U * pointer = nullptr)
- : pointer(pointer)
- , control(pointer != nullptr ? new shared_control_block() : nullptr)
- {
- assign_enable_shared_from_this(pointer);
- }
-
- /**
- * @brief Constructor a shared_ptr from a weak_ptr. If other is not expired, constructs a shared_ptr which shares
- * ownership of the object managed by other. Otherwise, constructs an empty shared_ptr.
- *
- * @param other The weak_ptr to construct from.
- */
- template<typename U>
- requires(std::is_convertible_v<U *, T *>)
- explicit shared_ptr(weak_ptr<U> const & other)
- : pointer(nullptr)
- , control(nullptr)
- {
- if (other.control != nullptr && other.control->shared_count != 0)
- {
- pointer = other.pointer;
- control = other.control;
- ++(control->shared_count);
- }
- }
-
- /**
- * @brief Copy constructor.
- *
- * @param other The shared_ptr to copy from.
- */
- shared_ptr(shared_ptr const & other)
- : pointer(other.pointer)
- , control(other.control)
- {
- if (control != nullptr)
- {
- ++(control->shared_count);
- }
- }
-
- /**
- * @brief Converting copy constructor for compatible shared_ptr types.
- *
- * @tparam U Source pointer element type.
- * @param other The shared_ptr to copy from.
- */
- template<typename U>
- requires(std::is_convertible_v<U *, T *>)
- shared_ptr(shared_ptr<U> const & other)
- : pointer(other.pointer)
- , control(other.control)
- {
- if (control != nullptr)
- {
- ++(control->shared_count);
- }
- }
-
- /**
- * @brief Move constructor.
- *
- * @param other The shared_ptr to move from.
- */
- shared_ptr(shared_ptr && other) noexcept
- : pointer(other.pointer)
- , control(other.control)
- {
- other.pointer = nullptr;
- other.control = nullptr;
- }
-
- /**
- * @brief Converting move constructor for compatible shared_ptr types.
- *
- * @tparam U Source pointer element type.
- * @param other The shared_ptr to move from.
- */
- template<typename U>
- requires(std::is_convertible_v<U *, T *>)
- shared_ptr(shared_ptr<U> && other) noexcept
- : pointer(other.pointer)
- , control(other.control)
- {
- other.pointer = nullptr;
- other.control = 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.
- */
- auto operator=(shared_ptr const & other) -> shared_ptr &
- {
- if (this != &other)
- {
- cleanup();
- pointer = other.pointer;
- control = other.control;
-
- if (control != nullptr)
- {
- ++(control->shared_count);
- }
- }
-
- return *this;
- }
-
- /**
- * @brief Converting copy assignment for compatible shared_ptr types.
- *
- * @tparam U Source pointer element type.
- * @param other Another smart pointer to share ownership with.
- * @return Reference to this shared pointer.
- */
- template<typename U>
- requires(std::is_convertible_v<U *, T *>)
- auto operator=(shared_ptr<U> const & other) -> shared_ptr &
- {
- cleanup();
- pointer = other.pointer;
- control = other.control;
-
- if (control != nullptr)
- {
- ++(control->shared_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.
- */
- auto operator=(shared_ptr && other) noexcept -> shared_ptr &
- {
- if (this != &other)
- {
- cleanup();
- pointer = other.pointer;
- control = other.control;
- other.pointer = nullptr;
- other.control = nullptr;
- }
-
- return *this;
- }
-
- /**
- * @brief Converting move assignment for compatible shared_ptr types.
- *
- * @tparam U Source pointer element type.
- * @param other Another smart pointer to acquire ownership from.
- * @return Reference to this shared pointer.
- */
- template<typename U>
- requires(std::is_convertible_v<U *, T *>)
- auto operator=(shared_ptr<U> && other) noexcept -> shared_ptr &
- {
- cleanup();
- pointer = other.pointer;
- control = other.control;
- other.pointer = nullptr;
- other.control = nullptr;
-
- return *this;
- }
-
- /**
- * @brief Reset this shared_ptr to empty via nullptr assignment.
- */
- auto operator=(std::nullptr_t) noexcept -> shared_ptr &
- {
- cleanup();
- pointer = nullptr;
- control = nullptr;
- return *this;
- }
-
- /**
- * @brief Destructor. Cleans up resources if necessary.
- */
- ~shared_ptr()
- {
- cleanup();
- }
-
- /**
- * @brief Replaces the managed object.
- *
- * @param ptr Pointer to a new object to manage (default = nullptr).
- */
- void reset(T * ptr = nullptr)
- {
- cleanup();
- pointer = ptr;
- control = ptr != nullptr ? new shared_control_block() : nullptr;
- assign_enable_shared_from_this(ptr);
- }
-
- /**
- * @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.
- */
- void swap(shared_ptr & other)
- {
- std::swap(pointer, other.pointer);
- std::swap(control, other.control);
- }
-
- /**
- * @brief Dereference operator. If get() is a null pointer, the behavior is undefined.
- *
- * @return Returns the object owned by *this, equivalent to *get().
- */
- [[nodiscard]] auto operator*() const -> T &
- {
- return *pointer;
- }
-
- /**
- * @brief Member access operator.
- *
- * @return Returns a pointer to the object owned by *this, i.e. get().
- */
- [[nodiscard]] 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.
- */
- [[nodiscard]] 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.
- */
- [[nodiscard]] auto use_count() const -> std::size_t
- {
- if (control != nullptr)
- {
- return control->shared_count;
- }
-
- return 0;
- }
-
- /**
- * @brief Checks whether *this owns an object, i.e. whether get() != nullptr.
- *
- * @return true if *this owns an object, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const
- {
- return pointer != nullptr;
- }
-
- /**
- * @brief Compare shared_ptr with nullptr.
- */
- [[nodiscard]] auto operator==(std::nullptr_t) const -> bool
- {
- return pointer == nullptr;
- }
-
- /**
- * @brief Compare nullptr with shared_ptr.
- */
- [[nodiscard]] friend auto operator==(std::nullptr_t, shared_ptr const & ptr) -> bool
- {
- return ptr.pointer == nullptr;
- }
-
- private:
- /**
- * @brief If the candidate type inherits from enable_shared_from_this, assigns the internal weak pointer to this
- * shared_ptr. This weak_ptr is used to implement shared_from_this functionality for the candidate type. If the
- * candidate type does not inherit from enable_shared_from_this, this function does nothing.
- *
- * @tparam U The candidate type to check for enable_shared_from_this inheritance.
- * @param candidate The candidate object to assign the internal weak pointer for.
- */
- template<typename U>
- auto assign_enable_shared_from_this(U * candidate) -> void
- {
- if constexpr (requires(U * p, shared_ptr<T> const & sp) { p->internal_assign_ptr(sp); })
- {
- if (candidate != nullptr)
- {
- candidate->internal_assign_ptr(*this);
- }
- }
- }
-
- /**
- * @brief Releases ownership and deletes the object if this was the last reference to the owned managed object.
- */
- auto cleanup() -> void
- {
- if (control != nullptr)
- {
- if (--(control->shared_count) == 0)
- {
- delete pointer;
- pointer = nullptr;
-
- if (control->weak_count == 0)
- {
- delete control;
- }
- }
- }
- }
-
- T * pointer; ///< The managed object.
- shared_control_block * control; ///< Shared control block.
- };
-
- /**
- * @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)...));
- }
-
- /**
- * @brief Equality operator for shared_ptr. Two shared_ptr instances are equal if they point to the same object
- * @tparam T, U Types of the managed objects of the shared_ptr instances being compared.
- * @param lhs, rhs The shared_ptr instances to compare.
- * @return true if lhs and rhs point to the same object, false otherwise.
- */
- template<typename T, typename U>
- [[nodiscard]] auto inline operator==(shared_ptr<T> const & lhs, shared_ptr<U> const & rhs) -> bool
- {
- return lhs.get() == rhs.get();
- }
-
- /**
- * @brief Three-way comparison operator for shared_ptr. Compares the stored pointers of lhs and rhs using operator<=>.
- * @tparam T, U Types of the managed objects of the shared_ptr instances being compared.
- * @param lhs, rhs The shared_ptr instances to compare.
- * @return The result of comparing the stored pointers of lhs and rhs using operator<=>
- */
- template<typename T, typename U>
- [[nodiscard]] auto inline operator<=>(shared_ptr<T> const & lhs, shared_ptr<U> const & rhs)
- {
- return lhs.get() <=> rhs.get();
- }
-} // 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
deleted file mode 100644
index 3d803b4..0000000
--- a/libs/kstd/include/kstd/bits/unique_ptr.hpp
+++ /dev/null
@@ -1,199 +0,0 @@
-#ifndef KSTD_BITS_UNIQUE_POINTER_HPP
-#define KSTD_BITS_UNIQUE_POINTER_HPP
-
-#include <utility>
-
-// IWYU pragma: private, include <kstd/memory>
-
-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
- {
- template<typename U>
- friend struct unique_ptr;
-
- /**
- * @brief Constructor.
- *
- * @param ptr A pointer to an object to manage (default is nullptr).
- */
- explicit unique_ptr(T * ptr = nullptr)
- : pointer(ptr)
- {
- // Nothing to do.
- }
-
- /**
- * @brief Destructor that deletes the managed object.
- */
- ~unique_ptr()
- {
- delete pointer;
- }
-
- /**
- * @brief Deleted copy constructor to enforce unique ownership.
- */
- unique_ptr(unique_ptr const &) = delete;
-
- template<typename U>
- requires(std::is_convertible_v<U *, T *>)
- unique_ptr(unique_ptr<U> && other) noexcept
- : pointer{std::exchange(other.pointer, nullptr)}
- {}
-
- /**
- * @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.
- */
- unique_ptr(unique_ptr && other) noexcept
- : pointer{std::exchange(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.
- */
- auto operator=(unique_ptr && other) noexcept -> unique_ptr &
- {
- if (this != &other)
- {
- delete pointer;
- pointer = std::exchange(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().
- */
- auto operator*() const -> T &
- {
- return *pointer;
- }
-
- /**
- * @brief Member access operator.
- *
- * @return Returns a pointer to the object owned by *this, i.e. get().
- */
- 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.
- */
- [[nodiscard]] 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.
- */
- 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.
- */
- auto release() -> T *
- {
- return std::exchange(pointer, nullptr);
- }
-
- /**
- * @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).
- */
- auto reset(T * ptr = nullptr) -> void
- {
- delete std::exchange(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.
- */
- auto swap(unique_ptr & other) -> void
- {
- using std::swap;
- swap(pointer, other.pointer);
- }
-
- /**
- * @brief Defaulted three-way comparator operator.
- */
- 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/cstring b/libs/kstd/include/kstd/cstring
deleted file mode 100644
index bd8b28d..0000000
--- a/libs/kstd/include/kstd/cstring
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef KSTD_CSTRING
-#define KSTD_CSTRING
-
-#include <cstddef>
-
-namespace kstd::libc
-{
-
- extern "C"
- {
- auto memcpy(void * dest, void const * src, std::size_t size) noexcept -> void *;
- auto memset(void * dest, int value, std::size_t size) noexcept -> void *;
- auto memmove(void * dest, void const * src, std::size_t size) noexcept -> void *;
- auto memcmp(void const * lhs, void const * rhs, std::size_t size) noexcept -> int;
-
- auto strlen(char const * string) noexcept -> std::size_t;
- }
-
-} // namespace kstd::libc
-
-#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
deleted file mode 100644
index 80fe9d2..0000000
--- a/libs/kstd/include/kstd/ext/bitfield_enum
+++ /dev/null
@@ -1,65 +0,0 @@
-#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/flat_map b/libs/kstd/include/kstd/flat_map
deleted file mode 100644
index f12b1b5..0000000
--- a/libs/kstd/include/kstd/flat_map
+++ /dev/null
@@ -1,365 +0,0 @@
-#ifndef KSTD_FLAT_MAP_HPP
-#define KSTD_FLAT_MAP_HPP
-
-#include <kstd/bits/flat_map.hpp>
-#include <kstd/os/error.hpp>
-#include <kstd/vector>
-
-#include <algorithm>
-#include <concepts>
-#include <cstddef>
-#include <functional>
-#include <iterator>
-#include <utility>
-
-namespace kstd
-{
-
- template<typename KeyType, typename MappedType, typename KeyCompare = std::less<KeyType>,
- typename KeyContainerType = kstd::vector<KeyType>, typename MappedContainerType = kstd::vector<MappedType>>
- struct flat_map
- {
- using key_container_type = KeyContainerType;
- using mapped_container_type = MappedContainerType;
- using key_type = KeyType;
- using mapped_type = MappedType;
- using value_type = std::pair<key_type, mapped_type>;
- using key_compare = KeyCompare;
- using reference = std::pair<key_type const &, mapped_type &>;
- using const_reference = std::pair<key_type const &, mapped_type const &>;
- using size_type = std::size_t;
- using difference_type = std::ptrdiff_t;
- using iterator = bits::flat_map_iterator<KeyType, MappedType, typename key_container_type::iterator,
- typename mapped_container_type::iterator>;
- using const_iterator =
- bits::flat_map_iterator<KeyType, MappedType const, typename key_container_type::const_iterator,
- typename mapped_container_type::const_iterator>;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using containers = struct
- {
- key_container_type keys;
- mapped_container_type values;
- };
-
- //! Compare two object of type value_type.
- struct value_compare
- {
- constexpr auto operator()(const_reference lhs, const_reference rhs) const -> bool
- {
- return lhs.first < rhs.first;
- }
- };
-
- //! Construct an empty flat map.
- constexpr flat_map()
- : flat_map{key_compare{}}
- {}
-
- //! Construct an empty flat map using the given custom comparator.
- //!
- //! @param comparator The comparator to use for comparing keys.
- constexpr explicit flat_map(key_compare const & comparator)
- : m_containers{}
- , m_comparator{comparator}
- {}
-
- //! Get a reference to the mapped value associated with the given key.
- //!
- //! @warning This function will panic if the key is not found.
- //! @param key The key to look up.
- //! @return A reference to the mapped value.
- [[nodiscard]] constexpr auto at(key_type const & key) -> mapped_type &
- {
- auto found = std::ranges::lower_bound(m_containers.keys, key, m_comparator);
- if (found != m_containers.keys.cend() && !m_comparator(key, *found) && !m_comparator(*found, key))
- {
- auto offset = std::distance(m_containers.keys.begin(), found);
- return *(m_containers.values.begin() + offset);
- }
- os::panic("[kstd::flat_map] Key not found");
- }
-
- //! Get a reference to the mapped value associated with the given key.
- //!
- //! @warning This function will panic if the key is not found.
- //! @param key The key to look up.
- //! @return A const reference to the mapped value.
- [[nodiscard]] constexpr auto at(key_type const & key) const -> mapped_type const &
- {
- auto found = std::ranges::lower_bound(m_containers.keys, key, m_comparator);
- if (found != m_containers.keys.cend() && !m_comparator(key, *found) && !m_comparator(*found, key))
- {
- auto offset = std::distance(m_containers.keys.cbegin(), found);
- return *(m_containers.values.cbegin() + offset);
- }
- os::panic("[kstd::flat_map] Key not found");
- }
-
- //! Get a reference to the mapped value associated with the given key.
- //!
- //! @note This overload only participates in overload resolution if the key compare type is transparent.
- //! @warning This function will panic if the key is not found.
- //! @param x The key to look up.
- //! @return A reference to the mapped value.
- template<typename K>
- requires requires(K const & k, key_type const & l) { typename key_compare::is_transparent; }
- [[nodiscard]] constexpr auto at(K const & x) -> mapped_type &
- {
- auto found = find(x);
- if (found != end())
- {
- auto offset = std::distance(m_containers.keys.begin(), found.key_iterator());
- return *(m_containers.values.begin() + offset);
- }
- os::panic("[kstd::flat_map] Key not found");
- }
-
- //! Get a reference to the mapped value associated with the given key.
- //! @note This overload only participates in overload resolution if the key compare type is transparent.
- //! @warning This function will panic if the key is not found.
- //! @param x The key to look up.
- //! @return A const reference to the mapped value.
- template<typename K>
- requires requires(K const & k, key_type const & l) { typename key_compare::is_transparent; }
- [[nodiscard]] auto at(K const & x) const -> mapped_type const &
- {
- auto found = find(x);
- if (found != end())
- {
- auto offset = std::distance(m_containers.keys.cbegin(), found.key_iterator());
- return *(m_containers.values.cbegin() + offset);
- }
- os::panic("[kstd::flat_map] Key not found");
- }
-
- //! Get an iterator to the first element.
- [[nodiscard]] auto begin() noexcept -> iterator
- {
- return iterator{m_containers.keys.begin(), m_containers.values.begin()};
- }
-
- //! Get an iterator to the first element.
- [[nodiscard]] auto begin() const noexcept -> const_iterator
- {
- return const_iterator{m_containers.keys.cbegin(), m_containers.values.cbegin()};
- }
-
- //! Get an iterator to the first element.
- [[nodiscard]] auto cbegin() const noexcept -> const_iterator
- {
- return const_iterator{m_containers.keys.cbegin(), m_containers.values.cbegin()};
- }
-
- //! Get an iterator to the element past the last element.
- [[nodiscard]] auto end() noexcept -> iterator
- {
- return iterator{m_containers.keys.end(), m_containers.values.end()};
- }
-
- //! Get an iterator to the element past the last element.
- [[nodiscard]] auto end() const noexcept -> const_iterator
- {
- return const_iterator{m_containers.keys.cend(), m_containers.values.cend()};
- }
-
- //! Get an iterator to the element past the last element.
- [[nodiscard]] auto cend() const noexcept -> const_iterator
- {
- return const_iterator{m_containers.keys.cend(), m_containers.values.cend()};
- }
-
- //! Get an iterator to the first element.
- [[nodiscard]] auto rbegin() noexcept -> reverse_iterator
- {
- return reverse_iterator{end()};
- }
-
- //! Get an iterator to the first element.
- [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator
- {
- return const_reverse_iterator{cend()};
- }
-
- //! Get an iterator to the first element.
- [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator
- {
- return const_reverse_iterator{cend()};
- }
-
- //! Get an iterator to the element past the last element.
- [[nodiscard]] auto rend() noexcept -> reverse_iterator
- {
- return reverse_iterator{begin()};
- }
-
- //! Get an iterator to the element past the last element.
- [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator
- {
- return const_reverse_iterator{cbegin()};
- }
-
- //! Get an iterator to the element past the last element.
- [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator
- {
- return const_reverse_iterator{cbegin()};
- }
-
- //! Check whether this flat map is empty or not
- [[nodiscard]] auto empty() const noexcept -> bool
- {
- return m_containers.keys.empty();
- }
-
- //! Get the number of elements in this flat map.
- [[nodiscard]] auto size() const noexcept -> size_type
- {
- return m_containers.keys.size();
- }
-
- //! Get the maximum number of elements possible in this flat map
- [[nodiscard]] auto max_size() const noexcept -> size_type
- {
- return std::min(m_containers.keys.max_size(), m_containers.values.max_size());
- }
-
- //! Try to insert a new key-value pair into the map.
- //!
- //! @param args Arguments to use for constructing the key-value pair.
- //! @return A pair of an iterator to the inserted element and a boolean indicating whether the insertion took place.
- template<typename... Args>
- auto emplace(Args &&... args) -> std::pair<iterator, bool>
- requires std::constructible_from<value_type, Args...>
- {
- auto value = value_type{std::forward<Args>(args)...};
- auto found = std::ranges::lower_bound(m_containers.keys, value.first, m_comparator);
-
- if (found != m_containers.keys.cend() && !m_comparator(value.first, *found) && !m_comparator(*found, value.first))
- {
- auto offset = std::distance(m_containers.keys.begin(), found);
- return {
- iterator{m_containers.keys.begin() + offset, m_containers.values.begin() + offset},
- false
- };
- }
-
- auto offset = std::distance(m_containers.keys.begin(), found);
- auto key_iterator = m_containers.keys.begin() + offset;
- auto mapped_iterator = m_containers.values.begin() + offset;
-
- auto inserted_key = m_containers.keys.insert(key_iterator, std::move(value.first));
- auto inserted_mapped = m_containers.values.insert(mapped_iterator, std::move(value.second));
-
- return {
- iterator{inserted_key, inserted_mapped},
- true
- };
- }
-
- //! Try to insert a element for the given key into this map.
- //!
- //! This function does nothing if the key is already present.
- //!
- //! @param key The key to insert a value for.
- //! @param args The arguments to use to construct the mapped value.
- template<typename... Args>
- auto try_emplace(key_type const & key, Args &&... args) -> std::pair<iterator, bool>
- {
- auto found = std::ranges::lower_bound(m_containers.keys, key, m_comparator);
- if (found != m_containers.keys.cend() && !m_comparator(*found, key) && !m_comparator(key, *found))
- {
- return {found, false};
- }
-
- auto offset = std::distance(m_containers.keys.cbegin(), found);
- auto intersertion_point = m_containers.value.begin() + offset;
-
- auto inserted_key = m_containers.keys.emplace(key);
- auto inserted_mapped = m_containers.values.emplace(std::forward<Args>(args)...);
-
- return {
- iterator{inserted_key, inserted_mapped},
- true
- };
- }
-
- //! Find an element with an equivalent key.
- //!
- //! @param key The key to look up.
- //! @return An iterator to the element with the equivalent key, or end() if no such element is found.
- [[nodiscard]] auto find(key_type const & key) noexcept -> iterator
- {
- auto found = std::ranges::lower_bound(m_containers.keys, key, m_comparator);
- if (found != m_containers.keys.cend() && !m_comparator(key, *found) && !m_comparator(*found, key))
- {
- auto offset = std::distance(m_containers.keys.begin(), found);
- return iterator{m_containers.keys.begin() + offset, m_containers.values.begin() + offset};
- }
- return end();
- }
-
- //! Find an element with an equivalent key.
- //!
- //! @param key The key to look up.
- //! @return An iterator to the element with the equivalent key, or end() if no such element is found.
- [[nodiscard]] auto find(key_type const & key) const noexcept -> const_iterator
- {
- auto found = std::ranges::lower_bound(m_containers.keys, key, m_comparator);
- if (found != m_containers.keys.cend() && !m_comparator(key, *found) && !m_comparator(*found, key))
- {
- auto offset = std::distance(m_containers.keys.cbegin(), found);
- return const_iterator{m_containers.keys.cbegin() + offset, m_containers.values.cbegin() + offset};
- }
- return cend();
- }
-
- //! Find an element with an equivalent key.
- //! @note This overload only participates in overload resolution if the key compare type is transparent.
- //! @param x The key to look up.
- //! @return An iterator to the element with the equivalent key, or end() if no such element is found.
- template<typename K>
- requires requires(K const & k, key_type const & l) { typename key_compare::is_transparent; }
- [[nodiscard]] auto find(K const & x) noexcept -> iterator
- {
- auto found = std::ranges::lower_bound(m_containers.keys, x, m_comparator);
- if (found != m_containers.keys.cend() && !m_comparator(x, *found) && !m_comparator(*found, x))
- {
- auto offset = std::distance(m_containers.keys.begin(), found);
- return iterator{m_containers.keys.begin() + offset, m_containers.values.begin() + offset};
- }
- return end();
- }
-
- //! Find an element with an equivalent key.
- //! @note This overload only participates in overload resolution if the key compare type is transparent.
- //! @param x The key to look up.
- //! @return An iterator to the element with the equivalent key, or end() if no such element is found.
- template<typename K>
- requires requires(K const & k, key_type const & l) { typename key_compare::is_transparent; }
- [[nodiscard]] auto find(K const & x) const noexcept -> const_iterator
- {
- auto found = std::ranges::lower_bound(m_containers.keys, x, m_comparator);
- if (found != m_containers.keys.cend() && !m_comparator(x, *found) && !m_comparator(*found, x))
- {
- auto offset = std::distance(m_containers.keys.cbegin(), found);
- return const_iterator{m_containers.keys.cbegin() + offset, m_containers.values.cbegin() + offset};
- }
- return cend();
- }
-
- //! Check if the map contains the given key.
- //!
- //! @param key The key to check.
- //! @return true iff. the key is found, false otherwise.
- [[nodiscard]] constexpr auto contains(key_type const & key) const noexcept -> bool
- {
- return find(key) != cend();
- }
-
- private:
- containers m_containers;
- key_compare m_comparator;
- };
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/format b/libs/kstd/include/kstd/format
deleted file mode 100644
index e04b79a..0000000
--- a/libs/kstd/include/kstd/format
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef KSTD_FORMAT_HPP
-#define KSTD_FORMAT_HPP
-
-#include <kstd/bits/format/arg.hpp> // IWYU pragma: export
-#include <kstd/bits/format/args.hpp> // IWYU pragma: export
-#include <kstd/bits/format/context.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/bool.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/byte.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/char.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/cstring.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/integral.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/ordering.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/pointer.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/range.hpp> // IWYU pragma: export
-#include <kstd/bits/format/formatter/string_view.hpp> // IWYU pragma: export
-#include <kstd/bits/format/output_buffer.hpp> // IWYU pragma: export
-#include <kstd/bits/format/parse_context.hpp> // IWYU pragma: export
-#include <kstd/bits/format/string.hpp> // IWYU pragma: export
-#include <kstd/bits/format/vformat.hpp> // IWYU pragma: export
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/memory b/libs/kstd/include/kstd/memory
deleted file mode 100644
index f108c6d..0000000
--- a/libs/kstd/include/kstd/memory
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef KSTD_MEMORY_HPP
-#define KSTD_MEMORY_HPP
-
-#include <kstd/bits/observer_ptr.hpp> // IWYU pragma: export
-#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
deleted file mode 100644
index b2a31aa..0000000
--- a/libs/kstd/include/kstd/mutex
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef KSTD_MUTEX_HPP
-#define KSTD_MUTEX_HPP
-
-#include <atomic>
-
-namespace kstd
-{
-
- //! A non-recursive mutex.
- struct mutex
- {
- mutex();
- ~mutex();
-
- mutex(mutex const &) = delete;
- mutex(mutex &&) = delete;
-
- auto operator=(mutex const &) -> mutex & = delete;
- auto operator=(mutex &&) -> mutex & = delete;
-
- //! Lock the mutex.
- //!
- //! @note This function blocks for as long as the mutex is not available.
- auto lock() -> void;
-
- //! Try to lock the mutex.
- //!
- //! @note This function never blocks.
- //! @return @p true iff. the mutex was successfully locked, @p false otherwise.
- auto try_lock() -> bool;
-
- //! Unlock the mutex.
- //!
- //! @note The behavior is undefined if the mutex is not currently held by the thread unlocking it.
- auto unlock() -> void;
-
- private:
- std::atomic_flag m_locked{};
- };
-
- //! A tag type to specify that a given @p lockable wrapper should adopt ownership of the @p lockable.
- struct adopt_lock_t
- {
- explicit adopt_lock_t() = default;
- } constexpr inline adopt_lock{};
-
- //! A tag type to specify that a given @p lockable wrapper should defer locking the @p lockable.
- struct defer_lock_t
- {
- explicit defer_lock_t() = default;
- } constexpr inline defer_lock{};
-
- //! A tag type to specify that a given @p lockable wrapper should attempt to lock the @p lockable.
- struct try_to_lock_t
- {
- explicit try_to_lock_t() = default;
- } constexpr inline try_to_lock{};
-
- //! An RAII wrapper for a single @p lockable like a kstd::mutex.
- template<typename MutexType>
- struct lock_guard
- {
- using mutex_type = MutexType;
-
- //! Construct a new lock_guard and immediately lock the given mutex.
- //!
- //! @note This function will block until the mutex was successfully locked.
- //! @param mutex The mutex to lock.
- lock_guard(MutexType & mutex) noexcept
- : m_mutex(mutex)
- {
- m_mutex.lock();
- }
-
- //! Construct a new lock_guard and take ownership of the given mutex.
- //!
- //! @note The behavior is undefined if the mutex is not owned by the current thread.
- //! @param mutex The mutex to take ownership of.
- lock_guard(MutexType & mutex, adopt_lock_t) noexcept
- : m_mutex(mutex)
- {}
-
- //! Destroy this lock_guard and release the owned mutex.
- ~lock_guard()
- {
- m_mutex.unlock();
- }
-
- lock_guard(lock_guard const &) noexcept = delete;
- lock_guard(lock_guard &&) noexcept = delete;
-
- auto operator=(lock_guard const &) noexcept -> lock_guard & = delete;
- auto operator=(lock_guard &&) noexcept -> lock_guard & = delete;
-
- private:
- mutex_type & m_mutex;
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/os/error.hpp b/libs/kstd/include/kstd/os/error.hpp
deleted file mode 100644
index 9d43fb1..0000000
--- a/libs/kstd/include/kstd/os/error.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef KSTD_OS_ERROR_HPP
-#define KSTD_OS_ERROR_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/os/print.hpp b/libs/kstd/include/kstd/os/print.hpp
deleted file mode 100644
index 36cb43d..0000000
--- a/libs/kstd/include/kstd/os/print.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef KSTD_OS_PRINT_HPP
-#define KSTD_OS_PRINT_HPP
-
-#include <kstd/bits/format/args.hpp>
-#include <kstd/bits/print_sink.hpp>
-
-#include <string_view>
-
-namespace kstd::os
-{
- auto vprint(print_sink sink, std::string_view format, kstd::format_args args) -> void;
-} // namespace kstd::os
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/print b/libs/kstd/include/kstd/print
deleted file mode 100644
index 1033f72..0000000
--- a/libs/kstd/include/kstd/print
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef KSTD_PRINT
-#define KSTD_PRINT
-
-#include <kstd/bits/print_sink.hpp> // IWYU pragma: export
-#include <kstd/format>
-#include <kstd/os/print.hpp>
-
-#include <type_traits>
-
-namespace kstd
-{
-
- //! @qualifier kernel-defined
- //! Format the given string using the given arguments and print it to the currently active output device.
- //!
- //! @param format The format string
- //! @param args The arguments to use to place in the format string's placeholders.
- template<typename... Args>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- auto print(kstd::format_string<std::type_identity_t<Args>...> format, Args const &... args) -> void
- {
- auto const arg_store = kstd::make_format_args(args...);
- os::vprint(print_sink::stdout, format.str_view, arg_store.args);
- }
-
- //! @qualifier kernel-defined
- //! Format the given error string using the given arguments and print it to the currently active output device.
- //!
- //! @param format The format string
- //! @param args The arguments to use to place in the format string's placeholders.
- template<typename... Args>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- auto print(print_sink sink, kstd::format_string<std::type_identity_t<Args>...> format, Args &&... args) -> void
- {
- auto const arg_store = kstd::make_format_args(args...);
- os::vprint(sink, format.str_view, arg_store.args);
- }
-
- //! @qualifier kernel-defined
- //! Format the given string using the given arguments and print it, including a newline, to the currently active
- //! output device.
- //!
- //! @param format The format string
- //! @param args The arguments to use to place in the format string's placeholders.
- template<typename... Args>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- auto println(kstd::format_string<std::type_identity_t<Args>...> format, Args &&... args) -> void
- {
- print(print_sink::stdout, format, std::forward<Args>(args)...);
- print(print_sink::stdout, "\n");
- }
-
- //! @qualifier kernel-defined
- //! Format the given error string using the given arguments and print it, including a newline, to the currently active
- //! output device.
- //!
- //! @param format The format string
- //! @param args The arguments
- template<typename... Args>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- auto println(print_sink sink, kstd::format_string<std::type_identity_t<Args>...> format, Args &&... args) -> void
- {
- print(sink, format, std::forward<Args>(args)...);
- print(sink, "\n");
- }
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/ranges b/libs/kstd/include/kstd/ranges
deleted file mode 100644
index 78c3adb..0000000
--- a/libs/kstd/include/kstd/ranges
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef KSTD_RANGES
-#define KSTD_RANGES
-
-#include <ranges> // IWYU pragma: export
-
-namespace kstd
-{
-#if __glibcxx_ranges_to_container
- using std::from_range;
- using std::from_range_t;
-#else
- struct from_range_t
- {
- explicit from_range_t() = default;
- };
- constexpr auto inline from_range = from_range_t{};
-#endif
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/stack b/libs/kstd/include/kstd/stack
deleted file mode 100644
index 02e44ea..0000000
--- a/libs/kstd/include/kstd/stack
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef KSTD_STACK_HPP
-#define KSTD_STACK_HPP
-
-#include <kstd/vector>
-
-#include <initializer_list>
-#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.
- */
- 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>
- 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.
- */
- 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.
- */
- 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.
- */
- 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.
- */
- 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.
- */
- 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>
- 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>
- auto emplace(Args &&... args) -> reference
- {
- _container.emplace_back(std::forward<Args>(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.
- */
- auto pop() -> void
- {
- _container.pop_back();
- }
-
- /**
- * @brief Whether there are currently any items this container or not.
- *
- * @return True if there are no elements, false if there are.
- */
- 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/string b/libs/kstd/include/kstd/string
deleted file mode 100644
index e228a04..0000000
--- a/libs/kstd/include/kstd/string
+++ /dev/null
@@ -1,380 +0,0 @@
-#ifndef KSTD_STRING_HPP
-#define KSTD_STRING_HPP
-
-#include <kstd/bits/format/context.hpp>
-#include <kstd/bits/format/formatter.hpp>
-#include <kstd/bits/format/formatter/string_view.hpp>
-#include <kstd/cstring>
-#include <kstd/os/error.hpp>
-#include <kstd/vector>
-
-#include <algorithm>
-#include <concepts>
-#include <cstddef>
-#include <string_view>
-
-namespace kstd
-{
- /**
- * @brief A simple string implementation that owns its data and provides basic operations.
- */
- struct string
- {
- //! The type of the characters contained in this string.
- using value_type = char;
- //! The type of the underlying storage used by this string.
- using storage_type = kstd::vector<value_type>;
- //! The type of all sizes used in and with this string.
- using size_type = std::size_t;
- //! The type of the difference between two iterators.
- using difference_type = std::ptrdiff_t;
- //! The type of references to single values in this string.
- using reference = value_type &;
- //! The type of references to constant single values in this string.
- using const_reference = value_type const &;
- //! The type of pointers to single values in this string.
- using pointer = value_type *;
- //! The type of pointers to constant single values in this string.
- using const_pointer = value_type const *;
- //! The type of iterators into this string.
- using iterator = pointer;
- //! The type of constant iterators into this string.
- using const_iterator = const_pointer;
-
- /**
- * @brief Constructs an empty null-terminated string.
- */
- string()
- : m_storage{value_type{'\0'}}
- {}
-
- /**
- * @brief Constructs a string from a string view by copying the characters into owned storage.
- * @param view The string view to copy the characters from.
- */
- string(std::string_view view)
- : string()
- {
- append(view);
- }
-
- /**
- * @brief Constructs a string from a null-terminated C-style string by copying the characters into owned storage.
- * @param c_str The null-terminated C-style string to copy.
- */
- string(char const * c_str)
- : string()
- {
- if (c_str != nullptr)
- {
- append(std::string_view{c_str});
- }
- }
-
- /**
- * @brief Constructs a string containing a single character.
- * @param c The character to copy.
- */
- string(value_type c)
- : string()
- {
- push_back(c);
- }
-
- /**
- * @brief Constructs a string by copying another string.
- * @param other The string to copy.
- */
- constexpr string(string const & other)
- : m_storage{other.m_storage}
- {}
-
- /**
- * @brief Destructs the string.
- */
- constexpr ~string() = default;
-
- /**
- * @brief Assigns the value of another string to this string.
- * @param other The string to assign from.
- * @return A reference to this string.
- */
- constexpr auto operator=(string const & other) -> string & = default;
-
- /**
- * @brief Returns the number of characters in this string, not including the null terminator.
- */
- [[nodiscard]] constexpr auto size() const noexcept -> size_type
- {
- return m_storage.empty() ? 0 : m_storage.size() - 1;
- }
-
- /**
- * @brief Checks if this string is empty, not including the null terminator.
- */
- [[nodiscard]] constexpr auto empty() const noexcept -> bool
- {
- return size() == 0;
- }
-
- /**
- * @brief Clears the content of the string, resulting in an empty string.
- * The string remains null-terminated after this operation.
- */
- constexpr auto clear() -> void
- {
- m_storage.clear();
- m_storage.push_back(value_type{'\0'});
- }
-
- //! Get a pointer to the underlying storage of the string
- [[nodiscard]] constexpr auto data() noexcept -> pointer
- {
- return m_storage.data();
- }
-
- //! Get a const pointer to the underlying storage of the string
- [[nodiscard]] constexpr auto data() const noexcept -> const_pointer
- {
- return m_storage.data();
- }
-
- //! Get a const pointer to the underlying storage of the string
- [[nodiscard]] constexpr auto c_str() const noexcept -> const_pointer
- {
- return data();
- }
-
- //! Get an iterator to the beginning of the string
- [[nodiscard]] constexpr auto begin() noexcept -> iterator
- {
- return data();
- }
-
- //! Get an const iterator to the beginning of the string
- [[nodiscard]] constexpr auto begin() const noexcept -> const_iterator
- {
- return data();
- }
-
- //! Get an const iterator to the beginning of the string
- [[nodiscard]] constexpr auto cbegin() const noexcept -> const_iterator
- {
- return begin();
- }
-
- //! Get an iterator to the end of the string
- [[nodiscard]] constexpr auto end() noexcept -> iterator
- {
- return data() + size();
- }
-
- //! Get an const iterator to the end of the string
- [[nodiscard]] constexpr auto end() const noexcept -> const_iterator
- {
- return data() + size();
- }
-
- //! Get an const iterator to the end of the string
- [[nodiscard]] constexpr auto cend() const noexcept -> const_iterator
- {
- return end();
- }
-
- //! Get a reference to the first character of the string
- [[nodiscard]] constexpr auto front() -> reference
- {
- return m_storage.front();
- }
-
- //! Get a const reference to the first character of the string
- [[nodiscard]] constexpr auto front() const -> const_reference
- {
- return m_storage.front();
- }
-
- //! Get a reference to the last character of the string
- [[nodiscard]] constexpr auto back() -> reference
- {
- return m_storage[size() - 1];
- }
-
- //! Get a const reference to the last character of the string
- [[nodiscard]] constexpr auto back() const -> const_reference
- {
- return m_storage[size() - 1];
- }
-
- /**
- * @brief Appends a character to the end of the string.
- * @param ch The character to append.
- */
- constexpr auto push_back(value_type ch) -> void
- {
- m_storage.back() = ch;
- m_storage.push_back(value_type{'\0'});
- }
-
- /**
- * @brief Appends a string view to the end of the string by copying the characters into owned storage.
- * @param view The string view to append.
- * @return A reference to this string.
- */
- constexpr auto append(std::string_view view) -> string &
- {
- if (!view.empty())
- {
- std::ranges::for_each(view, [this](auto const ch) { push_back(ch); });
- }
-
- return *this;
- }
-
- /**
- * @brief Appends another string to the end of this string by copying the characters into owned storage.
- * @param other The string to append.
- * @return A reference to this string.
- */
- constexpr auto append(string const & other) -> string &
- {
- return append(other.view());
- }
-
- /**
- * @brief Appends another string to the end of this string by copying the characters into owned storage.
- * @param other The string to append.
- * @return A reference to this string.
- */
- constexpr auto operator+=(string const & other) -> string &
- {
- return append(other);
- }
-
- /**
- * @brief Appends a character to the end of the string.
- * @param ch The character to append.
- * @return A reference to this string.
- */
- constexpr auto operator+=(value_type ch) -> string &
- {
- push_back(ch);
- return *this;
- }
-
- /**
- * @brief Returns a string view of this string, which is a non-owning view into the characters of this string.
- */
- [[nodiscard]] constexpr auto view() const noexcept -> std::string_view
- {
- return std::string_view{data(), size()};
- }
-
- private:
- //! The underlying storage of the string, which owns the characters and ensures null-termination.
- storage_type m_storage{};
- };
-
- /**
- * @brief Concatenates a strings and a character and returns the result as a new string.
- * @param lhs The string to concatenate.
- * @param rhs The string to concatenate.
- * @return A new string that is the result of concatenating @p lhs and @p rhs.
- */
- [[nodiscard]] constexpr auto inline operator+(string const & lhs, string const & rhs) -> string
- {
- string result{lhs};
- result += rhs;
- return result;
- }
-
- /**
- * @brief Converts an unsigned integer to a string by converting each digit to the corresponding character and
- * concatenating them.
- * @tparam N The type of the unsigned integer to convert.
- * @param value The unsigned integer to convert.
- * @return A string representation of the given unsigned integer.
- */
- template<typename N>
- requires std::unsigned_integral<N>
- [[nodiscard]] constexpr auto inline to_string(N value) -> string
- {
- if (value == 0)
- {
- return "0";
- }
-
- string result;
-
- while (value > 0)
- {
- char const digit = '0' + (value % 10);
- result.push_back(digit);
- value /= 10;
- }
-
- std::reverse(result.begin(), result.end());
- return result;
- }
-
- [[nodiscard]] constexpr auto inline operator==(string const & lhs, string const & rhs) -> bool
- {
- return lhs.view() == rhs.view();
- }
-
- [[nodiscard]] constexpr auto inline operator!=(string const & lhs, string const & rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] constexpr auto inline operator==(string const & lhs, std::string_view rhs) -> bool
- {
- return lhs.view() == rhs;
- }
-
- [[nodiscard]] constexpr auto inline operator!=(string const & lhs, std::string_view rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] constexpr auto inline operator==(std::string_view lhs, string const & rhs) -> bool
- {
- return lhs == rhs.view();
- }
-
- [[nodiscard]] constexpr auto inline operator!=(std::string_view lhs, string const & rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] constexpr auto inline operator==(string const & lhs, char const * rhs) -> bool
- {
- return lhs.view() == std::string_view{rhs};
- }
-
- [[nodiscard]] constexpr auto inline operator!=(string const & lhs, char const * rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] constexpr auto inline operator==(char const * lhs, string const & rhs) -> bool
- {
- return std::string_view{lhs} == rhs.view();
- }
-
- [[nodiscard]] constexpr auto inline operator!=(char const * lhs, string const & rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- template<>
- struct formatter<string> : formatter<std::string_view>
- {
- auto format(string const & str, format_context & context) const -> void
- {
- formatter<std::string_view>::format(str.view(), context);
- }
- };
-
-} // namespace kstd
-
-#endif \ No newline at end of file
diff --git a/libs/kstd/include/kstd/units b/libs/kstd/include/kstd/units
deleted file mode 100644
index df5eb37..0000000
--- a/libs/kstd/include/kstd/units
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef KSTD_UNITS_HPP
-#define KSTD_UNITS_HPP
-
-#include <compare>
-#include <concepts>
-#include <cstddef>
-
-namespace kstd
-{
-
- //! A basic template for strongly typed units.
- template<typename ValueType, typename Tag>
- struct basic_unit
- {
- using value_type = ValueType;
-
- constexpr basic_unit() noexcept
- : value{}
- {}
-
- explicit constexpr basic_unit(value_type value) noexcept
- : value{value}
- {}
-
- explicit constexpr operator value_type() const noexcept
- {
- return value;
- }
-
- constexpr auto operator+(basic_unit const & other) const noexcept -> basic_unit
- {
- return basic_unit{value + other.value};
- }
-
- constexpr auto operator+=(basic_unit const & other) noexcept -> basic_unit &
- {
- return *this = *this + other;
- }
-
- constexpr auto operator-(basic_unit const & other) const noexcept -> basic_unit
- {
- return basic_unit{value - other.value};
- }
-
- constexpr auto operator-=(basic_unit const & other) noexcept -> basic_unit &
- {
- return *this = *this - other;
- }
-
- constexpr auto operator*(std::integral auto factor) noexcept -> basic_unit
- {
- return basic_unit{value * factor};
- }
-
- constexpr auto operator*=(std::integral auto factor) noexcept -> basic_unit
- {
- return *this = *this * factor;
- }
-
- constexpr auto operator/(std::integral auto divisor) noexcept -> basic_unit
- {
- return basic_unit{value / divisor};
- }
-
- constexpr auto operator/=(std::integral auto divisor) noexcept -> basic_unit
- {
- return *this = *this / divisor;
- }
-
- constexpr auto operator/(basic_unit const & other) const noexcept
- {
- return value / other.value;
- }
-
- constexpr auto operator<=>(basic_unit const & other) const noexcept -> std::strong_ordering = default;
-
- value_type value;
- };
-
- template<std::integral Factor, typename ValueType, typename Tag>
- constexpr auto operator*(Factor factor, basic_unit<ValueType, Tag> const & unit) noexcept
- -> basic_unit<ValueType, Tag>
- {
- return basic_unit<ValueType, Tag>{unit.value * factor};
- }
-
- namespace units
- {
- using bytes = basic_unit<std::size_t, struct bytes_tag>;
-
- constexpr auto KiB(std::size_t value) noexcept -> bytes
- {
- return bytes{value * 1024};
- }
-
- constexpr auto MiB(std::size_t value) noexcept -> bytes
- {
- return bytes{value * 1024 * 1024};
- }
-
- constexpr auto GiB(std::size_t value) noexcept -> bytes
- {
- return bytes{value * 1024 * 1024 * 1024};
- }
-
- template<typename ValueType>
- constexpr auto operator+(ValueType * pointer, bytes offset) -> ValueType *
- {
- return pointer + offset.value;
- }
-
- } // namespace units
-
- namespace units_literals
- {
- constexpr auto operator""_B(unsigned long long value) noexcept -> units::bytes
- {
- return units::bytes{value};
- }
-
- constexpr auto operator""_KiB(unsigned long long value) noexcept -> units::bytes
- {
- return units::KiB(value);
- }
-
- constexpr auto operator""_MiB(unsigned long long value) noexcept -> units::bytes
- {
- return units::MiB(value);
- }
-
- constexpr auto operator""_GiB(unsigned long long value) noexcept -> units::bytes
- {
- return units::GiB(value);
- }
-
- } // namespace units_literals
-
- template<typename ValueType>
- constexpr auto object_size(ValueType const &) -> units::bytes
- {
- return units::bytes{sizeof(ValueType)};
- }
-
- template<typename T>
- constexpr auto type_size = units::bytes{sizeof(T)};
-
-} // namespace kstd
-
-#endif
diff --git a/libs/kstd/include/kstd/vector b/libs/kstd/include/kstd/vector
deleted file mode 100644
index c714957..0000000
--- a/libs/kstd/include/kstd/vector
+++ /dev/null
@@ -1,1154 +0,0 @@
-#ifndef KSTD_VECTOR_HPP
-#define KSTD_VECTOR_HPP
-
-#include <kstd/allocator>
-#include <kstd/bits/concepts.hpp>
-#include <kstd/os/error.hpp>
-#include <kstd/ranges>
-
-#include <algorithm>
-#include <concepts>
-#include <cstddef>
-#include <initializer_list>
-#include <iterator>
-#include <memory>
-#include <ranges>
-#include <type_traits>
-#include <utility>
-
-namespace kstd
-{
- //! A resizable, contiguous container.
- //!
- //! @tparam ValueType The type of values contained in this vector.
- //! @tparam Allocator The type of allocator used for memory management by this container.
- template<typename ValueType, typename Allocator = kstd::allocator<ValueType>>
- struct vector
- {
- //! The type of the elements contained in this vector.
- using value_type = ValueType;
- //! The allocator used by this vector for memory management.
- using allocator_type = Allocator;
- //! The type of all sizes used in and with this vector.
- using size_type = std::size_t;
- //! The type of the difference between two iterators.
- using difference_type = std::ptrdiff_t;
- //! The type of references to elements in this vector.
- using reference = value_type &;
- //! The type of references to constant elements in this vector.
- using const_reference = value_type const &;
- //! The type of pointers to elements in this vector.
- using pointer = std::allocator_traits<allocator_type>::pointer;
- //! The type of pointers to constant elements in this vector.
- using const_pointer = std::allocator_traits<allocator_type>::const_pointer;
- //! The type of iterators into this container.
- using iterator = pointer;
- //! The type of constant iterators into this container.
- using const_iterator = const_pointer;
- //! The type of reverse iterators into this container.
- using reverse_iterator = std::reverse_iterator<iterator>;
- //! The type of constant reverse iterators into this container.
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
-
- //! Construct a new, empty vector.
- constexpr vector() noexcept(std::is_nothrow_default_constructible_v<allocator_type>)
- : vector(allocator_type{})
- {}
-
- //! Construct a new, empty vector with a given allocator.
- //!
- //! @param allocator The allocator to use in the vector.
- explicit constexpr vector(allocator_type const & allocator) noexcept(
- std::is_nothrow_copy_constructible_v<allocator_type>)
- : m_allocator{allocator}
- , m_size{0}
- , m_capacity{0}
- , m_data{allocate_n(m_capacity)}
- {}
-
- //! Construct a new vector and fill it with the given number of default constructed elements.
- //!
- //! @param count The number of element to create the vector with.
- //! @param allocator The allocator to use in the vector.
- explicit constexpr vector(size_type count, allocator_type const & allocator = allocator_type{}) noexcept(
- std::is_nothrow_copy_constructible_v<allocator_type>)
- : m_allocator{allocator}
- , m_size{count}
- , m_capacity{count}
- , m_data{allocate_n(m_capacity)}
- {
- for (auto i = 0uz; i < count; ++i)
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, m_data + i);
- }
- }
-
- //! Construct a new vector and fill it with the given number of copy constructed elements.
- //!
- //! @param count The number of element to create the vector with.
- //! @param value The value to copy for each element
- //! @param allocator The allocator to use in the vector.
- constexpr vector(size_type count, const_reference value,
- allocator_type const & allocator =
- allocator_type{}) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : m_allocator{allocator}
- , m_size{count}
- , m_capacity{m_size}
- , m_data{allocate_n(m_capacity)}
- {
- for (auto i = 0uz; i < count; ++i)
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, m_data + i, value);
- }
- }
-
- //! Construct a new vector and initialize it's content by copying all elements in the given range.
- //!
- //! @tparam ForwardIterator An iterator type used to describe the source range.
- //! @param first The start of the source range.
- //! @param last The end of the source range.
- template<std::forward_iterator ForwardIterator>
- constexpr vector(ForwardIterator first, ForwardIterator last,
- allocator_type const & allocator =
- allocator_type{}) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : m_allocator{allocator}
- , m_size{static_cast<std::size_t>(std::ranges::distance(first, last))}
- , m_capacity{m_size}
- , m_data{allocate_n(m_capacity)}
- {
- for (auto destination = m_data; first != last; ++first, ++destination)
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, destination, *first);
- }
- }
-
- //! Construct a new vector and initialize it's content by copying all elements in the given range.
- //!
- //! @tparam InputIterator An iterator type used to describe the source range.
- //! @param first The start of the source range.
- //! @param last The end of the source range.
- template<std::input_iterator InputIterator>
- constexpr vector(InputIterator first, InputIterator last,
- allocator_type const & allocator =
- allocator_type{}) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : m_allocator{allocator}
- , m_size{0}
- , m_capacity{0}
- , m_data{}
- {
- while (first != last)
- {
- emplace_back(*first);
- ++first;
- }
- }
-
- //! Construct a new vector and initialize it's content by copying all elements in the given range.
- //!
- //!
- template<typename Range>
- requires((std::ranges::forward_range<Range> || std::ranges::sized_range<Range>) &&
- kstd::bits::container_compatible_range<Range, value_type>)
- constexpr vector(kstd::from_range_t, Range && range, allocator_type const & allocator = allocator_type{})
- : m_allocator{allocator}
- , m_size{std::ranges::size(range)}
- , m_capacity{m_size}
- , m_data{allocate_n(m_capacity)}
- {
- auto destination = m_data;
- for (auto && element : std::forward<Range>(range))
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, destination++,
- std::forward<std::ranges::range_reference_t<Range>>(element));
- }
- }
-
- //! Construct a new vector and initialize it's content by copying all elements from a given vector.
- //!
- //! @param other The source vector.
- constexpr vector(vector const & other)
- : m_allocator{other.m_allocator}
- , m_size{other.m_size}
- , m_capacity{other.m_capacity}
- , m_data(allocate_n(m_capacity))
- {
- uninitialized_copy_with_allocator(other.begin(), begin(), other.size());
- }
-
- //! Construct a new vector and initialize it's content by moving from a given vector.
- //!
- //! @param other The source vector.
- constexpr vector(vector && other) noexcept
- : m_allocator{std::move(other.m_allocator)}
- , m_size{std::exchange(other.m_size, size_type{})}
- , m_capacity(std::exchange(other.m_capacity, size_type{}))
- , m_data(std::exchange(other.m_data, nullptr))
- {}
-
- //! Construct a new vector and initialize it's content by copying from a given vector.
- //!
- //! @param other The source vector.
- //! @param allocator The allocator to use in the vector.
- constexpr vector(vector const & other, std::type_identity_t<Allocator> const & allocator)
- : m_allocator{allocator}
- , m_size{other.m_size}
- , m_capacity{other.m_capacity}
- , m_data{allocate_n(m_capacity)}
- {
- uninitialized_copy_with_allocator(other.begin(), begin(), other.size());
- }
-
- //! Construct a new vector and initialize it's content by copying from a given vector.
- //!
- //! @param other The source vector.
- //! @param allocator The allocator to use in the vector.
- constexpr vector(vector && other, std::type_identity_t<Allocator> const & allocator)
- : m_allocator{allocator}
- , m_size{}
- , m_capacity{}
- , m_data{}
- {
- if constexpr (!std::allocator_traits<allocator_type>::is_always_equal::value)
- {
- if (m_allocator != other.m_allocator)
- {
- m_capacity = other.size();
- m_data = allocate_n(capacity());
- m_size = other.size();
- uninitialized_move_with_allocator(other.begin(), begin(), other.size());
- other.clear();
- return;
- }
- }
- m_size = std::exchange(other.m_size, size_type{});
- m_capacity = std::exchange(other.m_capacity, size_type{});
- m_data = std::exchange(other.m_data, nullptr);
- }
-
- //! Construct a new vector and initialize it's content by copying all elements in the given initializer list.
- //!
- //! @param list The initializer list containing the source objects.
- vector(std::initializer_list<value_type> list, allocator_type const & allocator = allocator_type{})
- : vector{std::ranges::begin(list), std::ranges::end(list), allocator}
- {}
-
- //! Destroy this vector.
- constexpr ~vector()
- {
- clear_and_deallocate();
- }
-
- //! Replace the contents of this vector by the copying from the given source vector.
- //!
- //! @param other The source vector.
- constexpr auto operator=(vector const & other) -> vector &
- {
- if (this == std::addressof(other))
- {
- return *this;
- }
-
- if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value)
- {
- if (get_allocator() != other.get_allocator())
- {
- clear_and_deallocate();
- }
- m_allocator = other.get_allocator();
- }
-
- if (capacity() >= other.size())
- {
- auto const overlap = std::min(m_size, other.m_size);
- std::ranges::copy(other.begin(), other.begin() + overlap, begin());
-
- if (m_size < other.m_size)
- {
- uninitialized_copy_with_allocator(other.begin() + size(), begin() + size(), other.m_size - size());
- }
- else if (m_size > other.m_size)
- {
- destroy_n(begin() + other.size(), size() - other.size());
- }
- }
- else
- {
- auto new_data = allocate_n(other.size());
- uninitialized_copy_with_allocator(other.begin(), new_data, other.size());
- clear_and_deallocate();
- m_data = new_data;
- m_capacity = other.size();
- }
-
- m_size = other.size();
- return *this;
- }
-
- //! Replace the contents fo this vector by moving from the given source.
- //!
- //! @param other The source vector.
- constexpr auto operator=(vector && other) noexcept(
- std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value ||
- std::allocator_traits<allocator_type>::is_always_equal::value) -> vector &
- {
- using std::swap;
-
- if (this == std::addressof(other))
- {
- return *this;
- }
-
- if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
- {
- clear_and_deallocate();
- swap(m_allocator, other.m_allocator);
- swap(m_size, other.m_size);
- swap(m_capacity, other.m_capacity);
- swap(m_data, other.m_data);
- }
- else if (m_allocator == other.m_allocator)
- {
- clear_and_deallocate();
- swap(m_size, other.m_size);
- swap(m_capacity, other.m_capacity);
- swap(m_data, other.m_data);
- }
- else
- {
- if (capacity() >= other.size())
- {
- auto const overlap = std::min(size(), other.size());
- std::ranges::move(other.begin(), other.begin() + overlap, begin());
-
- if (size() < other.size())
- {
- uninitialized_move_with_allocator(other.begin() + size(), begin() + size(), other.size() - size());
- }
- else if (size() > other.size())
- {
- destroy_n(begin() + other.size(), size() - other.size());
- }
- }
- else
- {
- auto new_data = allocate_n(other.size());
- uninitialized_move_with_allocator(other.begin(), new_data, other.size());
- clear_and_deallocate();
- m_data = new_data;
- m_capacity = other.m_size;
- }
-
- other.destroy_n(other.begin(), other.size());
- m_size = std::exchange(other.m_size, size_type{});
- }
-
- return *this;
- }
-
- //! Get a copy of the allocator associated with this vector.
- [[nodiscard]] constexpr auto get_allocator() const noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- -> allocator_type
- {
- return m_allocator;
- }
-
- //! Get a reference to the element at the given index.
- //!
- //! This function will panic if the index is out of bounds for this vector.
- //!
- //! @param index The index of the element to retrieve.
- //! @return A reference to the element at the specified index.
- [[nodiscard]] constexpr auto at(size_type index) -> reference
- {
- panic_if_out_of_bounds(index);
- return (*this)[index];
- }
-
- //! Get a reference to the element at the given index.
- //!
- //! This function will panic if the index is out of bounds for this vector.
- //!
- //! @param index The index of the element to retrieve.
- //! @return A reference to the element at the specified index.
- [[nodiscard]] constexpr auto at(size_type index) const -> const_reference
- {
- panic_if_out_of_bounds(index);
- return (*this)[index];
- }
-
- //! Get a reference to the element at the given index.
- //!
- //! The behavior is undefined if the index is out of bounds for this vector.
- //!
- //! @param index The index of the element to retrieve.
- //! @return A reference to the element at the specified index.
- [[nodiscard]] constexpr auto operator[](size_type index) -> reference
- {
- return data()[index];
- }
-
- //! Get a reference to the element at the given index.
- //!
- //! The behavior is undefined if the index is out of bounds for this vector.
- //!
- //! @param index The index of the element to retrieve.
- //! @return A reference to the element at the specified index.
- [[nodiscard]] constexpr auto operator[](size_type index) const -> const_reference
- {
- return data()[index];
- }
-
- //! Get a reference to the first element of this vector.
- //!
- //! The behavior is undefined if this vector is empty.
- [[nodiscard]] constexpr auto front() -> reference
- {
- return *begin();
- }
-
- //! Get a reference to the first element of this vector.
- //!
- //! The behavior is undefined if this vector is empty.
- [[nodiscard]] constexpr auto front() const -> const_reference
- {
- return *begin();
- }
-
- //! Get a reference to the last element of this vector.
- //!
- //! The behavior is undefined if this vector is empty.
- [[nodiscard]] constexpr auto back() -> reference
- {
- return *rbegin();
- }
-
- //! Get a reference to the last element of this vector.
- //!
- //! The behavior is undefined if this vector is empty.
- [[nodiscard]] constexpr auto back() const -> const_reference
- {
- return *rbegin();
- }
-
- //! Get a pointer to the beginning of the underlying contiguous storage.
- [[nodiscard]] constexpr auto data() noexcept -> pointer
- {
- return m_data;
- }
-
- //! Get a pointer to the beginning of the underlying contiguous storage.
- [[nodiscard]] constexpr auto data() const noexcept -> const_pointer
- {
- return m_data;
- }
-
- //! Get an iterator to the first element of this vector.
- //!
- //! @return An iterator to the first element of this container, or end() if the container is empty.
- [[nodiscard]] constexpr auto begin() noexcept -> iterator
- {
- return empty() ? end() : data();
- }
-
- //! Get an iterator to the first element of this vector.
- //!
- //! @return An iterator to the first element of this container, or end() if the container is empty.
- [[nodiscard]] constexpr auto begin() const noexcept -> const_iterator
- {
- return empty() ? end() : data();
- }
-
- //! Get an iterator to the first element of this vector.
- //!
- //! @return An iterator to the first element of this container, or end() if the container is empty.
- [[nodiscard]] constexpr auto cbegin() const noexcept -> const_iterator
- {
- return begin();
- }
-
- //! Get an iterator past the last element of this vector.
- [[nodiscard]] constexpr auto end() noexcept -> pointer
- {
- return capacity() ? data() + size() : nullptr;
- }
-
- //! Get an iterator past the last element of this vector.
- [[nodiscard]] constexpr auto end() const noexcept -> const_pointer
- {
- return capacity() ? data() + size() : nullptr;
- }
-
- //! Get an iterator past the last element of this vector.
- [[nodiscard]] constexpr auto cend() const noexcept -> const_pointer
- {
- return end();
- }
-
- //! Get a reverse iterator to the reverse beginning.
- [[nodiscard]] constexpr auto rbegin() noexcept -> reverse_iterator
- {
- return empty() ? rend() : reverse_iterator{end()};
- }
-
- //! Get a reverse iterator to the reverse beginning.
- [[nodiscard]] constexpr auto rbegin() const noexcept -> const_reverse_iterator
- {
- return empty() ? rend() : const_reverse_iterator{end()};
- }
-
- //! Get a reverse iterator to the reverse beginning.
- [[nodiscard]] constexpr auto crbegin() const noexcept -> const_reverse_iterator
- {
- return rbegin();
- }
-
- //! Get a reverse iterator to the reverse end.
- [[nodiscard]] constexpr auto rend() noexcept -> reverse_iterator
- {
- return reverse_iterator{begin()};
- }
-
- //! Get a reverse iterator to the reverse end.
- [[nodiscard]] constexpr auto rend() const noexcept -> const_reverse_iterator
- {
- return const_reverse_iterator{begin()};
- }
-
- //! Get a reverse iterator to the reverse end.
- [[nodiscard]] constexpr auto crend() const noexcept -> const_reverse_iterator
- {
- return rend();
- }
-
- //! Check whether this vector is empty.
- [[nodiscard]] constexpr auto empty() const noexcept -> bool
- {
- return !size();
- }
-
- //! Get the number of elements present in this vector.
- [[nodiscard]] constexpr auto size() const noexcept -> size_type
- {
- return m_size;
- }
-
- //! Get the maximum possible number of element for this vector.
- [[nodiscard]] constexpr auto max_size() const noexcept -> size_type
- {
- return std::allocator_traits<allocator_type>::max_size(m_allocator);
- }
-
- //! Reserve storage for at list the given number of elements.
- constexpr auto reserve(size_type new_capacity) -> void
- {
- if (new_capacity <= capacity())
- {
- return;
- }
-
- if (new_capacity > max_size())
- {
- kstd::os::panic("[kstd:vector] Tried to reserve more space than theoretically possible.");
- }
-
- auto new_data = allocate_n(new_capacity);
- auto old_size = size();
- uninitialized_move_with_allocator(begin(), new_data, size());
- clear_and_deallocate();
- m_data = new_data;
- m_capacity = new_capacity;
- m_size = old_size;
- }
-
- //! Resize this vector to contain @p new_size elements.
- constexpr auto resize(size_type new_size) -> void
- {
- resize(new_size, value_type{});
- }
-
- //! Resize this vector to contain @p new_size elements, filling new elements with @p value.
- constexpr auto resize(size_type new_size, const_reference value) -> void
- {
- if (new_size < size())
- {
- destroy_n(begin() + new_size, size() - new_size);
- m_size = new_size;
- return;
- }
-
- if (new_size == size())
- {
- return;
- }
-
- if (new_size > max_size())
- {
- kstd::os::panic("[kstd:vector] Tried to resize more space than theoretically possible.");
- }
-
- if (new_size > capacity())
- {
- reserve(new_size);
- }
-
- for (auto i = size(); i < new_size; ++i)
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, m_data + i, value);
- }
-
- m_size = new_size;
- }
-
- //! Get the number of element this vector has currently space for, including elements currently in this vector.
- [[nodiscard]] constexpr auto capacity() const noexcept -> size_type
- {
- return m_capacity;
- }
-
- //! Try to release unused storage space.
- constexpr auto shrink_to_fit() -> void
- {
- if (m_size == m_capacity)
- {
- return;
- }
-
- auto new_data = allocate_n(m_size);
- auto old_size = size();
- uninitialized_move_with_allocator(begin(), new_data, old_size);
- clear_and_deallocate();
- std::exchange(m_data, new_data);
- m_capacity = old_size;
- m_size = old_size;
- }
-
- //! Clear the contents of this vector.
- constexpr auto clear() noexcept -> void
- {
- destroy_n(begin(), size());
- m_size = 0;
- }
-
- //! Insert an element at a given position.
- //!
- //! @param position The position to insert the element at.
- //! @param value The value to insert.
- //! @return An iterator to the inserted element.
- constexpr auto insert(const_iterator position, value_type const & value) -> iterator
- {
- auto prefix_size = std::ranges::distance(begin(), position);
- auto suffix_size = std::ranges::distance(position, end());
-
- if (position == end())
- {
- push_back(value);
- return begin() + prefix_size;
- }
-
- if (m_capacity == m_size)
- {
- auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
- auto new_data = allocate_n(new_capacity);
- auto old_size = size();
- std::allocator_traits<allocator_type>::construct(m_allocator, new_data + prefix_size, value);
- uninitialized_move_with_allocator(begin(), new_data, prefix_size);
- uninitialized_move_with_allocator(begin() + prefix_size, new_data + prefix_size + 1, suffix_size);
- destroy_n(begin(), old_size);
- deallocate();
- m_data = new_data;
- m_capacity = new_capacity;
- m_size = old_size;
- }
- else if (&value >= begin() && &value < end())
- {
- auto value_copy = value;
- auto insert_position = begin() + prefix_size;
- std::allocator_traits<allocator_type>::construct(m_allocator, end(), std::move(*(end() - 1)));
- std::ranges::move_backward(insert_position, end() - 1, end());
- *insert_position = std::move(value_copy);
- }
- else
- {
- auto insert_position = begin() + prefix_size;
- std::allocator_traits<allocator_type>::construct(m_allocator, end(), std::move(*(end() - 1)));
- std::ranges::move_backward(insert_position, end() - 1, end());
- *insert_position = value;
- }
-
- ++m_size;
- return begin() + prefix_size;
- }
-
- //! Insert an element at a given position.
- //!
- //! @param position The position to insert the element at.
- //! @param value The value to insert.
- //! @return An iterator to the inserted element.
- constexpr auto insert(const_iterator position, value_type && value) -> iterator
- {
- auto prefix_size = std::ranges::distance(begin(), position);
- auto suffix_size = std::ranges::distance(position, end());
-
- if (position == end())
- {
- push_back(std::move(value));
- return begin() + prefix_size;
- }
-
- if (m_capacity == m_size)
- {
- auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
- auto new_data = allocate_n(new_capacity);
- auto old_size = size();
- std::allocator_traits<allocator_type>::construct(m_allocator, new_data + prefix_size, std::move(value));
- uninitialized_move_with_allocator(begin(), new_data, prefix_size);
- uninitialized_move_with_allocator(begin() + prefix_size, new_data + prefix_size + 1, suffix_size);
- destroy_n(begin(), old_size);
- deallocate();
- m_data = new_data;
- m_capacity = new_capacity;
- m_size = old_size;
- }
- else if (&value >= begin() && &value < end())
- {
- auto value_copy = std::move(value);
- auto insert_position = begin() + prefix_size;
- std::allocator_traits<allocator_type>::construct(m_allocator, end(), std::move(*(end() - 1)));
- std::ranges::move_backward(insert_position, end() - 1, end());
- *insert_position = std::move(value_copy);
- }
- else
- {
- auto insert_position = begin() + prefix_size;
- std::allocator_traits<allocator_type>::construct(m_allocator, end(), std::move(*(end() - 1)));
- std::ranges::move_backward(insert_position, end() - 1, end());
- *insert_position = std::move(value);
- }
-
- ++m_size;
- return begin() + prefix_size;
- }
-
- //! Insert the element of a given range into the vector at a given position.
- //!
- //! @param range The source range to insert elements from.
- //! @tparam SourceRange A container compatible range type.
- template<typename SourceRange>
- requires requires(allocator_type allocator, pointer destination, SourceRange range) {
- requires kstd::bits::container_compatible_range<SourceRange, ValueType>;
- requires std::move_constructible<value_type>;
- requires std::is_move_assignable_v<value_type>;
- requires std::swappable<value_type>;
- std::allocator_traits<allocator_type>::construct(allocator, destination, *std::ranges::begin(range));
- }
- // NOLINTNEXTLINE(misc-no-recursion)
- constexpr auto insert_range(const_iterator position, SourceRange && range) -> iterator
- {
- auto prefix_size = std::ranges::distance(begin(), position);
-
- if (position == end())
- {
- append_range(std::forward<SourceRange>(range));
- return begin() + prefix_size;
- }
-
- if constexpr (std::ranges::forward_range<SourceRange> || std::ranges::sized_range<SourceRange>)
- {
- auto number_of_elements = static_cast<size_type>(std::ranges::distance(range));
- if (!number_of_elements)
- {
- return begin() + prefix_size;
- }
-
- if (capacity() - size() < number_of_elements)
- {
- reserve(size() + std::max(size(), number_of_elements));
- }
-
- auto insert_position = begin() + prefix_size;
- auto suffix_size = static_cast<size_type>(std::ranges::distance(insert_position, end()));
-
- if (number_of_elements >= suffix_size)
- {
- uninitialized_move_with_allocator(insert_position, insert_position + number_of_elements, suffix_size);
- auto result = std::ranges::copy_n(std::ranges::begin(range), suffix_size, insert_position);
- uninitialized_copy_with_allocator(std::move(result.in), end(), number_of_elements - suffix_size);
- }
- else
- {
- uninitialized_move_with_allocator(end() - number_of_elements, end(), number_of_elements);
- std::ranges::move_backward(insert_position, end() - number_of_elements, end());
- std::ranges::copy_n(std::ranges::begin(range), number_of_elements, insert_position);
- }
-
- m_size += number_of_elements;
- return insert_position;
- }
-
- auto range_begin = std::ranges::begin(range);
- auto range_end = std::ranges::end(range);
-
- auto remainder = vector{get_allocator()};
- for (; range_begin != range_end; ++range_begin)
- {
- remainder.emplace_back(*static_cast<std::ranges::iterator_t<SourceRange>>(range_begin));
- }
- reserve(size() + std::max(size(), remainder.size()));
-
- return insert_range(begin() + prefix_size, remainder);
- }
-
- template<typename... Args>
- constexpr auto emplace(const_iterator position, Args &&... args) -> iterator
- {
- auto prefix_size = std::ranges::distance(begin(), position);
- auto suffix_size = std::ranges::distance(position, end());
-
- if (position == end())
- {
- emplace_back(std::forward<Args>(args)...);
- return begin() + prefix_size;
- }
-
- if (m_capacity == m_size)
- {
- auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
- auto new_data = allocate_n(new_capacity);
- auto old_size = size();
- std::allocator_traits<allocator_type>::construct(m_allocator, new_data + prefix_size,
- std::forward<Args>(args)...);
- uninitialized_move_with_allocator(begin(), new_data, prefix_size);
- uninitialized_move_with_allocator(begin() + prefix_size, new_data + prefix_size + 1, suffix_size);
- destroy_n(begin(), old_size);
- deallocate();
- m_data = new_data;
- m_capacity = new_capacity;
- m_size = old_size;
- }
- else
- {
- auto insert_position = begin() + prefix_size;
- std::allocator_traits<allocator_type>::construct(m_allocator, end(), std::move(*(end() - 1)));
- std::ranges::move_backward(insert_position, end() - 1, end());
- *insert_position = value_type{std::forward<Args>(args)...};
- }
-
- ++m_size;
- return begin() + prefix_size;
- }
-
- //! Erase an element at a given position.
- //!
- //! @note This function will panic if position == end()
- //!
- //! @param position An interator pointing to the element to delete
- //! @return An iterator pointing to the element after the deleted element
- constexpr auto erase(const_iterator position) -> iterator
- {
- if (position == end())
- {
- os::panic("[kstd:vector] Attempted to erase end()!");
- }
-
- auto prefix_size = std::ranges::distance(cbegin(), position);
-
- std::ranges::move(begin() + prefix_size + 1, end(), begin() + prefix_size);
- std::allocator_traits<allocator_type>::destroy(m_allocator, end() - 1);
- --m_size;
-
- return begin() + prefix_size;
- }
-
- //! Erase a range of elements from this vector.
- //!
- //! @param first The start of the range to erase.
- //! @param last The end of the range to erase.
- //! @return An iterator pointing to the element after the last deleted element.
- constexpr auto erase(const_iterator first, const_iterator last) -> iterator
- {
- if (first == last)
- {
- return begin() + std::ranges::distance(cbegin(), first);
- }
-
- auto prefix_size = std::ranges::distance(cbegin(), first);
- auto element_count = std::ranges::distance(first, last);
-
- std::ranges::move(begin() + prefix_size + element_count, end(), begin() + prefix_size);
- destroy_n(end() - element_count, element_count);
- m_size -= element_count;
-
- return begin() + prefix_size;
- }
-
- //! Append a given element to this vector via copy construction.
- constexpr auto push_back(value_type const & value) -> void
- {
- if (m_capacity == m_size)
- {
- auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
- auto new_data = allocate_n(new_capacity);
- auto old_size = size();
- std::allocator_traits<allocator_type>::construct(m_allocator, new_data + m_size, value);
- uninitialized_move_with_allocator(begin(), new_data, size());
- destroy_n(begin(), size());
- deallocate();
- m_data = new_data;
- m_capacity = new_capacity;
- m_size = old_size;
- }
- else
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, data() + size(), value);
- }
- ++m_size;
- }
-
- //! Append a given element to this vector via move construction.
- constexpr auto push_back(value_type && value) -> void
- {
- if (m_capacity == m_size)
- {
- auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
- auto new_data = allocate_n(new_capacity);
- auto old_size = size();
- std::allocator_traits<allocator_type>::construct(m_allocator, new_data + m_size, std::move(value));
- uninitialized_move_with_allocator(begin(), new_data, size());
- destroy_n(begin(), size());
- deallocate();
- m_data = new_data;
- m_capacity = new_capacity;
- m_size = old_size;
- }
- else
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, data() + size(), std::move(value));
- }
- ++m_size;
- }
-
- //! Append a given element to this vector via direct construction.
- template<class... Args>
- constexpr auto emplace_back(Args &&... args) -> reference
- {
- if (m_capacity == m_size)
- {
- auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
- auto new_data = allocate_n(new_capacity);
- auto old_size = size();
- std::allocator_traits<allocator_type>::construct(m_allocator, new_data + m_size, std::forward<Args>(args)...);
- uninitialized_move_with_allocator(begin(), new_data, size());
- destroy_n(begin(), size());
- deallocate();
- m_data = new_data;
- m_capacity = new_capacity;
- m_size = old_size;
- }
- else
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, data() + size(), std::forward<Args>(args)...);
- }
- ++m_size;
- return this->back();
- }
-
- //! Append the elements of a given range to this vector.
- //!
- //! @param range The range of elements to be appended.
- //! @tparam SourceRange A container compatible range type.
- template<kstd::bits::container_compatible_range<ValueType> SourceRange>
- requires requires(Allocator allocator, pointer destination, SourceRange range) {
- std::allocator_traits<Allocator>::construct(allocator, destination, *std::ranges::begin(range));
- }
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward, misc-no-recursion)
- constexpr auto append_range(SourceRange && range) -> void
- {
- if constexpr (std::ranges::forward_range<SourceRange> || std::ranges::sized_range<SourceRange>)
- {
- auto number_of_elements = static_cast<size_type>(std::ranges::distance(range));
-
- if (!capacity())
- {
- reserve(number_of_elements);
- }
-
- if (capacity() - size() >= number_of_elements)
- {
- uninitialized_copy_with_allocator(std::ranges::begin(range), end(), number_of_elements);
- m_size += number_of_elements;
- return;
- }
-
- auto new_capacity = m_capacity + std::max(size(), number_of_elements);
- auto new_data = allocate_n(new_capacity);
- auto old_size = size();
-
- uninitialized_move_with_allocator(begin(), new_data, size());
- uninitialized_copy_with_allocator(std::ranges::begin(range), new_data + size(), number_of_elements);
- clear_and_deallocate();
- m_data = new_data;
- m_capacity = new_capacity;
- m_size = old_size + number_of_elements;
- return;
- }
-
- auto range_begin = std::ranges::begin(range);
- auto range_end = std::ranges::end(range);
-
- for (auto i = capacity() - size(); i > 0; --i, ++range_begin)
- {
- emplace_back(*range_begin);
- }
-
- if (range_begin == range_end)
- {
- return;
- }
-
- auto remainder = vector{get_allocator()};
- for (; range_begin != range_end; ++range_begin)
- {
- remainder.emplace_back(*static_cast<std::ranges::iterator_t<SourceRange>>(range_begin));
- }
- reserve(size() + std::max(size(), remainder.size()));
- append_range(remainder);
- }
-
- //! Remove the last element of this vector.
- //!
- //! If this vector is empty, the behavior is undefined.
- constexpr auto pop_back() -> void
- {
- --m_size;
- std::allocator_traits<allocator_type>::destroy(m_allocator, data() + size());
- }
-
- private:
- //! Use the allocator of this vector to allocate enough space for the given number of elements.
- //!
- //! @param count The number of elements to allocate space for.
- [[nodiscard]] constexpr auto allocate_n(std::size_t count) -> std::allocator_traits<allocator_type>::pointer
- {
- if (count)
- {
- return std::allocator_traits<allocator_type>::allocate(m_allocator, count);
- }
- return nullptr;
- }
-
- //! Clear this vector and release it's memory.
- constexpr auto clear_and_deallocate() -> void
- {
- clear();
- deallocate();
- }
-
- //! Release the memory of this vector.
- constexpr auto deallocate()
- {
- if (m_data)
- {
- std::allocator_traits<allocator_type>::deallocate(m_allocator, m_data, m_capacity);
- m_capacity = 0;
- m_size = 0;
- m_data = nullptr;
- }
- }
-
- //! Destroy a number of elements in this vector.
- //!
- //! @param first The start of the range of the elements to be destroyed.
- //! @param count The number of elements to destroy.
- constexpr auto destroy_n(iterator first, std::size_t count) -> void
- {
- std::ranges::for_each(first, first + count, [&](auto & element) {
- std::allocator_traits<allocator_type>::destroy(m_allocator, std::addressof(element));
- });
- }
-
- //! Panic the kernel if the given index is out of bounds.
- //!
- //! @param index The index to check.
- constexpr auto panic_if_out_of_bounds(size_type index) const -> void
- {
- if (index >= m_size)
- {
- os::panic("[kstd:vector] Attempted to read element at invalid index");
- }
- }
-
- //! Copy a number of elements from a source range into the uninitialized destination range inside this vector.
- //!
- //! @param from The start of the source range.
- //! @param to The start of the target range inside this vector.
- //! @param count The number of elements to copy
- template<typename SourceIterator>
- constexpr auto uninitialized_copy_with_allocator(SourceIterator from, iterator to, size_type count)
- {
- for (auto i = 0uz; i < count; ++i)
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, to++, *from++);
- }
- }
-
- //! Move a number of elements from a source range into the uninitialized destination range inside this vector.
- //!
- //! @param from The start of the source range.
- //! @param to The start of the target range inside this vector.
- //! @param count The number of elements to copy
- template<typename SourceIterator>
- constexpr auto uninitialized_move_with_allocator(SourceIterator from, iterator to, size_type count)
- {
- for (auto i = 0uz; i < count; ++i)
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, to++, std::move(*from++));
- }
- }
-
- //! The allocator used by this vector.
- [[no_unique_address]] allocator_type m_allocator{};
-
- //! The number of elements in this vector.
- size_type m_size{};
-
- //! The number of elements this vector has room for.
- size_type m_capacity{};
-
- //! The pointer to the start of the memory managed by this vector.
- value_type * m_data{};
- };
-
- //! Check if the content of two vectors is equal.
- template<typename ValueType, typename Allocator>
- constexpr auto operator==(vector<ValueType, Allocator> const & lhs, vector<ValueType, Allocator> const & rhs) -> bool
- {
- return std::ranges::equal(lhs, rhs);
- }
-
- //! Perform a lexicographical comparison of the content of two vectors.
- template<typename ValueType, typename Allocator>
- constexpr auto operator<=>(vector<ValueType, Allocator> const & lhs, vector<ValueType, Allocator> const & rhs)
- -> decltype(std::declval<ValueType const &>() <=> std::declval<ValueType const &>())
- {
- return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
-
- //! Deduction guide for vector construction from an interator pair.
- template<std::forward_iterator ForwardIterator,
- typename Allocator = kstd::allocator<typename std::iterator_traits<ForwardIterator>::value_type>>
- vector(ForwardIterator, ForwardIterator, Allocator = Allocator())
- -> vector<typename std::iterator_traits<ForwardIterator>::value_type, Allocator>;
-
- //! Deduction guide for vector construction from an interator pair.
- template<std::input_iterator InputIterator,
- typename Allocator = kstd::allocator<typename std::iterator_traits<InputIterator>::value_type>>
- vector(InputIterator, InputIterator, Allocator = Allocator())
- -> vector<typename std::iterator_traits<InputIterator>::value_type, Allocator>;
-
- //! Deduction guide for vector construction from a range.
- template<std::ranges::input_range Range, typename Allocator = kstd::allocator<std::ranges::range_value_t<Range>>>
- vector(kstd::from_range_t, Range &&, Allocator = Allocator()) -> vector<std::ranges::range_value_t<Range>, Allocator>;
-
-} // namespace kstd
-
-#endif