util.h (11243B)
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 #if COMPILER_MSVC 69 #define thread_static __declspec(thread) 70 #elif COMPILER_CLANG || COMPILER_GCC 71 #define thread_static __thread 72 #else 73 #error thread_static not defined for this compiler 74 #endif 75 76 #define alignof _Alignof 77 #define static_assert _Static_assert 78 79 /* NOTE: garbage to get the prepocessor to properly stringize the value of a macro */ 80 #define str_(...) #__VA_ARGS__ 81 #define str(...) str_(__VA_ARGS__) 82 83 #define countof(a) (iz)(sizeof(a) / sizeof(*a)) 84 #define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) 85 #define ABS(x) ((x) < 0 ? (-x) : (x)) 86 #define BETWEEN(x, a, b) ((x) >= (a) && (x) <= (b)) 87 #define CLAMP(x, a, b) ((x) < (a) ? (a) : (x) > (b) ? (b) : (x)) 88 #define CLAMP01(x) CLAMP(x, 0, 1) 89 #define ISPOWEROF2(a) (((a) & ((a) - 1)) == 0) 90 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 91 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 92 #define ORONE(x) ((x)? (x) : 1) 93 #define SIGN(x) ((x) < 0? -1 : 1) 94 #define swap(a, b) do {typeof(a) __tmp = (a); (a) = (b); (b) = __tmp;} while(0) 95 96 #define ISDIGIT(c) (BETWEEN((c), '0', '9')) 97 #define ISUPPER(c) (((c) & 0x20u) == 0) 98 #define TOLOWER(c) (((c) | 0x20u)) 99 #define TOUPPER(c) (((c) & ~(0x20u))) 100 101 #define f32_cmp(x, y) (ABS((x) - (y)) <= F32_EPSILON * MAX(1.0f, MAX(ABS(x), ABS(y)))) 102 103 #define DeferLoop(begin, end) for (i32 _i_ = ((begin), 0); !_i_; _i_ += 1, (end)) 104 #define DeferLoopTag(begin, end, tag) for (i32 __##tag = ((begin), 0); !__##tag ; __##tag += 1, (end)) 105 106 #define EachBit(a, it) (u64 it = ctz_u64(a); it != 64; a &= ~(1u << (it)), it = ctz_u64(a)) 107 #define EachElement(array, it) (u64 it = 0; it < countof(array); it += 1) 108 #define EachEnumValue(type, it) (type it = (type)0; it < type##_Count; it = (type)(it + 1)) 109 #define EachNonZeroEnumValue(type, it) (type it = (type)1; it < type##_Count; it = (type)(it + 1)) 110 111 #define spin_wait(c) while ((c)) cpu_yield() 112 113 #define DA_STRUCT(kind, name) typedef struct { \ 114 kind *data; \ 115 iz count; \ 116 iz capacity; \ 117 } name ##List; 118 119 /* NOTE(rnp): no guarantees about actually getting an element */ 120 #define SLLPop(list) list; list = list ? list->next : 0 121 #define SLLPush(v, list) do { \ 122 (v)->next = (list); \ 123 (list) = v; \ 124 } while (0) 125 126 #define SLLPopFreelist(list) list; do { \ 127 asan_unpoison_region((list), sizeof(*(list))); \ 128 (void)SLLPop((list)); \ 129 } while(0) 130 131 #define SLLPushFreelist(v, list) do { \ 132 SLLPush((v), (list)); \ 133 asan_poison_region((v), sizeof(*(v))); \ 134 } while(0) 135 136 #define DLLPushDown(v, list) do { \ 137 (v)->next = (list); \ 138 if ((v)->next) (v)->next->prev = (v); \ 139 (list) = (v); \ 140 } while (0) 141 142 #define DLLRemove(v) do { \ 143 if ((v)->next) (v)->next->prev = (v)->prev; \ 144 if ((v)->prev) (v)->prev->next = (v)->next; \ 145 } while (0) 146 147 #define KB(a) ((u64)(a) << 10ULL) 148 #define MB(a) ((u64)(a) << 20ULL) 149 #define GB(a) ((u64)(a) << 30ULL) 150 151 #define I32_MAX (0x7FFFFFFFL) 152 #define U16_MAX (0x0000FFFFUL) 153 #define U32_MAX (0xFFFFFFFFUL) 154 #define U64_MAX (0xFFFFFFFFFFFFFFFFULL) 155 #define F32_INFINITY (1e+300*1e+300) 156 #define F32_EPSILON (1e-6f) 157 #ifndef PI 158 #define PI (3.14159265358979323846f) 159 #endif 160 161 typedef char c8; 162 typedef uint8_t u8; 163 typedef int16_t i16; 164 typedef uint16_t u16; 165 typedef uint16_t b16; 166 typedef int32_t i32; 167 typedef uint32_t u32; 168 typedef int64_t i64; 169 typedef uint64_t u64; 170 typedef uint32_t b32; 171 typedef float f32; 172 typedef double f64; 173 typedef ptrdiff_t iz; 174 typedef size_t uz; 175 typedef ptrdiff_t iptr; 176 typedef size_t uptr; 177 178 #include "intrinsics.c" 179 180 typedef alignas(16) union { 181 u8 U8[16]; 182 u16 U16[8]; 183 u32 U32[4]; 184 u64 U64[2]; 185 u32x4 U32x4; 186 } u128; 187 188 typedef struct { u8 *beg, *end; } Arena; 189 typedef struct { Arena *arena; u8 *old_beg; } TempArena; 190 191 typedef struct { iz len; u8 *data; } s8; 192 #define s8(s) (s8){.len = countof(s) - 1, .data = (u8 *)s} 193 #define s8_comp(s) {sizeof(s) - 1, (u8 *)s} 194 195 typedef struct { iz len; u16 *data; } s16; 196 197 typedef struct { u32 cp, consumed; } UnicodeDecode; 198 199 typedef enum { 200 IntegerConversionResult_Invalid, 201 IntegerConversionResult_OutOfRange, 202 IntegerConversionResult_Success, 203 } IntegerConversionResult; 204 205 typedef struct { 206 IntegerConversionResult result; 207 union { 208 u64 U64; 209 i64 S64; 210 }; 211 s8 unparsed; 212 } IntegerConversion; 213 214 /* NOTE: raylib stubs */ 215 #ifndef RAYLIB_H 216 typedef struct { f32 x, y; } Vector2; 217 typedef struct { f32 x, y, w, h; } Rectangle; 218 #endif 219 220 typedef struct { u64 start, stop; } RangeU64; 221 222 typedef union { 223 struct { i32 x, y; }; 224 struct { i32 w, h; }; 225 i32 E[2]; 226 } iv2; 227 228 typedef union { 229 struct { i32 x, y, z; }; 230 struct { i32 w, h, d; }; 231 iv2 xy; 232 i32 E[3]; 233 } iv3; 234 235 typedef union { 236 struct { i32 x, y, z, w; }; 237 struct { iv3 xyz; i32 _w; }; 238 i32 E[4]; 239 } iv4; 240 241 typedef union { 242 struct { u32 x, y; }; 243 struct { u32 w, h; }; 244 u32 E[2]; 245 } uv2; 246 247 typedef union { 248 struct { u32 x, y, z; }; 249 struct { u32 w, h, d; }; 250 uv2 xy; 251 u32 E[3]; 252 } uv3; 253 254 typedef union { 255 struct { u32 x, y, z, w; }; 256 struct { uv3 xyz; u32 _w; }; 257 u32 E[4]; 258 } uv4; 259 260 typedef union { 261 struct { f32 x, y; }; 262 struct { f32 w, h; }; 263 Vector2 rl; 264 f32 E[2]; 265 } v2; 266 267 typedef union { 268 struct { f32 x, y, z; }; 269 struct { f32 w, h, d; }; 270 f32 E[3]; 271 } v3; 272 273 typedef union { 274 struct { f32 x, y, z, w; }; 275 struct { f32 r, g, b, a; }; 276 struct { v3 xyz; f32 _1; }; 277 struct { f32 _2; v3 yzw; }; 278 struct { v2 xy, zw; }; 279 f32 E[4]; 280 } v4; 281 282 #define XZ(v) (v2){.x = v.x, .y = v.z} 283 #define YZ(v) (v2){.x = v.y, .y = v.z} 284 #define XY(v) (v2){.x = v.x, .y = v.y} 285 286 typedef union { 287 struct { v4 x, y, z, w; }; 288 v4 c[4]; 289 f32 E[16]; 290 } m4; 291 292 /* TODO(rnp): delete raylib */ 293 typedef struct { 294 v3 origin; 295 v3 direction; 296 } ray; 297 298 typedef union { 299 struct { v2 pos, size; }; 300 Rectangle rl; 301 } Rect; 302 #define INVERTED_INFINITY_RECT (Rect){.pos = {.x = -F32_INFINITY, .y = -F32_INFINITY}, \ 303 .size = {.x = -F32_INFINITY, .y = -F32_INFINITY}} 304 305 typedef struct { 306 u8 *data; 307 i32 widx; 308 i32 cap; 309 b32 errors; 310 } Stream; 311 312 #define INVALID_FILE (-1) 313 314 typedef struct OS OS; 315 316 typedef struct { 317 Arena arena; 318 iptr handle; 319 iptr window_handle; 320 iptr gl_context; 321 iptr user_context; 322 i32 sync_variable; 323 b32 asleep; 324 } GLWorkerThreadContext; 325 326 #define FILE_WATCH_CALLBACK_FN(name) b32 name(s8 path, iptr user_data, Arena arena) 327 typedef FILE_WATCH_CALLBACK_FN(file_watch_callback); 328 329 typedef struct { 330 iptr user_data; 331 u64 hash; 332 file_watch_callback *callback; 333 } FileWatch; 334 335 typedef struct { 336 u64 hash; 337 iptr handle; 338 s8 name; 339 340 FileWatch *data; 341 iz count; 342 iz capacity; 343 Arena buffer; 344 } FileWatchDirectory; 345 DA_STRUCT(FileWatchDirectory, FileWatchDirectory); 346 347 typedef struct { 348 void *region; 349 iptr os_context; 350 } SharedMemoryRegion; 351 352 typedef struct { u64 value[1]; } Barrier; 353 354 typedef struct { 355 u64 index; 356 u64 count; 357 Barrier barrier; 358 u64 *broadcast_memory; 359 } LaneContext; 360 361 typedef struct { 362 u8 name[16]; 363 u64 name_length; 364 365 LaneContext lane_context; 366 } ThreadContext; 367 368 #define OS_ALLOC_ARENA_FN(name) Arena name(iz capacity) 369 typedef OS_ALLOC_ARENA_FN(os_alloc_arena_fn); 370 371 #define OS_ADD_FILE_WATCH_FN(name) void name(FileWatchDirectoryList *fwctx, Arena *a, s8 path, \ 372 file_watch_callback *callback, iptr user_data) 373 typedef OS_ADD_FILE_WATCH_FN(os_add_file_watch_fn); 374 375 #define OS_WAKE_WORKER_FN(name) void name(GLWorkerThreadContext *ctx) 376 typedef OS_WAKE_WORKER_FN(os_wake_worker_fn); 377 378 #define OS_READ_WHOLE_FILE_FN(name) s8 name(Arena *arena, char *file) 379 typedef OS_READ_WHOLE_FILE_FN(os_read_whole_file_fn); 380 381 #define OS_WAIT_ON_VALUE_FN(name) b32 name(i32 *value, i32 current, u32 timeout_ms) 382 typedef OS_WAIT_ON_VALUE_FN(os_wait_on_value_fn); 383 384 #define OS_WAKE_WAITERS_FN(name) void name(i32 *sync) 385 typedef OS_WAKE_WAITERS_FN(os_wake_waiters_fn); 386 387 #define OS_WRITE_NEW_FILE_FN(name) b32 name(char *fname, s8 raw) 388 typedef OS_WRITE_NEW_FILE_FN(os_write_new_file_fn); 389 390 #define OS_WRITE_FILE_FN(name) b32 name(iptr file, s8 raw) 391 typedef OS_WRITE_FILE_FN(os_write_file_fn); 392 393 #define OS_THREAD_ENTRY_POINT_FN(name) iptr name(iptr _ctx) 394 typedef OS_THREAD_ENTRY_POINT_FN(os_thread_entry_point_fn); 395 396 #define OS_SHARED_MEMORY_LOCK_REGION_FN(name) b32 name(SharedMemoryRegion *sm, i32 *locks, i32 lock_index, u32 timeout_ms) 397 typedef OS_SHARED_MEMORY_LOCK_REGION_FN(os_shared_memory_region_lock_fn); 398 399 #define OS_SHARED_MEMORY_UNLOCK_REGION_FN(name) void name(SharedMemoryRegion *sm, i32 *locks, i32 lock_index) 400 typedef OS_SHARED_MEMORY_UNLOCK_REGION_FN(os_shared_memory_region_unlock_fn); 401 402 #define RENDERDOC_GET_API_FN(name) b32 name(u32 version, void **out_api) 403 typedef RENDERDOC_GET_API_FN(renderdoc_get_api_fn); 404 405 #define RENDERDOC_START_FRAME_CAPTURE_FN(name) void name(iptr gl_context, iptr window_handle) 406 typedef RENDERDOC_START_FRAME_CAPTURE_FN(renderdoc_start_frame_capture_fn); 407 408 #define RENDERDOC_END_FRAME_CAPTURE_FN(name) b32 name(iptr gl_context, iptr window_handle) 409 typedef RENDERDOC_END_FRAME_CAPTURE_FN(renderdoc_end_frame_capture_fn); 410 411 typedef alignas(16) u8 RenderDocAPI[216]; 412 #define RENDERDOC_API_FN_ADDR(a, offset) (*(iptr *)((*a) + offset)) 413 #define RENDERDOC_START_FRAME_CAPTURE(a) (renderdoc_start_frame_capture_fn *)RENDERDOC_API_FN_ADDR(a, 152) 414 #define RENDERDOC_END_FRAME_CAPTURE(a) (renderdoc_end_frame_capture_fn *) RENDERDOC_API_FN_ADDR(a, 168) 415 416 typedef struct { 417 u32 logical_processor_count; 418 u32 page_size; 419 } OS_SystemInfo; 420 421 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, (i32)_s.len, (c8 *)_s.data);} 422 423 #include "util.c" 424 #include "math.c" 425 426 #endif /* _UTIL_H_ */