// Copyright 2024 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include #include #include "Common/CommonTypes.h" namespace Common { // Like std::span::subspan, except undefined behavior is replaced with returning a 0-length span. template [[nodiscard]] constexpr std::span SafeSubspan(std::span 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 [[nodiscard]] T SafeSpanRead(std::span span, size_t offset) { static_assert(std::is_trivially_copyable()); const std::span subspan = SafeSubspan(span, offset); T result{}; std::memcpy(&result, subspan.data(), std::min(subspan.size(), sizeof(result))); return result; } } // namespace Common