diff options
| author | Tilka <tilkax@gmail.com> | 2024-04-20 21:16:54 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-20 21:16:54 +0100 |
| commit | f1e40f73bd2a9da298d9aceafa7f956041bac142 (patch) | |
| tree | 16727f3ab7552bc6d668df2c0b3482ba3a23284b /Source/Core/Common | |
| parent | 6443084e8c355001ad298b03423b8e4f1a6cf042 (diff) | |
| parent | c204b33314802d5e5719990d76bccc87a1907c9d (diff) | |
Merge pull request #12705 from JosJuice/get-span-for-address
Memmap: Replace GetPointer with GetSpanForAddress
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 |
