util.h (10055B)
1 /* See LICENSE for license details. */ 2 #ifndef _UTIL_H_ 3 #define _UTIL_H_ 4 5 #include <stddef.h> 6 #include <stdint.h> 7 8 #include "compiler.h" 9 10 #ifndef asm 11 #define asm __asm__ 12 #endif 13 14 #ifndef typeof 15 #define typeof __typeof__ 16 #endif 17 18 #if OS_WINDOWS 19 #define EXPORT __declspec(dllexport) 20 #else 21 #define EXPORT 22 #endif 23 24 #ifdef _DEBUG 25 #define DEBUG_EXPORT EXPORT 26 #if OS_WINDOWS 27 #ifdef _BEAMFORMER_DLL 28 #define DEBUG_IMPORT __declspec(dllimport) 29 #else 30 #define DEBUG_IMPORT __declspec(dllexport) 31 #endif 32 #else 33 #ifdef _BEAMFORMER_DLL 34 #define DEBUG_IMPORT extern 35 #else 36 #define DEBUG_IMPORT 37 #endif 38 #endif 39 #define DEBUG_DECL(a) a 40 #define assert(c) do { if (!(c)) debugbreak(); } while (0) 41 #else 42 #define DEBUG_IMPORT global 43 #define DEBUG_EXPORT function 44 #define DEBUG_DECL(a) 45 #define assert(c) (void)(c) 46 #endif 47 #define ASSERT assert 48 49 #if ASAN_ACTIVE 50 void __asan_poison_memory_region(void *, ptrdiff_t); 51 void __asan_unpoison_memory_region(void *, ptrdiff_t); 52 #define asan_poison_region(region, size) __asan_poison_memory_region((region), (size)) 53 #define asan_unpoison_region(region, size) __asan_unpoison_memory_region((region), (size)) 54 #else 55 #define asan_poison_region(...) 56 #define asan_unpoison_region(...) 57 #endif 58 59 #define InvalidCodePath assert(0) 60 #define InvalidDefaultCase default: assert(0); break 61 62 #define arg_list(type, ...) (type []){__VA_ARGS__}, sizeof((type []){__VA_ARGS__}) / sizeof(type) 63 64 #define function static 65 #define global static 66 #define local_persist static 67 68 #define alignof _Alignof 69 #define static_assert _Static_assert 70 71 /* NOTE: garbage to get the prepocessor to properly stringize the value of a macro */ 72 #define str_(...) #__VA_ARGS__ 73 #define str(...) str_(__VA_ARGS__) 74 75 #define countof(a) (iz)(sizeof(a) / sizeof(*a)) 76 #define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) 77 #define ABS(x) ((x) < 0 ? (-x) : (x)) 78 #define BETWEEN(x, a, b) ((x) >= (a) && (x) <= (b)) 79 #define CLAMP(x, a, b) ((x) < (a) ? (a) : (x) > (b) ? (b) : (x)) 80 #define CLAMP01(x) CLAMP(x, 0, 1) 81 #define ISPOWEROF2(a) (((a) & ((a) - 1)) == 0) 82 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 83 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 84 #define ORONE(x) ((x)? (x) : 1) 85 #define SIGN(x) ((x) < 0? -1 : 1) 86 #define swap(a, b) do {typeof(a) __tmp = (a); (a) = (b); (b) = __tmp;} while(0) 87 88 #define ISDIGIT(c) (BETWEEN((c), '0', '9')) 89 #define ISUPPER(c) (((c) & 0x20u) == 0) 90 #define TOLOWER(c) (((c) | 0x20u)) 91 #define TOUPPER(c) (((c) & ~(0x20u))) 92 93 #define f32_cmp(x, y) (ABS((x) - (y)) <= F32_EPSILON * MAX(1.0f, MAX(ABS(x), ABS(y)))) 94 95 #define EachBit(a, it) (u64 it = ctz_u64(a); it != 64; a &= ~(1u << (it)), it = ctz_u64(a)) 96 #define EachElement(array, it) (u64 it = 0; it < countof(array); it += 1) 97 #define EachEnumValue(type, it) (type it = (type)0; it < type##_Count; it = (type)(it + 1)) 98 #define EachNonZeroEnumValue(type, it) (type it = (type)1; it < type##_Count; it = (type)(it + 1)) 99 100 #define spin_wait(c) while ((c)) cpu_yield() 101 102 #define DA_STRUCT(kind, name) typedef struct { \ 103 kind *data; \ 104 iz count; \ 105 iz capacity; \ 106 } name ##List; 107 108 /* NOTE(rnp): no guarantees about actually getting an element */ 109 #define SLLPop(list) list; list = list ? list->next : 0 110 #define SLLPush(v, list) do { \ 111 (v)->next = (list); \ 112 (list) = v; \ 113 } while (0) 114 115 #define SLLPopFreelist(list) list; do { \ 116 asan_unpoison_region((list), sizeof(*(list))); \ 117 (void)SLLPop((list)); \ 118 } while(0) 119 120 #define SLLPushFreelist(v, list) do { \ 121 SLLPush((v), (list)); \ 122 asan_poison_region((v), sizeof(*(v))); \ 123 } while(0) 124 125 #define DLLPushDown(v, list) do { \ 126 (v)->next = (list); \ 127 if ((v)->next) (v)->next->prev = (v); \ 128 (list) = (v); \ 129 } while (0) 130 131 #define DLLRemove(v) do { \ 132 if ((v)->next) (v)->next->prev = (v)->prev; \ 133 if ((v)->prev) (v)->prev->next = (v)->next; \ 134 } while (0) 135 136 #define KB(a) ((u64)(a) << 10ULL) 137 #define MB(a) ((u64)(a) << 20ULL) 138 #define GB(a) ((u64)(a) << 30ULL) 139 140 #define I32_MAX (0x7FFFFFFFL) 141 #define U16_MAX (0x0000FFFFUL) 142 #define U32_MAX (0xFFFFFFFFUL) 143 #define F32_INFINITY (1e+300*1e+300) 144 #define F32_EPSILON (1e-6f) 145 #ifndef PI 146 #define PI (3.14159265358979323846f) 147 #endif 148 149 typedef char c8; 150 typedef uint8_t u8; 151 typedef int16_t i16; 152 typedef uint16_t u16; 153 typedef uint16_t b16; 154 typedef int32_t i32; 155 typedef uint32_t u32; 156 typedef int64_t i64; 157 typedef uint64_t u64; 158 typedef uint32_t b32; 159 typedef float f32; 160 typedef double f64; 161 typedef ptrdiff_t iz; 162 typedef size_t uz; 163 typedef ptrdiff_t iptr; 164 typedef size_t uptr; 165 166 #include "intrinsics.c" 167 168 typedef alignas(16) union { 169 u8 U8[16]; 170 u16 U16[8]; 171 u32 U32[4]; 172 u64 U64[2]; 173 u32x4 U32x4; 174 } u128; 175 176 typedef struct { u8 *beg, *end; } Arena; 177 typedef struct { Arena *arena; u8 *old_beg; } TempArena; 178 179 typedef struct { iz len; u8 *data; } s8; 180 #define s8(s) (s8){.len = countof(s) - 1, .data = (u8 *)s} 181 #define s8_comp(s) {sizeof(s) - 1, (u8 *)s} 182 183 typedef struct { iz len; u16 *data; } s16; 184 185 typedef struct { u32 cp, consumed; } UnicodeDecode; 186 187 /* NOTE: raylib stubs */ 188 #ifndef RAYLIB_H 189 typedef struct { f32 x, y; } Vector2; 190 typedef struct { f32 x, y, w, h; } Rectangle; 191 #endif 192 193 typedef union { 194 struct { i32 x, y; }; 195 struct { i32 w, h; }; 196 i32 E[2]; 197 } iv2; 198 199 typedef union { 200 struct { i32 x, y, z; }; 201 struct { i32 w, h, d; }; 202 iv2 xy; 203 i32 E[3]; 204 } iv3; 205 206 typedef union { 207 struct { u32 x, y; }; 208 struct { u32 w, h; }; 209 u32 E[2]; 210 } uv2; 211 212 typedef union { 213 struct { u32 x, y, z; }; 214 struct { u32 w, h, d; }; 215 uv2 xy; 216 u32 E[3]; 217 } uv3; 218 219 typedef union { 220 struct { u32 x, y, z, w; }; 221 struct { uv3 xyz; u32 _w; }; 222 u32 E[4]; 223 } uv4; 224 225 typedef union { 226 struct { f32 x, y; }; 227 struct { f32 w, h; }; 228 Vector2 rl; 229 f32 E[2]; 230 } v2; 231 232 typedef union { 233 struct { f32 x, y, z; }; 234 struct { f32 w, h, d; }; 235 f32 E[3]; 236 } v3; 237 238 typedef union { 239 struct { f32 x, y, z, w; }; 240 struct { f32 r, g, b, a; }; 241 struct { v3 xyz; f32 _1; }; 242 struct { f32 _2; v3 yzw; }; 243 struct { v2 xy, zw; }; 244 f32 E[4]; 245 } v4; 246 247 #define XZ(v) (v2){.x = v.x, .y = v.z} 248 #define YZ(v) (v2){.x = v.y, .y = v.z} 249 #define XY(v) (v2){.x = v.x, .y = v.y} 250 251 typedef union { 252 struct { v4 x, y, z, w; }; 253 v4 c[4]; 254 f32 E[16]; 255 } m4; 256 257 /* TODO(rnp): delete raylib */ 258 typedef struct { 259 v3 origin; 260 v3 direction; 261 } ray; 262 263 typedef union { 264 struct { v2 pos, size; }; 265 Rectangle rl; 266 } Rect; 267 #define INVERTED_INFINITY_RECT (Rect){.pos = {.x = -F32_INFINITY, .y = -F32_INFINITY}, \ 268 .size = {.x = -F32_INFINITY, .y = -F32_INFINITY}} 269 270 typedef struct { 271 u8 *data; 272 i32 widx; 273 i32 cap; 274 b32 errors; 275 } Stream; 276 277 #define INVALID_FILE (-1) 278 279 typedef struct OS OS; 280 281 typedef struct { 282 Arena arena; 283 iptr handle; 284 iptr window_handle; 285 iptr gl_context; 286 iptr user_context; 287 i32 sync_variable; 288 b32 asleep; 289 } GLWorkerThreadContext; 290 291 #define FILE_WATCH_CALLBACK_FN(name) b32 name(s8 path, iptr user_data, Arena arena) 292 typedef FILE_WATCH_CALLBACK_FN(file_watch_callback); 293 294 typedef struct { 295 iptr user_data; 296 u64 hash; 297 file_watch_callback *callback; 298 } FileWatch; 299 300 typedef struct { 301 u64 hash; 302 iptr handle; 303 s8 name; 304 305 FileWatch *data; 306 iz count; 307 iz capacity; 308 Arena buffer; 309 } FileWatchDirectory; 310 DA_STRUCT(FileWatchDirectory, FileWatchDirectory); 311 312 typedef struct { 313 void *region; 314 iptr os_context; 315 } SharedMemoryRegion; 316 317 #define OS_ALLOC_ARENA_FN(name) Arena name(iz capacity) 318 typedef OS_ALLOC_ARENA_FN(os_alloc_arena_fn); 319 320 #define OS_ADD_FILE_WATCH_FN(name) void name(FileWatchDirectoryList *fwctx, Arena *a, s8 path, \ 321 file_watch_callback *callback, iptr user_data) 322 typedef OS_ADD_FILE_WATCH_FN(os_add_file_watch_fn); 323 324 #define OS_WAKE_WORKER_FN(name) void name(GLWorkerThreadContext *ctx) 325 typedef OS_WAKE_WORKER_FN(os_wake_worker_fn); 326 327 #define OS_READ_WHOLE_FILE_FN(name) s8 name(Arena *arena, char *file) 328 typedef OS_READ_WHOLE_FILE_FN(os_read_whole_file_fn); 329 330 #define OS_WAIT_ON_VALUE_FN(name) b32 name(i32 *value, i32 current, u32 timeout_ms) 331 typedef OS_WAIT_ON_VALUE_FN(os_wait_on_value_fn); 332 333 #define OS_WAKE_WAITERS_FN(name) void name(i32 *sync) 334 typedef OS_WAKE_WAITERS_FN(os_wake_waiters_fn); 335 336 #define OS_WRITE_NEW_FILE_FN(name) b32 name(char *fname, s8 raw) 337 typedef OS_WRITE_NEW_FILE_FN(os_write_new_file_fn); 338 339 #define OS_WRITE_FILE_FN(name) b32 name(iptr file, s8 raw) 340 typedef OS_WRITE_FILE_FN(os_write_file_fn); 341 342 #define OS_THREAD_ENTRY_POINT_FN(name) iptr name(iptr _ctx) 343 typedef OS_THREAD_ENTRY_POINT_FN(os_thread_entry_point_fn); 344 345 #define OS_SHARED_MEMORY_LOCK_REGION_FN(name) b32 name(SharedMemoryRegion *sm, i32 *locks, i32 lock_index, u32 timeout_ms) 346 typedef OS_SHARED_MEMORY_LOCK_REGION_FN(os_shared_memory_region_lock_fn); 347 348 #define OS_SHARED_MEMORY_UNLOCK_REGION_FN(name) void name(SharedMemoryRegion *sm, i32 *locks, i32 lock_index) 349 typedef OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock_fn); 350 351 #define RENDERDOC_GET_API_FN(name) b32 name(u32 version, void **out_api) 352 typedef RENDERDOC_GET_API_FN(renderdoc_get_api_fn); 353 354 #define RENDERDOC_START_FRAME_CAPTURE_FN(name) void name(iptr gl_context, iptr window_handle) 355 typedef RENDERDOC_START_FRAME_CAPTURE_FN(renderdoc_start_frame_capture_fn); 356 357 #define RENDERDOC_END_FRAME_CAPTURE_FN(name) b32 name(iptr gl_context, iptr window_handle) 358 typedef RENDERDOC_END_FRAME_CAPTURE_FN(renderdoc_end_frame_capture_fn); 359 360 typedef alignas(16) u8 RenderDocAPI[216]; 361 #define RENDERDOC_API_FN_ADDR(a, offset) (*(iptr *)((*a) + offset)) 362 #define RENDERDOC_START_FRAME_CAPTURE(a) (renderdoc_start_frame_capture_fn *)RENDERDOC_API_FN_ADDR(a, 152) 363 #define RENDERDOC_END_FRAME_CAPTURE(a) (renderdoc_end_frame_capture_fn *) RENDERDOC_API_FN_ADDR(a, 168) 364 365 366 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, (i32)_s.len, (c8 *)_s.data);} 367 368 #include "util.c" 369 #include "math.c" 370 371 #endif /* _UTIL_H_ */