libluna: Document Alignment.h

This commit is contained in:
apio 2023-08-23 11:04:05 +02:00
parent a35ca0b367
commit e247310ded
Signed by: apio
GPG Key ID: B8A7D06E42258954

View File

@ -1,37 +1,70 @@
/**
* @file Alignment.h
* @author apio (cloudapio.eu)
* @brief Functions to align addresses and sizes to specified boundaries.
*
* @copyright Copyright (c) 2022-2023, the Luna authors.
*
*/
#pragma once #pragma once
#include <luna/TypeTraits.h>
#include <luna/Types.h> #include <luna/Types.h>
template <usize alignment, typename T> constexpr inline T is_aligned(T value) /**
* @brief Check whether a value is aligned to a specific alignment.
*
* @tparam alignment The alignment to use. It must be provided as a template parameter to help the compiler with
* optimizations. For best results, use a power of two.
* @tparam T The type of the value.
* @param value The value to check.
* @return constexpr bool Whether the value is aligned.
*/
template <usize alignment, typename T> constexpr inline bool is_aligned(T value)
{ {
return (value % alignment == 0); return (value % alignment == 0);
} }
static_assert(is_aligned<512>(1024u)); /**
static_assert(!is_aligned<32>(235u)); * @brief Find the closest aligned value that is smaller than the value provided.
static_assert(is_aligned<4096>(40960u)); *
* @tparam alignment The alignment to use. It must be provided as a template parameter to help the compiler with
* optimizations. For best results, use a power of two.
* @tparam T The type of the value.
* @param value The value to use.
* @return constexpr T The aligned value.
*/
template <usize alignment, typename T> constexpr inline T align_down(T value) template <usize alignment, typename T> constexpr inline T align_down(T value)
{ {
return value - value % alignment; return value - value % alignment;
} }
static_assert(align_down<512>(598ul) == 512ul); /**
static_assert(align_down<64>(194ul) == 192ul); * @brief Find the closest aligned value that is bigger than the value provided.
static_assert(align_down<32>(64ul) == 64ul); *
* @tparam alignment The alignment to use. It must be provided as a template parameter to help the compiler with
* optimizations. For best results, use a power of two.
* @tparam T The type of the value.
* @param value The value to use.
* @return constexpr T The aligned value.
*/
template <usize alignment, typename T> constexpr inline T align_up(T value) template <usize alignment, typename T> constexpr inline T align_up(T value)
{ {
if (is_aligned<alignment>(value)) return value; if (is_aligned<alignment>(value)) return value;
return align_down<alignment>(value) + alignment; return align_down<alignment>(value) + alignment;
} }
static_assert(align_up<512>(598ul) == 1024ul); /**
static_assert(align_up<64>(194ul) == 256ul); * @brief Offset a pointer by exactly <offset> bytes, no matter the type.
static_assert(align_up<32>(64ul) == 64ul); *
* Generally only useful for pointers to void (or char), because breaking other pointers' alignments is not a good
// Offset a pointer by exactly <offset> bytes, no matter the type. Useful to avoid the quirks that come from C pointer * idea...
// arithmetic. *
* @tparam T The underlying type of the pointer.
* @tparam Offset The type of the offset.
* @param ptr The pointer to offset.
* @param offset The offset to use (depending on the type, this could be negative).
* @return constexpr T* The new pointer.
*/
template <typename T, typename Offset> constexpr inline T* offset_ptr(T* ptr, Offset offset) template <typename T, typename Offset> constexpr inline T* offset_ptr(T* ptr, Offset offset)
{ {
return (T*)((u8*)ptr + offset); return (T*)((u8*)ptr + offset);