cbase 1.46.11
C/C++ Static Template
Loading...
Searching...
No Matches
base_macros.h
Go to the documentation of this file.
1
11
12#ifndef BASE_MACROS_H
13#define BASE_MACROS_H
14
15#if defined(_WIN32)
16# ifndef WIN32_LEAN_AND_MEAN
18# define WIN32_LEAN_AND_MEAN
19# endif
20// Note: We don't include <windows.h> here to prevent namespace pollution.
21// Include it manually in the specific .c files that need it.
22#elif defined(__linux__) || (defined(__APPLE__) && defined(__MACH__))
24# include <unistd.h>
25#endif
26
27#if defined(__clang__)
29# define COMPILER_CLANG 1
31# define COMPILER_NAME "Clang"
32#elif defined(__GNUC__)
34# define COMPILER_GCC 1
36# define COMPILER_NAME "GCC"
37#elif defined(_MSC_VER)
39# define COMPILER_MSVC 1
41# define COMPILER_NAME "MSVC"
42#else
43# error "Compiler not supported"
44#endif
45
46#if defined(_WIN32)
48# define OS_WINDOWS 1
50# define OS_NAME "Windows"
51#elif defined(__linux__)
53# define OS_LINUX 1
55# define OS_NAME "Linux"
56#elif defined(__APPLE__) && defined(__MACH__)
58# define OS_MAC 1
60# define OS_NAME "macOS"
61#else
62# error "Operating system not supported"
63#endif
64
65#if defined(_M_X64) || defined(__x86_64__)
67# define ARCH_X64 1
69# define ARCH_NAME "x86_64"
70#elif defined(_M_IX86) || defined(__i386__)
72# define ARCH_X86 1
74# define ARCH_NAME "x86"
75#elif defined(_M_ARM64) || defined(__aarch64__)
77# define ARCH_ARM64 1
79# define ARCH_NAME "ARM64"
80#elif defined(_M_ARM) || defined(__arm__)
82# define ARCH_ARM 1
84# define ARCH_NAME "ARM"
85#else
86# error "Architecture not supported"
87#endif
88
89#if defined(NDEBUG)
91# define BUILD_RELEASE 1
93# define BUILD_NAME "Release"
94#else
96# define BUILD_DEBUG 1
98# define BUILD_NAME "Debug"
99#endif
100
101#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(_M_IX86) || \
102 defined(_M_X64) || defined(__i386__) || defined(__x86_64__) || defined(_M_ARM) || \
103 defined(_M_ARM64)
105# define ENDIAN_LITTLE 1
107# define ENDIAN_NAME "Little Endian"
108#elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || defined(__BIG_ENDIAN__)
110# define ENDIAN_BIG 1
112# define ENDIAN_NAME "Big Endian"
113#else
114# error "Could not determine endianness"
115#endif
116
117#if defined(__STDC_VERSION__)
118# if __STDC_VERSION__ >= 202311L
120# define C_STANDARD 23
122# define C_STANDARD_NAME "C23"
123# elif __STDC_VERSION__ >= 201710L
124# define C_STANDARD 17
125# define C_STANDARD_NAME "C17"
126# elif __STDC_VERSION__ >= 201112L
127# define C_STANDARD 11
128# define C_STANDARD_NAME "C11"
129# elif __STDC_VERSION__ >= 199901L
130# define C_STANDARD 99
131# define C_STANDARD_NAME "C99"
132# else
133# define C_STANDARD 89
134# define C_STANDARD_NAME "C89"
135# endif
136#else
138# define C_STANDARD 89
140# define C_STANDARD_NAME "C89/Default"
141#endif
142
143#include <stddef.h>
144#include <stdint.h>
145#include <stdio.h>
146#include <string.h>
147
153
155#define function static
156
158#define global static
159
161#define local_persist static
162
164#define external extern
165
167#if defined(COMPILER_MSVC)
168# define thread_local __declspec(thread)
169#elif defined(COMPILER_CLANG) || defined(COMPILER_GCC)
170# define thread_local __thread
171#elif C_STANDARD >= 11
172# define thread_local _Thread_local
173#else
174# error "Thread local storage not supported on this compiler!"
175#endif
176
177#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
179# define API_EXPORT __attribute__((visibility("default")))
181# define API_LOCAL __attribute__((visibility("hidden")))
182#elif defined(COMPILER_MSVC)
184# define API_EXPORT __declspec(dllexport)
186# define API_LOCAL
187#else
189# define API_EXPORT
191# define API_LOCAL
192#endif
193
194#ifdef __cplusplus
196# define C_LINKAGE_BEGIN extern "C" {
198# define C_LINKAGE_END }
199#else
201# define C_LINKAGE_BEGIN
203# define C_LINKAGE_END
204#endif
206
212
214#define STRINGIFY_DETAIL(x) #x
220#define STRINGIFY(x) STRINGIFY_DETAIL(x)
221
223#define GLUE_DETAIL(x, y) x##y
229#define GLUE(x, y) GLUE_DETAIL(x, y)
230
236#define INT_FROM_PTR(ptr) ((uintptr_t)(ptr))
237
244#define PTR_FROM_INT(type, val) ((type *)(uintptr_t)(val))
245
252#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
253
254#if defined(__GNUC__) || defined(__clang__) || \
255 (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L)
256
257# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
258# define _TYPEOF(x) typeof(x)
259# else
260# define _TYPEOF(x) __typeof__(x)
261# endif
262
266# define MIN(a, b) \
267 ({ \
268 _TYPEOF(a) _a = (a); \
269 _TYPEOF(b) _b = (b); \
270 _a < _b ? _a : _b; \
271 })
272
276# define MAX(a, b) \
277 ({ \
278 _TYPEOF(a) _a = (a); \
279 _TYPEOF(b) _b = (b); \
280 _a > _b ? _a : _b; \
281 })
282
286# define CLAMP(val, min, max) \
287 ({ \
288 _TYPEOF(val) _v = (val); \
289 _TYPEOF(min) _mn = (min); \
290 _TYPEOF(max) _mx = (max); \
291 (_v < _mn) ? _mn : ((_v > _mx) ? _mx : _v); \
292 })
293
294#else
295// Fallbacks for standard C89/C11 (MSVC)
297# define MIN(a, b) (((a) < (b)) ? (a) : (b))
299# define MAX(a, b) (((a) > (b)) ? (a) : (b))
301# define CLAMP(val, min, max) (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val))
302#endif
303
310#define SWAP(type, a, b) \
311 do { \
312 type _tmp = (a); \
313 (a) = (b); \
314 (b) = _tmp; \
315 } while (0)
316
321#define Boolify(x) ((x) != 0)
322
330#define AsciiID4(a, b, c, d) (((d) << 24) | ((c) << 16) | ((b) << 8) | (a))
331
336#define ExpandAsciiID(x) (int)(sizeof(x)), (char *)(&(x))
338
344
351#define ALIGN_UP_POW2(x, p) (((x) + (p) - 1) & ~((p) - 1))
352
359#define ALIGN_DOWN_POW2(x, p) ((x) & ~((p) - 1))
360
366#define IS_POW2_OR_ZERO(x) (((x) & ((x) - 1)) == 0)
367
374#define SHIFT8(T, x, s) ((T)(x) << (s))
375
384#define PACK_U32_LE(a, b, c, d) \
385 (SHIFT8(U32, a, 0) | SHIFT8(U32, b, 8) | SHIFT8(U32, c, 16) | SHIFT8(U32, d, 24))
386
387
393
395#define MEM_ZERO(ptr, size) memset((ptr), 0, (size))
396
401#define MEM_ZERO_STRUCT(ptr) MEM_ZERO((ptr), sizeof(*(ptr)))
402
407#define MEM_ZERO_ARRAY(arr) MEM_ZERO((arr), sizeof(arr))
408
410#define MEM_COPY(dst, src, size) memmove((dst), (src), (size))
411
418#define MEM_COPY_STRUCT(dst, src) MEM_COPY((dst), (src), MIN(sizeof(*(dst)), sizeof(*(src))))
419
426#define MEM_COPY_ARRAY(dst, src) MEM_COPY((dst), (src), MIN(sizeof(dst), sizeof(src)))
428
441
450#define DLL_PUSH_BACK_NP(f, l, n, next, prev) \
451 ((f) == 0 ? ((f) = (l) = (n), (n)->next = (n)->prev = 0) \
452 : ((n)->prev = (l), (l)->next = (n), (l) = (n), (n)->next = 0))
453
473#define DLL_PUSH_BACK(f, l, n) DLL_PUSH_BACK_NP(f, l, n, next, prev)
474
484#define DLL_PUSH_FRONT(f, l, n) DLL_PUSH_BACK_NP(l, f, n, prev, next)
485
494#define DLL_REMOVE_NP(f, l, n, next, prev) \
495 ((f) == (n) ? ((f) == (l) ? ((f) = (l) = (0)) : ((f) = (f)->next, (f)->prev = 0)) \
496 : (l) == (n) ? ((l) = (l)->prev, (l)->next = 0) \
497 : ((n)->next->prev = (n)->prev, (n)->prev->next = (n)->next))
498
509#define DLL_REMOVE(f, l, n) DLL_REMOVE_NP(f, l, n, next, prev)
510
518#define SLL_QUEUE_PUSH_N(f, l, n, next) \
519 (((f) == 0 ? (f) = (l) = (n) : ((l)->next = (n), (l) = (n))), (n)->next = 0)
520
530#define SLL_QUEUE_PUSH(f, l, n) SLL_QUEUE_PUSH_N(f, l, n, next)
531
538#define SLL_STACK_PUSH_N(f, n, next) ((n)->next = (f), (f) = (n))
539
548#define SLL_STACK_PUSH(f, n) SLL_STACK_PUSH_N(f, n, next)
549
555#define SLL_STACK_POP_N(f, next) ((f) == 0 ? 0 : ((f) = (f)->next))
556
565#define SLL_STACK_POP(f) SLL_STACK_POP_N(f, next)
567
573
574#if defined(COMPILER_MSVC)
576# define debug_break() __debugbreak()
577#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
579# define debug_break() __builtin_trap()
580#else
582# define debug_break() (*(volatile int *)0 = 0)
583#endif
584
585#if BUILD_DEBUG
590# define ASSERT(expr) \
591 do { \
592 if (!(expr)) { \
593 fputs("Assertion failed: " #expr "\n", stderr); \
594 fputs("File: " __FILE__ "\n", stderr); \
595 fputs("Line: " STRINGIFY(__LINE__) "\n", stderr); \
596 debug_break(); \
597 } \
598 } while (0)
599
604# define ASSERT_NOT_NULL(ptr) \
605 do { \
606 if ((ptr) == NULL) { \
607 fputs("Assertion failed: " #ptr " is NULL\n", stderr); \
608 fputs("File: " __FILE__ "\n", stderr); \
609 fputs("Line: " STRINGIFY(__LINE__) "\n", stderr); \
610 debug_break(); \
611 } \
612 } while (0)
613#else
614// Compile assertions out completely in Release builds for zero overhead
615# define ASSERT(expr) ((void)0)
616# define ASSERT_NOT_NULL(ptr) ((void)0)
617#endif
619
620#endif // BASE_MACROS_H