memory_utility.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #pragma once
  2. #include <stddef.h>
  3. #include <stdint.h>
  4. #include <type_traits>
  5. namespace nkg {
  6. template<typename ptr1_t, typename ptr2_t>
  7. [[nodiscard]]
  8. inline ptrdiff_t address_delta(ptr1_t ptr1, ptr2_t ptr2) noexcept {
  9. static_assert(std::is_pointer_v<ptr1_t> && std::is_pointer_v<ptr2_t>);
  10. return reinterpret_cast<const volatile char*>(ptr1) - reinterpret_cast<const volatile char*>(ptr2);
  11. }
  12. template<typename ptr_t>
  13. [[nodiscard]]
  14. inline ptr_t address_offset(ptr_t ptr, ptrdiff_t off) noexcept {
  15. static_assert(std::is_pointer_v<ptr_t>);
  16. return reinterpret_cast<ptr_t>(
  17. const_cast<char*>(
  18. reinterpret_cast<const volatile char*>(ptr) + off
  19. )
  20. );
  21. }
  22. template<typename return_ptr_t, typename ptr_t>
  23. [[nodiscard]]
  24. inline return_ptr_t address_offset_cast(ptr_t ptr, ptrdiff_t off) noexcept {
  25. static_assert(std::is_pointer_v<return_ptr_t> && std::is_pointer_v<ptr_t>);
  26. return reinterpret_cast<return_ptr_t>(address_offset(ptr, off));
  27. }
  28. template<typename ptr_t, typename begin_ptr_t, typename end_ptr_t>
  29. [[nodiscard]]
  30. inline bool is_address_in_range(ptr_t ptr, begin_ptr_t begin, end_ptr_t end) {
  31. static_assert(std::is_pointer_v<ptr_t> && std::is_pointer_v<begin_ptr_t> && std::is_pointer_v<end_ptr_t>);
  32. auto _ptr = reinterpret_cast<const volatile char*>(ptr);
  33. auto _begin = reinterpret_cast<const volatile char*>(begin);
  34. auto _end = reinterpret_cast<const volatile char*>(end);
  35. return _begin <= _ptr && _ptr < _end;
  36. }
  37. template<typename ptr_t, typename base_ptr_t>
  38. [[nodiscard]]
  39. inline bool is_address_in_range(ptr_t ptr, base_ptr_t base, size_t size) {
  40. static_assert(std::is_pointer_v<ptr_t> && std::is_pointer_v<base_ptr_t>);
  41. return is_address_in_range(ptr, base, address_offset(base, size));
  42. }
  43. template<typename ptr1_t, typename ptr2_t, typename begin_ptr_t, typename end_ptr_t>
  44. [[nodiscard]]
  45. inline bool is_address_in_range(ptr1_t ptr1, ptr2_t ptr2, begin_ptr_t begin, end_ptr_t end) {
  46. static_assert(std::is_pointer_v<ptr1_t> && std::is_pointer_v<ptr2_t> && std::is_pointer_v<begin_ptr_t> && std::is_pointer_v<end_ptr_t>);
  47. auto _ptr1 = reinterpret_cast<const volatile char*>(ptr1);
  48. auto _ptr2 = reinterpret_cast<const volatile char*>(ptr2);
  49. auto _begin = reinterpret_cast<const volatile char*>(begin);
  50. auto _end = reinterpret_cast<const volatile char*>(end);
  51. return _begin <= _ptr1 && _ptr1 <= _ptr2 && _ptr2 <= _end;
  52. }
  53. template<typename ptr_t, typename begin_ptr_t, typename end_ptr_t>
  54. [[nodiscard]]
  55. inline bool is_address_in_range(ptr_t ptr, size_t size, begin_ptr_t begin, end_ptr_t end) {
  56. static_assert(std::is_pointer_v<ptr_t> && std::is_pointer_v<begin_ptr_t> && std::is_pointer_v<end_ptr_t>);
  57. return is_address_in_range(ptr, address_offset(ptr, size), begin, end);
  58. }
  59. template<typename ptr1_t, typename ptr2_t, typename base_ptr_t>
  60. [[nodiscard]]
  61. inline bool is_address_in_range(ptr1_t ptr1, ptr2_t ptr2, base_ptr_t base, size_t size) {
  62. static_assert(std::is_pointer_v<ptr1_t> && std::is_pointer_v<ptr2_t> && std::is_pointer_v<base_ptr_t>);
  63. return is_address_in_range(ptr1, ptr2, base, address_offset(base, size));
  64. }
  65. template<typename ptr_t, typename base_ptr_t>
  66. [[nodiscard]]
  67. inline bool is_address_in_range(ptr_t p, size_t s, base_ptr_t base, size_t size) {
  68. static_assert(std::is_pointer_v<ptr_t>);
  69. static_assert(std::is_pointer_v<base_ptr_t>);
  70. return is_address_in_range(p, address_offset(p, s), base, address_offset(base, size));
  71. }
  72. // template<typename __ReadType, typename __PtrType>
  73. // [[nodiscard]]
  74. // inline __ReadType AddressRead(__PtrType p) noexcept {
  75. // static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>);
  76. // static_assert(std::is_pointer_v<__PtrType>);
  77. // return *reinterpret_cast<const volatile __ReadType*>(p);
  78. // }
  79. //
  80. // template<typename __ReadType, typename __PtrType>
  81. // [[nodiscard]]
  82. // inline __ReadType AddressRead(__PtrType p, ptrdiff_t offset) noexcept {
  83. // static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>);
  84. // static_assert(std::is_pointer_v<__PtrType>);
  85. // return *reinterpret_cast<const volatile __ReadType*>(
  86. // reinterpret_cast<const volatile char*>(p) + offset
  87. // );
  88. // }
  89. //
  90. // template<typename __ReadType, typename __PtrType>
  91. // [[nodiscard]]
  92. // inline __ReadType AddressRead(__PtrType p, size_t scale, ptrdiff_t index) noexcept {
  93. // static_assert(std::is_trivial_v<__ReadType> && std::is_standard_layout_v<__ReadType>);
  94. // static_assert(std::is_pointer_v<__PtrType>);
  95. // return *reinterpret_cast<const volatile __ReadType*>(
  96. // reinterpret_cast<const volatile char*>(p) + scale * index
  97. // );
  98. // }
  99. //
  100. // template<typename __WriteType, typename __PtrType>
  101. // inline void AddressWrite(__PtrType p, const __WriteType& value) noexcept {
  102. // static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>);
  103. // static_assert(std::is_pointer_v<__PtrType>);
  104. // *reinterpret_cast<volatile __WriteType*>(p) = value;
  105. // }
  106. //
  107. // template<typename __WriteType, typename __PtrType>
  108. // inline void AddressWrite(__PtrType p, ptrdiff_t offset, const __WriteType& value) noexcept {
  109. // static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>);
  110. // static_assert(std::is_pointer_v<__PtrType>);
  111. // *reinterpret_cast<volatile __WriteType*>(
  112. // reinterpret_cast<volatile char*>(p) + offset
  113. // ) = value;
  114. // }
  115. //
  116. // template<typename __WriteType, typename __PtrType>
  117. // inline void AddressWrite(__PtrType p, size_t scale, ptrdiff_t index, const __WriteType& value) noexcept {
  118. // static_assert(std::is_trivial_v<__WriteType> && std::is_standard_layout_v<__WriteType>);
  119. // static_assert(std::is_pointer_v<__PtrType>);
  120. // *reinterpret_cast<volatile __WriteType*>(
  121. // reinterpret_cast<volatile char*>(p) + scale * index
  122. // ) = value;
  123. // }
  124. }