diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d22195aa..1986898a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,7 @@ add_library(dynarmic common/aes.h common/assert.h common/bit_util.h + common/cast_util.h common/common_types.h common/crc32.cpp common/crc32.h diff --git a/src/common/cast_util.h b/src/common/cast_util.h new file mode 100644 index 00000000..5a756b5c --- /dev/null +++ b/src/common/cast_util.h @@ -0,0 +1,38 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#pragma once + +#include +#include + +namespace Dynarmic::Common { + +/// Reinterpret objects of one type as another by bit-casting between object representations. +template +inline Dest BitCast(const Source& source) { + static_assert(sizeof(Dest) == sizeof(Source), "size of destination and source objects must be equal"); + static_assert(std::is_trivially_copyable_v, "destination type must be trivially copyable."); + static_assert(std::is_trivially_copyable_v, "source type must be trivially copyable"); + + typename std::aligned_storage_t dest; + std::memcpy(&dest, &source, sizeof(dest)); + return reinterpret_cast(dest); +} + +/// Reinterpret objects of any arbitrary type as another type by bit-casting between object representations. +/// Note that here we do not verify if source has enough bytes to read from. +template +inline Dest BitCastPointee(const SourcePtr source) { + static_assert(sizeof(SourcePtr) == sizeof(void*), "source pointer must have size of a pointer"); + static_assert(std::is_trivially_copyable_v, "destination type must be trivially copyable."); + + typename std::aligned_storage_t dest; + std::memcpy(&dest, BitCast(source), sizeof(dest)); + return reinterpret_cast(dest); +} + +} // namespace Dynarmic::Common