Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
alignment.hpp
Go to the documentation of this file.
1// Copyright 2024, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UTILITY_ALIGNMENT_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UTILITY_ALIGNMENT_HPP_
7
8// IWYU pragma: private, include "arene/base/utility.hpp"
9// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
10
11// AUTOSAR exceptions:
12// A5-2-4 "reinterpret_cast shall not be used"
13// The rationale for this rule indicates that use of reinterpret_cast may
14// violate type-safety and cause the program to access a variable as if it
15// were of another, unrelated type.
16//
17// However, the usage of reinterpret_cast in this file is only used to inspect
18// the bit-representation of a pointer as an integer for the purposes of
19// determining whether or not a pointer is aligned and if not, what offset
20// must be applied to that pointer to obtain an aligned pointer.
21// This restricted usage is thus not able to violate type-safety by
22// interpreting an object of one type as if it were another type as
23// the result of the reinterpret_cast is not used to access another object.
24
25// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
26#include "arene/base/constraints/constraints.hpp"
27#include "arene/base/contracts/contract.hpp"
28#include "arene/base/math/power_of_2.hpp"
29#include "arene/base/stdlib_choice/climits.hpp"
30#include "arene/base/stdlib_choice/cstddef.hpp"
31#include "arene/base/stdlib_choice/cstdint.hpp"
32#include "arene/base/stdlib_choice/enable_if.hpp"
33#include "arene/base/stdlib_choice/is_integral.hpp"
34#include "arene/base/stdlib_choice/is_unsigned.hpp"
35#include "arene/base/stdlib_choice/make_unsigned.hpp"
36#include "arene/base/stdlib_choice/numeric_limits.hpp"
37// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
38
39// parasoft-begin-suppress CERT_C-PRE31-c-3 "False Positive: static_assert is not a macro"
40
41namespace arene {
42namespace base {
43
44namespace alignment_detail {
45// parasoft-begin-suppress AUTOSAR-A2_11_1-a-2 "volatile used to allow pointing to volatile objects"
46/// @brief A pointer to anything at all
47using pointer_to_anything = void const volatile*;
48// parasoft-end-suppress AUTOSAR-A2_11_1-a-2
49
50} // namespace alignment_detail
51
52/// @brief Check if an integer is a multiple of the specified power-of-two alignment.
53///
54/// @tparam Alignment The alignment to check against. Must be a positive power-of-two.
55/// @tparam Integer An integral type.
56/// @param value The value to check.
57/// @return @c true if @c value is a multiple of @c alignment.
58template <
60 typename Integer,
62constexpr auto is_aligned(Integer value) -> bool {
63 static_assert(::arene::base::is_power_of_2(Alignment), "Alignment must be a positive power-of-two");
64 static_assert(
66 "Attempting to align to a value that is larger than the "
67 "maximum representable value."
68 );
70 constexpr std::size_t mask{Alignment - 1U};
71 return (static_cast<unsigned_integer>(value) & mask) == 0U;
72}
73
74/// @brief Check if an address is a multiple of the specified alignment.
75///
76/// @tparam Alignment The power-of-2 alignment to check for.
77/// @param pointer The pointer to check the address of.
78/// @return @c true if the pointer is aligned to a multiple of @c Alignment , otherwise @c false.
79template <std::size_t Alignment>
80// parasoft-begin-suppress AUTOSAR-A2_10_1-a "False positive: 'pointer' does not hide anything"
81// parasoft-begin-suppress AUTOSAR-A7_1_3-a-2 "False Positive: const is on rhs"
82constexpr auto is_aligned(alignment_detail::pointer_to_anything const pointer) -> bool {
83 // parasoft-end-suppress AUTOSAR-A7_1_3-a-2
84 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
85 return is_aligned<Alignment>(reinterpret_cast<std::uintptr_t>(pointer));
86}
87// parasoft-end-suppress AUTOSAR-A2_10_1-a
88
89/// @brief Align a value to the nearest multiple of alignment, rounding down.
90///
91/// @tparam Alignment The alignment to align to. Must be a positive power-of-two.
92/// @tparam Integer The type of the integer to align.
93/// @param value The value to align.
94/// @return Either @c value if it was already a multiple of @c alignment , otherwise the closest multiple of @c
95/// alignment less than @c value.
96template <
98 typename Integer,
100constexpr auto align_floor(Integer value) -> Integer {
101 static_assert(::arene::base::is_power_of_2(Alignment), "Alignment must be a positive power-of-two");
102 static_assert(
104 "Attempting to align to a value that is larger than the "
105 "maximum representable value."
106 );
108 constexpr std::size_t mask{Alignment - 1U};
109 return static_cast<Integer>(static_cast<unsigned_integer>(value) & ~mask);
110}
111
112/// @brief Align a value to the nearest multiple of alignment, rounding up.
113///
114/// @tparam Alignment The alignment to align to. Must be a positive power-of-two.
115/// @tparam Integer The type of integer to align.
116/// @param value The value to align.
117/// @return Either @c value if it was already a multiple of @c alignment , otherwise the closest multiple of @c
118/// alignment greather than @c value .
119template <
121 typename Integer,
123constexpr auto align_ceil(Integer value) -> Integer {
124 static_assert(::arene::base::is_power_of_2(Alignment), "Alignment must be a positive power-of-two");
125 static_assert(
127 "Attempting to align to a value that is larger than the "
128 "maximum representable value."
129 );
130 constexpr std::size_t mask{Alignment - 1U};
132 return static_cast<Integer>((static_cast<unsigned_integer>(value) + mask) & ~mask);
133}
134
135/// @brief Calculate the amount by which ptr needs to be adjusted to have the specified Alignment.
136///
137/// @tparam Alignment The alignment to calculate the offset to.
138/// @param ptr The address to calculate the offset for.
139/// @return The number of bytes that must be added to @c ptr address to obtain an address that is a multiple of @c
140/// Alignment.
141template <std::size_t Alignment>
142// parasoft-begin-suppress AUTOSAR-A7_1_3-a-2 "False Positive: const is on rhs"
143auto alignment_offset(alignment_detail::pointer_to_anything const ptr) noexcept -> std::size_t {
144 // parasoft-end-suppress AUTOSAR-A7_1_3-a-2
145 // parasoft-begin-suppress AUTOSAR-A7_1_3-a-2 "False Positive: const is on rhs"
146 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
147 std::uintptr_t const base{reinterpret_cast<std::uintptr_t>(ptr)};
148 // parasoft-end-suppress AUTOSAR-A7_1_3-a-2
149 std::size_t const offset{::arene::base::align_ceil<Alignment>(base) - base};
150 return offset;
151}
152
153/// @brief Construct a bit-mask with the lowest @c one_bits bits set to 1 and the rest of the bits set to 0.
154///
155/// For example:
156/// @snippet docs/examples/utility_examples.cpp bit_mask_usage_example
157///
158/// @tparam Integer The mask type to return.
159/// @param one_bits The number of bits to set to 1 in the mask. Must be in range [0, Integer-bit-width].
160/// @return A value of type @c Integer with the lowest @c one_bits bits set to 1 and the rest of the bits set to 0.
161template <typename Integer, constraints<std::enable_if_t<std::is_unsigned<Integer>::value>> = nullptr>
162constexpr auto bit_mask(std::uint32_t const one_bits) -> Integer {
163 constexpr std::uint32_t max_bits{std::uint32_t{sizeof(Integer)} * std::uint32_t{CHAR_BIT}};
165
166 // Note it is UB to shift by a number of bits greater or equal to the number of bits in the integer representation so
167 // need to handle this case separately.
168 if (one_bits != max_bits) {
169 constexpr Integer one{1U};
170 // parasoft-begin-suppress AUTOSAR-M5_8_1 "False Positive: this shifting operation is enclosed with if checking that
171 // RHS does not exceed the upper limit"
172 // parasoft-begin-suppress AUTOSAR-M4_5_1 "This function handles generic integer types, including bool"
173 // parasoft-begin-suppress CERT_C-EXP46-b "This function handles generic integer types, including bool"
174 return static_cast<Integer>((one << one_bits) - one);
175 // parasoft-end-suppress CERT_C-EXP46-b
176 // parasoft-end-suppress AUTOSAR-M4_5_1
177 // parasoft-end-suppress AUTOSAR-M5_8_1
178 }
179
180 return std::numeric_limits<Integer>::max();
181}
182
183} // namespace base
184} // namespace arene
185
186#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UTILITY_ALIGNMENT_HPP_
Definition array_exceptions_disabled.cpp:11
auto alignment_offset(alignment_detail::pointer_to_anything const ptr) noexcept -> std::size_t
Calculate the amount by which ptr needs to be adjusted to have the specified Alignment.
Definition alignment.hpp:143
constexpr auto is_aligned(alignment_detail::pointer_to_anything const pointer) -> bool
Check if an address is a multiple of the specified alignment.
Definition alignment.hpp:82
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10