From 0d779077c11c0fabce2291237fa503986c61e50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 30 Oct 2020 23:04:22 +0100 Subject: [PATCH] Core/Algorithm: Add AccessByOffset functions --- include/Nazara/Core/Algorithm.hpp | 2 ++ include/Nazara/Core/Algorithm.inl | 38 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index dec6312a4..6f0754c1b 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -21,6 +21,8 @@ namespace Nz { class ByteArray; + template decltype(auto) AccessByOffset(void* basePtr, std::size_t offset); + template decltype(auto) AccessByOffset(const void* basePtr, std::size_t offset); template constexpr T Align(T offset, T alignment); template constexpr T AlignPow2(T offset, T alignment); template decltype(auto) Apply(F&& fn, Tuple&& t); diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 3560f775c..3a163cd55 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -36,6 +36,44 @@ namespace Nz NAZARA_CORE_API extern const UInt8 BitReverseTable256[256]; } + /*! + * \ingroup core + * \brief Access a non-typed struct field by offset + * \return A pointer to the field of the asked type + * + * \param basePtr Pointer to the start of the struct + * \param offset Offset to the field (as generated by offsetof or similar) + */ + template + decltype(auto) AccessByOffset(void* basePtr, std::size_t offset) + { + static_assert((std::is_reference_v && !std::is_rvalue_reference_v) || std::is_pointer_v); + + if constexpr (std::is_reference_v) + return *reinterpret_cast*>(static_cast(basePtr) + offset); + else + return reinterpret_cast(static_cast(basePtr) + offset); + } + + /*! + * \ingroup core + * \brief Access a non-typed struct field by offset + * \return A pointer to the field of the asked type + * + * \param basePtr Pointer to the start of the struct + * \param offset Offset to the field (as generated by offsetof or similar) + */ + template + decltype(auto) AccessByOffset(const void* basePtr, std::size_t offset) + { + static_assert((std::is_reference_v && !std::is_rvalue_reference_v) || std::is_pointer_v); + + if constexpr (std::is_reference_v) + return *reinterpret_cast*>(static_cast(basePtr) + offset); + else + return reinterpret_cast(static_cast(basePtr) + offset); + } + /*! * \ingroup core * \brief Align an offset