8#include "../macros.hpp"
10#include "exception.hpp"
17#include <unordered_map>
22hi_export_module(hikogui.utility.memory);
27hi_warning_ignore_msvc(26474);
30hi_warning_ignore_msvc(26472);
32hi_export
namespace hi::inline
v1 {
40template<
template<
typename...>
typename T,
typename... Args>
43 using deduced_type =
decltype(T{std::forward<Args>(args)...});
44 return std::make_unique<deduced_type>(std::forward<Args>(args)...);
53template<
template<
typename...>
typename T,
typename... Args>
56 using deduced_type =
decltype(T{std::forward<Args>(args)...});
57 return std::make_shared<deduced_type>(std::forward<Args>(args)...);
60[[nodiscard]]
bool equal_ptr(
auto *p1,
auto *p2)
noexcept
62 return static_cast<void *
>(p1) ==
static_cast<void *
>(p2);
65template<
typename T,
typename U>
66void memswap(T& dst, U& src)
68 static_assert(
sizeof(T) ==
sizeof(U),
"memswap requires both objects of equal size");
69 std::byte tmp[
sizeof(T)];
70 memcpy(tmp, &src,
sizeof(T));
71 memcpy(&src, &dst,
sizeof(U));
72 memcpy(&dst, tmp,
sizeof(T));
85template<
typename InputIt,
typename T>
88 hi_axiom_not_null(dst);
89 return new (dst) T(*src);
96template<
typename InputIt,
typename T>
99 hi_axiom(src_first != dst_first);
100 hi_axiom(src_last >= src_first);
102 auto src = src_first;
103 auto dst = dst_first;
104 while (src != src_last) {
125 hi_axiom_not_null(src);
126 hi_axiom_not_null(dst);
128 auto dst_ =
new (dst) T(
std::move(*src));
129 std::destroy_at(src);
145 hi_axiom(src_last >= src_first);
147 if (src_first < dst_first) {
148 auto dst_last = dst_first + (src_last - src_first);
152 while (src != src_first) {
156 }
else if (src_first > dst_first) {
157 auto src = src_first;
158 auto dst = dst_first;
159 while (src != src_last) {
179 hi_axiom(src_last >= src);
181 while (src != src_last) {
188template<
typename It,
typename... Args>
191 for (
auto it = first; it != last; ++it) {
205constexpr T *ceil(T *ptr,
std::size_t alignment)
noexcept
207 auto const aligned_byte_offset = ceil(
reinterpret_cast<uintptr_t
>(ptr), wide_cast<uintptr_t>(alignment));
208 return reinterpret_cast<T *
>(aligned_byte_offset);
214 auto const aligned_byte_offset =
floor(
reinterpret_cast<uintptr_t
>(ptr), wide_cast<uintptr_t>(alignment));
215 return reinterpret_cast<T *
>(aligned_byte_offset);
226 hi_axiom_not_null(ptr);
227 return static_cast<char *
>(ptr) + distance;
238 hi_axiom_not_null(ptr);
239 return static_cast<char const *
>(ptr) + distance;
246 while (i != v.end()) {
255template<
typename K,
typename T>
259 while (i != v.end()) {
260 if (i->second.expired()) {
268template<
typename K,
typename T>
272 while (i != v.end()) {
273 cleanupWeakPointers(i->second);
274 if (i->second.size() == 0) {
282template<
typename Value,
typename Map,
typename Key,
typename... Args>
287 auto const i = map.find(key);
288 if (i == map.end()) {
289 value = std::make_shared<Value>(std::forward<Args>(args)...);
290 map.insert_or_assign(key, value);
299template<numeric T,
byte_like B>
304 if (not std::is_constant_evaluated()) {
310 if constexpr (std::endian::native == std::endian::little) {
311 for (
auto i =
sizeof(T); i != 0; --i) {
312 if constexpr (
sizeof(r) > 1) {
315 r |=
static_cast<uint8_t
>(src[i - 1]);
318 for (
auto i = 0; i !=
sizeof(T); ++i) {
319 if constexpr (
sizeof(r) > 1) {
322 r |=
static_cast<uint8_t
>(src[i]);
329[[nodiscard]]
inline T unaligned_load(
void const *src)
noexcept
331 return unaligned_load<T>(
static_cast<std::byte
const *
>(src));
334template<numeric T,
byte_like B>
335constexpr void unaligned_store(T src, B *dst)
noexcept
337 using unsigned_type = std::make_unsigned_t<T>;
339 auto const src_ =
static_cast<unsigned_type
>(src);
341 if (not std::is_constant_evaluated()) {
346 if constexpr (std::endian::native == std::endian::little) {
347 for (
auto i = 0; i !=
sizeof(T); ++i) {
348 dst[i] =
static_cast<B
>(src_);
352 for (
auto i =
sizeof(T); i != 0; --i) {
353 dst[i - 1] =
static_cast<B
>(src_);
360void unaligned_store(T src,
void *dst)
noexcept
362 return unaligned_store(src,
reinterpret_cast<std::byte *
>(dst));
365template<std::
integral T>
366hi_force_inline
constexpr void store_or(T src, uint8_t *dst)
noexcept
368 hi_axiom_not_null(dst);
370 using unsigned_type = std::make_unsigned_t<T>;
372 auto src_ = truncate<unsigned_type>(src);
374 if (not std::is_constant_evaluated()) {
381 if constexpr (std::endian::native == std::endian::little) {
382 for (
auto i = 0; i !=
sizeof(T); ++i) {
383 dst[i] |= truncate<uint8_t>(src_);
387 for (
auto i =
sizeof(T); i != 0; --i) {
388 dst[i] |= truncate<uint8_t>(src_);
Miscellaneous math functions.
Functions for casting values between types savely.
Utilities for throwing exceptions and terminating the application.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
T * placement_copy(InputIt src, T *dst)
Copy an object to another memory locations.
Definition memory.hpp:86
auto make_shared_ctad(Args &&...args)
make_shared with CTAD (Class Template Argument Deduction)
Definition memory.hpp:54
void * advance_bytes(void *ptr, std::ptrdiff_t distance) noexcept
Advance a pointer by a number of bytes.
Definition memory.hpp:224
void construct(It first, It last, Args const &...args)
Construct a set of objects.
Definition memory.hpp:189
auto make_unique_ctad(Args &&...args)
make_unique with CTAD (Class Template Argument Deduction)
Definition memory.hpp:41
constexpr bool is_aligned(T *p)
Check if a pointer is properly aligned for the object it is pointing at.
Definition memory.hpp:199
void placement_move_within_array(T *src_first, T *src_last, T *dst_first)
Move an objects between two memory locations.
Definition memory.hpp:143
constexpr T unaligned_load(B const *src) noexcept
Make an unaligned load of an unsigned integer.
Definition memory.hpp:300
T * placement_move(T *src, T *dst)
Move an object between two memory locations.
Definition memory.hpp:123