summaryrefslogtreecommitdiff
path: root/Source/Core/Common
diff options
context:
space:
mode:
authorTilka <tilkax@gmail.com>2024-04-20 21:16:54 +0100
committerGitHub <noreply@github.com>2024-04-20 21:16:54 +0100
commitf1e40f73bd2a9da298d9aceafa7f956041bac142 (patch)
tree16727f3ab7552bc6d668df2c0b3482ba3a23284b /Source/Core/Common
parent6443084e8c355001ad298b03423b8e4f1a6cf042 (diff)
parentc204b33314802d5e5719990d76bccc87a1907c9d (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.txt1
-rw-r--r--Source/Core/Common/SpanUtils.h41
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