LeviLamina
Loading...
Searching...
No Matches
Memory.h
1#pragma once
2
3#include <functional>
4#include <memory>
5#include <span>
6#include <string>
7#include <type_traits>
8#include <vector>
9
10#include "ll/api/base/FixedString.h"
11#include "ll/api/base/Macro.h"
12#include "ll/api/memory/Signature.h"
13#include "ll/api/memory/Symbol.h"
14#include "mc/platform/brstd/function_ref.h"
15
16namespace Bedrock::Memory {
17class IMemoryAllocator;
18}
19
20namespace ll::memory {
21
22using FuncPtr = void*;
23
24template <class T>
25 requires(sizeof(T) == sizeof(FuncPtr))
26constexpr FuncPtr toFuncPtr(T t) {
27 union {
28 FuncPtr fp;
29 T t;
30 } u{};
31 u.t = t;
32 return u.fp;
33}
34
35template <class T>
36 requires(std::is_member_function_pointer_v<T> && sizeof(T) == sizeof(FuncPtr) + sizeof(ptrdiff_t))
37constexpr FuncPtr toFuncPtr(T t) {
38 union {
39 struct {
40 FuncPtr fp;
41 ptrdiff_t offset;
42 };
43 T t;
44 } u{};
45 u.t = t;
46 return u.fp;
47}
48
49template <class T>
50inline void memcpy_t(void* dst, void const* src, size_t count) {
51 memcpy(dst, src, count * sizeof(T));
52}
53
54template <class T>
55inline void memcpy_t(void* dst, void const* src) {
56 memcpy(dst, src, sizeof(T));
57}
65LLAPI void modify(void* ptr, size_t len, brstd::function_ref<void()> callback);
66
67template <class T>
68inline void modify(T& ref, brstd::function_ref<void(std::remove_cv_t<T>&)> f) {
69 modify((void*)std::addressof(ref), sizeof(T), [&] { f((std::remove_cv_t<T>&)(ref)); });
70}
71
72template <class R = void, class... Args>
73constexpr auto addressCall(void const* address, auto&&... args) -> R {
74 return ((R(*)(Args...))address)(std::forward<decltype((args))>(args)...);
75}
76
77template <class R = void, class... Args>
78constexpr auto virtualCall(void const* self, ptrdiff_t vIndex, auto&&... args) -> R {
79 return (*(R(**)(void const*, Args...))(*(uintptr_t**)self + vIndex))(self, std::forward<decltype((args))>(args)...);
80}
81
82template <class T>
83[[nodiscard]] constexpr T& dAccess(void* ptr, ptrdiff_t off) {
84 return *(T*)((uintptr_t)((uintptr_t)ptr + off));
85}
86
87template <class T>
88[[nodiscard]] constexpr T const& dAccess(void const* ptr, ptrdiff_t off) {
89 return *(T*)((uintptr_t)((uintptr_t)ptr + off));
90}
91
92template <class T>
93constexpr void destruct(void* ptr, ptrdiff_t off) noexcept {
94 std::destroy_at(std::launder(reinterpret_cast<T*>((uintptr_t)((uintptr_t)ptr + off))));
95}
96
97template <class T, class... Args>
98constexpr auto construct(void* ptr, ptrdiff_t off, Args&&... args) {
99 return std::construct_at(
100 std::launder(reinterpret_cast<T*>((uintptr_t)((uintptr_t)ptr + off))),
101 std::forward<Args>(args)...
102 );
103}
104
105LLNDAPI ::Bedrock::Memory::IMemoryAllocator& getDefaultAllocator();
106
107[[noreturn]] LLAPI void throwMemoryException(size_t);
108
109LLNDAPI size_t getUsableSize(void* ptr);
110
111template <class T, class D>
112[[nodiscard]] inline size_t getUsableSize(std::unique_ptr<T, D>& ptr) {
113 if (!ptr) {
114 return 0;
115 }
116 return getUsableSize(ptr.get());
117}
118
119#ifdef _MSC_VER
120template <template <class> class P, class T>
121[[nodiscard]] inline size_t getUsableSize(P<T>& ptr)
122 requires(std::derived_from<P<T>, std::_Ptr_base<T>>)
123{
124 auto& refc = dAccess<std::_Ref_count_base*>(std::addressof(ptr), 8);
125 if (!refc) {
126 return 0;
127 }
128 auto& rawptr = dAccess<T*>(std::addressof(ptr), 0);
129 if (!rawptr) {
130 return 0;
131 }
132 if constexpr (!std::is_array_v<T>) {
133 if (rawptr == dAccess<T*>(refc, 8 + 4 * 2)) {
134 return getUsableSize(rawptr);
135 }
136 }
137 // clang-format off
138 return getUsableSize(refc // ptr* 8, rep* 8
139 ) - ( // rep:
140 8 + // vtable
141 4 * 2 + // uses & weaks
142 (std::is_array_v<T> ? 8 : 0)// size
143 // storage
144 );
145 // clang-format on
146}
147#endif
148
150 void* rw{};
151 void* rx{};
152 size_t memSize{};
153
154public:
155 LLAPI void alloc(size_t size);
156 LLAPI void free();
157
158 DualMapping() = default;
159
160 DualMapping(size_t size) { alloc(size); }
161
162 ~DualMapping() { free(); }
163
164 size_t size() const { return memSize; }
165
166 void* writable() const { return rw; }
167 void* executable() const { return rx; }
168};
169} // namespace ll::memory
Definition function_ref.h:60
Definition Memory.h:149