#pragma once #include <luna/TypeTraits.h> #include <luna/Types.h> template <usize alignment, typename T> constexpr inline T is_aligned(T value) { return (value % alignment == 0); } static_assert(is_aligned<512>(1024u)); static_assert(!is_aligned<32>(235u)); static_assert(is_aligned<4096>(40960u)); template <usize alignment, typename T> constexpr inline T align_down(T value) { return value - value % alignment; } static_assert(align_down<512>(598ul) == 512ul); static_assert(align_down<64>(194ul) == 192ul); static_assert(align_down<32>(64ul) == 64ul); template <usize alignment, typename T> constexpr inline T align_up(T value) { if (is_aligned<alignment>(value)) return value; return align_down<alignment>(value) + alignment; } static_assert(align_up<512>(598ul) == 1024ul); static_assert(align_up<64>(194ul) == 256ul); static_assert(align_up<32>(64ul) == 64ul); template <typename T> constexpr T get_blocks_from_size(T value, T block_size) { return (value + (block_size - 1)) / block_size; } static_assert(get_blocks_from_size(40960, 4096) == 10); static_assert(get_blocks_from_size(194, 64) == 4); static_assert(get_blocks_from_size(2, 32) == 1); static_assert(get_blocks_from_size(0, 256) == 0); // Offset a pointer by exactly <offset> bytes, no matter the type. Useful to avoid the quirks that come from C pointer // arithmetic. template <typename T, typename Offset> constexpr inline T* offset_ptr(T* ptr, Offset offset) { return (T*)((u8*)ptr + offset); }