CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Loading...
Searching...
No Matches
utils.hh
Go to the documentation of this file.
1// Copyright Microsoft and CHERIoT Contributors.
2// SPDX-License-Identifier: MIT
3
4/**
5 * \file
6 * \brief Miscellaneous utility functions and classes.
7 */
8
9#pragma once
10
11#include <cdefs.h>
12#include <limits>
13#include <stddef.h>
14#include <stdint.h>
15#include <type_traits>
16#include <utility>
17
18namespace utils
19{
20 /// Turn a byte count into a bit count
21 constexpr size_t bytes_to_bits(size_t in)
22 {
23 return in * __CHAR_BIT__;
24 }
25
26 /// Compute the log base 2 of a power of 2
27 template<size_t N>
28 constexpr size_t log2()
29 {
30 static_assert(N > 0 && (N & (N - 1)) == 0);
31
32 return 1U + log2<(N >> 1)>();
33 }
34 template<>
35 constexpr size_t log2<1U>()
36 {
37 return 0;
38 }
39
40 /// Return the extent of an array
41 template<typename T, size_t N>
42 [[deprecated("Use std::extent_v<decltype(arr)> for array_size(arr)")]]
43 constexpr size_t array_size(T (&a)[N])
44 {
45 return N;
46 }
47
48 /**
49 * Divide `value` by `divisor`, rounding up, unlike `/`.
50 *
51 * If `value + divisor` overflows their type `T`, the result is
52 * correct in a modular sense, but likely not useful in practice.
53 */
54 template<typename T>
55 requires std::is_integral_v<T>
56 constexpr T round_up_divide(T value, T divisor)
57 {
58 return (value + divisor - 1) / divisor;
59 }
60
61 /**
62 * Return the smallest `multiple` greater than or equal to `value`.
63 *
64 * If `value + multiple` overflows their type `T`, the result is
65 * correct in a modular sense, but likely not useful in practice.
66 */
67 template<typename T>
68 requires std::is_integral_v<T>
69 constexpr T align_up(T value, T multiple)
70 {
71 return round_up_divide(value, multiple) * multiple;
72 }
73 static_assert(align_up(15, 16) == 16);
74 static_assert(align_up(28, 16) == 32);
75 static_assert(align_up(17, 8) == 24);
76
77 /**
78 * Return the smallest `Multiple` greater than or equal to `value`,
79 * for the special case where Multiple is a static power of two.
80 *
81 * If `value + Multiple` overflows the type `T`, the result is correct
82 * in a modular sense, but likely not useful in practice.
83 */
84 template<auto Multiple, typename T>
85 requires std::is_integral_v<T> && (std::in_range<T>(Multiple)) &&
86 ((Multiple & (Multiple - 1)) == 0)
87 constexpr T align_up(T value)
88 {
89 return (value + Multiple - 1) & -Multiple;
90 }
91 static_assert(align_up<16>(15) == 16);
92 static_assert(align_up<16>(28) == 32);
93 static_assert(align_up<8>(17) == 24);
94
95 /**
96 * \brief Utility class to delete copy and move contructors.
97 *
98 * Inherit from this if want to prevent your class from being accidentally
99 * copied. This is especially useful for classes used for MMIO as they
100 * must be instantiated at a specific address so copying is a bad idea.
101 *
102 * The default no-argument constructor and destructor is provided.
103 */
104 class NoCopyNoMove
105 {
106 public:
107 NoCopyNoMove() = default;
108 NoCopyNoMove(const NoCopyNoMove &) = delete;
109 NoCopyNoMove &operator=(const NoCopyNoMove &) = delete;
110 NoCopyNoMove(NoCopyNoMove &&) = delete;
111 NoCopyNoMove &operator=(NoCopyNoMove &&) = delete;
112 ~NoCopyNoMove() = default;
113 };
114
115 /**
116 * A helper class modelled on `std::optional` that represents an optional
117 * `T&`. This is stored as a pointer with `nullptr` representing the
118 * not-present version.
119 *
120 * Unlike `std::optional`, this intentionally omits the APIs that make it
121 * possible to access the value without checking that it is present.
122 *
123 * This is intended to be used as an alternative to using bare pointers to
124 * represent `T& | None`.
125 */
126 template<typename T>
128 {
129 /// The pointer to the real value
130 T *pointer;
131
132 public:
133 /**
134 * Construct the optional wrapper from a real value.
135 */
136 __always_inline OptionalReference(T &value) : pointer(&value) {}
137
138 /**
139 * Construct the optional wrapper from not-present value.
140 */
141 OptionalReference(std::nullptr_t) : pointer(nullptr) {}
142
143 /**
144 * Returns a copy of the wrapped value if present or the provided
145 * default value if not.
146 */
147 T value_or(T defaultValue)
148 {
149 if (pointer == nullptr)
150 {
151 return defaultValue;
152 }
153 return *pointer;
154 }
155
156 /**
157 * Returns a reference to the wrapped value if present or the provided
158 * default value if not.
159 */
160 T &value_or(T &defaultValue)
161 {
162 if (pointer == nullptr)
163 {
164 return defaultValue;
165 }
166 return *pointer;
167 }
168
169 /**
170 * If this object holds a value then apply `f` to it and return the
171 * result, otherwise return the result of converting nullptr to the
172 * return type of `f`.
173 */
174 __always_inline auto and_then(auto &&f)
175 {
176 using Result = decltype(f(std::declval<T &>()));
177 if constexpr (std::is_same_v<void, Result>)
178 {
179 if (pointer != nullptr)
180 {
181 f(*pointer);
182 }
183 return;
184 }
185 else
186 {
187 if (pointer != nullptr)
188 {
189 return f(*pointer);
190 }
191 return Result{nullptr};
192 }
193 }
194 };
195
196} // namespace utils
OptionalReference(T &value)
Construct the optional wrapper from a real value.
Definition utils.hh:136
T & value_or(T &defaultValue)
Returns a reference to the wrapped value if present or the provided default value if not.
Definition utils.hh:160
T value_or(T defaultValue)
Returns a copy of the wrapped value if present or the provided default value if not.
Definition utils.hh:147
OptionalReference(std::nullptr_t)
Construct the optional wrapper from not-present value.
Definition utils.hh:141
auto and_then(auto &&f)
If this object holds a value then apply f to it and return the result, otherwise return the result of...
Definition utils.hh:174
constexpr size_t log2()
Compute the log base 2 of a power of 2.
Definition utils.hh:28
constexpr size_t bytes_to_bits(size_t in)
Turn a byte count into a bit count.
Definition utils.hh:21
constexpr T align_up(T value, T multiple)
Return the smallest multiple greater than or equal to value.
Definition utils.hh:69
constexpr T round_up_divide(T value, T divisor)
Divide value by divisor, rounding up, unlike /.
Definition utils.hh:56
constexpr size_t array_size(T(&a)[N])
Return the extent of an array.
Definition utils.hh:43