initial upload

This commit is contained in:
Ryan Fleury
2024-01-10 19:53:18 -08:00
commit a42ec6aeff
308 changed files with 162362 additions and 0 deletions
+316
View File
@@ -0,0 +1,316 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
// Implementation
internal Arena *
arena_alloc__sized(U64 init_res, U64 init_cmt)
{
ProfBeginFunction();
Assert(ARENA_HEADER_SIZE < init_cmt && init_cmt <= init_res);
void *memory;
U64 res;
U64 cmt;
B32 large_pages = os_large_pages_enabled();
if (large_pages) {
U64 page_size = os_large_page_size();
res = AlignPow2(init_res, page_size);
#if OS_WINDOWS
cmt = res;
#else
cmt AlignPow2(init_cmt, page_size);
#endif
memory = os_reserve_large(res);
if (!os_commit_large(memory, cmt)) {
memory = 0;
os_release(memory, res);
}
} else {
U64 page_size = os_page_size();
res = AlignPow2(init_res, page_size);
cmt = AlignPow2(init_cmt, page_size);
memory = os_reserve(res);
if (!os_commit(memory, cmt)) {
memory = 0;
os_release(memory, res);
}
}
Assert(memory);
AsanPoisonMemoryRegion(memory, cmt);
AsanUnpoisonMemoryRegion(memory, ARENA_HEADER_SIZE);
Arena *arena = (Arena*)memory;
if (arena) {
arena->prev = 0;
arena->current = arena;
arena->base_pos = 0;
arena->pos = ARENA_HEADER_SIZE;
arena->cmt = cmt;
arena->res = res;
arena->align = 8;
#if ENABLE_DEV
arena->dev = 0;
#endif
arena->grow = 1;
arena->large_pages = large_pages;
}
ProfEnd();
return arena;
}
internal Arena *
arena_alloc(void)
{
ProfBeginFunction();
U64 init_res, init_cmt;
if (os_large_pages_enabled()) {
init_res = ARENA_RESERVE_SIZE_LARGE_PAGES;
init_cmt = ARENA_COMMIT_SIZE_LARGE_PAGES;
} else {
init_res = ARENA_RESERVE_SIZE;
init_cmt = ARENA_COMMIT_SIZE;
}
Arena *arena = arena_alloc__sized(init_res, init_cmt);
ProfEnd();
return arena;
}
internal void
arena_release(Arena *arena)
{
for (Arena *node = arena->current, *prev = 0; node != 0; node = prev) {
prev = node->prev;
os_release(node, node->res);
}
}
internal U64
arena_huge_push_threshold(void)
{
U64 reserve_size = os_large_pages_enabled() ? ARENA_RESERVE_SIZE_LARGE_PAGES : ARENA_RESERVE_SIZE;
U64 threshold = (reserve_size - ARENA_HEADER_SIZE) / 2 + 1;
return threshold;
}
internal void *
arena_push__impl(Arena *arena, U64 size)
{
Arena *current = arena->current;
U64 pos_mem = AlignPow2(current->pos, arena->align);
U64 pos_new = pos_mem + size;
if (current->res < pos_new && arena->grow) {
Arena *new_block;
// normal growth path
if (size < arena_huge_push_threshold()) {
new_block = arena_alloc();
}
// huge growth path
else {
U64 new_block_size = size + ARENA_HEADER_SIZE;
new_block = arena_alloc__sized(new_block_size, new_block_size);
}
if (new_block) {
new_block->base_pos = current->base_pos + current->res;
SLLStackPush_N(arena->current, new_block, prev);
current = new_block;
pos_mem = AlignPow2(current->pos, current->align);
pos_new = pos_mem + size;
}
}
if (current->cmt < pos_new) {
U64 cmt_new_aligned, cmt_new_clamped, cmt_new_size;
B32 is_cmt_ok;
if (current->large_pages) {
cmt_new_aligned = AlignPow2(pos_new, ARENA_COMMIT_SIZE_LARGE_PAGES);
cmt_new_clamped = ClampTop(cmt_new_aligned, current->res);
cmt_new_size = cmt_new_clamped - current->cmt;
is_cmt_ok = os_commit_large((U8*)current + current->cmt, cmt_new_size);
} else {
cmt_new_aligned = AlignPow2(pos_new, ARENA_COMMIT_SIZE);
cmt_new_clamped = ClampTop(cmt_new_aligned, current->res);
cmt_new_size = cmt_new_clamped - current->cmt;
is_cmt_ok = os_commit((U8*)current + current->cmt, cmt_new_size);
}
Assert(is_cmt_ok);
if (is_cmt_ok) {
current->cmt = cmt_new_clamped;
}
}
void *memory = 0;
if (current->cmt >= pos_new) {
memory = (U8*)current + pos_mem;
current->pos = pos_new;
AsanUnpoisonMemoryRegion(memory, size);
}
#if OS_FEATURE_GRAPHICAL
if(Unlikely(memory == 0))
{
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
os_exit_process(1);
}
#endif
return memory;
}
internal U64
arena_pos(Arena *arena)
{
Arena *current = arena->current;
U64 pos = current->base_pos + current->pos;
return pos;
}
internal void
arena_pop_to(Arena *arena, U64 big_pos_unclamped)
{
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, big_pos_unclamped);
// unroll the chain
Arena *current = arena->current;
for (Arena *prev = 0; current->base_pos >= big_pos; current = prev) {
prev = current->prev;
os_release(current, current->res);
}
AssertAlways(current);
arena->current = current;
// compute arena-relative position
U64 new_pos = big_pos - current->base_pos;
AssertAlways(new_pos <= current->pos);
// poison popped memory block
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
// update position
current->pos = new_pos;
}
internal void
arena_absorb(Arena *arena, Arena *sub)
{
#if ENABLE_DEV
arena_annotate_absorb__dev(arena, sub);
#endif
// base adjustment
Arena *current = arena->current;
U64 base_adjust = current->base_pos + current->res;
for (Arena *node = sub->current; node != 0; node = node->prev) {
node->base_pos += base_adjust;
}
// attach sub to arena
sub->prev = arena->current;
arena->current = sub->current;
sub->current = sub;
}
////////////////////////////////
// Wrappers
internal void *
arena_push(Arena *arena, U64 size)
{
void *memory = arena_push__impl(arena, size);
#if ENABLE_DEV
arena_annotate_push__dev(arena, size, memory);
#endif
return memory;
}
internal void *
arena_push_contiguous(Arena *arena, U64 size)
{
B32 restore = arena->grow;
arena->grow = 0;
void *memory = arena_push(arena, size);
arena->grow = restore;
#if ENABLE_DEV
arena_annotate_push__dev(arena, size, memory);
#endif
return memory;
}
internal void
arena_push_align(Arena *arena, U64 align)
{
Assert(IsPow2(align));
U64 amt = AlignPadPow2(arena->pos, align);
void *ptr = arena_push(arena, amt);
MemoryZero(ptr, amt);
}
internal void
arena_put_back(Arena *arena, U64 amt)
{
U64 pos_old = arena_pos(arena);
U64 pos_new = pos_old;
if (amt < pos_old) {
pos_new = pos_old - amt;
}
arena_pop_to(arena, pos_new);
}
internal void
arena_clear(Arena *arena)
{
arena_pop_to(arena, 0);
}
internal Temp
temp_begin(Arena *arena)
{
U64 pos = arena_pos(arena);
Temp temp = {arena, pos};
return temp;
}
internal void
temp_end(Temp temp)
{
arena_pop_to(temp.arena, temp.pos);
}
////////////////////////////////
//~ NOTE(allen): "Mini-Arena" Helper
internal B32
ensure_commit(void **cmtptr, void *pos, U64 cmt_block_size){
B32 result = 0;
U8 *cmt = (U8*)*cmtptr;
if (cmt < (U8*)pos){
U64 cmt_size_raw = (U8*)pos - cmt;
U64 cmt_size = AlignPow2(cmt_size_raw, cmt_block_size);
if (os_commit(cmt, cmt_size)){
*cmtptr = cmt + cmt_size;
result = 1;
}
}
else{
result = 1;
}
return(result);
}
+94
View File
@@ -0,0 +1,94 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_ARENA_H
#define BASE_ARENA_H
////////////////////////////////
//~ rjf: Constants
#define ARENA_HEADER_SIZE 128
#ifndef ARENA_RESERVE_SIZE
# define ARENA_RESERVE_SIZE MB(64)
#endif
#ifndef ARENA_COMMIT_SIZE
# define ARENA_COMMIT_SIZE KB(64)
#endif
#ifndef ARENA_RESERVE_SIZE_LARGE_PAGES
# define ARENA_RESERVE_SIZE_LARGE_PAGES MB(8)
#endif
#ifndef ARENA_COMMIT_SIZE_LARGE_PAGES
# define ARENA_COMMIT_SIZE_LARGE_PAGES MB(2)
#endif
////////////////////////////////
//~ rjf: Arena Types
typedef struct Arena Arena;
struct Arena
{
struct Arena *prev;
struct Arena *current;
U64 base_pos;
U64 pos;
U64 cmt;
U64 res;
U64 align;
struct ArenaDev *dev;
B8 grow;
B8 large_pages;
};
typedef struct Temp Temp;
struct Temp
{
Arena *arena;
U64 pos;
};
////////////////////////////////
// Implementation
internal Arena* arena_alloc__sized(U64 init_res, U64 init_cmt);
internal Arena* arena_alloc(void);
internal void arena_release(Arena *arena);
internal void* arena_push__impl(Arena *arena, U64 size);
internal U64 arena_pos(Arena *arena);
internal void arena_pop_to(Arena *arena, U64 pos);
internal void arena_absorb(Arena *arena, Arena *sub);
////////////////////////////////
// Wrappers
internal void* arena_push(Arena *arena, U64 size);
internal void* arena_push_contiguous(Arena *arena, U64 size);
internal void arena_clear(Arena *arena);
internal void arena_push_align(Arena *arena, U64 align);
internal void arena_put_back(Arena *arena, U64 amt);
internal Temp temp_begin(Arena *arena);
internal void temp_end(Temp temp);
////////////////////////////////
//~ NOTE(allen): "Mini-Arena" Helper
internal B32 ensure_commit(void **cmt, void *pos, U64 cmt_block_size);
////////////////////////////////
//~ NOTE(allen): Main API Macros
#if !ENABLE_DEV
# define push_array_no_zero(a,T,c) (T*)arena_push((a), sizeof(T)*(c))
#else
# define push_array_no_zero(a,T,c) (tctx_write_this_srcloc(), (T*)arena_push((a), sizeof(T)*(c)))
#endif
#define push_array_no_zero__no_annotation(a,T,c) (T*)arena_push__impl((a), sizeof(T)*(c))
#define push_array(a,T,c) (T*)MemoryZero(push_array_no_zero(a,T,c), sizeof(T)*(c))
#endif // BASE_ARENA_H
+197
View File
@@ -0,0 +1,197 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
// NOTE(allen): Dev Arena
#if ENABLE_DEV
internal void
arena_annotate_push__dev(Arena *arena, U64 size, void *ptr){
ArenaDev *dev = arena->dev;
if (dev != 0 && ptr != 0){
//- read location
char *file_name = 0;
U64 line_number = 0;
tctx_read_srcloc(&file_name, &line_number);
tctx_write_srcloc(0, 0);
//- profile
ArenaProf *prof = dev->prof;
if (prof != 0){
// c string -> string
String8 file_name_str = str8_lit("(null)");
if (file_name != 0){
file_name_str = str8_cstring(file_name);
}
// record
arena_prof_inc_counters__dev(dev->arena, prof, file_name_str, line_number, size, 1);
}
}
}
internal void
arena_annotate_absorb__dev(Arena *arena, Arena *sub){
ArenaDev *dev = arena->dev;
ArenaDev *sub_dev = sub->dev;
if (dev != 0 && sub_dev != 0){
//- merge profiles
ArenaProf *prof = dev->prof;
ArenaProf *sub_prof = sub_dev->prof;
if (prof != 0 && sub_prof != 0){
for (ArenaProfNode *sub_node = sub_prof->first;
sub_node != 0;
sub_node = sub_node->next){
arena_prof_inc_counters__dev(dev->arena, prof, sub_node->file_name, sub_node->line,
sub_node->size, sub_node->count);
}
}
}
//- release the sub dev memory
if (sub_dev != 0){
arena_release(sub_dev->arena);
}
}
internal ArenaDev*
arena_equip__dev(Arena *arena){
ArenaDev *result = arena->dev;
if (result == 0){
Arena *dev_arena = arena_alloc();
ArenaDev *dev = (ArenaDev*)arena_push__impl(dev_arena, sizeof(ArenaDev));
MemoryZeroStruct(dev);
dev->arena = dev_arena;
arena->dev = dev;
result = dev;
}
return(result);
}
internal void
arena_equip_profile__dev(Arena *arena){
ArenaDev *dev = arena_equip__dev(arena);
if (dev->prof == 0){
dev->prof = (ArenaProf*)arena_push__impl(dev->arena, sizeof(ArenaProf));
MemoryZeroStruct(dev->prof);
}
}
internal void
arena_print_profile__dev(Arena *arena, Arena *out_arena, String8List *out){
Assert(arena != out_arena);
//- get dev & disable
ArenaDev *dev = arena->dev;
arena->dev = 0;
//- get prof
ArenaProf *prof = (dev != 0)?dev->prof:0;
//- not equipped with prof
if (prof == 0){
str8_list_push(out_arena, out, str8_lit("not equipped with a memory profile\n"));
}
//- print prof
if (prof != 0){
Temp scratch = temp_begin(dev->arena);
//- make flat array
U64 note_count = prof->count;
ArenaProfNode **notes = push_array_no_zero__no_annotation(scratch.arena, ArenaProfNode*, note_count);
{
ArenaProfNode **note_ptr = notes;
for (ArenaProfNode *node = prof->first;
node != 0;
node = node->next, note_ptr += 1){
*note_ptr = node;
}
}
//- file name size
U64 max_file_name_size = 0;
{
ArenaProfNode **note_ptr = notes;
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
max_file_name_size = Max(max_file_name_size, (**note_ptr).file_name.size);
}
}
//- sort (> size, < [address])
for (U64 i = 0; i < note_count; i += 1){
ArenaProfNode **i_note = notes + i;
ArenaProfNode **min_note = i_note;
for (U64 j = i + 1; j < note_count; j += 1){
ArenaProfNode **j_note = notes + j;
if ((**j_note).size > (**min_note).size ||
((**j_note).size == (**min_note).size && *j_note < *min_note)){
min_note = j_note;
}
}
if (min_note != i_note){
ArenaProfNode *t = *i_note;
*i_note = *min_note;
*min_note = t;
}
}
//- total size
U64 total_size = 0;
{
ArenaProfNode **note_ptr = notes;
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
ArenaProfNode *note = *note_ptr;
total_size += note->size;
}
}
//- print
{
str8_list_pushf(out_arena, out, "memory total: %llu\n", total_size);
ArenaProfNode **note_ptr = notes;
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
ArenaProfNode *note = *note_ptr;
String8 location = push_str8f(scratch.arena, "%S:%5llu:",
note->file_name, note->line);
F32 percent = 100.f*((F32)note->size)/total_size;
str8_list_pushf(out_arena, out, "%*.*s %12llu %5.2f%% [%5llu]\n",
max_file_name_size + 7, str8_varg(location),
note->size, percent, note->count);
}
}
temp_end(scratch);
}
//- restore dev
arena->dev = dev;
}
internal void
arena_prof_inc_counters__dev(Arena *dev_arena, ArenaProf *prof, String8 file_name, U64 line,
U64 size, U64 count){
// find existing profile node
ArenaProfNode *prof_node = 0;
for (ArenaProfNode *node = prof->first;
node != 0;
node = node->next){
if (node->line == line && str8_match(file_name, node->file_name, 0)){
prof_node = node;
break;
}
}
// make new histogram node if necessary
if (prof_node == 0){
prof_node = (ArenaProfNode*)arena_push(dev_arena, sizeof(*prof_node));
SLLQueuePush(prof->first, prof->last, prof_node);
prof->count += 1;
prof_node->file_name = file_name;
prof_node->line = line;
}
// record this allocation
prof_node->size += size;
prof_node->count += count;
}
#endif
+47
View File
@@ -0,0 +1,47 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_ARENA_DEV_H
#define BASE_ARENA_DEV_H
////////////////////////////////
//~ NOTE(allen): Dev Arena Types
typedef struct ArenaDev ArenaDev;
struct ArenaDev
{
Arena *arena;
struct ArenaProf *prof;
};
typedef struct ArenaProf ArenaProf;
struct ArenaProf
{
struct ArenaProfNode *first;
struct ArenaProfNode *last;
U64 count;
};
typedef struct ArenaProfNode ArenaProfNode;
struct ArenaProfNode
{
ArenaProfNode *next;
String8 file_name;
U64 line;
U64 size;
U64 count;
};
////////////////////////////////
//~ NOTE(allen): Dev Arena Functions
#if ENABLE_DEV
internal void arena_annotate_push__dev(Arena *arena, U64 size, void *ptr);
internal void arena_annotate_absorb__dev(Arena *arena, Arena *sub);
internal ArenaDev* arena_equip__dev(Arena *arena);
internal void arena_equip_profile__dev(Arena *arena);
internal void arena_print_profile__dev(Arena *arena, Arena *out_arena, String8List *out);
internal void arena_prof_inc_counters__dev(Arena *dev_arena, ArenaProf *prof, String8 file_name, U64 line, U64 size, U64 count);
#endif
#endif // BASE_ARENA_DEV_H
+103
View File
@@ -0,0 +1,103 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#if COMPILER_CL || (COMPILER_CLANG && OS_WINDOWS)
internal U64
count_bits_set16(U16 val)
{
return __popcnt16(val);
}
internal U64
count_bits_set32(U32 val)
{
return __popcnt(val);
}
internal U64
count_bits_set64(U64 val)
{
return __popcnt64(val);
}
internal U64
ctz32(U32 mask)
{
unsigned long idx;
_BitScanForward(&idx, mask);
return idx;
}
internal U64
ctz64(U64 mask)
{
unsigned long idx;
_BitScanForward64(&idx, mask);
return idx;
}
internal U64
clz32(U32 mask)
{
unsigned long idx;
_BitScanReverse(&idx, mask);
return 31 - idx;
}
internal U64
clz64(U64 mask)
{
unsigned long idx;
_BitScanReverse64(&idx, mask);
return 63 - idx;
}
#elif COMPILER_CLANG || COMPILER_GCC
internal U64
count_bits_set16(U16 val)
{
NotImplemented;
return 0;
}
internal U64
count_bits_set32(U32 val)
{
NotImplemented;
return 0;
}
internal U64
count_bits_set64(U64 val)
{
NotImplemented;
return 0;
}
internal U64
ctz32(U32 val)
{
NotImplemented;
return 0;
}
internal U64
clz32(U32 val)
{
NotImplemented;
return 0;
}
internal U64
clz64(U64 val)
{
NotImplemented;
return 0;
}
#else
# error "bits not defined for this target"
#endif
+18
View File
@@ -0,0 +1,18 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_BITS_H
#define BASE_BITS_H
#define ExtractBit(word, idx) (((word) >> (idx)) & 1)
internal U64 count_bits_set16(U16 val);
internal U64 count_bits_set32(U32 val);
internal U64 count_bits_set64(U64 val);
internal U64 ctz32(U32 val);
internal U64 ctz64(U64 val);
internal U64 clz32(U32 val);
internal U64 clz64(U64 val);
#endif // BASE_BITS_H
+229
View File
@@ -0,0 +1,229 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ NOTE(rjf): Command Line Option Parsing
internal U64
cmd_line_hash_from_string(String8 string)
{
U64 result = 5381;
for(U64 i = 0; i < string.size; i += 1)
{
result = ((result << 5) + result) + string.str[i];
}
return result;
}
internal CmdLineOpt **
cmd_line_slot_from_string(CmdLine *cmd_line, String8 string)
{
CmdLineOpt **slot = 0;
if(cmd_line->option_table_size != 0)
{
U64 hash = cmd_line_hash_from_string(string);
U64 bucket = hash % cmd_line->option_table_size;
slot = &cmd_line->option_table[bucket];
}
return slot;
}
internal CmdLineOpt *
cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string)
{
CmdLineOpt *result = 0;
for(CmdLineOpt *var = *slot; var; var = var->hash_next)
{
if(str8_match(string, var->string, 0))
{
result = var;
break;
}
}
return result;
}
internal void
cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var)
{
SLLQueuePush(list->first, list->last, var);
list->count += 1;
}
internal CmdLineOpt *
cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values)
{
CmdLineOpt *var = 0;
CmdLineOpt **slot = cmd_line_slot_from_string(cmd_line, string);
CmdLineOpt *existing_var = cmd_line_opt_from_slot(slot, string);
if(existing_var != 0)
{
var = existing_var;
}
else
{
var = push_array(arena, CmdLineOpt, 1);
var->hash_next = *slot;
var->hash = cmd_line_hash_from_string(string);
var->string = push_str8_copy(arena, string);
var->value_strings = values;
StringJoin join = {0};
join.pre = str8_lit("");
join.sep = str8_lit(",");
join.post = str8_lit("");
var->value_string = str8_list_join(arena, &var->value_strings, &join);
*slot = var;
cmd_line_push_opt(&cmd_line->options, var);
}
return var;
}
internal CmdLine
cmd_line_from_string_list(Arena *arena, String8List command_line)
{
CmdLine parsed = {0};
// NOTE(rjf): Set up config option table.
{
parsed.option_table_size = 4096;
parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size);
}
// NOTE(rjf): Parse command line.
B32 after_passthrough_option = 0;
for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next)
{
next = node->next;
String8 option_name = node->string;
// NOTE(rjf): Look at -- or - at the start of an argument to determine if it's
// a flag option. All arguments after a single "--" (with no trailing string
// on the command line will be considered as input files.
B32 is_option = 1;
if(after_passthrough_option == 0)
{
if(str8_match(node->string, str8_lit("--"), 0))
{
after_passthrough_option = 1;
is_option = 0;
}
else if(str8_match(str8_prefix(node->string, 2), str8_lit("--"), 0))
{
option_name = str8_skip(option_name, 2);
}
else if(str8_match(str8_prefix(node->string, 1), str8_lit("-"), 0))
{
option_name = str8_skip(option_name, 1);
}
else
{
is_option = 0;
}
}
else
{
is_option = 0;
}
// NOTE(rjf): This string is an option.
if(is_option)
{
B32 has_arguments = 0;
U64 arg_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0);
U64 arg_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0);
U64 arg_signifier_position = Min(arg_signifier_position1, arg_signifier_position2);
String8 arg_portion_this_string = str8_skip(option_name, arg_signifier_position+1);
if(arg_signifier_position < option_name.size)
{
has_arguments = 1;
}
option_name = str8_prefix(option_name, arg_signifier_position);
String8List arguments = {0};
// NOTE(rjf): Parse arguments.
if(has_arguments)
{
for(String8Node *n = node; n; n = n->next)
{
next = n->next;
String8 string = n->string;
if(n == node)
{
string = arg_portion_this_string;
}
U8 splits[] = { ',' };
String8List args_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0);
for(String8Node *sub_arg = args_in_this_string.first; sub_arg; sub_arg = sub_arg->next)
{
str8_list_push(arena, &arguments, sub_arg->string);
}
if(!str8_match(str8_postfix(n->string, 1), str8_lit(","), 0) &&
(n != node || arg_portion_this_string.size != 0))
{
break;
}
}
}
// NOTE(rjf): Register config variable.
cmd_line_insert_opt(arena, &parsed, option_name, arguments);
}
// NOTE(rjf): Default path, treat as a passthrough config option to be
// handled by tool-specific code.
else if(!str8_match(node->string, str8_lit("--"), 0))
{
str8_list_push(arena, &parsed.inputs, node->string);
after_passthrough_option = 1;
}
}
return parsed;
}
internal CmdLineOpt *
cmd_line_opt_from_string(CmdLine *cmd_line, String8 name)
{
return cmd_line_opt_from_slot(cmd_line_slot_from_string(cmd_line, name), name);
}
internal String8List
cmd_line_strings(CmdLine *cmd_line, String8 name)
{
String8List result = {0};
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
if(var != 0)
{
result = var->value_strings;
}
return result;
}
internal String8
cmd_line_string(CmdLine *cmd_line, String8 name)
{
String8 result = {0};
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
if(var != 0)
{
result = var->value_string;
}
return result;
}
internal B32
cmd_line_has_flag(CmdLine *cmd_line, String8 name)
{
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
return(var != 0);
}
internal B32
cmd_line_has_argument(CmdLine *cmd_line, String8 name)
{
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
return(var != 0 && var->value_strings.node_count > 0);
}
+53
View File
@@ -0,0 +1,53 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_COMMAND_LINE_H
#define BASE_COMMAND_LINE_H
////////////////////////////////
//~ rjf: Parsed Command Line Types
typedef struct CmdLineOpt CmdLineOpt;
struct CmdLineOpt
{
CmdLineOpt *next;
CmdLineOpt *hash_next;
U64 hash;
String8 string;
String8List value_strings;
String8 value_string;
};
typedef struct CmdLineOptList CmdLineOptList;
struct CmdLineOptList
{
U64 count;
CmdLineOpt *first;
CmdLineOpt *last;
};
typedef struct CmdLine CmdLine;
struct CmdLine
{
CmdLineOptList options;
String8List inputs;
U64 option_table_size;
CmdLineOpt **option_table;
};
////////////////////////////////
//~ NOTE(rjf): Command Line Option Parsing
internal U64 cmd_line_hash_from_string(String8 string);
internal CmdLineOpt** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string);
internal CmdLineOpt* cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string);
internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var);
internal CmdLineOpt* cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values);
internal CmdLine cmd_line_from_string_list(Arena *arena, String8List arguments);
internal CmdLineOpt* cmd_line_opt_from_string(CmdLine *cmd_line, String8 name);
internal String8List cmd_line_strings(CmdLine *cmd_line, String8 name);
internal String8 cmd_line_string(CmdLine *cmd_line, String8 name);
internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name);
internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name);
#endif // BASE_COMMAND_LINE_H
+144
View File
@@ -0,0 +1,144 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_CONTEXT_CRACKING_H
#define BASE_CONTEXT_CRACKING_H
#if defined(__clang__)
# define COMPILER_CLANG 1
# if defined(_WIN32)
# define OS_WINDOWS 1
# elif defined(__gnu_linux__) || defined(__linux__)
# define OS_LINUX 1
# elif defined(__APPLE__) && defined(__MACH__)
# define OS_MAC 1
# else
# error This compiler/platform combo is not supported yet
# endif
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
# define ARCH_X64 1
# elif defined(i386) || defined(__i386) || defined(__i386__)
# define ARCH_X86 1
# elif defined(__aarch64__)
# define ARCH_ARM64 1
# elif defined(__arm__)
# define ARCH_ARM32 1
# else
# error architecture not supported yet
# endif
#elif defined(_MSC_VER)
# define COMPILER_CL 1
# if defined(_WIN32)
# define OS_WINDOWS 1
# else
# error This compiler/platform combo is not supported yet
# endif
# if defined(_M_AMD64)
# define ARCH_X64 1
# elif defined(_M_IX86)
# define ARCH_X86 1
# elif defined(_M_ARM64)
# define ARCH_ARM64 1
# elif defined(_M_ARM)
# define ARCH_ARM32 1
# else
# error architecture not supported yet
# endif
#elif defined(__GNUC__) || defined(__GNUG__)
# define COMPILER_GCC 1
# if defined(__gnu_linux__) || defined(__linux__)
# define OS_LINUX 1
# else
# error This compiler/platform combo is not supported yet
# endif
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
# define ARCH_X64 1
# elif defined(i386) || defined(__i386) || defined(__i386__)
# define ARCH_X86 1
# elif defined(__aarch64__)
# define ARCH_ARM64 1
# elif defined(__arm__)
# define ARCH_ARM32 1
# else
# error architecture not supported yet
# endif
#else
# error This compiler is not supported yet
#endif
#if defined(ARCH_X64)
# define ARCH_64BIT 1
#elif defined(ARCH_X86)
# define ARCH_32BIT 1
#endif
#if defined(__cplusplus)
# define LANG_CPP 1
#else
# define LANG_C 1
#endif
// zeroify
#if !defined(ARCH_32BIT)
# define ARCH_32BIT 0
#endif
#if !defined(ARCH_64BIT)
# define ARCH_64BIT 0
#endif
#if !defined(ARCH_X64)
# define ARCH_X64 0
#endif
#if !defined(ARCH_X86)
# define ARCH_X86 0
#endif
#if !defined(ARCH_ARM64)
# define ARCH_ARM64 0
#endif
#if !defined(ARCH_ARM32)
# define ARCH_ARM32 0
#endif
#if !defined(COMPILER_CL)
# define COMPILER_CL 0
#endif
#if !defined(COMPILER_GCC)
# define COMPILER_GCC 0
#endif
#if !defined(COMPILER_CLANG)
# define COMPILER_CLANG 0
#endif
#if !defined(OS_WINDOWS)
# define OS_WINDOWS 0
#endif
#if !defined(OS_LINUX)
# define OS_LINUX 0
#endif
#if !defined(OS_MAC)
# define OS_MAC 0
#endif
#if !defined(LANG_CPP)
# define LANG_CPP 0
#endif
#if !defined(LANG_C)
# define LANG_C 0
#endif
#if ARCH_ARM32 || ARCH_ARM64 || ARCH_X64 || ARCH_X86
# define ARCH_LITTLE_ENDIAN 1
#else
# error Endianness of this architecture not understood by context cracker
#endif
#endif // BASE_CONTEXT_CRACKING_H
+18
View File
@@ -0,0 +1,18 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Base Includes
#undef RADDBG_LAYER_COLOR
#define RADDBG_LAYER_COLOR 0.20f, 0.60f, 0.80f
#include "base_types.c"
#include "base_markup.c"
#include "base_arena.c"
#include "base_math.c"
#include "base_string.c"
#include "base_thread_context.c"
#include "base_command_line.c"
#include "base_arena_dev.c"
#include "base_bits.c"
+23
View File
@@ -0,0 +1,23 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_INC_H
#define BASE_INC_H
////////////////////////////////
//~ rjf: Base Includes
#include "base_context_cracking.h"
#include "base_types.h"
#include "base_markup.h"
#include "base_ins.h"
#include "base_linked_lists.h"
#include "base_arena.h"
#include "base_math.h"
#include "base_string.h"
#include "base_thread_context.h"
#include "base_command_line.h"
#include "base_arena_dev.h"
#include "base_bits.h"
#endif // BASE_INC_H
+52
View File
@@ -0,0 +1,52 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_INS_H
#define BASE_INS_H
////////////////////////////////
// NOTE(allen): Implementations of Intrinsics
#if OS_WINDOWS
# include <windows.h>
# include <tmmintrin.h>
# include <wmmintrin.h>
# include <intrin.h>
# if ARCH_X64
# define ins_atomic_u64_eval(x) InterlockedAdd((volatile LONG *)(x), 0)
# define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x))
# define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x))
# define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c))
# define ins_atomic_u64_add_eval(x,c) InterlockedAdd((volatile LONG *)(x), c)
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c))
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c))
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile __int64 *)(x), (__int64)(c))
# endif
#elif OS_LINUX
# if ARCH_X64
# define ins_atomic_u64_inc_eval(x) __sync_fetch_and_add((volatile U64 *)(x), 1)
# endif
#else
// TODO(allen):
#endif
////////////////////////////////
// NOTE(allen): Intrinsic Checks
#if ARCH_X64
# if !defined(ins_atomic_u64_inc_eval)
# error missing: ins_atomic_u64_inc_eval
# endif
#else
# error the intrinsic set for this arch is not developed
#endif
#endif //BASE_INS_H
+73
View File
@@ -0,0 +1,73 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_LINKED_LIST_H
#define BASE_LINKED_LIST_H
////////////////////////////////
//~ rjf: Helpers
#define CheckNil(nil,p) ((p) == 0 || (p) == nil)
#define SetNil(nil,p) ((p) = nil)
////////////////////////////////
//~ rjf: Base Macros
//- rjf: Base Doubly-Linked-List Macros
#define DLLInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) :\
CheckNil(nil,p) ? \
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) :\
((p)==(l)) ? \
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) :\
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
#define DLLPushBack_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,f,l,l,n,next,prev)
#define DLLPushFront_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,l,f,f,n,prev,next)
#define DLLRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\
((n) == (l) ? (l) = (l)->prev : (0)),\
(CheckNil(nil,(n)->prev) ? (0) :\
((n)->prev->next = (n)->next)),\
(CheckNil(nil,(n)->next) ? (0) :\
((n)->next->prev = (n)->prev)))
//- rjf: Base Singly-Linked-List Queue Macros
#define SLLQueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
((f)=(l)=(n),SetNil(nil,(n)->next)):\
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)))
#define SLLQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
((f)=(l)=(n),SetNil(nil,(n)->next)):\
((n)->next=(f),(f)=(n)))
#define SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\
(SetNil(nil,f),SetNil(nil,l)):\
((f)=(f)->next))
//- rjf: Base Singly-Linked-List Stack Macros
#define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
#define SLLStackPop_N(f,next) ((f)=(f)->next)
////////////////////////////////
//~ rjf: Convenience Wrappers
//- rjf: Doubly-Linked-List Wrappers
#define DLLInsert_NP(f,l,p,n,next,prev) DLLInsert_NPZ(0,f,l,p,n,next,prev)
#define DLLPushBack_NP(f,l,n,next,prev) DLLPushBack_NPZ(0,f,l,n,next,prev)
#define DLLPushFront_NP(f,l,n,next,prev) DLLPushFront_NPZ(0,f,l,n,next,prev)
#define DLLRemove_NP(f,l,n,next,prev) DLLRemove_NPZ(0,f,l,n,next,prev)
#define DLLInsert(f,l,p,n) DLLInsert_NPZ(0,f,l,p,n,next,prev)
#define DLLPushBack(f,l,n) DLLPushBack_NPZ(0,f,l,n,next,prev)
#define DLLPushFront(f,l,n) DLLPushFront_NPZ(0,f,l,n,next,prev)
#define DLLRemove(f,l,n) DLLRemove_NPZ(0,f,l,n,next,prev)
//- rjf: Singly-Linked-List Queue Wrappers
#define SLLQueuePush_N(f,l,n,next) SLLQueuePush_NZ(0,f,l,n,next)
#define SLLQueuePushFront_N(f,l,n,next) SLLQueuePushFront_NZ(0,f,l,n,next)
#define SLLQueuePop_N(f,l,next) SLLQueuePop_NZ(0,f,l,next)
#define SLLQueuePush(f,l,n) SLLQueuePush_NZ(0,f,l,n,next)
#define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(0,f,l,n,next)
#define SLLQueuePop(f,l) SLLQueuePop_NZ(0,f,l,next)
//- rjf: Singly-Linked-List Stack Wrappers
#define SLLStackPush(f,n) SLLStackPush_N(f,n,next)
#define SLLStackPop(f) SLLStackPop_N(f,next)
#endif //BASE_LINKED_LIST_H
+2
View File
@@ -0,0 +1,2 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
+79
View File
@@ -0,0 +1,79 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_MARKUP_H
#define BASE_MARKUP_H
////////////////////////////////
//~ rjf: Zero Settings
#if !defined(PROFILE_TELEMETRY)
# define PROFILE_TELEMETRY 0
#endif
#if !defined(MARKUP_LAYER_COLOR)
# define MARKUP_LAYER_COLOR 1.00f, 0.00f, 1.00f
#endif
////////////////////////////////
//~ rjf: Third Party Includes
#if PROFILE_TELEMETRY
# include "rad_tm.h"
# if OS_WINDOWS
# pragma comment(lib, "rad_tm_win64.lib")
# endif
#endif
////////////////////////////////
//~ rjf: Telemetry Profile Defines
#if PROFILE_TELEMETRY
# define ProfBegin(...) tmEnter(0, 0, __VA_ARGS__)
# define ProfBeginDynamic(...) (TM_API_PTR ? TM_API_PTR->_tmEnterZoneV_Core(0, 0, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0)
# define ProfEnd(...) (TM_API_PTR ? TM_API_PTR->_tmLeaveZone(0) : (void)0)
# define ProfTick(...) tmTick(0)
# define ProfIsCapturing(...) tmRunning()
# define ProfBeginCapture(...) tmOpen(0, __VA_ARGS__, __DATE__, "localhost", TMCT_TCP, TELEMETRY_DEFAULT_PORT, TMOF_INIT_NETWORKING|TMOF_CAPTURE_CONTEXT_SWITCHES, 100)
# define ProfEndCapture(...) tmClose(0)
# define ProfThreadName(...) (TM_API_PTR ? TM_API_PTR->_tmThreadName(0, 0, __VA_ARGS__) : (void)0)
# define ProfMsg(...) (TM_API_PTR ? TM_API_PTR->_tmMessageV_Core(0, TMMF_ICON_NOTE, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0)
# define ProfBeginLockWait(...) tmStartWaitForLock(0, 0, __VA_ARGS__)
# define ProfEndLockWait(...) tmEndWaitForLock(0)
# define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__)
# define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__)
# define ProfColor(color) tmZoneColorSticky(color)
#endif
////////////////////////////////
//~ rjf: Zeroify Undefined Defines
#if !defined(ProfBegin)
# define ProfBegin(...) (0)
# define ProfBeginDynamic(...) (0)
# define ProfEnd(...) (0)
# define ProfTick(...) (0)
# define ProfIsCapturing(...) (0)
# define ProfBeginCapture(...) (0)
# define ProfEndCapture(...) (0)
# define ProfThreadName(...) (0)
# define ProfMsg(...) (0)
# define ProfBeginLockWait(...) (0)
# define ProfEndLockWait(...) (0)
# define ProfLockTake(...) (0)
# define ProfLockDrop(...) (0)
# define ProfColor(...) (0)
#endif
////////////////////////////////
//~ rjf: Helper Wrappers
#define ProfBeginFunction(...) ProfBegin(this_function_name)
#define ProfScope(...) DeferLoop(ProfBeginDynamic(__VA_ARGS__), ProfEnd())
////////////////////////////////
//~ rjf: General Markup
#define ThreadName(...) (ProfThreadName(__VA_ARGS__))
#endif // BASE_MARKUP_H
+607
View File
@@ -0,0 +1,607 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Scalar Ops
internal F32
mix_1f32(F32 a, F32 b, F32 t)
{
F32 c = (a + (b-a) * Clamp(0.f, t, 1.f));
return c;
}
internal F64
mix_1f64(F64 a, F64 b, F64 t)
{
F64 c = (a + (b-a) * Clamp(0.0, t, 1.0));
return c;
}
////////////////////////////////
//~ rjf: Vector Ops
internal Vec2F32 vec_2f32(F32 x, F32 y) {Vec2F32 v = {x, y}; return v;}
internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x+b.x, a.y+b.y}; return c;}
internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x-b.x, a.y-b.y}; return c;}
internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x*b.x, a.y*b.y}; return c;}
internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x/b.x, a.y/b.y}; return c;}
internal Vec2F32 scale_2f32(Vec2F32 v, F32 s) {Vec2F32 c = {v.x*s, v.y*s}; return c;}
internal F32 dot_2f32(Vec2F32 a, Vec2F32 b) {F32 c = a.x*b.x + a.y*b.y; return c;}
internal F32 length_squared_2f32(Vec2F32 v) {F32 c = v.x*v.x + v.y*v.y; return c;}
internal F32 length_2f32(Vec2F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y); return c;}
internal Vec2F32 normalize_2f32(Vec2F32 v) {v = scale_2f32(v, 1.f/length_2f32(v)); return v;}
internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t) {Vec2F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t)}; return c;}
internal Vec2S64 vec_2s64(S64 x, S64 y) {Vec2S64 v = {x, y}; return v;}
internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x+b.x, a.y+b.y}; return c;}
internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x-b.x, a.y-b.y}; return c;}
internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x*b.x, a.y*b.y}; return c;}
internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x/b.x, a.y/b.y}; return c;}
internal Vec2S64 scale_2s64(Vec2S64 v, S64 s) {Vec2S64 c = {v.x*s, v.y*s}; return c;}
internal S64 dot_2s64(Vec2S64 a, Vec2S64 b) {S64 c = a.x*b.x + a.y*b.y; return c;}
internal S64 length_squared_2s64(Vec2S64 v) {S64 c = v.x*v.x + v.y*v.y; return c;}
internal S64 length_2s64(Vec2S64 v) {S64 c = (S64)sqrt_f64((F64)(v.x*v.x + v.y*v.y)); return c;}
internal Vec2S64 normalize_2s64(Vec2S64 v) {v = scale_2s64(v, (S64)(1.f/length_2s64(v))); return v;}
internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t) {Vec2S64 c = {(S64)mix_1f32((F32)a.x, (F32)b.x, t), (S64)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;}
internal Vec2S32 vec_2s32(S32 x, S32 y) {Vec2S32 v = {x, y}; return v;}
internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x+b.x, a.y+b.y}; return c;}
internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x-b.x, a.y-b.y}; return c;}
internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x*b.x, a.y*b.y}; return c;}
internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x/b.x, a.y/b.y}; return c;}
internal Vec2S32 scale_2s32(Vec2S32 v, S32 s) {Vec2S32 c = {v.x*s, v.y*s}; return c;}
internal S32 dot_2s32(Vec2S32 a, Vec2S32 b) {S32 c = a.x*b.x + a.y*b.y; return c;}
internal S32 length_squared_2s32(Vec2S32 v) {S32 c = v.x*v.x + v.y*v.y; return c;}
internal S32 length_2s32(Vec2S32 v) {S32 c = (S32)sqrt_f32((F32)v.x*(F32)v.x + (F32)v.y*(F32)v.y); return c;}
internal Vec2S32 normalize_2s32(Vec2S32 v) {v = scale_2s32(v, (S32)(1.f/length_2s32(v))); return v;}
internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t) {Vec2S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;}
internal Vec2S16 vec_2s16(S16 x, S16 y) {Vec2S16 v = {x, y}; return v;}
internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x+b.x), (S16)(a.y+b.y)}; return c;}
internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x-b.x), (S16)(a.y-b.y)}; return c;}
internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x*b.x), (S16)(a.y*b.y)}; return c;}
internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x/b.x), (S16)(a.y/b.y)}; return c;}
internal Vec2S16 scale_2s16(Vec2S16 v, S16 s) {Vec2S16 c = {(S16)(v.x*s), (S16)(v.y*s)}; return c;}
internal S16 dot_2s16(Vec2S16 a, Vec2S16 b) {S16 c = a.x*b.x + a.y*b.y; return c;}
internal S16 length_squared_2s16(Vec2S16 v) {S16 c = v.x*v.x + v.y*v.y; return c;}
internal S16 length_2s16(Vec2S16 v) {S16 c = (S16)sqrt_f32((F32)(v.x*v.x + v.y*v.y)); return c;}
internal Vec2S16 normalize_2s16(Vec2S16 v) {v = scale_2s16(v, (S16)(1.f/length_2s16(v))); return v;}
internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t) {Vec2S16 c = {(S16)mix_1f32((F32)a.x, (F32)b.x, t), (S16)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;}
internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z) {Vec3F32 v = {x, y, z}; return v;}
internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;}
internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;}
internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;}
internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;}
internal Vec3F32 scale_3f32(Vec3F32 v, F32 s) {Vec3F32 c = {v.x*s, v.y*s, v.z*s}; return c;}
internal F32 dot_3f32(Vec3F32 a, Vec3F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;}
internal F32 length_squared_3f32(Vec3F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;}
internal F32 length_3f32(Vec3F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z); return c;}
internal Vec3F32 normalize_3f32(Vec3F32 v) {v = scale_3f32(v, 1.f/length_3f32(v)); return v;}
internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t) {Vec3F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t)}; return c;}
internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;}
internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z) {Vec3S32 v = {x, y, z}; return v;}
internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;}
internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;}
internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;}
internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;}
internal Vec3S32 scale_3s32(Vec3S32 v, S32 s) {Vec3S32 c = {v.x*s, v.y*s, v.z*s}; return c;}
internal S32 dot_3s32(Vec3S32 a, Vec3S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;}
internal S32 length_squared_3s32(Vec3S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;}
internal S32 length_3s32(Vec3S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z)); return c;}
internal Vec3S32 normalize_3s32(Vec3S32 v) {v = scale_3s32(v, (S32)(1.f/length_3s32(v))); return v;}
internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t) {Vec3S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t)}; return c;}
internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;}
internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w) {Vec4F32 v = {x, y, z, w}; return v;}
internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;}
internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;}
internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;}
internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;}
internal Vec4F32 scale_4f32(Vec4F32 v, F32 s) {Vec4F32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;}
internal F32 dot_4f32(Vec4F32 a, Vec4F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;}
internal F32 length_squared_4f32(Vec4F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;}
internal F32 length_4f32(Vec4F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w); return c;}
internal Vec4F32 normalize_4f32(Vec4F32 v) {v = scale_4f32(v, 1.f/length_4f32(v)); return v;}
internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t) {Vec4F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t), mix_1f32(a.w, b.w, t)}; return c;}
internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w) {Vec4S32 v = {x, y, z, w}; return v;}
internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;}
internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;}
internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;}
internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;}
internal Vec4S32 scale_4s32(Vec4S32 v, S32 s) {Vec4S32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;}
internal S32 dot_4s32(Vec4S32 a, Vec4S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;}
internal S32 length_squared_4s32(Vec4S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;}
internal S32 length_4s32(Vec4S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w)); return c;}
internal Vec4S32 normalize_4s32(Vec4S32 v) {v = scale_4s32(v, (S32)(1.f/length_4s32(v))); return v;}
internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t) {Vec4S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t), (S32)mix_1f32((F32)a.w, (F32)b.w, t)}; return c;}
////////////////////////////////
//~ rjf: Matrix Ops
internal Mat3x3F32
mat_3x3f32(F32 diagonal)
{
Mat3x3F32 result = {0};
result.v[0][0] = diagonal;
result.v[1][1] = diagonal;
result.v[2][2] = diagonal;
return result;
}
internal Mat3x3F32
make_translate_3x3f32(Vec2F32 delta)
{
Mat3x3F32 mat = mat_3x3f32(1.f);
mat.v[2][0] = delta.x;
mat.v[2][1] = delta.y;
return mat;
}
internal Mat3x3F32
mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b)
{
Mat3x3F32 c = {0};
for(int j = 0; j < 3; j += 1)
{
for(int i = 0; i < 3; i += 1)
{
c.v[i][j] = (a.v[0][j]*b.v[i][0] +
a.v[1][j]*b.v[i][1] +
a.v[2][j]*b.v[i][2]);
}
}
return c;
}
internal Mat4x4F32
mat_4x4f32(F32 diagonal)
{
Mat4x4F32 result = {0};
result.v[0][0] = diagonal;
result.v[1][1] = diagonal;
result.v[2][2] = diagonal;
result.v[3][3] = diagonal;
return result;
}
internal Mat4x4F32
make_translate_4x4f32(Vec3F32 delta)
{
Mat4x4F32 result = mat_4x4f32(1.f);
result.v[3][0] = delta.x;
result.v[3][1] = delta.y;
result.v[3][2] = delta.z;
return result;
}
internal Mat4x4F32
make_scale_4x4f32(Vec3F32 scale)
{
Mat4x4F32 result = mat_4x4f32(1.f);
result.v[0][0] = scale.x;
result.v[1][1] = scale.y;
result.v[2][2] = scale.z;
return result;
}
internal Mat4x4F32
make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z)
{
Mat4x4F32 result = mat_4x4f32(1.f);
F32 tan_theta_over_2 = tan_f32(fov / 2);
result.v[0][0] = 1.f / tan_theta_over_2;
result.v[1][1] = aspect_ratio / tan_theta_over_2;
result.v[2][3] = 1.f;
result.v[2][2] = -(near_z + far_z) / (near_z - far_z);
result.v[3][2] = (2.f * near_z * far_z) / (near_z - far_z);
result.v[3][3] = 0.f;
return result;
}
internal Mat4x4F32
make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z)
{
Mat4x4F32 result = mat_4x4f32(1.f);
result.v[0][0] = 2.f / (right - left);
result.v[1][1] = 2.f / (top - bottom);
result.v[2][2] = 2.f / (far_z - near_z);
result.v[3][3] = 1.f;
result.v[3][0] = (left + right) / (left - right);
result.v[3][1] = (bottom + top) / (bottom - top);
result.v[3][2] = (near_z + far_z) / (near_z - far_z);
return result;
}
internal Mat4x4F32
make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up)
{
Mat4x4F32 result;
Vec3F32 f = normalize_3f32(sub_3f32(eye, center));
Vec3F32 s = normalize_3f32(cross_3f32(f, up));
Vec3F32 u = cross_3f32(s, f);
result.v[0][0] = s.x;
result.v[0][1] = u.x;
result.v[0][2] = -f.x;
result.v[0][3] = 0.0f;
result.v[1][0] = s.y;
result.v[1][1] = u.y;
result.v[1][2] = -f.y;
result.v[1][3] = 0.0f;
result.v[2][0] = s.z;
result.v[2][1] = u.z;
result.v[2][2] = -f.z;
result.v[2][3] = 0.0f;
result.v[3][0] = -dot_3f32(s, eye);
result.v[3][1] = -dot_3f32(u, eye);
result.v[3][2] = dot_3f32(f, eye);
result.v[3][3] = 1.0f;
return result;
}
internal Mat4x4F32
make_rotate_4x4f32(Vec3F32 axis, F32 turns)
{
Mat4x4F32 result = mat_4x4f32(1.f);
axis = normalize_3f32(axis);
F32 sin_theta = sin_f32(turns);
F32 cos_theta = cos_f32(turns);
F32 cos_value = 1.f - cos_theta;
result.v[0][0] = (axis.x * axis.x * cos_value) + cos_theta;
result.v[0][1] = (axis.x * axis.y * cos_value) + (axis.z * sin_theta);
result.v[0][2] = (axis.x * axis.z * cos_value) - (axis.y * sin_theta);
result.v[1][0] = (axis.y * axis.x * cos_value) - (axis.z * sin_theta);
result.v[1][1] = (axis.y * axis.y * cos_value) + cos_theta;
result.v[1][2] = (axis.y * axis.z * cos_value) + (axis.x * sin_theta);
result.v[2][0] = (axis.z * axis.x * cos_value) + (axis.y * sin_theta);
result.v[2][1] = (axis.z * axis.y * cos_value) - (axis.x * sin_theta);
result.v[2][2] = (axis.z * axis.z * cos_value) + cos_theta;
return result;
}
internal Mat4x4F32
mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b)
{
Mat4x4F32 c = {0};
for(int j = 0; j < 4; j += 1)
{
for(int i = 0; i < 4; i += 1)
{
c.v[i][j] = (a.v[0][j]*b.v[i][0] +
a.v[1][j]*b.v[i][1] +
a.v[2][j]*b.v[i][2] +
a.v[3][j]*b.v[i][3]);
}
}
return c;
}
internal Mat4x4F32
scale_4x4f32(Mat4x4F32 m, F32 scale)
{
for(int j = 0; j < 4; j += 1)
{
for(int i = 0; i < 4; i += 1)
{
m.v[i][j] *= scale;
}
}
return m;
}
internal Mat4x4F32
inverse_4x4f32(Mat4x4F32 m)
{
F32 coef00 = m.v[2][2] * m.v[3][3] - m.v[3][2] * m.v[2][3];
F32 coef02 = m.v[1][2] * m.v[3][3] - m.v[3][2] * m.v[1][3];
F32 coef03 = m.v[1][2] * m.v[2][3] - m.v[2][2] * m.v[1][3];
F32 coef04 = m.v[2][1] * m.v[3][3] - m.v[3][1] * m.v[2][3];
F32 coef06 = m.v[1][1] * m.v[3][3] - m.v[3][1] * m.v[1][3];
F32 coef07 = m.v[1][1] * m.v[2][3] - m.v[2][1] * m.v[1][3];
F32 coef08 = m.v[2][1] * m.v[3][2] - m.v[3][1] * m.v[2][2];
F32 coef10 = m.v[1][1] * m.v[3][2] - m.v[3][1] * m.v[1][2];
F32 coef11 = m.v[1][1] * m.v[2][2] - m.v[2][1] * m.v[1][2];
F32 coef12 = m.v[2][0] * m.v[3][3] - m.v[3][0] * m.v[2][3];
F32 coef14 = m.v[1][0] * m.v[3][3] - m.v[3][0] * m.v[1][3];
F32 coef15 = m.v[1][0] * m.v[2][3] - m.v[2][0] * m.v[1][3];
F32 coef16 = m.v[2][0] * m.v[3][2] - m.v[3][0] * m.v[2][2];
F32 coef18 = m.v[1][0] * m.v[3][2] - m.v[3][0] * m.v[1][2];
F32 coef19 = m.v[1][0] * m.v[2][2] - m.v[2][0] * m.v[1][2];
F32 coef20 = m.v[2][0] * m.v[3][1] - m.v[3][0] * m.v[2][1];
F32 coef22 = m.v[1][0] * m.v[3][1] - m.v[3][0] * m.v[1][1];
F32 coef23 = m.v[1][0] * m.v[2][1] - m.v[2][0] * m.v[1][1];
Vec4F32 fac0 = { coef00, coef00, coef02, coef03 };
Vec4F32 fac1 = { coef04, coef04, coef06, coef07 };
Vec4F32 fac2 = { coef08, coef08, coef10, coef11 };
Vec4F32 fac3 = { coef12, coef12, coef14, coef15 };
Vec4F32 fac4 = { coef16, coef16, coef18, coef19 };
Vec4F32 fac5 = { coef20, coef20, coef22, coef23 };
Vec4F32 vec0 = { m.v[1][0], m.v[0][0], m.v[0][0], m.v[0][0] };
Vec4F32 vec1 = { m.v[1][1], m.v[0][1], m.v[0][1], m.v[0][1] };
Vec4F32 vec2 = { m.v[1][2], m.v[0][2], m.v[0][2], m.v[0][2] };
Vec4F32 vec3 = { m.v[1][3], m.v[0][3], m.v[0][3], m.v[0][3] };
Vec4F32 inv0 = add_4f32(sub_4f32(mul_4f32(vec1, fac0), mul_4f32(vec2, fac1)), mul_4f32(vec3, fac2));
Vec4F32 inv1 = add_4f32(sub_4f32(mul_4f32(vec0, fac0), mul_4f32(vec2, fac3)), mul_4f32(vec3, fac4));
Vec4F32 inv2 = add_4f32(sub_4f32(mul_4f32(vec0, fac1), mul_4f32(vec1, fac3)), mul_4f32(vec3, fac5));
Vec4F32 inv3 = add_4f32(sub_4f32(mul_4f32(vec0, fac2), mul_4f32(vec1, fac4)), mul_4f32(vec2, fac5));
Vec4F32 sign_a = { +1, -1, +1, -1 };
Vec4F32 sign_b = { -1, +1, -1, +1 };
Mat4x4F32 inverse;
for(U32 i = 0; i < 4; i += 1)
{
inverse.v[0][i] = inv0.v[i] * sign_a.v[i];
inverse.v[1][i] = inv1.v[i] * sign_b.v[i];
inverse.v[2][i] = inv2.v[i] * sign_a.v[i];
inverse.v[3][i] = inv3.v[i] * sign_b.v[i];
}
Vec4F32 row0 = { inverse.v[0][0], inverse.v[1][0], inverse.v[2][0], inverse.v[3][0] };
Vec4F32 m0 = { m.v[0][0], m.v[0][1], m.v[0][2], m.v[0][3] };
Vec4F32 dot0 = mul_4f32(m0, row0);
F32 dot1 = (dot0.x + dot0.y) + (dot0.z + dot0.w);
F32 one_over_det = 1 / dot1;
return scale_4x4f32(inverse, one_over_det);
}
internal Mat4x4F32
derotate_4x4f32(Mat4x4F32 mat)
{
Vec3F32 scale =
{
length_3f32(v3f32(mat.v[0][0], mat.v[0][1], mat.v[0][2])),
length_3f32(v3f32(mat.v[1][0], mat.v[1][1], mat.v[1][2])),
length_3f32(v3f32(mat.v[2][0], mat.v[2][1], mat.v[2][2])),
};
mat.v[0][0] = scale.x;
mat.v[1][0] = 0.f;
mat.v[2][0] = 0.f;
mat.v[0][1] = 0.f;
mat.v[1][1] = scale.y;
mat.v[2][1] = 0.f;
mat.v[0][2] = 0.f;
mat.v[1][2] = 0.f;
mat.v[2][2] = scale.z;
return mat;
}
////////////////////////////////
//~ rjf: Range Ops
internal Rng1U32 rng_1u32(U32 min, U32 max) {Rng1U32 r = {min, max}; if(r.min > r.max) { Swap(U32, r.min, r.max); } return r;}
internal Rng1U32 shift_1u32(Rng1U32 r, U32 x) {r.min += x; r.max += x; return r;}
internal Rng1U32 pad_1u32(Rng1U32 r, U32 x) {r.min -= x; r.max += x; return r;}
internal U32 center_1u32(Rng1U32 r) {U32 c = (r.min+r.max)/2; return c;}
internal B32 contains_1u32(Rng1U32 r, U32 x) {B32 c = (r.min <= x && x < r.max); return c;}
internal U32 dim_1u32(Rng1U32 r) {U32 c = r.max-r.min; return c;}
internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
internal U32 clamp_1u32(Rng1U32 r, U32 v) {v = Clamp(r.min, v, r.max); return v;}
internal Rng1S32 rng_1s32(S32 min, S32 max) {Rng1S32 r = {min, max}; if(r.min > r.max) { Swap(S32, r.min, r.max); } return r;}
internal Rng1S32 shift_1s32(Rng1S32 r, S32 x) {r.min += x; r.max += x; return r;}
internal Rng1S32 pad_1s32(Rng1S32 r, S32 x) {r.min -= x; r.max += x; return r;}
internal S32 center_1s32(Rng1S32 r) {S32 c = (r.min+r.max)/2; return c;}
internal B32 contains_1s32(Rng1S32 r, S32 x) {B32 c = (r.min <= x && x < r.max); return c;}
internal S32 dim_1s32(Rng1S32 r) {S32 c = r.max-r.min; return c;}
internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
internal S32 clamp_1s32(Rng1S32 r, S32 v) {v = Clamp(r.min, v, r.max); return v;}
internal Rng1U64 rng_1u64(U64 min, U64 max) {Rng1U64 r = {min, max}; if(r.min > r.max) { Swap(U64, r.min, r.max); } return r;}
internal Rng1U64 shift_1u64(Rng1U64 r, U64 x) {r.min += x; r.max += x; return r;}
internal Rng1U64 pad_1u64(Rng1U64 r, U64 x) {r.min -= x; r.max += x; return r;}
internal U64 center_1u64(Rng1U64 r) {U64 c = (r.min+r.max)/2; return c;}
internal B32 contains_1u64(Rng1U64 r, U64 x) {B32 c = (r.min <= x && x < r.max); return c;}
internal U64 dim_1u64(Rng1U64 r) {U64 c = r.max-r.min; return c;}
internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
internal U64 clamp_1u64(Rng1U64 r, U64 v) {v = Clamp(r.min, v, r.max); return v;}
internal Rng1S64 rng_1s64(S64 min, S64 max) {Rng1S64 r = {min, max}; if(r.min > r.max) { Swap(S64, r.min, r.max); } return r;}
internal Rng1S64 shift_1s64(Rng1S64 r, S64 x) {r.min += x; r.max += x; return r;}
internal Rng1S64 pad_1s64(Rng1S64 r, S64 x) {r.min -= x; r.max += x; return r;}
internal S64 center_1s64(Rng1S64 r) {S64 c = (r.min+r.max)/2; return c;}
internal B32 contains_1s64(Rng1S64 r, S64 x) {B32 c = (r.min <= x && x < r.max); return c;}
internal S64 dim_1s64(Rng1S64 r) {S64 c = r.max-r.min; return c;}
internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
internal S64 clamp_1s64(Rng1S64 r, S64 v) {v = Clamp(r.min, v, r.max); return v;}
internal Rng1F32 rng_1f32(F32 min, F32 max) {Rng1F32 r = {min, max}; if(r.min > r.max) { Swap(F32, r.min, r.max); } return r;}
internal Rng1F32 shift_1f32(Rng1F32 r, F32 x) {r.min += x; r.max += x; return r;}
internal Rng1F32 pad_1f32(Rng1F32 r, F32 x) {r.min -= x; r.max += x; return r;}
internal F32 center_1f32(Rng1F32 r) {F32 c = (r.min+r.max)/2; return c;}
internal B32 contains_1f32(Rng1F32 r, F32 x) {B32 c = (r.min <= x && x < r.max); return c;}
internal F32 dim_1f32(Rng1F32 r) {F32 c = r.max-r.min; return c;}
internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
internal F32 clamp_1f32(Rng1F32 r, F32 v) {v = Clamp(r.min, v, r.max); return v;}
internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max) {Rng2S16 r = {min, max}; return r;}
internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x) {r.min = add_2s16(r.min, x); r.max = add_2s16(r.max, x); return r;}
internal Rng2S16 pad_2s16(Rng2S16 r, S16 x) {Vec2S16 xv = {x, x}; r.min = sub_2s16(r.min, xv); r.max = add_2s16(r.max, xv); return r;}
internal Vec2S16 center_2s16(Rng2S16 r) {Vec2S16 c = {(S16)((r.min.x+r.max.x)/2), (S16)((r.min.y+r.max.y)/2)}; return c;}
internal B32 contains_2s16(Rng2S16 r, Vec2S16 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
internal Vec2S16 dim_2s16(Rng2S16 r) {Vec2S16 dim = {(S16)(r.max.x-r.min.x), (S16)(r.max.y-r.min.y)}; return dim;}
internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max) {Rng2S32 r = {min, max}; return r;}
internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x) {r.min = add_2s32(r.min, x); r.max = add_2s32(r.max, x); return r;}
internal Rng2S32 pad_2s32(Rng2S32 r, S32 x) {Vec2S32 xv = {x, x}; r.min = sub_2s32(r.min, xv); r.max = add_2s32(r.max, xv); return r;}
internal Vec2S32 center_2s32(Rng2S32 r) {Vec2S32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
internal B32 contains_2s32(Rng2S32 r, Vec2S32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
internal Vec2S32 dim_2s32(Rng2S32 r) {Vec2S32 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max) {Rng2S64 r = {min, max}; return r;}
internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x) {r.min = add_2s64(r.min, x); r.max = add_2s64(r.max, x); return r;}
internal Rng2S64 pad_2s64(Rng2S64 r, S64 x) {Vec2S64 xv = {x, x}; r.min = sub_2s64(r.min, xv); r.max = add_2s64(r.max, xv); return r;}
internal Vec2S64 center_2s64(Rng2S64 r) {Vec2S64 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
internal B32 contains_2s64(Rng2S64 r, Vec2S64 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
internal Vec2S64 dim_2s64(Rng2S64 r) {Vec2S64 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max) {Rng2F32 r = {min, max}; return r;}
internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x) {r.min = add_2f32(r.min, x); r.max = add_2f32(r.max, x); return r;}
internal Rng2F32 pad_2f32(Rng2F32 r, F32 x) {Vec2F32 xv = {x, x}; r.min = sub_2f32(r.min, xv); r.max = add_2f32(r.max, xv); return r;}
internal Vec2F32 center_2f32(Rng2F32 r) {Vec2F32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
internal B32 contains_2f32(Rng2F32 r, Vec2F32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
internal Vec2F32 dim_2f32(Rng2F32 r) {Vec2F32 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
////////////////////////////////
//~ rjf: Miscellaneous Ops
internal Vec3F32
hsv_from_rgb(Vec3F32 rgb)
{
F32 c_max = Max(rgb.x, Max(rgb.y, rgb.z));
F32 c_min = Min(rgb.x, Min(rgb.y, rgb.z));
F32 delta = c_max - c_min;
F32 h = ((delta == 0.f) ? 0.f :
(c_max == rgb.x) ? mod_f32((rgb.y - rgb.z)/delta + 6.f, 6.f) :
(c_max == rgb.y) ? (rgb.z - rgb.x)/delta + 2.f :
(c_max == rgb.z) ? (rgb.x - rgb.y)/delta + 4.f :
0.f);
F32 s = (c_max == 0.f) ? 0.f : (delta/c_max);
F32 v = c_max;
Vec3F32 hsv = {h/6.f, s, v};
return hsv;
}
internal Vec3F32
rgb_from_hsv(Vec3F32 hsv)
{
F32 h = mod_f32(hsv.x * 360.f, 360.f);
F32 s = hsv.y;
F32 v = hsv.z;
F32 c = v*s;
F32 x = c*(1.f - abs_f32(mod_f32(h/60.f, 2.f) - 1.f));
F32 m = v - c;
F32 r = 0;
F32 g = 0;
F32 b = 0;
if ((h >= 0.f && h < 60.f) || (h >= 360.f && h < 420.f)){
r = c;
g = x;
b = 0;
}
else if (h >= 60.f && h < 120.f){
r = x;
g = c;
b = 0;
}
else if (h >= 120.f && h < 180.f){
r = 0;
g = c;
b = x;
}
else if (h >= 180.f && h < 240.f){
r = 0;
g = x;
b = c;
}
else if (h >= 240.f && h < 300.f){
r = x;
g = 0;
b = c;
}
else if ((h >= 300.f && h <= 360.f) || (h >= -60.f && h <= 0.f)){
r = c;
g = 0;
b = x;
}
Vec3F32 rgb = {r + m, g + m, b + m};
return(rgb);
}
internal Vec4F32
hsva_from_rgba(Vec4F32 rgba)
{
Vec3F32 rgb = v3f32(rgba.x, rgba.y, rgba.z);
Vec3F32 hsv = hsv_from_rgb(rgb);
Vec4F32 hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w);
return hsva;
}
internal Vec4F32
rgba_from_hsva(Vec4F32 hsva)
{
Vec3F32 hsv = v3f32(hsva.x, hsva.y, hsva.z);
Vec3F32 rgb = rgb_from_hsv(hsv);
Vec4F32 rgba = v4f32(rgb.x, rgb.y, rgb.z, hsva.w);
return rgba;
}
internal Vec4F32
rgba_from_u32(U32 hex)
{
Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f,
((hex&0x00ff0000)>>16)/255.f,
((hex&0x0000ff00)>> 8)/255.f,
((hex&0x000000ff)>> 0)/255.f);
return result;
}
internal U32
u32_from_rgba(Vec4F32 rgba)
{
U32 result = 0;
result |= ((U32)((U8)(rgba.x*255.f))) << 24;
result |= ((U32)((U8)(rgba.y*255.f))) << 16;
result |= ((U32)((U8)(rgba.z*255.f))) << 8;
result |= ((U32)((U8)(rgba.w*255.f))) << 0;
return result;
}
////////////////////////////////
//~ rjf: List Type Functions
internal void
rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng)
{
Rng1S64Node *n = push_array(arena, Rng1S64Node, 1);
MemoryCopyStruct(&n->v, &rng);
SLLQueuePush(list->first, list->last, n);
list->count += 1;
}
internal Rng1S64Array
rng1s64_array_from_list(Arena *arena, Rng1S64List *list)
{
Rng1S64Array arr = {0};
arr.count = list->count;
arr.v = push_array_no_zero(arena, Rng1S64, arr.count);
U64 idx = 0;
for(Rng1S64Node *n = list->first; n != 0; n = n->next)
{
arr.v[idx] = n->v;
idx += 1;
}
return arr;
}
+648
View File
@@ -0,0 +1,648 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_MATH_H
#define BASE_MATH_H
////////////////////////////////
//~ rjf: Vector Types
//- rjf: 2-vectors
typedef union Vec2F32 Vec2F32;
union Vec2F32
{
struct
{
F32 x;
F32 y;
};
F32 v[2];
};
typedef union Vec2S64 Vec2S64;
union Vec2S64
{
struct
{
S64 x;
S64 y;
};
S64 v[2];
};
typedef union Vec2S32 Vec2S32;
union Vec2S32
{
struct
{
S32 x;
S32 y;
};
S32 v[2];
};
typedef union Vec2S16 Vec2S16;
union Vec2S16
{
struct
{
S16 x;
S16 y;
};
S16 v[2];
};
//- rjf: 3-vectors
typedef union Vec3F32 Vec3F32;
union Vec3F32
{
struct
{
F32 x;
F32 y;
F32 z;
};
struct
{
Vec2F32 xy;
F32 _z0;
};
struct
{
F32 _x0;
Vec2F32 yz;
};
F32 v[3];
};
typedef union Vec3S32 Vec3S32;
union Vec3S32
{
struct
{
S32 x;
S32 y;
S32 z;
};
struct
{
Vec2S32 xy;
S32 _z0;
};
struct
{
S32 _x0;
Vec2S32 yz;
};
S32 v[3];
};
//- rjf: 4-vectors
typedef union Vec4F32 Vec4F32;
union Vec4F32
{
struct
{
F32 x;
F32 y;
F32 z;
F32 w;
};
struct
{
Vec2F32 xy;
Vec2F32 zw;
};
struct
{
Vec3F32 xyz;
F32 _z0;
};
struct
{
F32 _x0;
Vec3F32 yzw;
};
F32 v[4];
};
typedef union Vec4S32 Vec4S32;
union Vec4S32
{
struct
{
S32 x;
S32 y;
S32 z;
S32 w;
};
struct
{
Vec2S32 xy;
Vec2S32 zw;
};
struct
{
Vec3S32 xyz;
S32 _z0;
};
struct
{
S32 _x0;
Vec3S32 yzw;
};
S32 v[4];
};
////////////////////////////////
//~ rjf: Matrix Types
typedef struct Mat3x3F32 Mat3x3F32;
struct Mat3x3F32
{
F32 v[3][3];
};
typedef struct Mat4x4F32 Mat4x4F32;
struct Mat4x4F32
{
F32 v[4][4];
};
////////////////////////////////
//~ rjf: Range Types
//- rjf: 1-range
typedef union Rng1U32 Rng1U32;
union Rng1U32
{
struct
{
U32 min;
U32 max;
};
U32 v[2];
};
typedef union Rng1S32 Rng1S32;
union Rng1S32
{
struct
{
S32 min;
S32 max;
};
S32 v[2];
};
typedef union Rng1U64 Rng1U64;
union Rng1U64
{
struct
{
U64 min;
U64 max;
};
U64 v[2];
};
typedef union Rng1S64 Rng1S64;
union Rng1S64
{
struct
{
S64 min;
S64 max;
};
S64 v[2];
};
typedef union Rng1F32 Rng1F32;
union Rng1F32
{
struct
{
F32 min;
F32 max;
};
F32 v[2];
};
//- rjf: 2-range (rectangles)
typedef union Rng2S16 Rng2S16;
union Rng2S16
{
struct
{
Vec2S16 min;
Vec2S16 max;
};
struct
{
Vec2S16 p0;
Vec2S16 p1;
};
struct
{
S16 x0;
S16 y0;
S16 x1;
S16 y1;
};
Vec2S16 v[2];
};
typedef union Rng2S32 Rng2S32;
union Rng2S32
{
struct
{
Vec2S32 min;
Vec2S32 max;
};
struct
{
Vec2S32 p0;
Vec2S32 p1;
};
struct
{
S32 x0;
S32 y0;
S32 x1;
S32 y1;
};
Vec2S32 v[2];
};
typedef union Rng2F32 Rng2F32;
union Rng2F32
{
struct
{
Vec2F32 min;
Vec2F32 max;
};
struct
{
Vec2F32 p0;
Vec2F32 p1;
};
struct
{
F32 x0;
F32 y0;
F32 x1;
F32 y1;
};
Vec2F32 v[2];
};
typedef union Rng2S64 Rng2S64;
union Rng2S64
{
struct
{
Vec2S64 min;
Vec2S64 max;
};
struct
{
Vec2S64 p0;
Vec2S64 p1;
};
struct
{
S64 x0;
S64 y0;
S64 x1;
S64 y1;
};
Vec2S64 v[2];
};
////////////////////////////////
//~ rjf: List Types
typedef struct Rng1S64Node Rng1S64Node;
struct Rng1S64Node
{
Rng1S64Node *next;
Rng1S64 v;
};
typedef struct Rng1S64List Rng1S64List;
struct Rng1S64List
{
Rng1S64Node *first;
Rng1S64Node *last;
U64 count;
};
typedef struct Rng1S64Array Rng1S64Array;
struct Rng1S64Array
{
Rng1S64 *v;
U64 count;
};
////////////////////////////////
//~ rjf: Scalar Ops
#define abs_s64(v) (S64)llabs(v)
#define sqrt_f32(v) sqrtf(v)
#define mod_f32(a, b) fmodf((a), (b))
#define pow_f32(b, e) powf((b), (e))
#define ceil_f32(v) ceilf(v)
#define floor_f32(v) floorf(v)
#define round_f32(v) roundf(v)
#define abs_f32(v) fabsf(v)
#define radians_from_turns_f32(v) ((v)*2*3.1415926535897f)
#define turns_from_radians_f32(v) ((v)/2*3.1415926535897f)
#define degrees_from_turns_f32(v) ((v)*360.f)
#define turns_from_degrees_f32(v) ((v)/360.f)
#define degrees_from_radians_f32(v) (degrees_from_turns_f32(turns_from_radians_f32(v)))
#define radians_from_degrees_f32(v) (radians_from_turns_f32(turns_from_degrees_f32(v)))
#define sin_f32(v) sinf(radians_from_turns_f32(v))
#define cos_f32(v) cosf(radians_from_turns_f32(v))
#define tan_f32(v) tanf(radians_from_turns_f32(v))
#define sqrt_f64(v) sqrt(v)
#define mod_f64(a, b) fmod((a), (b))
#define pow_f64(b, e) pow((b), (e))
#define ceil_f64(v) ceil(v)
#define floor_f64(v) floor(v)
#define round_f64(v) round(v)
#define abs_f64(v) fabs(v)
#define radians_from_turns_f64(v) ((v)*2*3.1415926535897)
#define turns_from_radians_f64(v) ((v)/2*3.1415926535897)
#define degrees_from_turns_f64(v) ((v)*360.0)
#define turns_from_degrees_f64(v) ((v)/360.0)
#define degrees_from_radians_f64(v) (degrees_from_turns_f64(turns_from_radians_f64(v)))
#define radians_from_degrees_f64(v) (radians_from_turns_f64(turns_from_degrees_f64(v)))
#define sin_f64(v) sin(radians_from_turns_f64(v))
#define cos_f64(v) cos(radians_from_turns_f64(v))
#define tan_f64(v) tan(radians_from_turns_f64(v))
internal F32 mix_1f32(F32 a, F32 b, F32 t);
internal F64 mix_1f64(F64 a, F64 b, F64 t);
////////////////////////////////
//~ rjf: Vector Ops
#define v2f32(x, y) vec_2f32((x), (y))
internal Vec2F32 vec_2f32(F32 x, F32 y);
internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b);
internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b);
internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b);
internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b);
internal Vec2F32 scale_2f32(Vec2F32 v, F32 s);
internal F32 dot_2f32(Vec2F32 a, Vec2F32 b);
internal F32 length_squared_2f32(Vec2F32 v);
internal F32 length_2f32(Vec2F32 v);
internal Vec2F32 normalize_2f32(Vec2F32 v);
internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t);
#define v2s64(x, y) vec_2s64((x), (y))
internal Vec2S64 vec_2s64(S64 x, S64 y);
internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b);
internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b);
internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b);
internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b);
internal Vec2S64 scale_2s64(Vec2S64 v, S64 s);
internal S64 dot_2s64(Vec2S64 a, Vec2S64 b);
internal S64 length_squared_2s64(Vec2S64 v);
internal S64 length_2s64(Vec2S64 v);
internal Vec2S64 normalize_2s64(Vec2S64 v);
internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t);
#define v2s32(x, y) vec_2s32((x), (y))
internal Vec2S32 vec_2s32(S32 x, S32 y);
internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b);
internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b);
internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b);
internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b);
internal Vec2S32 scale_2s32(Vec2S32 v, S32 s);
internal S32 dot_2s32(Vec2S32 a, Vec2S32 b);
internal S32 length_squared_2s32(Vec2S32 v);
internal S32 length_2s32(Vec2S32 v);
internal Vec2S32 normalize_2s32(Vec2S32 v);
internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t);
#define v2s16(x, y) vec_2s16((x), (y))
internal Vec2S16 vec_2s16(S16 x, S16 y);
internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b);
internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b);
internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b);
internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b);
internal Vec2S16 scale_2s16(Vec2S16 v, S16 s);
internal S16 dot_2s16(Vec2S16 a, Vec2S16 b);
internal S16 length_squared_2s16(Vec2S16 v);
internal S16 length_2s16(Vec2S16 v);
internal Vec2S16 normalize_2s16(Vec2S16 v);
internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t);
#define v3f32(x, y, z) vec_3f32((x), (y), (z))
internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z);
internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b);
internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b);
internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b);
internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b);
internal Vec3F32 scale_3f32(Vec3F32 v, F32 s);
internal F32 dot_3f32(Vec3F32 a, Vec3F32 b);
internal F32 length_squared_3f32(Vec3F32 v);
internal F32 length_3f32(Vec3F32 v);
internal Vec3F32 normalize_3f32(Vec3F32 v);
internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t);
internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b);
#define v3s32(x, y, z) vec_3s32((x), (y), (z))
internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z);
internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b);
internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b);
internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b);
internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b);
internal Vec3S32 scale_3s32(Vec3S32 v, S32 s);
internal S32 dot_3s32(Vec3S32 a, Vec3S32 b);
internal S32 length_squared_3s32(Vec3S32 v);
internal S32 length_3s32(Vec3S32 v);
internal Vec3S32 normalize_3s32(Vec3S32 v);
internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t);
internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b);
#define v4f32(x, y, z, w) vec_4f32((x), (y), (z), (w))
internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w);
internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b);
internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b);
internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b);
internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b);
internal Vec4F32 scale_4f32(Vec4F32 v, F32 s);
internal F32 dot_4f32(Vec4F32 a, Vec4F32 b);
internal F32 length_squared_4f32(Vec4F32 v);
internal F32 length_4f32(Vec4F32 v);
internal Vec4F32 normalize_4f32(Vec4F32 v);
internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t);
#define v4s32(x, y, z, w) vec_4s32((x), (y), (z), (w))
internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w);
internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b);
internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b);
internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b);
internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b);
internal Vec4S32 scale_4s32(Vec4S32 v, S32 s);
internal S32 dot_4s32(Vec4S32 a, Vec4S32 b);
internal S32 length_squared_4s32(Vec4S32 v);
internal S32 length_4s32(Vec4S32 v);
internal Vec4S32 normalize_4s32(Vec4S32 v);
internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t);
////////////////////////////////
//~ rjf: Matrix Ops
internal Mat3x3F32 mat_3x3f32(F32 diagonal);
internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta);
internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b);
internal Mat4x4F32 mat_4x4f32(F32 diagonal);
internal Mat4x4F32 make_translate_4x4f32(Vec3F32 delta);
internal Mat4x4F32 make_scale_4x4f32(Vec3F32 scale);
internal Mat4x4F32 make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z);
internal Mat4x4F32 make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z);
internal Mat4x4F32 make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up);
internal Mat4x4F32 make_rotate_4x4f32(Vec3F32 axis, F32 turns);
internal Mat4x4F32 mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b);
internal Mat4x4F32 scale_4x4f32(Mat4x4F32 m, F32 scale);
internal Mat4x4F32 inverse_4x4f32(Mat4x4F32 m);
internal Mat4x4F32 derotate_4x4f32(Mat4x4F32 mat);
////////////////////////////////
//~ rjf: Range Ops
#define r1u32(min, max) rng_1u32((min), (max))
internal Rng1U32 rng_1u32(U32 min, U32 max);
internal Rng1U32 shift_1u32(Rng1U32 r, U32 x);
internal Rng1U32 pad_1u32(Rng1U32 r, U32 x);
internal U32 center_1u32(Rng1U32 r);
internal B32 contains_1u32(Rng1U32 r, U32 x);
internal U32 dim_1u32(Rng1U32 r);
internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b);
internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b);
internal U32 clamp_1u32(Rng1U32 r, U32 v);
#define r1s32(min, max) rng_1s32((min), (max))
internal Rng1S32 rng_1s32(S32 min, S32 max);
internal Rng1S32 shift_1s32(Rng1S32 r, S32 x);
internal Rng1S32 pad_1s32(Rng1S32 r, S32 x);
internal S32 center_1s32(Rng1S32 r);
internal B32 contains_1s32(Rng1S32 r, S32 x);
internal S32 dim_1s32(Rng1S32 r);
internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b);
internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b);
internal S32 clamp_1s32(Rng1S32 r, S32 v);
#define r1u64(min, max) rng_1u64((min), (max))
internal Rng1U64 rng_1u64(U64 min, U64 max);
internal Rng1U64 shift_1u64(Rng1U64 r, U64 x);
internal Rng1U64 pad_1u64(Rng1U64 r, U64 x);
internal U64 center_1u64(Rng1U64 r);
internal B32 contains_1u64(Rng1U64 r, U64 x);
internal U64 dim_1u64(Rng1U64 r);
internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b);
internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b);
internal U64 clamp_1u64(Rng1U64 r, U64 v);
#define r1s64(min, max) rng_1s64((min), (max))
internal Rng1S64 rng_1s64(S64 min, S64 max);
internal Rng1S64 shift_1s64(Rng1S64 r, S64 x);
internal Rng1S64 pad_1s64(Rng1S64 r, S64 x);
internal S64 center_1s64(Rng1S64 r);
internal B32 contains_1s64(Rng1S64 r, S64 x);
internal S64 dim_1s64(Rng1S64 r);
internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b);
internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b);
internal S64 clamp_1s64(Rng1S64 r, S64 v);
#define r1f32(min, max) rng_1f32((min), (max))
internal Rng1F32 rng_1f32(F32 min, F32 max);
internal Rng1F32 shift_1f32(Rng1F32 r, F32 x);
internal Rng1F32 pad_1f32(Rng1F32 r, F32 x);
internal F32 center_1f32(Rng1F32 r);
internal B32 contains_1f32(Rng1F32 r, F32 x);
internal F32 dim_1f32(Rng1F32 r);
internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b);
internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b);
internal F32 clamp_1f32(Rng1F32 r, F32 v);
#define r2s16(min, max) rng_2s16((min), (max))
#define r2s16p(x, y, z, w) r2s16(v2s16((x), (y)), v2s16((z), (w)))
internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max);
internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x);
internal Rng2S16 pad_2s16(Rng2S16 r, S16 x);
internal Vec2S16 center_2s16(Rng2S16 r);
internal B32 contains_2s16(Rng2S16 r, Vec2S16 x);
internal Vec2S16 dim_2s16(Rng2S16 r);
internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b);
internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b);
internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v);
#define r2s32(min, max) rng_2s32((min), (max))
#define r2s32p(x, y, z, w) r2s32(v2s32((x), (y)), v2s32((z), (w)))
internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max);
internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x);
internal Rng2S32 pad_2s32(Rng2S32 r, S32 x);
internal Vec2S32 center_2s32(Rng2S32 r);
internal B32 contains_2s32(Rng2S32 r, Vec2S32 x);
internal Vec2S32 dim_2s32(Rng2S32 r);
internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b);
internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b);
internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v);
#define r2s64(min, max) rng_2s64((min), (max))
#define r2s64p(x, y, z, w) r2s64(v2s64((x), (y)), v2s64((z), (w)))
internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max);
internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x);
internal Rng2S64 pad_2s64(Rng2S64 r, S64 x);
internal Vec2S64 center_2s64(Rng2S64 r);
internal B32 contains_2s64(Rng2S64 r, Vec2S64 x);
internal Vec2S64 dim_2s64(Rng2S64 r);
internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b);
internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b);
internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v);
#define r2f32(min, max) rng_2f32((min), (max))
#define r2f32p(x, y, z, w) r2f32(v2f32((x), (y)), v2f32((z), (w)))
internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max);
internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x);
internal Rng2F32 pad_2f32(Rng2F32 r, F32 x);
internal Vec2F32 center_2f32(Rng2F32 r);
internal B32 contains_2f32(Rng2F32 r, Vec2F32 x);
internal Vec2F32 dim_2f32(Rng2F32 r);
internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b);
internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b);
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v);
////////////////////////////////
//~ rjf: Miscellaneous Ops
internal Vec3F32 hsv_from_rgb(Vec3F32 rgb);
internal Vec3F32 rgb_from_hsv(Vec3F32 hsv);
internal Vec4F32 hsva_from_rgba(Vec4F32 rgba);
internal Vec4F32 rgba_from_hsva(Vec4F32 hsva);
internal Vec4F32 rgba_from_u32(U32 hex);
internal U32 u32_from_rgba(Vec4F32 rgba);
#define rgba_from_u32_lit_comp(h) { (((h)&0xff000000)>>24)/255.f, (((h)&0x00ff0000)>>16)/255.f, (((h)&0x0000ff00)>> 8)/255.f, (((h)&0x000000ff)>> 0)/255.f }
////////////////////////////////
//~ rjf: List Type Functions
internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng);
internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list);
#endif // BASE_MATH_H
File diff suppressed because it is too large Load Diff
+351
View File
@@ -0,0 +1,351 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_STRING_H
#define BASE_STRING_H
////////////////////////////////
//~ rjf: Third Party Includes
#define STB_SPRINTF_DECORATE(name) raddbg_##name
#include "third_party/stb/stb_sprintf.h"
////////////////////////////////
//~ rjf: String Types
typedef struct String8 String8;
struct String8
{
U8 *str;
U64 size;
};
typedef struct String16 String16;
struct String16
{
U16 *str;
U64 size;
};
typedef struct String32 String32;
struct String32
{
U32 *str;
U64 size;
};
////////////////////////////////
//~ rjf: String List & Array Types
typedef struct String8Node String8Node;
struct String8Node
{
String8Node *next;
String8 string;
};
typedef struct String8MetaNode String8MetaNode;
struct String8MetaNode
{
String8MetaNode *next;
String8Node *node;
};
typedef struct String8List String8List;
struct String8List
{
String8Node *first;
String8Node *last;
U64 node_count;
U64 total_size;
};
typedef struct String8Array String8Array;
struct String8Array
{
String8 *strings;
U64 count;
};
////////////////////////////////
//~ rjf: String Matching, Splitting, & Joining Types
typedef U32 StringMatchFlags;
enum
{
StringMatchFlag_CaseInsensitive = (1 << 0),
StringMatchFlag_RightSideSloppy = (1 << 1),
StringMatchFlag_SlashInsensitive = (1 << 2),
};
typedef U32 StringSplitFlags;
enum
{
StringSplitFlag_KeepEmpties = (1 << 0),
};
typedef enum PathStyle
{
PathStyle_Relative,
PathStyle_WindowsAbsolute,
PathStyle_UnixAbsolute,
#if OS_WINDOWS
PathStyle_SystemAbsolute = PathStyle_WindowsAbsolute
#elif OS_LINUX
PathStyle_SystemAbsolute = PathStyle_UnixAbsolute
#else
# error "absolute path style is undefined for this OS"
#endif
}
PathStyle;
typedef struct StringJoin StringJoin;
struct StringJoin
{
String8 pre;
String8 sep;
String8 post;
};
////////////////////////////////
//~ rjf: String Pair Types
typedef struct String8TxtPtPair String8TxtPtPair;
struct String8TxtPtPair
{
String8 string;
TxtPt pt;
};
////////////////////////////////
//~ rjf: UTF Decoding Types
typedef struct UnicodeDecode UnicodeDecode;
struct UnicodeDecode
{
U32 inc;
U32 codepoint;
};
////////////////////////////////
//~ rjf: Character Classification & Conversion Functions
internal B32 char_is_space(U8 c);
internal B32 char_is_upper(U8 c);
internal B32 char_is_lower(U8 c);
internal B32 char_is_alpha(U8 c);
internal B32 char_is_slash(U8 c);
internal B32 char_is_digit(U8 c, U32 base);
internal U8 char_to_lower(U8 c);
internal U8 char_to_upper(U8 c);
internal U8 char_to_correct_slash(U8 c);
////////////////////////////////
//~ rjf: C-String Measurement
internal U64 cstring8_length(U8 *c);
internal U64 cstring16_length(U16 *c);
internal U64 cstring32_length(U32 *c);
////////////////////////////////
//~ rjf: String Constructors
#define str8_lit(S) str8((U8*)(S), sizeof(S) - 1)
#define str8_lit_comp(S) {(U8*)(S), sizeof(S) - 1,}
#define str8_varg(S) (int)((S).size), ((S).str)
#define str8_array(S,C) str8((U8*)(S), sizeof(*(S))*(C))
#define str8_array_fixed(S) str8((U8*)(S), sizeof(S))
#define str8_struct(S) str8((U8*)(S), sizeof(*(S)))
internal String8 str8(U8 *str, U64 size);
internal String8 str8_range(U8 *first, U8 *one_past_last);
internal String8 str8_zero(void);
internal String16 str16(U16 *str, U64 size);
internal String16 str16_range(U16 *first, U16 *one_past_last);
internal String16 str16_zero(void);
internal String32 str32(U32 *str, U64 size);
internal String32 str32_range(U32 *first, U32 *one_past_last);
internal String32 str32_zero(void);
internal String8 str8_cstring(char *c);
internal String16 str16_cstring(U16 *c);
internal String32 str32_cstring(U32 *c);
internal String8 str8_cstring_capped(void *cstr, void *cap);
////////////////////////////////
//~ rjf: String Stylization
internal String8 upper_from_str8(Arena *arena, String8 string);
internal String8 lower_from_str8(Arena *arena, String8 string);
internal String8 backslashed_from_str8(Arena *arena, String8 string);
////////////////////////////////
//~ rjf: String Matching
internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags);
internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags);
internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags);
////////////////////////////////
//~ rjf: String Slicing
internal String8 str8_substr(String8 str, Rng1U64 range);
internal String8 str8_prefix(String8 str, U64 size);
internal String8 str8_skip(String8 str, U64 amt);
internal String8 str8_postfix(String8 str, U64 size);
internal String8 str8_chop(String8 str, U64 amt);
internal String8 str8_skip_chop_whitespace(String8 string);
////////////////////////////////
//~ rjf: String Formatting & Copying
internal String8 push_str8_cat(Arena *arena, String8 s1, String8 s2);
internal String8 push_str8_copy(Arena *arena, String8 s);
internal String8 push_str8fv(Arena *arena, char *fmt, va_list args);
internal String8 push_str8f(Arena *arena, char *fmt, ...);
////////////////////////////////
//~ rjf: String <=> Integer Conversions
//- rjf: string -> integer
internal S64 sign_from_str8(String8 string, String8 *string_tail);
internal B32 str8_is_integer(String8 string, U32 radix);
internal U64 u64_from_str8(String8 string, U32 radix);
internal S64 s64_from_str8(String8 string, U32 radix);
internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x);
internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x);
//- rjf: string -> integer (base64 & base16)
internal U64 base64_size_from_data_size(U64 size_in_bytes);
internal U64 base64_from_data(U8 *dst, U8 *src, U64 src_size);
internal U64 base16_size_from_data_size(U64 size_in_bytes);
internal U64 base16_from_data(U8 *dst, U8 *src, U64 src_size);
//- rjf: integer -> string
internal String8 str8_from_memory_size(Arena *arena, U64 z);
internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator);
////////////////////////////////
//~ rjf: String <=> Float Conversions
internal F64 f64_from_str8(String8 string);
////////////////////////////////
//~ rjf: String List Construction Functions
internal String8Node* str8_list_push_node(String8List *list, String8Node *node);
internal String8Node* str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string);
internal String8Node* str8_list_push_node_front(String8List *list, String8Node *node);
internal String8Node* str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string);
internal String8Node* str8_list_push(Arena *arena, String8List *list, String8 string);
internal String8Node* str8_list_push_front(Arena *arena, String8List *list, String8 string);
internal void str8_list_concat_in_place(String8List *list, String8List *to_push);
internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align);
internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...);
internal String8Node* str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...);
internal String8List str8_list_copy(Arena *arena, String8List *list);
#define str8_list_first(list) ((list)->first ? (list)->first->string : str8_zero())
////////////////////////////////
//~ rjf: String Splitting & Joining
internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags);
internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags);
internal String8List str8_list_split_by_string_chars(Arena *arena, String8List list, String8 split_chars, StringSplitFlags flags);
internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params);
internal void str8_list_from_flags(Arena *arena, String8List *list, U32 flags, String8 *flag_string_table, U32 flag_string_count);
////////////////////////////////
//~ rjf; String Arrays
internal String8Array str8_array_from_list(Arena *arena, String8List *list);
internal String8Array str8_array_reserve(Arena *arena, U64 count);
////////////////////////////////
//~ rjf: String Path Helpers
internal String8 str8_chop_last_slash(String8 string);
internal String8 str8_skip_last_slash(String8 string);
internal String8 str8_chop_last_dot(String8 string);
internal String8 str8_skip_last_dot(String8 string);
internal PathStyle path_style_from_str8(String8 string);
internal String8List str8_split_path(Arena *arena, String8 string);
internal void str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style);
internal String8 str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style);
internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string);
////////////////////////////////
//~ rjf: UTF-8 & UTF-16 Decoding/Encoding
internal UnicodeDecode utf8_decode(U8 *str, U64 max);
internal UnicodeDecode utf16_decode(U16 *str, U64 max);
internal U32 utf8_encode(U8 *str, U32 codepoint);
internal U32 utf16_encode(U16 *str, U32 codepoint);
internal U32 utf8_from_utf32_single(U8 *buffer, U32 character);
////////////////////////////////
//~ rjf: Unicode String Conversions
internal String8 str8_from_16(Arena *arena, String16 in);
internal String16 str16_from_8(Arena *arena, String8 in);
internal String8 str8_from_32(Arena *arena, String32 in);
internal String32 str32_from_8(Arena *arena, String8 in);
////////////////////////////////
//~ rjf: Basic Types & Space Enum -> String Conversions
internal String8 string_from_dimension(Dimension dimension);
internal String8 string_from_side(Side side);
internal String8 string_from_operating_system(OperatingSystem os);
internal String8 string_from_architecture(Architecture arch);
////////////////////////////////
//~ rjf: Time Types -> String
internal String8 string_from_week_day(WeekDay week_day);
internal String8 string_from_month(Month month);
internal String8 push_date_time_string(Arena *arena, DateTime *date_time);
internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time);
internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
////////////////////////////////
//~ rjf: String <-> Color
internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba);
internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
////////////////////////////////
//~ NOTE(allen): Serialization Helpers
internal void str8_serial_begin(Arena *arena, String8List *srl);
internal String8 str8_serial_end(Arena *arena, String8List *srl);
internal void str8_serial_write_to_dst(String8List *srl, void *out);
internal U64 str8_serial_push_align(Arena *arena, String8List *srl, U64 align);
internal void * str8_serial_push_size(Arena *arena, String8List *srl, U64 size);
internal void * str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size);
internal void str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first);
internal void str8_serial_push_u64(Arena *arena, String8List *srl, U64 x);
internal void str8_serial_push_u32(Arena *arena, String8List *srl, U32 x);
internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x);
internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x);
internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str);
internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str);
#define str8_serial_push_array(arena, srl, ptr, count) str8_serial_push_data(arena, srl, ptr, sizeof(*(ptr)) * (count))
#define str8_serial_push_struct(arena, srl, ptr) str8_serial_push_array(arena, srl, ptr, 1)
////////////////////////////////
//~ rjf: Deserialization Helpers
internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity);
internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val);
internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size);internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out);
internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out);
internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out);
#define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr)))
#define str8_deserial_read_struct(string, off, ptr) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)), sizeof(*(ptr)))
#endif // BASE_STRING_H
+78
View File
@@ -0,0 +1,78 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
// NOTE(allen): Thread Context Functions
C_LINKAGE thread_static TCTX* tctx_thread_local;
#if !SUPPLEMENT_UNIT
C_LINKAGE thread_static TCTX* tctx_thread_local = 0;
#endif
internal void
tctx_init_and_equip(TCTX *tctx){
MemoryZeroStruct(tctx);
Arena **arena_ptr = tctx->arenas;
for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){
*arena_ptr = arena_alloc();
}
tctx_thread_local = tctx;
}
internal TCTX*
tctx_get_equipped(void){
return(tctx_thread_local);
}
internal Arena*
tctx_get_scratch(Arena **conflicts, U64 count){
TCTX *tctx = tctx_get_equipped();
Arena *result = 0;
Arena **arena_ptr = tctx->arenas;
for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){
Arena **conflict_ptr = conflicts;
B32 has_conflict = 0;
for (U64 j = 0; j < count; j += 1, conflict_ptr += 1){
if (*arena_ptr == *conflict_ptr){
has_conflict = 1;
break;
}
}
if (!has_conflict){
result = *arena_ptr;
break;
}
}
return(result);
}
internal void
tctx_set_thread_name(String8 string){
TCTX *tctx = tctx_get_equipped();
U64 size = ClampTop(string.size, sizeof(tctx->thread_name));
MemoryCopy(tctx->thread_name, string.str, size);
tctx->thread_name_size = size;
}
internal String8
tctx_get_thread_name(void){
TCTX *tctx = tctx_get_equipped();
String8 result = str8(tctx->thread_name, tctx->thread_name_size);
return(result);
}
internal void
tctx_write_srcloc(char *file_name, U64 line_number){
TCTX *tctx = tctx_get_equipped();
tctx->file_name = file_name;
tctx->line_number = line_number;
}
internal void
tctx_read_srcloc(char **file_name, U64 *line_number){
TCTX *tctx = tctx_get_equipped();
*file_name = tctx->file_name;
*line_number = tctx->line_number;
}
+40
View File
@@ -0,0 +1,40 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_THREAD_CONTEXT_H
#define BASE_THREAD_CONTEXT_H
////////////////////////////////
// NOTE(allen): Thread Context
typedef struct TCTX TCTX;
struct TCTX
{
Arena *arenas[2];
U8 thread_name[32];
U64 thread_name_size;
char *file_name;
U64 line_number;
};
////////////////////////////////
// NOTE(allen): Thread Context Functions
internal void tctx_init_and_equip(TCTX *tctx);
internal TCTX* tctx_get_equipped(void);
internal Arena* tctx_get_scratch(Arena **conflicts, U64 count);
internal void tctx_set_thread_name(String8 name);
internal String8 tctx_get_thread_name(void);
internal void tctx_write_srcloc(char *file_name, U64 line_number);
internal void tctx_read_srcloc(char **file_name, U64 *line_number);
#define tctx_write_this_srcloc() tctx_write_srcloc(__FILE__, __LINE__)
#define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
#define scratch_end(scratch) temp_end(scratch)
#endif //BASE_THREAD_CONTEXT_H
+454
View File
@@ -0,0 +1,454 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ Safe Casts
internal U16
safe_cast_u16(U32 x)
{
AssertAlways(x <= max_U16);
U16 result = (U16)x;
return result;
}
internal U32
safe_cast_u32(U64 x)
{
AssertAlways(x <= max_U32);
U32 result = (U32)x;
return result;
}
internal S32
safe_cast_s32(S64 x)
{
AssertAlways(x <= max_S32);
S32 result = (S32)x;
return result;
}
////////////////////////////////
//~ rjf: Large Base Type Functions
internal U128
u128_zero(void)
{
U128 v = {0};
return v;
}
internal U128
u128_make(U64 v0, U64 v1)
{
U128 v = {v0, v1};
return v;
}
internal B32
u128_match(U128 a, U128 b)
{
return MemoryMatchStruct(&a, &b);
}
////////////////////////////////
//~ rjf: Bit Patterns
internal U32
u32_from_u64_saturate(U64 x){
U32 x32 = (x > max_U32)?max_U32:(U32)x;
return(x32);
}
internal U64
u64_up_to_pow2(U64 x){
if (x == 0){
x = 1;
}
else{
x -= 1;
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
x |= (x >> 32);
x += 1;
}
return(x);
}
internal S32
extend_sign32(U32 x, U32 size){
U32 high_bit = size * 8;
U32 shift = 32 - high_bit;
S32 result = ((S32)x << shift) >> shift;
return result;
}
internal S64
extend_sign64(U64 x, U64 size){
U64 high_bit = size * 8;
U64 shift = 64 - high_bit;
S64 result = ((S64)x << shift) >> shift;
return result;
}
internal F32
inf32(void){
union { U32 u; F32 f; } x;
x.u = exponent32;
return(x.f);
}
internal F32
neg_inf32(void){
union { U32 u; F32 f; } x;
x.u = sign32 | exponent32;
return(x.f);
}
internal U16
bswap_u16(U16 x)
{
U16 result = (((x & 0xFF00) >> 8) |
((x & 0x00FF) << 8));
return result;
}
internal U32
bswap_u32(U32 x)
{
U32 result = (((x & 0xFF000000) >> 24) |
((x & 0x00FF0000) >> 8) |
((x & 0x0000FF00) << 8) |
((x & 0x000000FF) << 24));
return result;
}
internal U64
bswap_u64(U64 x)
{
// TODO(nick): naive bswap, replace with something that is faster like an intrinsic
U64 result = (((x & 0xFF00000000000000ULL) >> 56) |
((x & 0x00FF000000000000ULL) >> 40) |
((x & 0x0000FF0000000000ULL) >> 24) |
((x & 0x000000FF00000000ULL) >> 8) |
((x & 0x00000000FF000000ULL) << 8) |
((x & 0x0000000000FF0000ULL) << 24) |
((x & 0x000000000000FF00ULL) << 40) |
((x & 0x00000000000000FFULL) << 56));
return result;
}
////////////////////////////////
//~ rjf: Enum -> Sign
internal S32
sign_from_side_S32(Side side){
return((side == Side_Min)?-1:1);
}
internal F32
sign_from_side_F32(Side side){
return((side == Side_Min)?-1.f:1.f);
}
////////////////////////////////
//~ rjf: Memory Functions
internal B32
memory_is_zero(void *ptr, U64 size){
B32 result = 1;
// break down size
U64 extra = (size&0x7);
U64 count8 = (size >> 3);
// check with 8-byte stride
U64 *p64 = (U64*)ptr;
if(result)
{
for (U64 i = 0; i < count8; i += 1, p64 += 1){
if (*p64 != 0){
result = 0;
goto done;
}
}
}
// check extra
if(result)
{
U8 *p8 = (U8*)p64;
for (U64 i = 0; i < extra; i += 1, p8 += 1){
if (*p8 != 0){
result = 0;
goto done;
}
}
}
done:;
return(result);
}
////////////////////////////////
//~ rjf: Text 2D Coordinate/Range Functions
internal TxtPt
txt_pt(S64 line, S64 column)
{
TxtPt p = {0};
p.line = line;
p.column = column;
return p;
}
internal B32
txt_pt_match(TxtPt a, TxtPt b)
{
return a.line == b.line && a.column == b.column;
}
internal B32
txt_pt_less_than(TxtPt a, TxtPt b)
{
B32 result = 0;
if(a.line < b.line)
{
result = 1;
}
else if(a.line == b.line)
{
result = a.column < b.column;
}
return result;
}
internal TxtPt
txt_pt_min(TxtPt a, TxtPt b)
{
TxtPt result = b;
if(txt_pt_less_than(a, b))
{
result = a;
}
return result;
}
internal TxtPt
txt_pt_max(TxtPt a, TxtPt b)
{
TxtPt result = a;
if(txt_pt_less_than(a, b))
{
result = b;
}
return result;
}
internal TxtRng
txt_rng(TxtPt min, TxtPt max)
{
TxtRng range = {0};
if(txt_pt_less_than(min, max))
{
range.min = min;
range.max = max;
}
else
{
range.min = max;
range.max = min;
}
return range;
}
internal TxtRng
txt_rng_intersect(TxtRng a, TxtRng b)
{
TxtRng result = {0};
result.min = txt_pt_max(a.min, b.min);
result.max = txt_pt_min(a.max, b.max);
if(txt_pt_less_than(result.max, result.min))
{
MemoryZeroStruct(&result);
}
return result;
}
internal TxtRng
txt_rng_union(TxtRng a, TxtRng b)
{
TxtRng result = {0};
result.min = txt_pt_min(a.min, b.min);
result.max = txt_pt_max(a.max, b.max);
return result;
}
////////////////////////////////
//~ rjf: Toolchain/Environment Enum Functions
internal U64
bit_size_from_arch(Architecture arch)
{
// TODO(rjf): metacode
U64 arch_bitsize = 0;
switch(arch)
{
case Architecture_x64: arch_bitsize = 64; break;
case Architecture_x86: arch_bitsize = 32; break;
case Architecture_arm64: arch_bitsize = 64; break;
case Architecture_arm32: arch_bitsize = 32; break;
default: break;
}
return arch_bitsize;
}
internal U64
max_instruction_size_from_arch(Architecture arch)
{
// TODO(rjf): make this real
return 64;
}
internal OperatingSystem
operating_system_from_context(void){
OperatingSystem os = OperatingSystem_Null;
#if OS_WINDOWS
os = OperatingSystem_Windows;
#elif OS_LINUX
os = OperatingSystem_Linux;
#elif OS_MAC
os = OperatingSystem_Mac;
#endif
return os;
}
internal Architecture
architecture_from_context(void){
Architecture arch = Architecture_Null;
#if ARCH_X64
arch = Architecture_x64;
#elif ARCH_X86
arch = Architecture_x86;
#elif ARCH_ARM64
arch = Architecture_arm64;
#elif ARCH_ARM32
arch = Architecture_arm32;
#endif
return arch;
}
internal Compiler
compiler_from_context(void){
Compiler compiler = Compiler_Null;
#if COMPILER_CL
compiler = Compiler_cl;
#elif COMPILER_GCC
compiler = Compiler_gcc;
#elif COMPILER_CLANG
compiler = Compiler_clang;
#endif
return compiler;
}
////////////////////////////////
//~ rjf: Time Functions
internal DenseTime
dense_time_from_date_time(DateTime date_time){
DenseTime result = 0;
result += date_time.year;
result *= 12;
result += date_time.mon;
result *= 31;
result += date_time.day;
result *= 24;
result += date_time.hour;
result *= 60;
result += date_time.min;
result *= 61;
result += date_time.sec;
result *= 1000;
result += date_time.msec;
return(result);
}
internal DateTime
date_time_from_dense_time(DenseTime time){
DateTime result = {0};
result.msec = time%1000;
time /= 1000;
result.sec = time%61;
time /= 61;
result.min = time%60;
time /= 60;
result.hour = time%24;
time /= 24;
result.day = time%31;
time /= 31;
result.mon = time%12;
time /= 12;
Assert(time <= max_U32);
result.year = (U32)time;
return(result);
}
internal DateTime
date_time_from_micro_seconds(U64 time){
DateTime result = {0};
result.micro_sec = time%1000;
time /= 1000;
result.msec = time%1000;
time /= 1000;
result.sec = time%60;
time /= 60;
result.min = time%60;
time /= 60;
result.hour = time%24;
time /= 24;
result.day = time%31;
time /= 31;
result.mon = time%12;
time /= 12;
Assert(time <= max_U32);
result.year = (U32)time;
return(result);
}
////////////////////////////////
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
internal U64
ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size)
{
Assert(src_data_size <= ring_size);
{
U64 ring_off = ring_pos%ring_size;
U64 bytes_before_split = ring_size-ring_off;
U64 pre_split_bytes = Min(bytes_before_split, src_data_size);
U64 pst_split_bytes = src_data_size-pre_split_bytes;
void *pre_split_data = src_data;
void *pst_split_data = ((U8 *)src_data + pre_split_bytes);
MemoryCopy(ring_base+ring_off, pre_split_data, pre_split_bytes);
MemoryCopy(ring_base+0, pst_split_data, pst_split_bytes);
}
return src_data_size;
}
internal U64
ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size)
{
Assert(read_size <= ring_size);
{
U64 ring_off = ring_pos%ring_size;
U64 bytes_before_split = ring_size-ring_off;
U64 pre_split_bytes = Min(bytes_before_split, read_size);
U64 pst_split_bytes = read_size-pre_split_bytes;
MemoryCopy(dst_data, ring_base+ring_off, pre_split_bytes);
MemoryCopy((U8 *)dst_data + pre_split_bytes, ring_base+0, pst_split_bytes);
}
return read_size;
}
+683
View File
@@ -0,0 +1,683 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_TYPES_H
#define BASE_TYPES_H
////////////////////////////////
//~ rjf: Foreign Includes
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <string.h>
#include <stdint.h>
////////////////////////////////
//~ rjf: Build Configuration
#if !defined(ENABLE_DEV)
# define ENABLE_DEV 0
#endif
#if !defined(SUPPLEMENT_UNIT)
# define SUPPLEMENT_UNIT 0
#endif
////////////////////////////////
//~ rjf: Codebase Keywords
#define internal static
#define global static
#define local_persist static
#if COMPILER_CL || (COMPILER_CLANG && OS_WINDOWS)
# pragma section(".rdata$", read)
# define read_only __declspec(allocate(".rdata$"))
#elif (COMPILER_CLANG && OS_LINUX)
# define read_only __attribute__((section(".rodata")))
#else
// NOTE(rjf): I don't know of a useful way to do this in GCC land.
// __attribute__((section(".rodata"))) looked promising, but it introduces a
// strange warning about malformed section attributes, and it doesn't look
// like writing to that section reliably produces access violations, strangely
// enough. (It does on Clang)
# define read_only
#endif
////////////////////////////////
//~ rjf: Memory Operation Macros
#define MemoryCopy(dst, src, size) memmove((dst), (src), (size))
#define MemorySet(dst, byte, size) memset((dst), (byte), (size))
#define MemoryCompare(a, b, size) memcmp((a), (b), (size))
#define MemoryStrlen(ptr) strlen(ptr)
#define MemoryCopyStruct(d,s) MemoryCopy((d),(s),sizeof(*(d)))
#define MemoryCopyArray(d,s) MemoryCopy((d),(s),sizeof(d))
#define MemoryCopyTyped(d,s,c) MemoryCopy((d),(s),sizeof(*(d))*(c))
#define MemoryZero(s,z) memset((s),0,(z))
#define MemoryZeroStruct(s) MemoryZero((s),sizeof(*(s)))
#define MemoryZeroArray(a) MemoryZero((a),sizeof(a))
#define MemoryZeroTyped(m,c) MemoryZero((m),sizeof(*(m))*(c))
#define MemoryMatch(a,b,z) (MemoryCompare((a),(b),(z)) == 0)
#define MemoryMatchStruct(a,b) MemoryMatch((a),(b),sizeof(*(a)))
#define MemoryMatchArray(a,b) MemoryMatch((a),(b),sizeof(a))
#define MemoryRead(T,p,e) ( ((p)+sizeof(T)<=(e))?(*(T*)(p)):(0) )
#define MemoryConsume(T,p,e) \
( ((p)+sizeof(T)<=(e))?((p)+=sizeof(T),*(T*)((p)-sizeof(T))):((p)=(e),0) )
////////////////////////////////
//~ rjf: Units
#define KB(n) (((U64)(n)) << 10)
#define MB(n) (((U64)(n)) << 20)
#define GB(n) (((U64)(n)) << 30)
#define TB(n) (((U64)(n)) << 40)
#define Thousand(n) ((n)*1000)
#define Million(n) ((n)*1000000)
#define Billion(n) ((n)*1000000000)
////////////////////////////////
//~ rjf: Asserts
#if COMPILER_CL
# define Trap() __debugbreak()
#elif COMPILER_CLANG || COMPILER_GCC
# define Trap() __builtin_trap()
# else
# error "undefined trap"
#endif
#define AssertAlways(x) do{if(!(x)) {Trap();}}while(0)
#if !defined(NDEBUG)
# define Assert(x) AssertAlways(x)
#else
# define Assert(x) (void)(x)
#endif
#define AssertImplies(a,b) Assert(!(a) || b)
#define AssertIff(a,b) Assert(!!(a) == !!(b))
#define InvalidPath Assert(!"Invalid Path!")
#define NotImplemented Assert(!"Not Implemented!")
#define StaticAssert(C,ID) global U8 Glue(ID,__LINE__)[(C)?1:-1]
////////////////////////////////
//~ rjf: Branch Predictor Hints
#if defined(__clang__)
# define Expect(expr, val) __builtin_expect((expr), (val))
#else
# define Expect(expr, val) (expr)
#endif
#define Likely(expr) Expect(expr,1)
#define Unlikely(expr) Expect(expr,0)
////////////////////////////////
//~ rjf: Misc. Helper Macros
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
#define Stmnt(S) do{ S }while(0)
#define Stringify_(S) #S
#define Stringify(S) Stringify_(S)
#define Glue_(A,B) A##B
#define Glue(A,B) Glue_(A,B)
#define Min(A,B) ( ((A)<(B))?(A):(B) )
#define Max(A,B) ( ((A)>(B))?(A):(B) )
#define ClampTop(A,X) Min(A,X)
#define ClampBot(X,B) Max(X,B)
#define Clamp(A,X,B) ( ((X)<(A))?(A):((X)>(B))?(B):(X) )
#define PtrClampTop(A,X) ClampTop(A,X)
#define PtrClampBot(X,B) ClampBot(X,B)
#define PtrClamp(A,X,B) Clamp(A,X,B)
#define CeilIntegerDiv(a,b) (((a) + (b) - 1)/(b))
#define Swap(T,a,b) Stmnt( T t__ = a; a = b; b = t__; )
#if ARCH_64BIT
# define IntFromPtr(ptr) ((U64)(ptr))
#elif ARCH_32BIT
# define IntFromPtr(ptr) ((U32)(ptr))
#else
# error missing ptr cast for this architecture
#endif
#define PtrFromInt(i) (void*)((U8*)0 + (i))
#define Member(T,m) (((T*)0)->m)
#define OffsetOf(T,m) IntFromPtr(&Member(T,m))
#define MemberFromOffset(T,ptr,off) (T)((((U8 *)ptr)+(off)))
#define CastFromMember(T,m,ptr) (T*)(((U8*)ptr) - OffsetOf(T,m))
#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b));
#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1)))
#define AlignDownPow2(x,b) ((x)&(~((b) - 1)))
#define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1))
#define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0)
#define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0)
#define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end))
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
#define B8 S8
#define B32 rrbool
#if LANG_CPP
# define zero_struct {}
#else
# define zero_struct {0}
#endif
#if COMPILER_MSVC && COMPILER_MSVC_YEAR < 2015
# define this_function_name "unknown"
#else
# define this_function_name __func__
#endif
#if LANG_CPP
# define C_LINKAGE_BEGIN extern "C"{
# define C_LINKAGE_END }
# define C_LINKAGE extern "C"
#else
# define C_LINKAGE_BEGIN
# define C_LINKAGE_END
# define C_LINKAGE
#endif
#if COMPILER_CL
# define thread_static __declspec(thread)
#elif COMPILER_CLANG || COMPILER_GCC
# define thread_static __thread
#endif
#if OS_WINDOWS
# define shared_function C_LINKAGE __declspec(dllexport)
#else
# define shared_function C_LINKAGE
#endif
////////////////////////////////
//~ ASAN
#if COMPILER_CL
# if defined(__SANITIZE_ADDRESS__)
# define ASAN_ENABLED 1
# define NO_ASAN __declspec(no_sanitize_address)
# else
# define NO_ASAN
# endif
#elif COMPILER_CLANG
# if defined(__has_feature)
# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
# define ASAN_ENABLED 1
# endif
# endif
# define NO_ASAN __attribute__((no_sanitize("address")))
#else
# error "NO_ASAN is not defined"
#endif
#if ASAN_ENABLED
#pragma comment(lib, "clang_rt.asan-x86_64.lib")
C_LINKAGE_BEGIN
void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
C_LINKAGE_END
# define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size))
# define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size))
#else
# define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size))
# define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size))
#endif
////////////////////////////////
//~ rjf: Base Types
typedef uint8_t U8;
typedef uint16_t U16;
typedef uint32_t U32;
typedef uint64_t U64;
typedef int8_t S8;
typedef int16_t S16;
typedef int32_t S32;
typedef int64_t S64;
typedef S8 B8;
typedef S16 B16;
typedef S32 B32;
typedef S64 B64;
typedef float F32;
typedef double F64;
////////////////////////////////
//~ rjf: Large Base Types
typedef struct U128 U128;
struct U128
{
U64 u64[2];
};
////////////////////////////////
//~ rjf: Basic Types & Spaces
typedef void VoidProc(void);
typedef enum Dimension
{
Dimension_X,
Dimension_Y,
Dimension_Z,
Dimension_W,
}
Dimension;
typedef enum Side
{
Side_Invalid = -1,
Side_Min,
Side_Max,
Side_COUNT,
}
Side;
#define side_flip(s) ((Side)(!(s)))
typedef enum Axis2
{
Axis2_Invalid = -1,
Axis2_X,
Axis2_Y,
Axis2_COUNT,
}
Axis2;
#define axis2_flip(a) ((Axis2)(!(a)))
typedef enum Corner
{
Corner_Invalid = -1,
Corner_00,
Corner_01,
Corner_10,
Corner_11,
Corner_COUNT
}
Corner;
////////////////////////////////
//~ rjf: Toolchain/Environment Enums
typedef enum OperatingSystem
{
OperatingSystem_Null,
OperatingSystem_Windows,
OperatingSystem_Linux,
OperatingSystem_Mac,
OperatingSystem_COUNT,
}
OperatingSystem;
typedef enum Architecture
{
Architecture_Null,
Architecture_x64,
Architecture_x86,
Architecture_arm64,
Architecture_arm32,
Architecture_COUNT,
}
Architecture;
typedef enum Compiler
{
Compiler_Null,
Compiler_cl,
Compiler_gcc,
Compiler_clang,
Compiler_COUNT,
}
Compiler;
////////////////////////////////
//~ rjf: Text 2D Coordinates & Ranges
typedef struct TxtPt TxtPt;
struct TxtPt
{
S64 line;
S64 column;
};
typedef struct TxtRng TxtRng;
struct TxtRng
{
TxtPt min;
TxtPt max;
};
////////////////////////////////
//~ NOTE(allen): Constants
global U32 sign32 = 0x80000000;
global U32 exponent32 = 0x7F800000;
global U32 mantissa32 = 0x007FFFFF;
global F32 big_golden32 = 1.61803398875f;
global F32 small_golden32 = 0.61803398875f;
global F32 pi32 = 3.1415926535897f;
global F64 machine_epsilon64 = 4.94065645841247e-324;
global U64 max_U64 = 0xffffffffffffffffull;
global U32 max_U32 = 0xffffffff;
global U16 max_U16 = 0xffff;
global U8 max_U8 = 0xff;
global S64 max_S64 = (S64)0x7fffffffffffffffull;
global S32 max_S32 = (S32)0x7fffffff;
global S16 max_S16 = (S16)0x7fff;
global S8 max_S8 = (S8)0x7f;
global S64 min_S64 = (S64)0xffffffffffffffffull;
global S32 min_S32 = (S32)0xffffffff;
global S16 min_S16 = (S16)0xffff;
global S8 min_S8 = (S8)0xff;
global const U32 bitmask1 = 0x00000001;
global const U32 bitmask2 = 0x00000003;
global const U32 bitmask3 = 0x00000007;
global const U32 bitmask4 = 0x0000000f;
global const U32 bitmask5 = 0x0000001f;
global const U32 bitmask6 = 0x0000003f;
global const U32 bitmask7 = 0x0000007f;
global const U32 bitmask8 = 0x000000ff;
global const U32 bitmask9 = 0x000001ff;
global const U32 bitmask10 = 0x000003ff;
global const U32 bitmask11 = 0x000007ff;
global const U32 bitmask12 = 0x00000fff;
global const U32 bitmask13 = 0x00001fff;
global const U32 bitmask14 = 0x00003fff;
global const U32 bitmask15 = 0x00007fff;
global const U32 bitmask16 = 0x0000ffff;
global const U32 bitmask17 = 0x0001ffff;
global const U32 bitmask18 = 0x0003ffff;
global const U32 bitmask19 = 0x0007ffff;
global const U32 bitmask20 = 0x000fffff;
global const U32 bitmask21 = 0x001fffff;
global const U32 bitmask22 = 0x003fffff;
global const U32 bitmask23 = 0x007fffff;
global const U32 bitmask24 = 0x00ffffff;
global const U32 bitmask25 = 0x01ffffff;
global const U32 bitmask26 = 0x03ffffff;
global const U32 bitmask27 = 0x07ffffff;
global const U32 bitmask28 = 0x0fffffff;
global const U32 bitmask29 = 0x1fffffff;
global const U32 bitmask30 = 0x3fffffff;
global const U32 bitmask31 = 0x7fffffff;
global const U32 bitmask32 = 0xffffffff;
global const U64 bitmask33 = 0x00000001ffffffffull;
global const U64 bitmask34 = 0x00000003ffffffffull;
global const U64 bitmask35 = 0x00000007ffffffffull;
global const U64 bitmask36 = 0x0000000fffffffffull;
global const U64 bitmask37 = 0x0000001fffffffffull;
global const U64 bitmask38 = 0x0000003fffffffffull;
global const U64 bitmask39 = 0x0000007fffffffffull;
global const U64 bitmask40 = 0x000000ffffffffffull;
global const U64 bitmask41 = 0x000001ffffffffffull;
global const U64 bitmask42 = 0x000003ffffffffffull;
global const U64 bitmask43 = 0x000007ffffffffffull;
global const U64 bitmask44 = 0x00000fffffffffffull;
global const U64 bitmask45 = 0x00001fffffffffffull;
global const U64 bitmask46 = 0x00003fffffffffffull;
global const U64 bitmask47 = 0x00007fffffffffffull;
global const U64 bitmask48 = 0x0000ffffffffffffull;
global const U64 bitmask49 = 0x0001ffffffffffffull;
global const U64 bitmask50 = 0x0003ffffffffffffull;
global const U64 bitmask51 = 0x0007ffffffffffffull;
global const U64 bitmask52 = 0x000fffffffffffffull;
global const U64 bitmask53 = 0x001fffffffffffffull;
global const U64 bitmask54 = 0x003fffffffffffffull;
global const U64 bitmask55 = 0x007fffffffffffffull;
global const U64 bitmask56 = 0x00ffffffffffffffull;
global const U64 bitmask57 = 0x01ffffffffffffffull;
global const U64 bitmask58 = 0x03ffffffffffffffull;
global const U64 bitmask59 = 0x07ffffffffffffffull;
global const U64 bitmask60 = 0x0fffffffffffffffull;
global const U64 bitmask61 = 0x1fffffffffffffffull;
global const U64 bitmask62 = 0x3fffffffffffffffull;
global const U64 bitmask63 = 0x7fffffffffffffffull;
global const U64 bitmask64 = 0xffffffffffffffffull;
global const U32 bit1 = (1<<0);
global const U32 bit2 = (1<<1);
global const U32 bit3 = (1<<2);
global const U32 bit4 = (1<<3);
global const U32 bit5 = (1<<4);
global const U32 bit6 = (1<<5);
global const U32 bit7 = (1<<6);
global const U32 bit8 = (1<<7);
global const U32 bit9 = (1<<8);
global const U32 bit10 = (1<<9);
global const U32 bit11 = (1<<10);
global const U32 bit12 = (1<<11);
global const U32 bit13 = (1<<12);
global const U32 bit14 = (1<<13);
global const U32 bit15 = (1<<14);
global const U32 bit16 = (1<<15);
global const U32 bit17 = (1<<16);
global const U32 bit18 = (1<<17);
global const U32 bit19 = (1<<18);
global const U32 bit20 = (1<<19);
global const U32 bit21 = (1<<20);
global const U32 bit22 = (1<<21);
global const U32 bit23 = (1<<22);
global const U32 bit24 = (1<<23);
global const U32 bit25 = (1<<24);
global const U32 bit26 = (1<<25);
global const U32 bit27 = (1<<26);
global const U32 bit28 = (1<<27);
global const U32 bit29 = (1<<28);
global const U32 bit30 = (1<<29);
global const U32 bit31 = (1<<30);
global const U32 bit32 = (1<<31);
global const U64 bit33 = (1ull<<32);
global const U64 bit34 = (1ull<<33);
global const U64 bit35 = (1ull<<34);
global const U64 bit36 = (1ull<<35);
global const U64 bit37 = (1ull<<36);
global const U64 bit38 = (1ull<<37);
global const U64 bit39 = (1ull<<38);
global const U64 bit40 = (1ull<<39);
global const U64 bit41 = (1ull<<40);
global const U64 bit42 = (1ull<<41);
global const U64 bit43 = (1ull<<42);
global const U64 bit44 = (1ull<<43);
global const U64 bit45 = (1ull<<44);
global const U64 bit46 = (1ull<<45);
global const U64 bit47 = (1ull<<46);
global const U64 bit48 = (1ull<<47);
global const U64 bit49 = (1ull<<48);
global const U64 bit50 = (1ull<<49);
global const U64 bit51 = (1ull<<50);
global const U64 bit52 = (1ull<<51);
global const U64 bit53 = (1ull<<52);
global const U64 bit54 = (1ull<<53);
global const U64 bit55 = (1ull<<54);
global const U64 bit56 = (1ull<<55);
global const U64 bit57 = (1ull<<56);
global const U64 bit58 = (1ull<<57);
global const U64 bit59 = (1ull<<58);
global const U64 bit60 = (1ull<<59);
global const U64 bit61 = (1ull<<60);
global const U64 bit62 = (1ull<<61);
global const U64 bit63 = (1ull<<62);
global const U64 bit64 = (1ull<<63);
////////////////////////////////
//~ allen: Time
typedef enum WeekDay
{
WeekDay_Sun,
WeekDay_Mon,
WeekDay_Tue,
WeekDay_Wed,
WeekDay_Thu,
WeekDay_Fri,
WeekDay_Sat,
WeekDay_COUNT,
}
WeekDay;
typedef enum Month
{
Month_Jan,
Month_Feb,
Month_Mar,
Month_Apr,
Month_May,
Month_Jun,
Month_Jul,
Month_Aug,
Month_Sep,
Month_Oct,
Month_Nov,
Month_Dec,
Month_COUNT,
}
Month;
typedef struct DateTime DateTime;
struct DateTime
{
U16 micro_sec; // [0,999]
U16 msec; // [0,999]
U16 sec; // [0,60]
U16 min; // [0,59]
U16 hour; // [0,24]
U16 day; // [0,30]
union{
WeekDay week_day;
U32 wday;
};
union{
Month month;
U32 mon;
};
U32 year; // 1 = 1 CE, 0 = 1 BC
};
typedef U64 DenseTime;
////////////////////////////////
//~ allen: Files
typedef U32 FilePropertyFlags;
enum
{
FilePropertyFlag_IsFolder = (1 << 0),
};
typedef struct FileProperties FileProperties;
struct FileProperties
{
U64 size;
DenseTime modified;
DenseTime created;
FilePropertyFlags flags;
};
////////////////////////////////
//~ Safe Casts
internal U16 safe_cast_u16(U32 x);
internal U32 safe_cast_u32(U64 x);
internal S32 safe_cast_s32(S64 x);
////////////////////////////////
//~ rjf: Large Base Type Functions
internal U128 u128_zero(void);
internal U128 u128_make(U64 v0, U64 v1);
internal B32 u128_match(U128 a, U128 b);
////////////////////////////////
//~ rjf: Bit Patterns
internal U32 u32_from_u64_saturate(U64 x);
internal U64 u64_up_to_pow2(U64 x);
internal S32 extend_sign32(U32 x, U32 size);
internal S64 extend_sign64(U64 x, U64 size);
internal F32 inf32(void);
internal F32 neg_inf32(void);
internal U16 bswap_u16(U16 x);
internal U32 bswap_u32(U32 x);
internal U64 bswap_u64(U64 x);
////////////////////////////////
//~ rjf: Enum -> Sign
internal S32 sign_from_side_S32(Side side);
internal F32 sign_from_side_F32(Side side);
////////////////////////////////
//~ rjf: Memory Functions
internal B32 memory_is_zero(void *ptr, U64 size);
////////////////////////////////
//~ rjf: Text 2D Coordinate/Range Functions
internal TxtPt txt_pt(S64 line, S64 column);
internal B32 txt_pt_match(TxtPt a, TxtPt b);
internal B32 txt_pt_less_than(TxtPt a, TxtPt b);
internal TxtPt txt_pt_min(TxtPt a, TxtPt b);
internal TxtPt txt_pt_max(TxtPt a, TxtPt b);
internal TxtRng txt_rng(TxtPt min, TxtPt max);
internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b);
internal TxtRng txt_rng_union(TxtRng a, TxtRng b);
////////////////////////////////
//~ rjf: Toolchain/Environment Enum Functions
internal U64 bit_size_from_arch(Architecture arch);
internal U64 max_instruction_size_from_arch(Architecture arch);
internal OperatingSystem operating_system_from_context(void);
internal Architecture architecture_from_context(void);
internal Compiler compiler_from_context(void);
////////////////////////////////
//~ rjf: Time Functions
internal DenseTime dense_time_from_date_time(DateTime date_time);
internal DateTime date_time_from_dense_time(DenseTime time);
internal DateTime date_time_from_micro_seconds(U64 time);
////////////////////////////////
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size);
internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size);
#define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
#define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
#endif // BASE_TYPES_H