summaryrefslogtreecommitdiff
path: root/asl/memory/memory.hpp
blob: 2c5301eed528f8b1727f6ec0cd71c4feba3d1533 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2025 Steven Le Rouzic
//
// SPDX-License-Identifier: BSD-3-Clause

#pragma once

#include "asl/base/integers.hpp"
#include "asl/base/meta.hpp"
#include "asl/base/utility.hpp"
#include "asl/memory/layout.hpp"

constexpr void* operator new(size_t, void* ptr) noexcept
{
    return ptr;
}

namespace asl
{

constexpr isize_t memcmp(const void* a, const void* b, isize_t size)
{
    return __builtin_memcmp(a, b, static_cast<size_t>(size));
}

constexpr void memcpy(void* dst, const void* src, isize_t size)
{
    __builtin_memcpy(dst, src, static_cast<size_t>(size));
}

inline void memzero(void* dst, isize_t size)
{
    __builtin_memset(dst, 0, static_cast<size_t>(size));
}

constexpr isize_t strlen(const char* s)
{
    return static_cast<isize_t>(__builtin_strlen(s));
}

template<typename T, typename... Args>
constexpr T* construct_at(void* ptr, Args&&... args)
    requires constructible_from<T, Args&&...>
{
    return new (ptr) T{ std::forward<Args>(args)... }; // NOLINT(*-owning-memory)
}

template<typename T>
constexpr void destroy(T* data)
{
    if constexpr (!trivially_destructible<T>)
    {
        data->~T();
    }
}

template<typename T>
constexpr void destroy_n(T* data, isize_t n)
{
    if constexpr (!trivially_destructible<T>)
    {
        for (isize_t i = 0; i < n; ++i)
        {
            destroy(data + i);
        }
    }
}

template<copy_constructible T>
constexpr void copy_uninit_n(T* to, const T* from, isize_t n)
{
    if constexpr (trivially_copy_constructible<T>)
    {
        memcpy(to, from, size_of<T> * n);
    }
    else
    {
        for (isize_t i = 0; i < n; ++i)
        {
            // NOLINTNEXTLINE(*-pointer-arithmetic)
            construct_at<T>(to + i, from[i]);
        }
    }
}

template<copy_assignable T>
constexpr void copy_assign_n(T* to, const T* from, isize_t n)
{
    if constexpr (trivially_copy_constructible<T>)
    {
        memcpy(to, from, size_of<T> * n);
    }
    else
    {
        for (isize_t i = 0; i < n; ++i)
        {
            // NOLINTNEXTLINE(*-pointer-arithmetic)
            to[i] = from[i];
        }
    }
}

template<move_constructible T>
constexpr void relocate_uninit_n(T* to, T* from, isize_t n)
{
    if constexpr (trivially_move_constructible<T>)
    {
        static_assert(trivially_destructible<T>);
        memcpy(to, from, size_of<T> * n);
    }
    else
    {
        for (isize_t i = 0; i < n; ++i)
        {
            // NOLINTNEXTLINE(*-pointer-arithmetic)
            construct_at<T>(to + i, std::move(from[i]));
        }
        destroy_n(from, n);
    }
}

template<move_assignable T>
constexpr void relocate_assign_n(T* to, T* from, isize_t n)
{
    if constexpr (trivially_move_assignable<T>)
    {
        static_assert(trivially_destructible<T>);
        memcpy(to, from, size_of<T> * n);
    }
    else
    {
        for (isize_t i = 0; i < n; ++i)
        {
            // NOLINTNEXTLINE(*-pointer-arithmetic)
            to[i] = std::move(from[i]);
        }
        destroy_n(from, n);
    }
}

} // namespace asl