summaryrefslogtreecommitdiff
path: root/deimos/core/base.h
blob: 5cd3a408a579ce60f9e92bf5590a6a6afbee4dbd (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#pragma once

#include "deimos/core/std.h"
#include "deimos/core/gsl.h"

#define deimos_StaticAssert(...) static_assert(__VA_ARGS__, #__VA_ARGS__)

#define deimos_Panic(MSG) do { __builtin_trap(); } while (0)

#define deimos_NO_COPY(TYPE)                            \
    TYPE(const TYPE&) = delete;                         \
    TYPE& operator=(const TYPE&) = delete;

#define deimos_NO_MOVE(TYPE)                            \
    TYPE(TYPE&&) = delete;                              \
    TYPE& operator=(TYPE&&) = delete;

#define deimos_NO_COPY_MOVE(TYPE)                       \
    deimos_NO_COPY(TYPE);                               \
    deimos_NO_MOVE(TYPE);

#define deimos_DEFAULT_COPY(TYPE)                       \
    TYPE(const TYPE&) = default;                        \
    TYPE& operator=(const TYPE&) = default;

#define deimos_DEFAULT_MOVE(TYPE)                       \
    TYPE(TYPE&&) = default;                             \
    TYPE& operator=(TYPE&&) = default;

#define deimos_DEFAULT_COPY_MOVE(TYPE)                  \
    deimos_DEFAULT_COPY(TYPE);                          \
    deimos_DEFAULT_MOVE(TYPE);

namespace deimos
{

struct uint128_t
{
    uint64_t high;
    uint64_t low;

    constexpr bool operator==(const uint128_t& other) const = default;
};

struct SourceLocation
{
    gsl::czstring   file;
    int32_t         line;

    constexpr SourceLocation( // NOLINT
        gsl::czstring file_ = __builtin_FILE(),
        int32_t line_ = __builtin_LINE()) :
        file{file_},
        line{line_}
    {}
};

template<typename T> T Min(T a, T b) { return (a < b) ? a : b; }
template<typename T> T Max(T a, T b) { return (a > b) ? a : b; }

[[maybe_unused]] static constexpr int64_t Kilobytes = 1024;
[[maybe_unused]] static constexpr int64_t Megabytes = 1024 * 1024;
[[maybe_unused]] static constexpr int64_t Gigabytes = 1024 * 1024 * 1024;

constexpr int64_t AlignUp(int64_t value, int64_t align)
{
    return __builtin_align_up(value, align);
}

template<typename T>
constexpr T* OffsetBytes(T* p, int64_t offset)
{
    return std::bit_cast<T*>(std::bit_cast<uintptr_t>(p) + std::bit_cast<uintptr_t>(offset));
}

constexpr void MemoryCopy(void* dst, const void* src, int64_t size)
{
    __builtin_memcpy(dst, src, (size_t)size);
}

template<typename T, int64_t N>
constexpr int64_t ArraySize(const T (&)[N]) { return N; }

template<typename T>
class Span
{
    T*      m_begin = nullptr;
    int64_t m_size  = 0;

public:
    constexpr Span() = default;
    ~Span() = default;

    deimos_DEFAULT_COPY_MOVE(Span);

    constexpr Span(T* begin, int64_t size) :
        m_begin{begin},
        m_size{size}
    {
        Expects(size >= 0);
    }

    constexpr Span(std::initializer_list<T> list) :
        m_begin{list.begin()},
        m_size{(int64_t)list.size()}
    {}

    template<typename U>
    requires std::convertible_to<U*, T*>
    constexpr Span(const Span<U>& other) : // NOLINT(*-explicit-conversions)
        m_begin{other.begin()},
        m_size{other.size()}
    {}

    constexpr T* data() const { return m_begin; }
    constexpr T* begin() const { return m_begin; }
    constexpr T* end() const { return m_begin + m_size; } // NOLINT
    constexpr int64_t size() const { return m_size; }
    constexpr bool empty() const { return m_size == 0; }
};

template<typename T>
inline Span<const std::byte> AsBytes(Span<T> span)
{
    return { reinterpret_cast<const std::byte*>(span.data()), span.size() * (int64_t)sizeof(T) };
}

class StringView
{
    const char*     m_begin = nullptr;
    int64_t         m_size  = 0;

public:
    constexpr StringView() = default;

    deimos_DEFAULT_COPY_MOVE(StringView);
    ~StringView() = default;

    constexpr StringView(gsl::czstring str) : // NOLINT(*-explicit-conversions)
        m_begin{str}, m_size{(int64_t)__builtin_strlen(str)}
    {}

    constexpr StringView(const char* begin, int64_t size) :
        m_begin{begin}, m_size{size}
    {}

    constexpr const char* data() const { return m_begin; }
    constexpr int64_t size() const { return m_size; }
    constexpr bool empty() const { return m_size == 0; }
};

inline Span<const std::byte> AsBytes(StringView span)
{
    return { reinterpret_cast<const std::byte*>(span.data()), span.size() };
}

deimos_StaticAssert(std::is_trivially_destructible_v<StringView>);
deimos_StaticAssert(std::is_trivially_copyable_v<StringView>);

} // namespace deimos