SDEngine
Game Engine
Loading...
Searching...
No Matches
base.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <meta>
4#include <ostream>
5#include <string_view>
6#include <type_traits>
7#if defined(_MSC_VER)
8#define TRAP() __debugbreak()
9#elif defined(__GNUC__) || defined(__clang__)
10#define TRAP() __builtin_trap()
11#else
12#error Unknown trap intrinsic for compiler.
13#endif
14#define ASSERT_ALWAYS(x) \
15 do { \
16 if (!(x)) { \
17 TRAP(); \
18 } \
19 } while (0)
20
21#ifdef SD_DEBUG
22#define ASSERT(x) ASSERT_ALWAYS(x)
23#else
24#define ASSERT(x) (void)(x)
25#endif
26#define INVALID_PATH ASSERT(!"Invalid Path!")
27#define NOT_IMPLEMENTED ASSERT(!"Not Implemented!")
28#define NO_OP ((void)0)
29
30#if defined(__GNUC__) || defined(__clang__)
31#define FORCE_INLINE [[gnu::always_inline]] inline
32#else
33#error "Not defined for your compiler"
34#endif
35
36
37//~ BITMASK ENUM OPERATIONS
38template<typename T>
39struct sdIsBitmaskEnum : std::false_type {};
40template<typename T> concept BitmaskEnum = sdIsBitmaskEnum<T>::value;
41
42#define BITMASK_ENUM(Type) \
43 static_assert(std::is_enum_v<Type>, "BITMASK_ENUM can only be used on enum types"); \
44 template<> \
45 struct sdIsBitmaskEnum<Type> : std::true_type {};
46
47template<BitmaskEnum T>
49 using U = std::underlying_type_t<T>;
51
52 FORCE_INLINE constexpr operator bool() const noexcept { return value != 0; } // NOLINT
53 FORCE_INLINE constexpr operator T() const noexcept { return static_cast<T>(value); } // NOLINT
54};
55template<BitmaskEnum T>
56FORCE_INLINE constexpr BitmaskResult<T> operator&(T lhs, T rhs) {
57 using U = std::underlying_type_t<T>;
58 return {static_cast<U>(lhs) & static_cast<U>(rhs)};
59}
60
61template<BitmaskEnum T>
62FORCE_INLINE constexpr BitmaskResult<T> operator|(T lhs, T rhs) {
63 using U = std::underlying_type_t<T>;
64 return {static_cast<U>(lhs) | static_cast<U>(rhs)};
65}
66
67template<BitmaskEnum T>
68FORCE_INLINE constexpr BitmaskResult<T> operator~(T rhs) {
69 using U = std::underlying_type_t<T>;
70 return {static_cast<U>(~static_cast<U>(rhs))};
71}
72
73template<BitmaskEnum T>
74FORCE_INLINE constexpr T& operator|=(T& lhs, T rhs) {
75 using U = std::underlying_type_t<T>;
76 lhs = static_cast<T>(static_cast<U>(lhs) | static_cast<U>(rhs));
77 return lhs;
78}
79
80template<BitmaskEnum T>
81FORCE_INLINE constexpr T& operator&=(T& lhs, T rhs) {
82 using U = std::underlying_type_t<T>;
83 lhs = static_cast<T>(static_cast<U>(lhs) & static_cast<U>(rhs));
84 return lhs;
85}
86
87//~ AUTOMATIC ENUM STRING CONVERSION
88template<typename T>
91
92 friend std::ostream& operator<<(std::ostream& os, BitmaskStreamer wrapper) {
93 using U = std::underlying_type_t<T>;
94 U numeric_value = static_cast<U>(wrapper.value);
95
96 if (numeric_value == 0) {
97 return os << "None";
98 }
99
100 static constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
101 bool first = true;
102
103 template for (constexpr auto e : enumerators) {
104 constexpr U flag_val = static_cast<U>([:e:]);
105 if constexpr (flag_val != 0) {
106 if ((numeric_value & flag_val) == flag_val) {
107 if (!first)
108 os << " | ";
109 first = false;
110 os << std::meta::identifier_of(e);
111 }
112 }
113 }
114 return os;
115 }
116};
117
118template<typename T>
119 requires std::is_enum_v<T> && (!sdIsBitmaskEnum<T>::value)
120[[nodiscard]] FORCE_INLINE constexpr std::string_view enum_to_string(T value) noexcept {
121 static constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
122
123 template for (constexpr auto e : enumerators) {
124 if (value == [:e:]) {
125 return std::meta::identifier_of(e);
126 }
127 }
128 return "Unknown";
129}
130
131template<typename T>
132 requires BitmaskEnum<T>
133[[nodiscard]] FORCE_INLINE constexpr BitmaskStreamer<T> enum_to_string(T value) noexcept {
134 return {value};
135}
136
137
138//~ SourceLocation
139#if defined(__GNUC__) || defined(__clang__) || (defined(_MSC_VER) && (_MSC_VER >= 1926))
140#define SD_FILE __builtin_FILE()
141#define SD_LINE __builtin_LINE()
142#else
143#error "__buitin_FILE() not defined for your compiler"
144#endif
145
146
147namespace sd {
149 const char* file;
150 unsigned line;
151
152 static consteval SourceLocation current(const char* file = __builtin_FILE(),
153 unsigned line = __builtin_LINE()) {
154 return {file, line};
155 }
156};
157} // namespace sd
FORCE_INLINE constexpr BitmaskResult< T > operator~(T rhs)
Definition base.hpp:68
FORCE_INLINE constexpr T & operator|=(T &lhs, T rhs)
Definition base.hpp:74
FORCE_INLINE constexpr BitmaskResult< T > operator&(T lhs, T rhs)
Definition base.hpp:56
FORCE_INLINE constexpr BitmaskResult< T > operator|(T lhs, T rhs)
Definition base.hpp:62
FORCE_INLINE constexpr std::string_view enum_to_string(T value) noexcept
Definition base.hpp:120
FORCE_INLINE constexpr T & operator&=(T &lhs, T rhs)
Definition base.hpp:81
Definition base.hpp:40
Definition Application.hpp:22
Definition base.hpp:48
U value
Definition base.hpp:50
std::underlying_type_t< T > U
Definition base.hpp:49
Definition base.hpp:89
friend std::ostream & operator<<(std::ostream &os, BitmaskStreamer wrapper)
Definition base.hpp:92
T value
Definition base.hpp:90
Definition base.hpp:39
Definition base.hpp:148
unsigned line
Definition base.hpp:150
const char * file
Definition base.hpp:149
static consteval SourceLocation current(const char *file=__builtin_FILE(), unsigned line=__builtin_LINE())
Definition base.hpp:152