Luna/libluna/include/luna/Alignment.h
apio 77887eed80
All checks were successful
continuous-integration/drone/push Build is passing
luna -> libluna
2023-02-27 15:22:39 +01:00

54 lines
1.7 KiB
C++

#pragma once
#include <luna/TypeTraits.h>
#include <luna/Types.h>
// Must ALWAYS be called with a power of two as alignment.
template <usize alignment, typename T> constexpr T is_aligned(T value)
{
static_assert(IsPowerOfTwo<usize, alignment>);
return (value % alignment == 0);
}
static_assert(is_aligned<512>(1024u));
static_assert(!is_aligned<32>(235u));
static_assert(is_aligned<4096>(40960u));
// Must ALWAYS be called with a power of two as alignment.
template <usize alignment, typename T> constexpr T align_down(T value)
{
static_assert(IsPowerOfTwo<usize, alignment>);
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);
// Must ALWAYS be called with a power of two as alignment.
template <usize alignment, typename T> constexpr 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 T* offset_ptr(T* ptr, Offset offset)
{
return (T*)((u8*)ptr + offset);
}