0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-01 03:18:54 +01:00
construct/include/ircd/util/align.h
2022-10-01 22:06:45 +00:00

160 lines
3.9 KiB
C++

// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2022 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_UTIL_ALIGN_H
namespace ircd {
inline namespace util
{
// Alignment constant expressions
constexpr bool padded(const size_t, size_t alignment);
constexpr bool aligned(const uintptr_t, size_t alignment);
constexpr size_t padding(const size_t size, size_t alignment);
constexpr size_t pad_to(const size_t size, const size_t alignment);
constexpr uintptr_t align(uintptr_t, size_t alignment);
constexpr uintptr_t align_up(uintptr_t, size_t alignment);
constexpr ulong alignment(const uintptr_t);
// Alignment inline tools
bool aligned(const void *const &, const size_t &alignment);
bool aligned(const volatile void *const &, const size_t &alignment);
template<class T = char> const T *align(const void *const &, const size_t &alignment);
template<class T = char> T *align(void *const &, const size_t &alignment);
template<class T = char> const T *align_up(const void *const &, const size_t &alignment);
template<class T = char> T *align_up(void *const &, const size_t &alignment);
ulong alignment(const void *const &);
}}
[[gnu::always_inline]]
inline ulong
ircd::util::alignment(const void *const &ptr)
{
return alignment(uintptr_t(ptr));
}
template<class T>
[[gnu::always_inline]]
inline T *
ircd::util::align(void *const &ptr,
const size_t &alignment)
{
return reinterpret_cast<T *>
(
align(uintptr_t(ptr), alignment)
);
}
template<class T>
[[gnu::always_inline]]
inline const T *
ircd::util::align(const void *const &ptr,
const size_t &alignment)
{
return reinterpret_cast<const T *>
(
align(uintptr_t(ptr), alignment)
);
}
template<class T>
[[gnu::always_inline]]
inline T *
ircd::util::align_up(void *const &ptr,
const size_t &alignment)
{
return reinterpret_cast<T *>
(
align_up(uintptr_t(ptr), alignment)
);
}
template<class T>
[[gnu::always_inline]]
inline const T *
ircd::util::align_up(const void *const &ptr,
const size_t &alignment)
{
return reinterpret_cast<const T *>
(
align_up(uintptr_t(ptr), alignment)
);
}
[[gnu::always_inline]]
inline bool
ircd::util::aligned(const void *const &ptr,
const size_t &alignment)
{
return aligned(uintptr_t(ptr), alignment);
}
[[gnu::always_inline]]
inline bool
ircd::util::aligned(const volatile void *const &ptr,
const size_t &alignment)
{
return aligned(uintptr_t(ptr), alignment);
}
constexpr ulong
ircd::util::alignment(const uintptr_t ptr)
{
return 1UL << __builtin_ctzl(ptr);
}
constexpr uintptr_t
ircd::util::align_up(uintptr_t ptr,
size_t alignment)
{
alignment = std::max(alignment, 1UL);
ptr += (alignment - (ptr % alignment)) % alignment;
return ptr;
}
constexpr uintptr_t
ircd::util::align(uintptr_t ptr,
size_t alignment)
{
alignment = std::max(alignment, 1UL);
ptr -= (ptr % alignment);
return ptr;
}
constexpr size_t
ircd::util::pad_to(const size_t size,
const size_t alignment)
{
return size + padding(size, alignment);
}
constexpr size_t
ircd::util::padding(const size_t size,
size_t alignment)
{
alignment = std::max(alignment, 1UL);
return (alignment - (size % alignment)) % alignment;
}
constexpr bool
ircd::util::aligned(const uintptr_t ptr,
size_t alignment)
{
alignment = std::max(alignment, 1UL);
return ptr % alignment == 0;
}
constexpr bool
ircd::util::padded(const size_t size,
size_t alignment)
{
alignment = std::max(alignment, 1UL);
return size % alignment == 0;
}