| // Copyright Microsoft and CHERIoT Contributors. | |
| // SPDX-License-Identifier: MIT | |
| #pragma once | |
| #include <cdefs.h> | |
| #include <limits> | |
| #include <stddef.h> | |
| #include <stdint.h> | |
| #include <type_traits> | |
| namespace utils | |
| { | |
| constexpr size_t bytes2bits(size_t in) | |
| { | |
| return in * __CHAR_BIT__; | |
| } | |
| template<size_t N> | |
| constexpr size_t log2() | |
| { | |
| static_assert(N > 0 && (N & (N - 1)) == 0); | |
| return 1U + log2<(N >> 1)>(); | |
| } | |
| template<> | |
| constexpr size_t log2<1U>() | |
| { | |
| return 0; | |
| } | |
| template<typename T, size_t N> | |
| constexpr size_t array_size(T (&a)[N]) | |
| { | |
| return N; | |
| } | |
| class NoCopyNoMove | |
| { | |
| public: | |
| NoCopyNoMove() = default; | |
| NoCopyNoMove(const NoCopyNoMove &) = delete; | |
| NoCopyNoMove &operator=(const NoCopyNoMove &) = delete; | |
| NoCopyNoMove(NoCopyNoMove &&) = delete; | |
| NoCopyNoMove &operator=(NoCopyNoMove &&) = delete; | |
| ~NoCopyNoMove() = default; | |
| }; | |
| /** | |
| * A helper class modelled on `std::optional` that represents an optional | |
| * `T&`. This is stored as a pointer with `nullptr` representing the | |
| * not-present version. | |
| * | |
| * Unlike `std::optional`, this intentionally omits the APIs that make it | |
| * possible to access the value without checking that it is present. | |
| * | |
| * This is intended to be used as an alternative to using bare pointers to | |
| * represent `T& | None`. | |
| */ | |
| template<typename T> | |
| class OptionalReference | |
| { | |
| /// The pointer to the real value | |
| T *pointer; | |
| public: | |
| /** | |
| * Construct the optional wrapper from a real value. | |
| */ | |
| __always_inline OptionalReference(T &value) : pointer(&value) {} | |
| /** | |
| * Construct the optional wrapper from not-present value. | |
| */ | |
| OptionalReference(std::nullptr_t) : pointer(nullptr) {} | |
| /** | |
| * Returns a copy of the wrapped value if present or the provided | |
| * default value if not. | |
| */ | |
| T value_or(T defaultValue) | |
| { | |
| if (pointer == nullptr) | |
| { | |
| return defaultValue; | |
| } | |
| return *pointer; | |
| } | |
| /** | |
| * Returns a reference to the wrapped value if present or the provided | |
| * default value if not. | |
| */ | |
| T &value_or(T &defaultValue) | |
| { | |
| if (pointer == nullptr) | |
| { | |
| return defaultValue; | |
| } | |
| return *pointer; | |
| } | |
| /** | |
| * If this object holds a value then apply `f` to it and return the | |
| * result, otherwise return the result of converting nullptr to the | |
| * return type of `f`. | |
| */ | |
| __always_inline auto and_then(auto &&f) | |
| { | |
| using Result = decltype(f(std::declval<T &>())); | |
| if constexpr (std::is_same_v<void, Result>) | |
| { | |
| if (pointer != nullptr) | |
| { | |
| f(*pointer); | |
| } | |
| return; | |
| } | |
| else | |
| { | |
| if (pointer != nullptr) | |
| { | |
| return f(*pointer); | |
| } | |
| return Result{nullptr}; | |
| } | |
| } | |
| }; | |
| } // namespace utils |