dolphin/Source/Core/Common/SpanUtils.h

42 lines
1.3 KiB
C++

// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <algorithm>
#include <cstddef>
#include <span>
#include <utility>
#include "Common/CommonTypes.h"
namespace Common
{
// Like std::span::subspan, except undefined behavior is replaced with returning a 0-length span.
template <class T>
[[nodiscard]] constexpr std::span<T> SafeSubspan(std::span<T> span, size_t offset,
size_t count = std::dynamic_extent)
{
if (count == std::dynamic_extent || offset > span.size())
return span.subspan(std::min(offset, span.size()));
else
return span.subspan(offset, std::min(count, span.size() - offset));
}
// Default-constructs an object of type T, then copies data into it from the specified offset in
// the specified span. Out-of-bounds reads will be skipped, meaning that specifying a too large
// offset results in the object partially or entirely remaining default constructed.
template <class T>
[[nodiscard]] T SafeSpanRead(std::span<const u8> span, size_t offset)
{
static_assert(std::is_trivially_copyable<T>());
const std::span<const u8> subspan = SafeSubspan(span, offset);
T result{};
std::memcpy(&result, subspan.data(), std::min(subspan.size(), sizeof(result)));
return result;
}
} // namespace Common