8#include "../macros.hpp"
10#include "exception.hpp"
18#include <unordered_map>
23hi_export_module(hikogui.utility.memory);
28hi_warning_ignore_msvc(26474);
31hi_warning_ignore_msvc(26472);
33hi_export
namespace hi::inline
v1 {
41template<
template<
typename...>
typename T,
typename... Args>
54template<
template<
typename...>
typename T,
typename... Args>
61[[nodiscard]]
bool equal_ptr(
auto *p1,
auto *p2)
noexcept
63 return static_cast<void *
>(p1) ==
static_cast<void *
>(p2);
66template<
typename T,
typename U>
67void memswap(T& dst, U& src)
69 static_assert(
sizeof(T) ==
sizeof(U),
"memswap requires both objects of equal size");
70 std::byte tmp[
sizeof(T)];
71 memcpy(tmp, &src,
sizeof(T));
72 memcpy(&src, &dst,
sizeof(U));
73 memcpy(&dst, tmp,
sizeof(T));
86template<
typename InputIt,
typename T>
89 hi_axiom_not_null(dst);
90 return new (dst) T(*src);
97template<
typename InputIt,
typename T>
100 hi_axiom(src_first != dst_first);
101 hi_axiom(src_last >= src_first);
103 auto src = src_first;
104 auto dst = dst_first;
105 while (src != src_last) {
126 hi_axiom_not_null(src);
127 hi_axiom_not_null(dst);
129 auto dst_ =
new (dst) T(
std::move(*src));
130 std::destroy_at(src);
146 hi_axiom(src_last >= src_first);
148 if (src_first < dst_first) {
149 auto dst_last = dst_first + (src_last - src_first);
153 while (src != src_first) {
157 }
else if (src_first > dst_first) {
158 auto src = src_first;
159 auto dst = dst_first;
160 while (src != src_last) {
180 hi_axiom(src_last >= src);
182 while (src != src_last) {
189template<
typename It,
typename... Args>
192 for (
auto it = first; it != last; ++it) {
206constexpr T *ceil(T *ptr,
std::size_t alignment)
noexcept
208 auto const aligned_byte_offset = ceil(
reinterpret_cast<uintptr_t
>(ptr), wide_cast<uintptr_t>(alignment));
209 return reinterpret_cast<T *
>(aligned_byte_offset);
213constexpr T *
floor(T *ptr, std::size_t alignment)
noexcept
215 auto const aligned_byte_offset =
floor(
reinterpret_cast<uintptr_t
>(ptr), wide_cast<uintptr_t>(alignment));
216 return reinterpret_cast<T *
>(aligned_byte_offset);
227 hi_axiom_not_null(ptr);
228 return static_cast<char *
>(ptr) + distance;
239 hi_axiom_not_null(ptr);
240 return static_cast<char const *
>(ptr) + distance;
247 while (i != v.end()) {
256template<
typename K,
typename T>
257inline void cleanupWeakPointers(std::unordered_map<K, std::weak_ptr<T>>& v)
noexcept
260 while (i != v.end()) {
261 if (i->second.expired()) {
269template<
typename K,
typename T>
270inline void cleanupWeakPointers(std::unordered_map<K, std::vector<std::weak_ptr<T>>>& v)
noexcept
273 while (i != v.end()) {
274 cleanupWeakPointers(i->second);
275 if (i->second.size() == 0) {
283template<
typename Value,
typename Map,
typename Key,
typename... Args>
284inline std::shared_ptr<Value> try_make_shared(Map& map, Key key, Args... args)
286 std::shared_ptr<Value> value;
288 auto const i = map.find(key);
289 if (i == map.end()) {
291 map.insert_or_assign(key, value);
300template<numeric T,
byte_like B>
305 if (not std::is_constant_evaluated()) {
311 if constexpr (std::endian::native == std::endian::little) {
312 for (
auto i =
sizeof(T); i != 0; --i) {
313 if constexpr (
sizeof(r) > 1) {
316 r |=
static_cast<uint8_t
>(src[i - 1]);
319 for (
auto i = 0; i !=
sizeof(T); ++i) {
320 if constexpr (
sizeof(r) > 1) {
323 r |=
static_cast<uint8_t
>(src[i]);
330[[nodiscard]]
inline T unaligned_load(
void const *src)
noexcept
332 return unaligned_load<T>(
static_cast<std::byte
const *
>(src));
335template<numeric T,
byte_like B>
336constexpr void unaligned_store(T src, B *dst)
noexcept
338 using unsigned_type = std::make_unsigned_t<T>;
340 auto const src_ =
static_cast<unsigned_type
>(src);
342 if (not std::is_constant_evaluated()) {
347 if constexpr (std::endian::native == std::endian::little) {
348 for (
auto i = 0; i !=
sizeof(T); ++i) {
349 dst[i] =
static_cast<B
>(src_);
353 for (
auto i =
sizeof(T); i != 0; --i) {
354 dst[i - 1] =
static_cast<B
>(src_);
361void unaligned_store(T src,
void *dst)
noexcept
363 return unaligned_store(src,
reinterpret_cast<std::byte *
>(dst));
366template<std::
integral T>
367hi_force_inline
constexpr void store_or(T src, uint8_t *dst)
noexcept
369 hi_axiom_not_null(dst);
371 using unsigned_type = std::make_unsigned_t<T>;
373 auto src_ = truncate<unsigned_type>(src);
375 if (not std::is_constant_evaluated()) {
382 if constexpr (std::endian::native == std::endian::little) {
383 for (
auto i = 0; i !=
sizeof(T); ++i) {
384 dst[i] |= truncate<uint8_t>(src_);
388 for (
auto i =
sizeof(T); i != 0; --i) {
389 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:87
auto make_shared_ctad(Args &&...args)
make_shared with CTAD (Class Template Argument Deduction)
Definition memory.hpp:55
void * advance_bytes(void *ptr, std::ptrdiff_t distance) noexcept
Advance a pointer by a number of bytes.
Definition memory.hpp:225
void construct(It first, It last, Args const &...args)
Construct a set of objects.
Definition memory.hpp:190
auto make_unique_ctad(Args &&...args)
make_unique with CTAD (Class Template Argument Deduction)
Definition memory.hpp:42
constexpr bool is_aligned(T *p)
Check if a pointer is properly aligned for the object it is pointing at.
Definition memory.hpp:200
void placement_move_within_array(T *src_first, T *src_last, T *dst_first)
Move an objects between two memory locations.
Definition memory.hpp:144
constexpr T unaligned_load(B const *src) noexcept
Make an unaligned load of an unsigned integer.
Definition memory.hpp:301
T * placement_move(T *src, T *dst)
Move an object between two memory locations.
Definition memory.hpp:124