DynXX-Cxx
Loading...
Searching...
No Matches
Memory.hxx
Go to the documentation of this file.
1#pragma once
2
3#if defined(_WIN32)
4#include <malloc.h>
5#endif
6
7#include <memory>
8#if defined(__cpp_lib_ranges)
9#include <ranges>
10#endif
11
12#include "Types.hxx"
13#include "Macro.hxx"
14
15// C String Utils
16
17inline const char *dupCStr(const char *cstr, [[maybe_unused]] size_t len) {
18 if (cstr == nullptr) [[unlikely]] {
19 return nullptr;
20 }
21#if defined(_WIN32)
22 return _strdup(cstr);
23#else
24 return strndup(cstr, len);
25#endif
26}
27
28inline const char *dupStr(std::string_view sv) {
29 if (sv.empty()) [[unlikely]] {
30 return nullptr;
31 }
32 if (auto cstr = nullTerminatedCStr(sv); !cstr.has_value()) [[unlikely]] {
33 std::string tmpStr{sv};
34 return dupCStr(tmpStr.c_str(), tmpStr.size());
35 }
36 return dupCStr(sv.data(), sv.size());
37}
38
39// Memory Utils
40
41template<MemcpyableT T>
42void memcpyX(const T *src, T *dst, size_t count) {
43 std::memcpy(dst, src, count * sizeof(T));
44}
45
46// malloc for character types
47template<CharacterT T>
48T *mallocX(size_t count = 1) {
49 const auto len = count * sizeof(T) + 1;
50 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
51 auto ptr = std::malloc(len);
52 if (ptr == nullptr) [[unlikely]] {
53 return nullptr;
54 }
55 std::memset(ptr, 0, len);
56 return static_cast<T *>(ptr);
57}
58
59// malloc for non-character types
60template<typename T>
61 requires (!CharacterT<T>)
62T *mallocX(size_t count = 1) {
63 auto allocCount = count;
64 if constexpr (std::is_pointer_v<T>) {
65 allocCount = count + 1;
66 }
67 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
68 auto ptr = std::calloc(allocCount, sizeof(T));
69 if (ptr == nullptr) [[unlikely]] {
70 return nullptr;
71 }
72 return static_cast<T *>(ptr);
73}
74
75// free for non-const & non-void types
76template<typename T>
77 requires (!ConstT<T> && !VoidT<T>)
78void freeX(T * &ptr) {
79 if (ptr == nullptr) [[unlikely]] {
80 return;
81 }
82 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
83 std::free(static_cast<RawPtr>(ptr));
84 ptr = nullptr;
85}
86
87// free for non-const & void types
88template<typename T>
89 requires (!ConstT<T> && VoidT<T>)
90void freeX(T * &ptr) {
91 if (ptr == nullptr) [[unlikely]] {
92 return;
93 }
94 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
95 std::free(ptr);
96 ptr = nullptr;
97}
98
99// free for const & non-void types
100template<typename T>
101 requires (ConstT<T> && !VoidT<T>)
102void freeX(T * &ptr) {
103 if (ptr == nullptr) [[unlikely]] {
104 return;
105 }
106 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc,cppcoreguidelines-pro-type-const-cast)
107 std::free(const_cast<void *>(static_cast<const void *>(ptr)));
108 ptr = nullptr;
109}
110
111// free for const & void types
112template<typename T>
113 requires (ConstT<T> && VoidT<T>)
114void freeX(T * &ptr) {
115 if (ptr == nullptr) [[unlikely]] {
116 return;
117 }
118 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
119 std::free(const_cast<void *>(ptr));
120 ptr = nullptr;
121}
122
123template<InRangeT Src, OutRangeT Dst>
124requires std::indirectly_writable<
125 std::ranges::iterator_t<Dst>,
126 std::ranges::range_reference_t<Src>
127>
128void copyRange(const Src& src, Dst& dst, size_t len) {
129 if (len == 0) [[unlikely]] {
130 return;
131 }
132 len = std::min({len, src.size()});
133 dst.resize(len);
134#if defined(__cpp_lib_ranges)
135 std::ranges::copy(src | std::views::take(len), dst.begin());
136#else
137 std::copy_n(src.begin(), len, dst.begin());
138#endif
139}
140
141// Smart Pointers
142
144 void operator()(RawPtr p) const noexcept {
145 freeX(p);
146 }
147};
148using AutoFreePtr = std::unique_ptr<void, FreeDeleter>;
149
150// Classes
151
153 public:
154 DynXXStaticOnly() = delete;
155 DynXXStaticOnly(const DynXXStaticOnly& other) = delete;
159 void* operator new(std::size_t) = delete;
160 void* operator new[](std::size_t) = delete;
161 void operator delete(void*) noexcept = delete;
162 void operator delete[](void*) noexcept = delete;
164};
165
167public:
168 DynXXStackOnly() = default;
169 DynXXStackOnly(const DynXXStackOnly& other) = default;
170 DynXXStackOnly& operator=(const DynXXStackOnly& other) = default;
171 DynXXStackOnly(DynXXStackOnly&& other) noexcept = default;
172 DynXXStackOnly& operator=(DynXXStackOnly&& other) noexcept = default;
173 virtual ~DynXXStackOnly() = delete;
174 void* operator new(size_t) = delete;
175 void* operator new[](size_t) = delete;
176 void operator delete(void*) = delete;
177 void operator delete[](void*) = delete;
178};
179
181public:
182 DynXXHeapOnly(const DynXXHeapOnly& other) = delete;
183 DynXXHeapOnly& operator=(const DynXXHeapOnly& other) = delete;
184 DynXXHeapOnly(DynXXHeapOnly&& other) = delete;
186 virtual ~DynXXHeapOnly() = default;
187
188protected:
189 explicit DynXXHeapOnly() = default;
190};
191
192template <typename Derived>
194public:
199
200 template<typename... Args>
201 static std::shared_ptr<Derived> makeUnique(Args&&... args) {
202 return std::make_unique<Derived>(Token{}, std::forward<Args>(args)...);
203 }
204
205 template<typename... Args>
206 static std::shared_ptr<Derived> makeShared(Args&&... args) {
207 return std::make_shared<Derived>(Token{}, std::forward<Args>(args)...);
208 }
209
210protected:
211 struct Token {
212 explicit Token() = default;
213 };
214 explicit DynXXSmartHeapOnly(Token token) : DynXXHeapOnly(), token(token) {}
215private:
216 NO_UNIQUE_ADDRESS Token token;
217};
#define NO_UNIQUE_ADDRESS
Definition Macro.hxx:22
void freeX(T *&ptr)
Definition Memory.hxx:78
const char * dupStr(std::string_view sv)
Definition Memory.hxx:28
void memcpyX(const T *src, T *dst, size_t count)
Definition Memory.hxx:42
T * mallocX(size_t count=1)
Definition Memory.hxx:48
std::unique_ptr< void, FreeDeleter > AutoFreePtr
Definition Memory.hxx:148
void copyRange(const Src &src, Dst &dst, size_t len)
Definition Memory.hxx:128
const char * dupCStr(const char *cstr, size_t len)
Definition Memory.hxx:17
std::optional< const char * > nullTerminatedCStr(std::string_view str)
Definition Types.hxx:320
Definition Memory.hxx:180
virtual ~DynXXHeapOnly()=default
DynXXHeapOnly(DynXXHeapOnly &&other)=delete
DynXXHeapOnly & operator=(DynXXHeapOnly &&other)=delete
DynXXHeapOnly()=default
DynXXHeapOnly(const DynXXHeapOnly &other)=delete
DynXXHeapOnly & operator=(const DynXXHeapOnly &other)=delete
Definition Memory.hxx:193
static std::shared_ptr< Derived > makeShared(Args &&... args)
Definition Memory.hxx:206
DynXXSmartHeapOnly(const DynXXSmartHeapOnly &)=delete
DynXXSmartHeapOnly & operator=(const DynXXSmartHeapOnly &)=delete
DynXXSmartHeapOnly(DynXXSmartHeapOnly &&)=delete
DynXXSmartHeapOnly & operator=(DynXXSmartHeapOnly &&)=delete
static std::shared_ptr< Derived > makeUnique(Args &&... args)
Definition Memory.hxx:201
DynXXSmartHeapOnly(Token token)
Definition Memory.hxx:214
Definition Memory.hxx:166
virtual ~DynXXStackOnly()=delete
DynXXStackOnly & operator=(DynXXStackOnly &&other) noexcept=default
DynXXStackOnly()=default
DynXXStackOnly(const DynXXStackOnly &other)=default
DynXXStackOnly(DynXXStackOnly &&other) noexcept=default
DynXXStackOnly & operator=(const DynXXStackOnly &other)=default
Definition Memory.hxx:152
DynXXStaticOnly()=delete
DynXXStaticOnly & operator=(DynXXStaticOnly &&other)=delete
DynXXStaticOnly(DynXXStaticOnly &&other)=delete
DynXXStaticOnly(const DynXXStaticOnly &other)=delete
~DynXXStaticOnly()=delete
DynXXStaticOnly & operator=(const DynXXStaticOnly &other)=delete
Definition Types.hxx:49
Definition Types.hxx:29
Definition Types.hxx:32
Definition Memory.hxx:211
Definition Memory.hxx:143
void operator()(RawPtr p) const noexcept
Definition Memory.hxx:144