aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-18 17:18:37 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-18 17:18:37 +0100
commite7ccb96aecae7b231fb05818d7e45a767aebc31d (patch)
tree68f7a623018d025b3fb6d10ce49d022242cc14f2 /libs
parent12c0586ee15cadfa178e6982dc0f76b047cb2df9 (diff)
downloadteachos-e7ccb96aecae7b231fb05818d7e45a767aebc31d.tar.xz
teachos-e7ccb96aecae7b231fb05818d7e45a767aebc31d.zip
kstd: introduce strong type for memory amounts
Diffstat (limited to 'libs')
-rw-r--r--libs/kstd/include/kstd/units145
-rw-r--r--libs/multiboot2/CMakeLists.txt1
-rw-r--r--libs/multiboot2/include/multiboot2/information.hpp16
-rw-r--r--libs/multiboot2/include/multiboot2/information/data.hpp31
4 files changed, 186 insertions, 7 deletions
diff --git a/libs/kstd/include/kstd/units b/libs/kstd/include/kstd/units
new file mode 100644
index 0000000..f6dcdb1
--- /dev/null
+++ b/libs/kstd/include/kstd/units
@@ -0,0 +1,145 @@
+#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;
+
+ 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 \ No newline at end of file
diff --git a/libs/multiboot2/CMakeLists.txt b/libs/multiboot2/CMakeLists.txt
index 350a996..b306b66 100644
--- a/libs/multiboot2/CMakeLists.txt
+++ b/libs/multiboot2/CMakeLists.txt
@@ -20,6 +20,7 @@ target_include_directories("multiboot2" INTERFACE
target_link_libraries("multiboot2" INTERFACE
"libs::elf"
+ "libs::kstd"
)
set_target_properties("multiboot2" PROPERTIES
diff --git a/libs/multiboot2/include/multiboot2/information.hpp b/libs/multiboot2/include/multiboot2/information.hpp
index fbd534c..d2fac2e 100644
--- a/libs/multiboot2/include/multiboot2/information.hpp
+++ b/libs/multiboot2/include/multiboot2/information.hpp
@@ -5,11 +5,12 @@
#include "information/iterator.hpp" // IWYU pragma: export
#include "information/tag.hpp" // IWYU pragma: export
+#include <kstd/units>
+
#include <elf/format.hpp>
#include <elf/section_header.hpp>
#include <algorithm>
-#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <optional>
@@ -119,7 +120,12 @@ namespace multiboot2
*/
[[nodiscard]] auto string() const noexcept -> std::string_view
{
- return {data(), size()};
+ return {data(), vla_tag::size()};
+ }
+
+ [[nodiscard]] constexpr auto size() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{end_address - start_address};
}
};
@@ -130,9 +136,9 @@ namespace multiboot2
using pointer = iterator::pointer;
using reference = iterator::reference;
- [[nodiscard]] auto size_bytes() const noexcept -> std::size_t
+ [[nodiscard]] auto size() const noexcept -> kstd::units::bytes
{
- return m_size;
+ return kstd::units::bytes{m_size};
}
// Range access
@@ -190,7 +196,7 @@ namespace multiboot2
{
return get<multiboot2::elf_symbols<Format>>().and_then(
[](auto x) -> std::optional<multiboot2::elf_symbols<Format>> {
- if (x.entry_size == elf::section_header_size<Format>)
+ if (x.entry_size_in_B == elf::section_header_size<Format>)
{
return std::optional{x};
}
diff --git a/libs/multiboot2/include/multiboot2/information/data.hpp b/libs/multiboot2/include/multiboot2/information/data.hpp
index 9fa6d5b..3b07d20 100644
--- a/libs/multiboot2/include/multiboot2/information/data.hpp
+++ b/libs/multiboot2/include/multiboot2/information/data.hpp
@@ -6,6 +6,8 @@
#include "multiboot2/constants/information_id.hpp"
#include "multiboot2/constants/memory_type.hpp"
+#include <kstd/units>
+
#include <cstdint>
namespace multiboot2
@@ -27,6 +29,16 @@ namespace multiboot2
//! loader.
struct basic_memory : tag_data<information_id::basic_memory_information>
{
+ [[nodiscard]] constexpr auto lower() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{lower_KiB * 1024};
+ }
+
+ [[nodiscard]] constexpr auto upper() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{upper_KiB * 1024};
+ }
+
//! The amount of lower memory available to the system.
//!
//! Any memory below the 1 MiB address boundary is considered to be lower memory. The maximum possible value for
@@ -72,11 +84,16 @@ namespace multiboot2
//! time. The array begins after the last member of this structure.
struct elf_symbols : tag_data<information_id::elf_sections>
{
+ [[nodiscard]] constexpr auto entry_size() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{entry_size_in_B};
+ }
+
//! The number of section header table entries.
std::uint32_t count;
//! The size of each section header table entry.
- std::uint32_t entry_size;
+ std::uint32_t entry_size_in_B;
//! The section number of the string table containing the section names.
std::uint32_t string_table_index;
@@ -102,6 +119,11 @@ namespace multiboot2
return type == memory_type::available;
}
+ [[nodiscard]] constexpr auto size() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{size_in_B};
+ }
+
//! The physical start address of this region
std::uint64_t base;
@@ -117,11 +139,16 @@ namespace multiboot2
std::uint32_t : 0;
};
+ [[nodiscard]] constexpr auto entry_size() const noexcept -> kstd::units::bytes
+ {
+ return kstd::units::bytes{entry_size_in_B};
+ }
+
//! The size of each entry present in the map.
//!
//! This field is present to allow for future extension of the entry format. Each entry's size is guaranteed to
//! always be an integer multiple of 8.
- std::uint32_t entry_size;
+ std::uint32_t entry_size_in_B;
//! The version of each entry present in the map
std::uint32_t entry_version;