#pragma once #include #include #include namespace ARL { template [[nodiscard]] inline ptrdiff_t AddressDelta(__PtrType1 p1, __PtrType2 p2) noexcept { static_assert(std::is_pointer_v<__PtrType1>); static_assert(std::is_pointer_v<__PtrType2>); return reinterpret_cast(p1) - reinterpret_cast(p2); } template [[nodiscard]] inline __PtrType AddressOffset(__PtrType p, ptrdiff_t offset) noexcept { static_assert(std::is_pointer_v<__PtrType>); return reinterpret_cast<__PtrType>( const_cast( reinterpret_cast(p) + offset ) ); } template [[nodiscard]] inline __ReturnType AddressOffsetWithCast(__PtrType p, ptrdiff_t offset) noexcept { static_assert(std::is_pointer_v<__ReturnType>); static_assert(std::is_pointer_v<__PtrType>); return reinterpret_cast<__ReturnType>( const_cast( reinterpret_cast(p) + offset ) ); } template [[nodiscard]] inline bool AddressIsInRange(__PtrType p, __BeginPtrType begin, __EndPtrType end) { static_assert(std::is_pointer_v<__PtrType>); static_assert(std::is_pointer_v<__BeginPtrType>); static_assert(std::is_pointer_v<__EndPtrType>); return reinterpret_cast(begin) <= reinterpret_cast(p) && reinterpret_cast(p) < reinterpret_cast(end); } template [[nodiscard]] inline bool AddressIsInRange(__PtrType p, __BasePtrType base, size_t size) { static_assert(std::is_pointer_v<__PtrType>); static_assert(std::is_pointer_v<__BasePtrType>); return AddressIsInRange(p, base, AddressOffset(base, size)); } template [[nodiscard]] inline bool AddressIsInRangeEx(__PtrType1 p1, __PtrType2 p2, __BeginPtrType begin, __EndPtrType end) { static_assert(std::is_pointer_v<__PtrType1>); static_assert(std::is_pointer_v<__PtrType2>); static_assert(std::is_pointer_v<__BeginPtrType>); static_assert(std::is_pointer_v<__EndPtrType>); return reinterpret_cast(begin) <= reinterpret_cast(p1) && reinterpret_cast(p1) <= reinterpret_cast(p2) && reinterpret_cast(p2) <= reinterpret_cast(end); } template [[nodiscard]] inline bool AddressIsInRangeEx(__PtrType p, size_t s, __BeginPtrType begin, __EndPtrType end) { static_assert(std::is_pointer_v<__PtrType>); static_assert(std::is_pointer_v<__BeginPtrType>); static_assert(std::is_pointer_v<__EndPtrType>); return AddressIsInRange(p, AddressDelta(p, s), begin, end); } template [[nodiscard]] inline bool AddressIsInRangeEx(__PtrType1 p1, __PtrType2 p2, __BasePtrType base, size_t size) { static_assert(std::is_pointer_v<__PtrType1>); static_assert(std::is_pointer_v<__PtrType2>); static_assert(std::is_pointer_v<__BasePtrType>); return AddressIsInRangeEx(p1, p2, base, AddressOffset(base, size)); } template [[nodiscard]] inline bool AddressIsInRangeEx(__PtrType p, size_t s, __BasePtrType base, size_t size) { static_assert(std::is_pointer_v<__PtrType>); static_assert(std::is_pointer_v<__BasePtrType>); return AddressIsInRangeEx(p, AddressOffset(p, s), base, AddressOffset(base, size)); } template [[nodiscard]] inline __ReadType AddressRead(__PtrType p) noexcept { static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>); static_assert(std::is_pointer_v<__PtrType>); return *reinterpret_cast(p); } template [[nodiscard]] inline __ReadType AddressRead(__PtrType p, ptrdiff_t offset) noexcept { static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>); static_assert(std::is_pointer_v<__PtrType>); return *reinterpret_cast( reinterpret_cast(p) + offset ); } template [[nodiscard]] inline __ReadType AddressRead(__PtrType p, size_t scale, ptrdiff_t index) noexcept { static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>); static_assert(std::is_pointer_v<__PtrType>); return *reinterpret_cast( reinterpret_cast(p) + scale * index ); } template inline void AddressWrite(__PtrType p, const __WriteType& value) noexcept { static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>); static_assert(std::is_pointer_v<__PtrType>); *reinterpret_cast(p) = value; } template inline void AddressWrite(__PtrType p, ptrdiff_t offset, const __WriteType& value) noexcept { static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>); static_assert(std::is_pointer_v<__PtrType>); *reinterpret_cast( reinterpret_cast(p) + offset ) = value; } template inline void AddressWrite(__PtrType p, size_t scale, ptrdiff_t index, const __WriteType& value) noexcept { static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>); static_assert(std::is_pointer_v<__PtrType>); *reinterpret_cast( reinterpret_cast(p) + scale * index ) = value; } }