2022-07-15 15:00:38 -07:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstring>
|
|
|
|
|
2022-07-15 15:10:28 -07:00
|
|
|
#include "scaled_channel.h"
|
2024-07-23 10:55:04 -07:00
|
|
|
#include "critical_error.h"
|
2022-07-15 15:10:28 -07:00
|
|
|
|
2022-07-15 15:00:38 -07:00
|
|
|
/**
|
|
|
|
* Copies an array from src to dest. The lengths of the arrays must match.
|
|
|
|
*/
|
|
|
|
template <typename DElement, typename SElement, size_t N>
|
|
|
|
constexpr void copyArray(DElement (&dest)[N], const SElement (&src)[N]) {
|
|
|
|
for (size_t i = 0; i < N; i++) {
|
|
|
|
dest[i] = src[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// specialization that can use memcpy when src and dest types match
|
|
|
|
template <typename DElement, size_t N>
|
|
|
|
constexpr void copyArray(scaled_channel<DElement, 1, 1> (&dest)[N], const DElement (&src)[N]) {
|
|
|
|
memcpy(dest, src, sizeof(DElement) * N);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename DElement, size_t N>
|
|
|
|
constexpr void copyArray(DElement (&dest)[N], const DElement (&src)[N]) {
|
|
|
|
memcpy(dest, src, sizeof(DElement) * N);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Copies an array from src to the beginning of dst. If dst is larger
|
|
|
|
* than src, then only the elements copied from src will be touched.
|
|
|
|
* Any remaining elements at the end will be untouched.
|
|
|
|
*/
|
|
|
|
template <typename TElement, size_t NSrc, size_t NDest>
|
|
|
|
constexpr void copyArrayPartial(TElement (&dest)[NDest], const TElement (&src)[NSrc]) {
|
|
|
|
static_assert(NDest >= NSrc, "Source array must be larger than destination.");
|
|
|
|
|
|
|
|
for (size_t i = 0; i < NSrc; i++) {
|
|
|
|
dest[i] = src[i];
|
|
|
|
}
|
|
|
|
}
|
2022-07-16 22:15:59 -07:00
|
|
|
|
|
|
|
namespace efi
|
|
|
|
{
|
|
|
|
template <typename T, size_t N>
|
|
|
|
constexpr size_t size(const T(&)[N]) {
|
|
|
|
return N;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zero the passed object
|
|
|
|
template <typename T>
|
|
|
|
constexpr void clear(T* obj) {
|
2024-07-23 10:28:07 -07:00
|
|
|
#ifdef WE_HAVE_CRITICAL_ERROR_METHOD
|
|
|
|
if (obj == nullptr) {
|
2024-07-23 10:55:04 -07:00
|
|
|
efiCriticalError("clear nullptr");
|
2024-07-23 10:28:07 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif // WE_HAVE_CRITICAL_ERROR_METHOD
|
2022-07-16 22:15:59 -07:00
|
|
|
// The cast to void* is to prevent errors like:
|
|
|
|
// clearing an object of non-trivial type 'struct persistent_config_s'; use assignment or value-initialization instead
|
|
|
|
// This is technically wrong, but we know config objects only ever actually
|
|
|
|
// contain integral types, though they may be wrapped in a scaled_channel
|
|
|
|
memset(reinterpret_cast<void*>(obj), 0, sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
constexpr void clear(T& obj) {
|
|
|
|
clear(&obj);
|
|
|
|
}
|
|
|
|
} // namespace efi
|