cbase
1.50.0
C/C++ Static Template
Loading...
Searching...
No Matches
base_macros.h
Go to the documentation of this file.
1
34
35
#ifndef BASE_MACROS_H
36
#define BASE_MACROS_H
37
38
#if defined(_WIN32)
39
# ifndef WIN32_LEAN_AND_MEAN
41
# define WIN32_LEAN_AND_MEAN
42
# endif
43
// Note: We don't include <windows.h> here to prevent namespace pollution.
44
// Include it manually in the specific .c files that need it.
45
#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
47
# include <unistd.h>
48
#endif
49
50
#if defined(__clang__)
52
# define COMPILER_CLANG 1
54
# define COMPILER_NAME "Clang"
55
#elif defined(__GNUC__)
57
# define COMPILER_GCC 1
59
# define COMPILER_NAME "GCC"
60
#elif defined(_MSC_VER)
62
# define COMPILER_MSVC 1
64
# define COMPILER_NAME "MSVC"
65
#else
66
# error "Compiler not supported"
67
#endif
68
69
#if defined(_WIN32)
71
# define OS_WINDOWS 1
73
# define OS_NAME "Windows"
74
#elif defined(__linux__)
76
# define OS_LINUX 1
78
# define OS_NAME "Linux"
79
#elif defined(__APPLE__) && defined(__MACH__)
81
# define OS_MAC 1
83
# define OS_NAME "macOS"
84
#else
85
# error "Operating system not supported"
86
#endif
87
88
#if defined(_M_X64) || defined(__x86_64__)
90
# define ARCH_X64 1
92
# define ARCH_NAME "x86_64"
93
#elif defined(_M_IX86) || defined(__i386__)
95
# define ARCH_X86 1
97
# define ARCH_NAME "x86"
98
#elif defined(_M_ARM64) || defined(__aarch64__)
100
# define ARCH_ARM64 1
102
# define ARCH_NAME "ARM64"
103
#elif defined(_M_ARM) || defined(__arm__)
105
# define ARCH_ARM 1
107
# define ARCH_NAME "ARM"
108
#else
109
# error "Architecture not supported"
110
#endif
111
112
#if defined(NDEBUG)
114
# define BUILD_RELEASE 1
116
# define BUILD_NAME "Release"
117
#else
119
# define BUILD_DEBUG 1
121
# define BUILD_NAME "Debug"
122
#endif
123
124
#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(_M_IX86) || \
125
defined(_M_X64) || defined(__i386__) || defined(__x86_64__) || defined(_M_ARM) || \
126
defined(_M_ARM64)
128
# define ENDIAN_LITTLE 1
130
# define ENDIAN_NAME "Little Endian"
131
#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || defined(__BIG_ENDIAN__)
133
# define ENDIAN_BIG 1
135
# define ENDIAN_NAME "Big Endian"
136
#else
137
# error "Could not determine endianness"
138
#endif
139
140
#if defined(__STDC_VERSION__)
141
# if __STDC_VERSION__ >= 202311L
143
# define C_STANDARD 23
145
# define C_STANDARD_NAME "C23"
146
# elif __STDC_VERSION__ >= 201710L
147
# define C_STANDARD 17
148
# define C_STANDARD_NAME "C17"
149
# elif __STDC_VERSION__ >= 201112L
150
# define C_STANDARD 11
151
# define C_STANDARD_NAME "C11"
152
# elif __STDC_VERSION__ >= 199901L
153
# define C_STANDARD 99
154
# define C_STANDARD_NAME "C99"
155
# else
156
# define C_STANDARD 89
157
# define C_STANDARD_NAME "C89"
158
# endif
159
#else
161
# define C_STANDARD 89
163
# define C_STANDARD_NAME "C89/Default"
164
#endif
165
166
#include <stddef.h>
167
#include <stdint.h>
168
#include <stdio.h>
169
#include <string.h>
170
176
178
#define function static
179
181
#define global static
182
184
#define local_persist static
185
187
#define external extern
188
190
#if defined(COMPILER_MSVC)
191
# define thread_local __declspec(thread)
192
#elif defined(COMPILER_CLANG) || defined(COMPILER_GCC)
193
# define thread_local __thread
194
#elif C_STANDARD >= 11
195
# define thread_local _Thread_local
196
#else
197
# error "Thread local storage not supported on this compiler!"
198
#endif
199
200
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
202
# define API_EXPORT __attribute__((visibility("default")))
204
# define API_LOCAL __attribute__((visibility("hidden")))
205
#elif defined(COMPILER_MSVC)
207
# define API_EXPORT __declspec(dllexport)
209
# define API_LOCAL
210
#else
212
# define API_EXPORT
214
# define API_LOCAL
215
#endif
216
217
#ifdef __cplusplus
219
# define C_LINKAGE_BEGIN extern "C" {
221
# define C_LINKAGE_END }
222
#else
224
# define C_LINKAGE_BEGIN
226
# define C_LINKAGE_END
227
#endif
229
235
237
#define STRINGIFY_DETAIL(x) #x
253
#define STRINGIFY(x) STRINGIFY_DETAIL(x)
254
256
#define GLUE_DETAIL(x, y) x##y
271
#define GLUE(x, y) GLUE_DETAIL(x, y)
272
286
#define INT_FROM_PTR(ptr) ((uintptr_t)(ptr))
287
301
#define PTR_FROM_INT(type, val) ((type *)(uintptr_t)(val))
302
318
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
319
320
#if defined(__GNUC__) || defined(__clang__) || \
321
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
322
323
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
324
# define _TYPEOF(x) typeof(x)
325
# else
326
# define _TYPEOF(x) __typeof__(x)
327
# endif
328
332
# define MIN(a, b) \
333
({ \
334
_TYPEOF(a) _a = (a); \
335
_TYPEOF(b) _b = (b); \
336
_a < _b ? _a : _b; \
337
})
338
342
# define MAX(a, b) \
343
({ \
344
_TYPEOF(a) _a = (a); \
345
_TYPEOF(b) _b = (b); \
346
_a > _b ? _a : _b; \
347
})
348
352
# define CLAMP(val, min, max) \
353
({ \
354
_TYPEOF(val) _v = (val); \
355
_TYPEOF(min) _mn = (min); \
356
_TYPEOF(max) _mx = (max); \
357
(_v < _mn) ? _mn : ((_v > _mx) ? _mx : _v); \
358
})
359
360
#else
361
// Fallbacks for standard C89/C11 (MSVC)
363
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
365
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
367
# define CLAMP(val, min, max) (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val))
368
#endif
369
387
#define SWAP(type, a, b) \
388
do { \
389
type _tmp = (a); \
390
(a) = (b); \
391
(b) = _tmp; \
392
} while (0)
393
409
#define Boolify(x) ((x) != 0)
410
431
#define AsciiID4(a, b, c, d) \
432
(((u32)(u8)(d) << 24) | ((u32)(u8)(c) << 16) | ((u32)(u8)(b) << 8) | (u32)(u8)(a))
433
445
#define ExpandAsciiID(x) (int)(sizeof(x)), (char *)(&(x))
447
453
468
#define ALIGN_UP_POW2(x, p) (((x) + (p) - 1) & ~((p) - 1))
469
483
#define ALIGN_DOWN_POW2(x, p) ((x) & ~((p) - 1))
484
499
#define IS_POW2_OR_ZERO(x) (((x) & ((x) - 1)) == 0)
500
518
#define IS_POW2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
519
526
#define SHIFT8(T, x, s) ((T)(x) << (s))
527
536
#define PACK_U32_LE(a, b, c, d) \
537
(SHIFT8(U32, a, 0) | SHIFT8(U32, b, 8) | SHIFT8(U32, c, 16) | SHIFT8(U32, d, 24))
538
539
545
547
#define MEM_ZERO(ptr, size) memset((ptr), 0, (size))
548
560
#define MEM_ZERO_STRUCT(ptr) MEM_ZERO((ptr), sizeof(*(ptr)))
561
573
#define MEM_ZERO_ARRAY(arr) MEM_ZERO((arr), sizeof(arr))
574
576
#define MEM_COPY(dst, src, size) memmove((dst), (src), (size))
577
594
#define MEM_COPY_STRUCT(dst, src) MEM_COPY((dst), (src), MIN(sizeof(*(dst)), sizeof(*(src))))
595
609
#define MEM_COPY_ARRAY(dst, src) MEM_COPY((dst), (src), MIN(sizeof(dst), sizeof(src)))
611
624
633
#define DLL_PUSH_BACK_NP(f, l, n, next, prev) \
634
((f) == 0 ? ((f) = (l) = (n), (n)->next = (n)->prev = 0) \
635
: ((n)->prev = (l), (l)->next = (n), (l) = (n), (n)->next = 0))
636
656
#define DLL_PUSH_BACK(f, l, n) DLL_PUSH_BACK_NP(f, l, n, next, prev)
657
667
#define DLL_PUSH_FRONT(f, l, n) DLL_PUSH_BACK_NP(l, f, n, prev, next)
668
677
#define DLL_REMOVE_NP(f, l, n, next, prev) \
678
((f) == (n) ? ((f) == (l) ? ((f) = (l) = (0)) : ((f) = (f)->next, (f)->prev = 0)) \
679
: (l) == (n) ? ((l) = (l)->prev, (l)->next = 0) \
680
: ((n)->next->prev = (n)->prev, (n)->prev->next = (n)->next))
681
692
#define DLL_REMOVE(f, l, n) DLL_REMOVE_NP(f, l, n, next, prev)
693
701
#define SLL_QUEUE_PUSH_N(f, l, n, next) \
702
(((f) == 0 ? (f) = (l) = (n) : ((l)->next = (n), (l) = (n))), (n)->next = 0)
703
713
#define SLL_QUEUE_PUSH(f, l, n) SLL_QUEUE_PUSH_N(f, l, n, next)
714
721
#define SLL_STACK_PUSH_N(f, n, next) ((n)->next = (f), (f) = (n))
722
731
#define SLL_STACK_PUSH(f, n) SLL_STACK_PUSH_N(f, n, next)
732
738
#define SLL_STACK_POP_N(f, next) ((f) == 0 ? 0 : ((f) = (f)->next))
739
748
#define SLL_STACK_POP(f) SLL_STACK_POP_N(f, next)
750
756
757
#if defined(COMPILER_MSVC)
759
# define debug_break() __debugbreak()
760
#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
762
# define debug_break() __builtin_trap()
763
#else
765
# define debug_break() (*(volatile int *)0 = 0)
766
#endif
767
768
#if BUILD_DEBUG
773
# define ASSERT(expr) \
774
do { \
775
if (!(expr)) { \
776
fputs("Assertion failed: " #expr "\n", stderr); \
777
fputs("File: " __FILE__ "\n", stderr); \
778
fputs("Line: " STRINGIFY(__LINE__) "\n", stderr); \
779
debug_break(); \
780
} \
781
} while (0)
782
787
# define ASSERT_NOT_NULL(ptr) \
788
do { \
789
if ((ptr) == NULL) { \
790
fputs("Assertion failed: " #ptr " is NULL\n", stderr); \
791
fputs("File: " __FILE__ "\n", stderr); \
792
fputs("Line: " STRINGIFY(__LINE__) "\n", stderr); \
793
debug_break(); \
794
} \
795
} while (0)
796
#else
797
// Compile assertions out completely in Release builds for zero overhead
798
# define ASSERT(expr) ((void)0)
799
# define ASSERT_NOT_NULL(ptr) ((void)0)
800
#endif
802
803
#endif
// BASE_MACROS_H
include
base
base_macros.h
Generated by
1.16.1