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