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 if (src == nullptr || dst == nullptr || count == 0) [[unlikely]] {
44 return;
45 }
46 std::memcpy(dst, src, count * sizeof(T));
47}
48
49// malloc for character types
50template<CharacterT T>
51T *mallocX(size_t count = 1) {
52 const auto len = count * sizeof(T) + 1;
53 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
54 auto ptr = std::malloc(len);
55 if (ptr == nullptr) [[unlikely]] {
56 return nullptr;
57 }
58 std::memset(ptr, 0, len);
59 return static_cast<T *>(ptr);
60}
61
62// malloc for non-character types
63template<typename T>
64 requires (!CharacterT<T>)
65T *mallocX(size_t count = 1) {
66 auto allocCount = count;
67 if constexpr (std::is_pointer_v<T>) {
68 allocCount = count + 1;
69 }
70 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
71 auto ptr = std::calloc(allocCount, sizeof(T));
72 if (ptr == nullptr) [[unlikely]] {
73 return nullptr;
74 }
75 return static_cast<T *>(ptr);
76}
77
78// free for non-const & non-void types
79template<typename T>
80 requires (!ConstT<T> && !VoidT<T>)
81void freeX(T * &ptr) {
82 if (ptr == nullptr) [[unlikely]] {
83 return;
84 }
85 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
86 std::free(static_cast<RawPtr>(ptr));
87 ptr = nullptr;
88}
89
90// free for non-const & void types
91template<typename T>
92 requires (!ConstT<T> && VoidT<T>)
93void freeX(T * &ptr) {
94 if (ptr == nullptr) [[unlikely]] {
95 return;
96 }
97 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
98 std::free(ptr);
99 ptr = nullptr;
100}
101
102// free for const & non-void types
103template<typename T>
104 requires (ConstT<T> && !VoidT<T>)
105void freeX(T * &ptr) {
106 if (ptr == nullptr) [[unlikely]] {
107 return;
108 }
109 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc,cppcoreguidelines-pro-type-const-cast)
110 std::free(const_cast<void *>(static_cast<const void *>(ptr)));
111 ptr = nullptr;
112}
113
114// free for const & void types
115template<typename T>
116 requires (ConstT<T> && VoidT<T>)
117void freeX(T * &ptr) {
118 if (ptr == nullptr) [[unlikely]] {
119 return;
120 }
121 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
122 std::free(const_cast<void *>(ptr));
123 ptr = nullptr;
124}
125
126template<InRangeT Src, OutRangeT Dst>
127requires std::indirectly_writable<
128 std::ranges::iterator_t<Dst>,
129 std::ranges::range_reference_t<Src>
130>
131void copyRange(const Src& src, Dst& dst, size_t len) {
132 if (len == 0) [[unlikely]] {
133 return;
134 }
135 len = std::min({len, src.size()});
136 dst.resize(len);
137#if defined(__cpp_lib_ranges)
138 std::ranges::copy(src | std::views::take(len), dst.begin());
139#else
140 std::copy_n(src.begin(), len, dst.begin());
141#endif
142}
143
144// Smart Pointers
145
147 void operator()(RawPtr p) const noexcept {
148 freeX(p);
149 }
150};
151using AutoFreePtr = std::unique_ptr<void, FreeDeleter>;
152
153// Classes
154
156 public:
157 DynXXStaticOnly() = delete;
158 DynXXStaticOnly(const DynXXStaticOnly& other) = delete;
162 void* operator new(std::size_t) = delete;
163 void* operator new[](std::size_t) = delete;
164 void operator delete(void*) noexcept = delete;
165 void operator delete[](void*) noexcept = delete;
167};
168
170public:
171 DynXXStackOnly() = default;
172 DynXXStackOnly(const DynXXStackOnly& other) = default;
173 DynXXStackOnly& operator=(const DynXXStackOnly& other) = default;
174 DynXXStackOnly(DynXXStackOnly&& other) noexcept = default;
175 DynXXStackOnly& operator=(DynXXStackOnly&& other) noexcept = default;
176 virtual ~DynXXStackOnly() = delete;
177 void* operator new(size_t) = delete;
178 void* operator new[](size_t) = delete;
179 void operator delete(void*) = delete;
180 void operator delete[](void*) = delete;
181};
182
184public:
185 DynXXHeapOnly(const DynXXHeapOnly& other) = delete;
186 DynXXHeapOnly& operator=(const DynXXHeapOnly& other) = delete;
187 DynXXHeapOnly(DynXXHeapOnly&& other) = delete;
189 virtual ~DynXXHeapOnly() = default;
190
191protected:
192 explicit DynXXHeapOnly() = default;
193};
194
195template <typename Derived>
197public:
202
203 template<typename... Args>
204 static std::shared_ptr<Derived> makeUnique(Args&&... args) {
205 return std::make_unique<Derived>(Token{}, std::forward<Args>(args)...);
206 }
207
208 template<typename... Args>
209 static std::shared_ptr<Derived> makeShared(Args&&... args) {
210 return std::make_shared<Derived>(Token{}, std::forward<Args>(args)...);
211 }
212
213protected:
214 struct Token {
215 explicit Token() = default;
216 };
217 explicit DynXXSmartHeapOnly(Token token) : DynXXHeapOnly(), token(token) {}
218private:
219 DYNXX_NO_UNIQUE_ADDRESS Token token;
220};
#define DYNXX_NO_UNIQUE_ADDRESS
Definition Macro.hxx:22
void freeX(T *&ptr)
Definition Memory.hxx:81
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:51
std::unique_ptr< void, FreeDeleter > AutoFreePtr
Definition Memory.hxx:151
void copyRange(const Src &src, Dst &dst, size_t len)
Definition Memory.hxx:131
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:183
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:196
static std::shared_ptr< Derived > makeShared(Args &&... args)
Definition Memory.hxx:209
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:204
DynXXSmartHeapOnly(Token token)
Definition Memory.hxx:217
Definition Memory.hxx:169
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:155
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:214
Definition Memory.hxx:146
void operator()(RawPtr p) const noexcept
Definition Memory.hxx:147