aboutsummaryrefslogtreecommitdiff
path: root/libs/kstd/include
diff options
context:
space:
mode:
Diffstat (limited to 'libs/kstd/include')
-rw-r--r--libs/kstd/include/kstd/units145
1 files changed, 145 insertions, 0 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