MemoryAccess.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #pragma once
  2. #include <stddef.h>
  3. #include <stdint.h>
  4. #include <type_traits>
  5. namespace ARL {
  6. template<typename __PtrType1, typename __PtrType2>
  7. [[nodiscard]]
  8. inline ptrdiff_t AddressDelta(__PtrType1 p1, __PtrType2 p2) noexcept {
  9. static_assert(std::is_pointer_v<__PtrType1>);
  10. static_assert(std::is_pointer_v<__PtrType2>);
  11. return reinterpret_cast<const volatile char*>(p1) - reinterpret_cast<const volatile char*>(p2);
  12. }
  13. template<typename __PtrType>
  14. [[nodiscard]]
  15. inline __PtrType AddressOffset(__PtrType p, ptrdiff_t offset) noexcept {
  16. static_assert(std::is_pointer_v<__PtrType>);
  17. return reinterpret_cast<__PtrType>(
  18. const_cast<char*>(
  19. reinterpret_cast<const volatile char*>(p) + offset
  20. )
  21. );
  22. }
  23. template<typename __ReturnType, typename __PtrType>
  24. [[nodiscard]]
  25. inline __ReturnType AddressOffsetWithCast(__PtrType p, ptrdiff_t offset) noexcept {
  26. static_assert(std::is_pointer_v<__ReturnType>);
  27. static_assert(std::is_pointer_v<__PtrType>);
  28. return reinterpret_cast<__ReturnType>(
  29. const_cast<char*>(
  30. reinterpret_cast<const volatile char*>(p) + offset
  31. )
  32. );
  33. }
  34. template<typename __PtrType, typename __BeginPtrType, typename __EndPtrType>
  35. [[nodiscard]]
  36. inline bool AddressIsInRange(__PtrType p, __BeginPtrType begin, __EndPtrType end) {
  37. static_assert(std::is_pointer_v<__PtrType>);
  38. static_assert(std::is_pointer_v<__BeginPtrType>);
  39. static_assert(std::is_pointer_v<__EndPtrType>);
  40. return
  41. reinterpret_cast<const volatile char*>(begin) <= reinterpret_cast<const volatile char*>(p) &&
  42. reinterpret_cast<const volatile char*>(p) < reinterpret_cast<const volatile char*>(end);
  43. }
  44. template<typename __PtrType, typename __BasePtrType>
  45. [[nodiscard]]
  46. inline bool AddressIsInRange(__PtrType p, __BasePtrType base, size_t size) {
  47. static_assert(std::is_pointer_v<__PtrType>);
  48. static_assert(std::is_pointer_v<__BasePtrType>);
  49. return AddressIsInRange(p, base, AddressOffset(base, size));
  50. }
  51. template<typename __PtrType1, typename __PtrType2, typename __BeginPtrType, typename __EndPtrType>
  52. [[nodiscard]]
  53. inline bool AddressIsInRangeEx(__PtrType1 p1, __PtrType2 p2, __BeginPtrType begin, __EndPtrType end) {
  54. static_assert(std::is_pointer_v<__PtrType1>);
  55. static_assert(std::is_pointer_v<__PtrType2>);
  56. static_assert(std::is_pointer_v<__BeginPtrType>);
  57. static_assert(std::is_pointer_v<__EndPtrType>);
  58. return
  59. reinterpret_cast<const volatile char*>(begin) <= reinterpret_cast<const volatile char*>(p1) &&
  60. reinterpret_cast<const volatile char*>(p1) <= reinterpret_cast<const volatile char*>(p2) &&
  61. reinterpret_cast<const volatile char*>(p2) <= reinterpret_cast<const volatile char*>(end);
  62. }
  63. template<typename __PtrType, typename __BeginPtrType, typename __EndPtrType>
  64. [[nodiscard]]
  65. inline bool AddressIsInRangeEx(__PtrType p, size_t s, __BeginPtrType begin, __EndPtrType end) {
  66. static_assert(std::is_pointer_v<__PtrType>);
  67. static_assert(std::is_pointer_v<__BeginPtrType>);
  68. static_assert(std::is_pointer_v<__EndPtrType>);
  69. return AddressIsInRange(p, AddressDelta(p, s), begin, end);
  70. }
  71. template<typename __PtrType1, typename __PtrType2, typename __BasePtrType>
  72. [[nodiscard]]
  73. inline bool AddressIsInRangeEx(__PtrType1 p1, __PtrType2 p2, __BasePtrType base, size_t size) {
  74. static_assert(std::is_pointer_v<__PtrType1>);
  75. static_assert(std::is_pointer_v<__PtrType2>);
  76. static_assert(std::is_pointer_v<__BasePtrType>);
  77. return AddressIsInRangeEx(p1, p2, base, AddressOffset(base, size));
  78. }
  79. template<typename __PtrType, typename __BasePtrType>
  80. [[nodiscard]]
  81. inline bool AddressIsInRangeEx(__PtrType p, size_t s, __BasePtrType base, size_t size) {
  82. static_assert(std::is_pointer_v<__PtrType>);
  83. static_assert(std::is_pointer_v<__BasePtrType>);
  84. return AddressIsInRangeEx(p, AddressOffset(p, s), base, AddressOffset(base, size));
  85. }
  86. template<typename __ReadType, typename __PtrType>
  87. [[nodiscard]]
  88. inline __ReadType AddressRead(__PtrType p) noexcept {
  89. static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>);
  90. static_assert(std::is_pointer_v<__PtrType>);
  91. return *reinterpret_cast<const volatile __ReadType*>(p);
  92. }
  93. template<typename __ReadType, typename __PtrType>
  94. [[nodiscard]]
  95. inline __ReadType AddressRead(__PtrType p, ptrdiff_t offset) noexcept {
  96. static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>);
  97. static_assert(std::is_pointer_v<__PtrType>);
  98. return *reinterpret_cast<const volatile __ReadType*>(
  99. reinterpret_cast<const volatile char*>(p) + offset
  100. );
  101. }
  102. template<typename __ReadType, typename __PtrType>
  103. [[nodiscard]]
  104. inline __ReadType AddressRead(__PtrType p, size_t scale, ptrdiff_t index) noexcept {
  105. static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>);
  106. static_assert(std::is_pointer_v<__PtrType>);
  107. return *reinterpret_cast<const volatile __ReadType*>(
  108. reinterpret_cast<const volatile char*>(p) + scale * index
  109. );
  110. }
  111. template<typename __WriteType, typename __PtrType>
  112. inline void AddressWrite(__PtrType p, const __WriteType& value) noexcept {
  113. static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>);
  114. static_assert(std::is_pointer_v<__PtrType>);
  115. *reinterpret_cast<volatile __WriteType*>(p) = value;
  116. }
  117. template<typename __WriteType, typename __PtrType>
  118. inline void AddressWrite(__PtrType p, ptrdiff_t offset, const __WriteType& value) noexcept {
  119. static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>);
  120. static_assert(std::is_pointer_v<__PtrType>);
  121. *reinterpret_cast<volatile __WriteType*>(
  122. reinterpret_cast<volatile char*>(p) + offset
  123. ) = value;
  124. }
  125. template<typename __WriteType, typename __PtrType>
  126. inline void AddressWrite(__PtrType p, size_t scale, ptrdiff_t index, const __WriteType& value) noexcept {
  127. static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>);
  128. static_assert(std::is_pointer_v<__PtrType>);
  129. *reinterpret_cast<volatile __WriteType*>(
  130. reinterpret_cast<volatile char*>(p) + scale * index
  131. ) = value;
  132. }
  133. }