diff options
| author | JosJuice <josjuice@gmail.com> | 2024-04-13 18:29:52 +0200 |
|---|---|---|
| committer | JosJuice <josjuice@gmail.com> | 2024-04-20 18:31:08 +0200 |
| commit | 3cfa233b63dfcd734be2dd0ae4bd0d3e98109df6 (patch) | |
| tree | f4b111b5d43f9192b15f82250d3123d15585b001 /Source/Core/Common | |
| parent | 5c9bb80638ec05b32eaa129a8c763ac6bb3a5cb4 (diff) | |
VideoCommon: Use GetSpanForAddress safely in texture decoding
Now only VertexLoader remains... But that one might be tricky.
Diffstat (limited to 'Source/Core/Common')
| -rw-r--r-- | Source/Core/Common/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | Source/Core/Common/SpanUtils.h | 41 |
2 files changed, 42 insertions, 0 deletions
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 7b81cd2c6d..af48ba7e13 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -126,6 +126,7 @@ add_library(common SmallVector.h SocketContext.cpp SocketContext.h + SpanUtils.h SPSCQueue.h StringLiteral.h StringUtil.cpp diff --git a/Source/Core/Common/SpanUtils.h b/Source/Core/Common/SpanUtils.h new file mode 100644 index 0000000000..d09193b314 --- /dev/null +++ b/Source/Core/Common/SpanUtils.h @@ -0,0 +1,41 @@ +// 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 |
