mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-18 18:12:23 -07:00
update metagen base/os & entry point
This commit is contained in:
@@ -1,316 +1,195 @@
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
|
||||
internal Arena *
|
||||
arena_alloc_(ArenaParams *params)
|
||||
{
|
||||
// rjf: round up reserve/commit sizes
|
||||
U64 reserve_size = params->reserve_size;
|
||||
U64 commit_size = params->commit_size;
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size);
|
||||
commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size);
|
||||
commit_size = AlignPow2(commit_size, os_get_system_info()->page_size);
|
||||
}
|
||||
|
||||
// rjf: reserve/commit initial block
|
||||
void *base = params->optional_backing_buffer;
|
||||
if(base == 0)
|
||||
{
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
base = os_reserve_large(reserve_size);
|
||||
os_commit_large(base, commit_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = os_reserve(reserve_size);
|
||||
os_commit(base, commit_size);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: panic on arena creation failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(base == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// rjf: extract arena header & fill
|
||||
Arena *arena = (Arena *)base;
|
||||
arena->current = arena;
|
||||
arena->flags = params->flags;
|
||||
arena->cmt_size = (U32)params->commit_size;
|
||||
arena->res_size = params->reserve_size;
|
||||
arena->base_pos = 0;
|
||||
arena->pos = ARENA_HEADER_SIZE;
|
||||
arena->cmt = commit_size;
|
||||
arena->res = reserve_size;
|
||||
AsanPoisonMemoryRegion(base, commit_size);
|
||||
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
|
||||
return arena;
|
||||
}
|
||||
|
||||
internal void
|
||||
arena_release(Arena *arena)
|
||||
{
|
||||
for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
|
||||
{
|
||||
prev = n->prev;
|
||||
os_release(n, n->res);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: arena push/pop core functions
|
||||
|
||||
internal void *
|
||||
arena_push(Arena *arena, U64 size, U64 align)
|
||||
{
|
||||
Arena *current = arena->current;
|
||||
U64 pos_pre = AlignPow2(current->pos, align);
|
||||
U64 pos_pst = pos_pre + size;
|
||||
|
||||
// rjf: chain, if needed
|
||||
if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain))
|
||||
{
|
||||
U64 res_size = current->res_size;
|
||||
U64 cmt_size = current->cmt_size;
|
||||
if(size > cmt_size)
|
||||
{
|
||||
res_size = size + ARENA_HEADER_SIZE;
|
||||
cmt_size = size + ARENA_HEADER_SIZE;
|
||||
}
|
||||
Arena *new_block = arena_alloc(.reserve_size = res_size,
|
||||
.commit_size = cmt_size,
|
||||
.flags = current->flags);
|
||||
new_block->base_pos = current->base_pos + current->res;
|
||||
SLLStackPush_N(arena->current, new_block, prev);
|
||||
current = new_block;
|
||||
pos_pre = AlignPow2(current->pos, align);
|
||||
pos_pst = pos_pst + size;
|
||||
}
|
||||
|
||||
// rjf: commit new pages, if needed
|
||||
if(current->cmt < pos_pst && !(current->flags & ArenaFlag_LargePages))
|
||||
{
|
||||
U64 cmt_pst_aligned = AlignPow2(pos_pst, current->cmt_size);
|
||||
U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res);
|
||||
U64 cmt_size = cmt_pst_clamped - current->cmt;
|
||||
os_commit((U8 *)current + current->cmt, cmt_size);
|
||||
current->cmt = cmt_pst_clamped;
|
||||
}
|
||||
|
||||
// rjf: push onto current block
|
||||
void *result = 0;
|
||||
if(current->cmt >= pos_pst)
|
||||
{
|
||||
result = (U8 *)current+pos_pre;
|
||||
current->pos = pos_pst;
|
||||
AsanUnpoisonMemoryRegion(result, size);
|
||||
}
|
||||
|
||||
// rjf: panic on failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(result == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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 pos)
|
||||
{
|
||||
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos);
|
||||
Arena *current = arena->current;
|
||||
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
|
||||
{
|
||||
prev = current->prev;
|
||||
os_release(current, current->res);
|
||||
}
|
||||
arena->current = current;
|
||||
U64 new_pos = big_pos - current->base_pos;
|
||||
AssertAlways(new_pos <= current->pos);
|
||||
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
|
||||
current->pos = new_pos;
|
||||
}
|
||||
|
||||
//- rjf: arena push/pop helpers
|
||||
|
||||
internal void
|
||||
arena_clear(Arena *arena)
|
||||
{
|
||||
arena_pop_to(arena, 0);
|
||||
}
|
||||
|
||||
internal void
|
||||
arena_pop(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);
|
||||
}
|
||||
|
||||
//- rjf: temporary arena scopes
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,94 +1,80 @@
|
||||
// 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
|
||||
// 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 64
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Types
|
||||
|
||||
typedef U32 ArenaFlags;
|
||||
enum
|
||||
{
|
||||
ArenaFlag_NoChain = (1<<0),
|
||||
ArenaFlag_LargePages = (1<<1),
|
||||
};
|
||||
|
||||
typedef struct ArenaParams ArenaParams;
|
||||
struct ArenaParams
|
||||
{
|
||||
ArenaFlags flags;
|
||||
U64 reserve_size;
|
||||
U64 commit_size;
|
||||
void *optional_backing_buffer;
|
||||
};
|
||||
|
||||
typedef struct Arena Arena;
|
||||
struct Arena
|
||||
{
|
||||
Arena *prev; // previous arena in chain
|
||||
Arena *current; // current arena in chain
|
||||
ArenaFlags flags;
|
||||
U32 cmt_size;
|
||||
U64 res_size;
|
||||
U64 base_pos;
|
||||
U64 pos;
|
||||
U64 cmt;
|
||||
U64 res;
|
||||
};
|
||||
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
|
||||
|
||||
typedef struct Temp Temp;
|
||||
struct Temp
|
||||
{
|
||||
Arena *arena;
|
||||
U64 pos;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
internal Arena *arena_alloc_(ArenaParams *params);
|
||||
#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = MB(64), .commit_size = KB(64), __VA_ARGS__})
|
||||
internal void arena_release(Arena *arena);
|
||||
|
||||
//- rjf: arena push/pop/pos core functions
|
||||
internal void *arena_push(Arena *arena, U64 size, U64 align);
|
||||
internal U64 arena_pos(Arena *arena);
|
||||
internal void arena_pop_to(Arena *arena, U64 pos);
|
||||
|
||||
//- rjf: arena push/pop helpers
|
||||
internal void arena_clear(Arena *arena);
|
||||
internal void arena_pop(Arena *arena, U64 amt);
|
||||
|
||||
//- rjf: temporary arena scopes
|
||||
internal Temp temp_begin(Arena *arena);
|
||||
internal void temp_end(Temp temp);
|
||||
|
||||
//- rjf: push helper macros
|
||||
#define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align))
|
||||
#define push_array_aligned(a, T, c, align) (T *)MemoryZero(push_array_no_zero_aligned(a, T, c, align), sizeof(T)*(c))
|
||||
#define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, AlignOf(T)))
|
||||
#define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T)))
|
||||
|
||||
#endif // BASE_ARENA_H
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
// 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
|
||||
@@ -1,47 +0,0 @@
|
||||
// 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
|
||||
@@ -1,103 +0,0 @@
|
||||
// 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
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// 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
|
||||
@@ -1,229 +1,232 @@
|
||||
// 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);
|
||||
}
|
||||
// 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};
|
||||
parsed.exe_name = command_line.first->string;
|
||||
|
||||
// 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;
|
||||
B32 first_passthrough = 1;
|
||||
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) || !first_passthrough)
|
||||
{
|
||||
str8_list_push(arena, &parsed.inputs, node->string);
|
||||
after_passthrough_option = 1;
|
||||
first_passthrough = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,53 +1,54 @@
|
||||
// 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
|
||||
// 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
|
||||
{
|
||||
String8 exe_name;
|
||||
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
|
||||
|
||||
@@ -1,154 +1,247 @@
|
||||
// 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
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Unsupported Errors
|
||||
|
||||
#if ARCH_X86
|
||||
# error You tried to build in x86 (32 bit) mode, but currently, only building in x64 (64 bit) mode is supported.
|
||||
#endif
|
||||
#if !ARCH_X64
|
||||
# error You tried to build with an unsupported architecture. Currently, only building in x64 mode is supported.
|
||||
#endif
|
||||
|
||||
#endif // BASE_CONTEXT_CRACKING_H
|
||||
// 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
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Clang OS/Arch Cracking
|
||||
|
||||
#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/OS combo is not supported.
|
||||
# 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.
|
||||
# endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: MSVC OS/Arch Cracking
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
# define COMPILER_MSVC 1
|
||||
|
||||
# if _MSC_VER >= 1920
|
||||
# define COMPILER_MSVC_YEAR 2019
|
||||
# elif _MSC_VER >= 1910
|
||||
# define COMPILER_MSVC_YEAR 2017
|
||||
# elif _MSC_VER >= 1900
|
||||
# define COMPILER_MSVC_YEAR 2015
|
||||
# elif _MSC_VER >= 1800
|
||||
# define COMPILER_MSVC_YEAR 2013
|
||||
# elif _MSC_VER >= 1700
|
||||
# define COMPILER_MSVC_YEAR 2012
|
||||
# elif _MSC_VER >= 1600
|
||||
# define COMPILER_MSVC_YEAR 2010
|
||||
# elif _MSC_VER >= 1500
|
||||
# define COMPILER_MSVC_YEAR 2008
|
||||
# elif _MSC_VER >= 1400
|
||||
# define COMPILER_MSVC_YEAR 2005
|
||||
# else
|
||||
# define COMPILER_MSVC_YEAR 0
|
||||
# endif
|
||||
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# else
|
||||
# error This compiler/OS combo is not supported.
|
||||
# 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.
|
||||
# endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: GCC OS/Arch Cracking
|
||||
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
|
||||
# define COMPILER_GCC 1
|
||||
|
||||
# if defined(__gnu_linux__) || defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# else
|
||||
# error This compiler/OS combo is not supported.
|
||||
# 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.
|
||||
# endif
|
||||
|
||||
#else
|
||||
# error Compiler not supported.
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arch Cracking
|
||||
|
||||
#if defined(ARCH_X64)
|
||||
# define ARCH_64BIT 1
|
||||
#elif defined(ARCH_X86)
|
||||
# define ARCH_32BIT 1
|
||||
#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
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Language Cracking
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# define LANG_CPP 1
|
||||
#else
|
||||
# define LANG_C 1
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Build Option Cracking
|
||||
|
||||
#if !defined(BUILD_DEBUG)
|
||||
# define BUILD_DEBUG 1
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_SUPPLEMENTARY_UNIT)
|
||||
# define BUILD_SUPPLEMENTARY_UNIT 0
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_ENTRY_DEFINING_UNIT)
|
||||
# define BUILD_ENTRY_DEFINING_UNIT 1
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_CONSOLE_INTERFACE)
|
||||
# define BUILD_CONSOLE_INTERFACE 0
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_MAJOR)
|
||||
# define BUILD_VERSION_MAJOR 0
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_MINOR)
|
||||
# define BUILD_VERSION_MINOR 0
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_PATCH)
|
||||
# define BUILD_VERSION_PATCH 0
|
||||
#endif
|
||||
|
||||
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
|
||||
#if BUILD_DEBUG
|
||||
# define BUILD_MODE_STRING_LITERAL_APPEND " [Debug]"
|
||||
#else
|
||||
# define BUILD_MODE_STRING_LITERAL_APPEND ""
|
||||
#endif
|
||||
#if defined(BUILD_GIT_HASH)
|
||||
# define BUILD_GIT_HASH_STRING_LITERAL_APPEND " [" BUILD_GIT_HASH "]"
|
||||
#else
|
||||
# define BUILD_GIT_HASH_STRING_LITERAL_APPEND ""
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_TITLE)
|
||||
# define BUILD_TITLE "Untitled"
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_RELEASE_PHASE_STRING_LITERAL)
|
||||
# define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_ISSUES_LINK_STRING_LITERAL)
|
||||
# define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGames/raddebugger/issues"
|
||||
#endif
|
||||
|
||||
#define BUILD_TITLE_STRING_LITERAL BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ") - " __DATE__ "" BUILD_GIT_HASH_STRING_LITERAL_APPEND BUILD_MODE_STRING_LITERAL_APPEND
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Zero All Undefined Options
|
||||
|
||||
#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_MSVC)
|
||||
# define COMPILER_MSVC 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
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Unsupported Errors
|
||||
|
||||
#if ARCH_X86
|
||||
# error You tried to build in x86 (32 bit) mode, but currently, only building in x64 (64 bit) mode is supported.
|
||||
#endif
|
||||
#if !ARCH_X64
|
||||
# error You tried to build with an unsupported architecture. Currently, only building in x64 mode is supported.
|
||||
#endif
|
||||
|
||||
#endif // BASE_CONTEXT_CRACKING_H
|
||||
|
||||
+562
-454
File diff suppressed because it is too large
Load Diff
+800
-681
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal void
|
||||
main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count)
|
||||
{
|
||||
#if PROFILE_TELEMETRY
|
||||
local_persist U8 tm_data[MB(64)];
|
||||
tmLoadLibrary(TM_RELEASE);
|
||||
tmSetMaxThreadCount(256);
|
||||
tmInitialize(sizeof(tm_data), (char *)tm_data);
|
||||
#endif
|
||||
ThreadNameF("[main thread]");
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, (int)arguments_count, arguments);
|
||||
CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings);
|
||||
B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture"));
|
||||
if(capture)
|
||||
{
|
||||
ProfBeginCapture(arguments[0]);
|
||||
}
|
||||
#if defined(TASK_SYSTEM_H) && !defined(TS_INIT_MANUAL)
|
||||
ts_init();
|
||||
#endif
|
||||
#if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL)
|
||||
hs_init();
|
||||
#endif
|
||||
#if defined(FILE_STREAM_H) && !defined(FS_INIT_MANUAL)
|
||||
fs_init();
|
||||
#endif
|
||||
#if defined(TEXT_CACHE_H) && !defined(TXT_INIT_MANUAL)
|
||||
txt_init();
|
||||
#endif
|
||||
#if defined(MUTABLE_TEXT_H) && !defined(MTX_INIT_MANUAL)
|
||||
mtx_init();
|
||||
#endif
|
||||
#if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL)
|
||||
dasm_init();
|
||||
#endif
|
||||
#if defined(DI_H) && !defined(DI_INIT_MANUAL)
|
||||
di_init();
|
||||
#endif
|
||||
#if defined(FUZZY_SEARCH_H) && !defined(FZY_INIT_MANUAL)
|
||||
fzy_init();
|
||||
#endif
|
||||
#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL)
|
||||
dmn_init();
|
||||
#endif
|
||||
#if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL)
|
||||
ctrl_init();
|
||||
#endif
|
||||
#if defined(OS_GRAPHICAL_H) && !defined(OS_GFX_INIT_MANUAL)
|
||||
os_gfx_init();
|
||||
#endif
|
||||
#if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL)
|
||||
fp_init();
|
||||
#endif
|
||||
#if defined(RENDER_CORE_H) && !defined(R_INIT_MANUAL)
|
||||
r_init(&cmdline);
|
||||
#endif
|
||||
#if defined(TEXTURE_CACHE_H) && !defined(TEX_INIT_MANUAL)
|
||||
tex_init();
|
||||
#endif
|
||||
#if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL)
|
||||
geo_init();
|
||||
#endif
|
||||
#if defined(FONT_CACHE_H) && !defined(F_INIT_MANUAL)
|
||||
f_init();
|
||||
#endif
|
||||
#if defined(DF_CORE_H) && !defined(DF_INIT_MANUAL)
|
||||
DF_StateDeltaHistory *hist = df_state_delta_history_alloc();
|
||||
df_core_init(&cmdline, hist);
|
||||
#endif
|
||||
#if defined(DF_GFX_H) && !defined(DF_GFX_INIT_MANUAL)
|
||||
df_gfx_init(update_and_render, df_state_delta_history());
|
||||
#endif
|
||||
entry_point(&cmdline);
|
||||
if(capture)
|
||||
{
|
||||
ProfEndCapture();
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal void
|
||||
supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params)
|
||||
{
|
||||
TCTX tctx;
|
||||
tctx_init_and_equip(&tctx);
|
||||
entry_point(params);
|
||||
tctx_release();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_ENTRY_POINT_H
|
||||
#define BASE_ENTRY_POINT_H
|
||||
|
||||
internal void main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count);
|
||||
internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params);
|
||||
|
||||
#endif // BASE_ENTRY_POINT_H
|
||||
@@ -1,18 +1,19 @@
|
||||
// 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 "metagen_base_types.c"
|
||||
#include "metagen_base_markup.c"
|
||||
#include "metagen_base_arena.c"
|
||||
#include "metagen_base_math.c"
|
||||
#include "metagen_base_string.c"
|
||||
#include "metagen_base_thread_context.c"
|
||||
#include "metagen_base_command_line.c"
|
||||
#include "metagen_base_arena_dev.c"
|
||||
#include "metagen_base_bits.c"
|
||||
// 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 "metagen_base_core.c"
|
||||
#include "metagen_base_profile.c"
|
||||
#include "metagen_base_arena.c"
|
||||
#include "metagen_base_math.c"
|
||||
#include "metagen_base_strings.c"
|
||||
#include "metagen_base_thread_context.c"
|
||||
#include "metagen_base_command_line.c"
|
||||
#include "metagen_base_markup.c"
|
||||
#include "metagen_base_log.c"
|
||||
#include "metagen_base_entry_point.c"
|
||||
|
||||
@@ -1,23 +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 "metagen_base_context_cracking.h"
|
||||
#include "metagen_base_types.h"
|
||||
#include "metagen_base_markup.h"
|
||||
#include "metagen_base_ins.h"
|
||||
#include "metagen_base_linked_lists.h"
|
||||
#include "metagen_base_arena.h"
|
||||
#include "metagen_base_math.h"
|
||||
#include "metagen_base_string.h"
|
||||
#include "metagen_base_thread_context.h"
|
||||
#include "metagen_base_command_line.h"
|
||||
#include "metagen_base_arena_dev.h"
|
||||
#include "metagen_base_bits.h"
|
||||
|
||||
#endif // BASE_INC_H
|
||||
// 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 "metagen_base_context_cracking.h"
|
||||
|
||||
#include "metagen_base_core.h"
|
||||
#include "metagen_base_profile.h"
|
||||
#include "metagen_base_arena.h"
|
||||
#include "metagen_base_math.h"
|
||||
#include "metagen_base_strings.h"
|
||||
#include "metagen_base_thread_context.h"
|
||||
#include "metagen_base_command_line.h"
|
||||
#include "metagen_base_markup.h"
|
||||
#include "metagen_base_log.h"
|
||||
#include "metagen_base_entry_point.h"
|
||||
|
||||
#endif // BASE_INC_H
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// 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
|
||||
@@ -1,73 +0,0 @@
|
||||
// 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
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals/Thread-Locals
|
||||
|
||||
C_LINKAGE thread_static Log *log_active;
|
||||
#if !BUILD_SUPPLEMENTARY_UNIT
|
||||
C_LINKAGE thread_static Log *log_active = 0;
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Creation/Selection
|
||||
|
||||
internal Log *
|
||||
log_alloc(void)
|
||||
{
|
||||
Arena *arena = arena_alloc();
|
||||
Log *log = push_array(arena, Log, 1);
|
||||
log->arena = arena;
|
||||
return log;
|
||||
}
|
||||
|
||||
internal void
|
||||
log_release(Log *log)
|
||||
{
|
||||
arena_release(log->arena);
|
||||
}
|
||||
|
||||
internal void
|
||||
log_select(Log *log)
|
||||
{
|
||||
log_active = log;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Building/Clearing
|
||||
|
||||
internal void
|
||||
log_msg(LogMsgKind kind, String8 string)
|
||||
{
|
||||
if(log_active != 0 && log_active->top_scope != 0)
|
||||
{
|
||||
String8 string_copy = push_str8_copy(log_active->arena, string);
|
||||
str8_list_push(log_active->arena, &log_active->top_scope->strings[kind], string_copy);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
log_msgf(LogMsgKind kind, char *fmt, ...)
|
||||
{
|
||||
if(log_active != 0)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||
log_msg(kind, string);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Scopes
|
||||
|
||||
internal void
|
||||
log_scope_begin(void)
|
||||
{
|
||||
if(log_active != 0)
|
||||
{
|
||||
U64 pos = arena_pos(log_active->arena);
|
||||
LogScope *scope = push_array(log_active->arena, LogScope, 1);
|
||||
scope->pos = pos;
|
||||
SLLStackPush(log_active->top_scope, scope);
|
||||
}
|
||||
}
|
||||
|
||||
internal LogScopeResult
|
||||
log_scope_end(Arena *arena)
|
||||
{
|
||||
LogScopeResult result = {0};
|
||||
if(log_active != 0)
|
||||
{
|
||||
LogScope *scope = log_active->top_scope;
|
||||
if(scope != 0)
|
||||
{
|
||||
SLLStackPop(log_active->top_scope);
|
||||
if(arena != 0)
|
||||
{
|
||||
for(EachEnumVal(LogMsgKind, kind))
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0);
|
||||
result.strings[kind] = indented_from_string(arena, result_unindented);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
arena_pop_to(log_active->arena, scope->pos);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_LOG_H
|
||||
#define BASE_LOG_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Types
|
||||
|
||||
typedef enum LogMsgKind
|
||||
{
|
||||
LogMsgKind_Info,
|
||||
LogMsgKind_UserError,
|
||||
LogMsgKind_COUNT
|
||||
}
|
||||
LogMsgKind;
|
||||
|
||||
typedef struct LogScope LogScope;
|
||||
struct LogScope
|
||||
{
|
||||
LogScope *next;
|
||||
U64 pos;
|
||||
String8List strings[LogMsgKind_COUNT];
|
||||
};
|
||||
|
||||
typedef struct LogScopeResult LogScopeResult;
|
||||
struct LogScopeResult
|
||||
{
|
||||
String8 strings[LogMsgKind_COUNT];
|
||||
};
|
||||
|
||||
typedef struct Log Log;
|
||||
struct Log
|
||||
{
|
||||
Arena *arena;
|
||||
LogScope *top_scope;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Creation/Selection
|
||||
|
||||
internal Log *log_alloc(void);
|
||||
internal void log_release(Log *log);
|
||||
internal void log_select(Log *log);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Building
|
||||
|
||||
internal void log_msg(LogMsgKind kind, String8 string);
|
||||
internal void log_msgf(LogMsgKind kind, char *fmt, ...);
|
||||
#define log_info(s) log_msg(LogMsgKind_Info, (s))
|
||||
#define log_infof(fmt, ...) log_msgf(LogMsgKind_Info, (fmt), __VA_ARGS__)
|
||||
#define log_user_error(s) log_msg(LogMsgKind_UserError, (s))
|
||||
#define log_user_errorf(fmt, ...) log_msgf(LogMsgKind_UserError, (fmt), __VA_ARGS__)
|
||||
|
||||
#define LogInfoNamedBlock(s) DeferLoop(log_infof("%S:\n{\n", (s)), log_infof("}\n"))
|
||||
#define LogInfoNamedBlockF(fmt, ...) DeferLoop((log_infof(fmt, __VA_ARGS__), log_infof(":\n{\n")), log_infof("}\n"))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Scopes
|
||||
|
||||
internal void log_scope_begin(void);
|
||||
internal LogScopeResult log_scope_end(Arena *arena);
|
||||
|
||||
#endif // BASE_LOG_H
|
||||
@@ -1,2 +1,21 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal void
|
||||
set_thread_name(String8 string)
|
||||
{
|
||||
ProfThreadName("%.*s", str8_varg(string));
|
||||
os_set_thread_name(string);
|
||||
}
|
||||
|
||||
internal void
|
||||
set_thread_namef(char *fmt, ...)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||
set_thread_name(string);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
@@ -1,79 +1,12 @@
|
||||
// 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
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_MARKUP_H
|
||||
#define BASE_MARKUP_H
|
||||
|
||||
internal void set_thread_name(String8 string);
|
||||
internal void set_thread_namef(char *fmt, ...);
|
||||
#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__))
|
||||
#define ThreadName(str) (set_thread_name(str))
|
||||
|
||||
#endif // BASE_MARKUP_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_PROFILE_H
|
||||
#define BASE_PROFILE_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())
|
||||
|
||||
#endif // BASE_PROFILE_H
|
||||
+1975
-1878
File diff suppressed because it is too large
Load Diff
+381
-351
@@ -1,351 +1,381 @@
|
||||
// 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
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_STRINGS_H
|
||||
#define BASE_STRINGS_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 *v;
|
||||
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: String Fuzzy Matching Types
|
||||
|
||||
typedef struct FuzzyMatchRangeNode FuzzyMatchRangeNode;
|
||||
struct FuzzyMatchRangeNode
|
||||
{
|
||||
FuzzyMatchRangeNode *next;
|
||||
Rng1U64 range;
|
||||
};
|
||||
|
||||
typedef struct FuzzyMatchRangeList FuzzyMatchRangeList;
|
||||
struct FuzzyMatchRangeList
|
||||
{
|
||||
FuzzyMatchRangeNode *first;
|
||||
FuzzyMatchRangeNode *last;
|
||||
U64 count;
|
||||
U64 needle_part_count;
|
||||
U64 total_dim;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ 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: 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: Basic Text Indentation
|
||||
|
||||
internal String8 indented_from_string(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text Wrapping
|
||||
|
||||
internal String8List wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String <-> Color
|
||||
|
||||
internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba);
|
||||
internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Fuzzy Matching
|
||||
|
||||
internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack);
|
||||
internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ 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_STRINGS_H
|
||||
@@ -1,78 +1,87 @@
|
||||
// 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;
|
||||
}
|
||||
// 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 !BUILD_SUPPLEMENTARY_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 void
|
||||
tctx_release(void)
|
||||
{
|
||||
for(U64 i = 0; i < ArrayCount(tctx_thread_local->arenas); i += 1)
|
||||
{
|
||||
arena_release(tctx_thread_local->arenas[i]);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,40 +1,41 @@
|
||||
// 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
|
||||
// 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 void tctx_release(void);
|
||||
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
|
||||
|
||||
+656
-661
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,88 +1,134 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef LINUX_H
|
||||
#define LINUX_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Get all these linux includes
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): File Iterator
|
||||
|
||||
struct LNX_FileIter{
|
||||
int fd;
|
||||
DIR *dir;
|
||||
};
|
||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(LNX_FileIter), file_iter_memory_size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Threading Entities
|
||||
|
||||
enum LNX_EntityKind{
|
||||
LNX_EntityKind_Null,
|
||||
LNX_EntityKind_Thread,
|
||||
LNX_EntityKind_Mutex,
|
||||
LNX_EntityKind_ConditionVariable,
|
||||
};
|
||||
|
||||
struct LNX_Entity{
|
||||
LNX_Entity *next;
|
||||
LNX_EntityKind kind;
|
||||
volatile U32 reference_mask;
|
||||
union{
|
||||
struct{
|
||||
OS_ThreadFunctionType *func;
|
||||
void *ptr;
|
||||
pthread_t handle;
|
||||
} thread;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Safe Call Chain
|
||||
|
||||
struct LNX_SafeCallChain{
|
||||
LNX_SafeCallChain *next;
|
||||
OS_ThreadFunctionType *fail_handler;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Helpers
|
||||
|
||||
internal B32 lnx_write_list_to_file_descriptor(int fd, String8List list);
|
||||
|
||||
internal void lnx_date_time_from_tm(DateTime *out, struct tm *in, U32 msec);
|
||||
internal void lnx_tm_from_date_time(struct tm *out, DateTime *in);
|
||||
internal void lnx_dense_time_from_timespec(DenseTime *out, struct timespec *in);
|
||||
internal void lnx_file_properties_from_stat(FileProperties *out, struct stat *in);
|
||||
|
||||
internal String8 lnx_string_from_signal(int signum);
|
||||
internal String8 lnx_string_from_errno(int error_number);
|
||||
|
||||
internal LNX_Entity* lnx_alloc_entity(LNX_EntityKind kind);
|
||||
internal void lnx_free_entity(LNX_Entity *entity);
|
||||
internal void* lnx_thread_base(void *ptr);
|
||||
|
||||
internal void lnx_safe_call_sig_handler(int);
|
||||
|
||||
#endif //LINUX_H
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_LINUX_H
|
||||
#define OS_CORE_LINUX_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <features.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
int pthread_setname_np(pthread_t thread, const char *name);
|
||||
int pthread_getname_np(pthread_t thread, char *name, size_t size);
|
||||
|
||||
typedef struct tm tm;
|
||||
typedef struct timespec timespec;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: File Iterator
|
||||
|
||||
typedef struct OS_LNX_FileIter OS_LNX_FileIter;
|
||||
struct OS_LNX_FileIter
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
String8 path;
|
||||
};
|
||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Safe Call Handler Chain
|
||||
|
||||
typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain;
|
||||
struct OS_LNX_SafeCallChain
|
||||
{
|
||||
OS_LNX_SafeCallChain *next;
|
||||
OS_ThreadFunctionType *fail_handler;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entities
|
||||
|
||||
typedef enum OS_LNX_EntityKind
|
||||
{
|
||||
OS_LNX_EntityKind_Thread,
|
||||
OS_LNX_EntityKind_Mutex,
|
||||
OS_LNX_EntityKind_RWMutex,
|
||||
OS_LNX_EntityKind_ConditionVariable,
|
||||
}
|
||||
OS_LNX_EntityKind;
|
||||
|
||||
typedef struct OS_LNX_Entity OS_LNX_Entity;
|
||||
struct OS_LNX_Entity
|
||||
{
|
||||
OS_LNX_Entity *next;
|
||||
OS_LNX_EntityKind kind;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
pthread_t handle;
|
||||
OS_ThreadFunctionType *func;
|
||||
void *ptr;
|
||||
} thread;
|
||||
pthread_mutex_t mutex_handle;
|
||||
pthread_rwlock_t rwmutex_handle;
|
||||
struct
|
||||
{
|
||||
pthread_cond_t cond_handle;
|
||||
pthread_mutex_t rwlock_mutex_handle;
|
||||
} cv;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: State
|
||||
|
||||
typedef struct OS_LNX_State OS_LNX_State;
|
||||
struct OS_LNX_State
|
||||
{
|
||||
Arena *arena;
|
||||
OS_SystemInfo system_info;
|
||||
OS_ProcessInfo process_info;
|
||||
pthread_mutex_t entity_mutex;
|
||||
Arena *entity_arena;
|
||||
OS_LNX_Entity *entity_free;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global OS_LNX_State os_lnx_state = {0};
|
||||
thread_static OS_LNX_SafeCallChain *os_lnx_safe_call_chain = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec);
|
||||
internal tm os_lnx_tm_from_date_time(DateTime dt);
|
||||
internal timespec os_lnx_timespec_from_date_time(DateTime dt);
|
||||
internal DenseTime os_lnx_dense_time_from_timespec(timespec in);
|
||||
internal FileProperties os_lnx_file_properties_from_stat(struct stat *s);
|
||||
internal void os_lnx_safe_call_sig_handler(int x);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entities
|
||||
|
||||
internal OS_LNX_Entity *os_lnx_entity_alloc(OS_LNX_EntityKind kind);
|
||||
internal void os_lnx_entity_release(OS_LNX_Entity *entity);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Entry Point
|
||||
|
||||
internal void *os_lnx_thread_entry_point(void *ptr);
|
||||
|
||||
#endif // OS_CORE_LINUX_H
|
||||
|
||||
@@ -1,265 +1,173 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
|
||||
|
||||
internal OS_Handle
|
||||
os_handle_zero(void)
|
||||
{
|
||||
OS_Handle handle = {0};
|
||||
return handle;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_handle_match(OS_Handle a, OS_Handle b)
|
||||
{
|
||||
return a.u64[0] == b.u64[0];
|
||||
}
|
||||
|
||||
internal void
|
||||
os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle)
|
||||
{
|
||||
OS_HandleNode *n = push_array(arena, OS_HandleNode, 1);
|
||||
n->v = handle;
|
||||
SLLQueuePush(handles->first, handles->last, n);
|
||||
handles->count += 1;
|
||||
}
|
||||
|
||||
internal OS_HandleArray
|
||||
os_handle_array_from_list(Arena *arena, OS_HandleList *list)
|
||||
{
|
||||
OS_HandleArray result = {0};
|
||||
result.count = list->count;
|
||||
result.v = push_array_no_zero(arena, OS_Handle, result.count);
|
||||
U64 idx = 0;
|
||||
for(OS_HandleNode *n = list->first; n != 0; n = n->next, idx += 1)
|
||||
{
|
||||
result.v[idx] = n->v;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: System Path Helper (Helper, Implemented Once)
|
||||
|
||||
internal String8
|
||||
os_string_from_system_path(Arena *arena, OS_SystemPath path)
|
||||
{
|
||||
String8List strs = {0};
|
||||
os_string_list_from_system_path(arena, path, &strs);
|
||||
String8 result = str8_list_first(&strs);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
||||
|
||||
internal String8List
|
||||
os_string_list_from_argcv(Arena *arena, int argc, char **argv)
|
||||
{
|
||||
String8List result = {0};
|
||||
for(int i = 0; i < argc; i += 1)
|
||||
{
|
||||
String8 str = str8_cstring(argv[i]);
|
||||
str8_list_push(arena, &result, str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Helpers (Helper, Implemented Once)
|
||||
|
||||
internal void
|
||||
os_relaunch_self(void){
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
OS_LaunchOptions opts = {0};
|
||||
opts.cmd_line = os_get_command_line_arguments();
|
||||
opts.path = os_string_from_system_path(scratch.arena, OS_SystemPath_Initial);
|
||||
os_launch_process(&opts, 0);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8
|
||||
os_data_from_file_path(Arena *arena, String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path);
|
||||
FileProperties props = os_properties_from_file(file);
|
||||
String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size));
|
||||
os_file_close(file);
|
||||
return data;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_write_data_to_file_path(String8 path, String8 data)
|
||||
{
|
||||
B32 good = 0;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
good = 1;
|
||||
os_file_write(file, r1u64(0, data.size), data.str);
|
||||
os_file_close(file);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_write_data_list_to_file_path(String8 path, String8List list)
|
||||
{
|
||||
B32 good = 0;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
good = 1;
|
||||
U64 off = 0;
|
||||
for(String8Node *n = list.first; n != 0; n = n->next)
|
||||
{
|
||||
os_file_write(file, r1u64(off, off+n->string.size), n->string.str);
|
||||
off += n->string.size;
|
||||
}
|
||||
os_file_close(file);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal FileProperties
|
||||
os_properties_from_file_path(String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path);
|
||||
FileProperties props = os_properties_from_file(file);
|
||||
os_file_close(file);
|
||||
return props;
|
||||
}
|
||||
|
||||
internal OS_FileID
|
||||
os_id_from_file_path(String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path);
|
||||
OS_FileID id = os_id_from_file(file);
|
||||
os_file_close(file);
|
||||
return id;
|
||||
}
|
||||
|
||||
internal S64
|
||||
os_file_id_compare(OS_FileID a, OS_FileID b)
|
||||
{
|
||||
S64 cmp = MemoryCompare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v));
|
||||
return cmp;
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
|
||||
{
|
||||
U64 pre_pos = arena_pos(arena);
|
||||
String8 result;
|
||||
result.size = dim_1u64(range);
|
||||
result.str = push_array_no_zero(arena, U8, result.size);
|
||||
U64 actual_read_size = os_file_read(file, range, result.str);
|
||||
if(actual_read_size < result.size)
|
||||
{
|
||||
arena_pop_to(arena, pre_pos + actual_read_size);
|
||||
result.size = actual_read_size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Synchronization Primitive Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal void
|
||||
os_mutex_take(OS_Handle mutex){
|
||||
ProfBeginLockWait((void *)(mutex.u64[0]), "take mutex");
|
||||
os_mutex_take_(mutex);
|
||||
ProfEndLockWait();
|
||||
ProfLockTake((void *)(mutex.u64[0]), "take mutex");
|
||||
}
|
||||
|
||||
internal void
|
||||
os_mutex_drop(OS_Handle mutex){
|
||||
os_mutex_drop_(mutex);
|
||||
ProfLockDrop((void *)(mutex.u64[0]));
|
||||
}
|
||||
|
||||
internal void
|
||||
os_rw_mutex_take_r(OS_Handle rw_mutex){
|
||||
ProfBeginLockWait((void *)(rw_mutex.u64[0]), "rw mutex take r");
|
||||
os_rw_mutex_take_r_(rw_mutex);
|
||||
ProfEndLockWait();
|
||||
ProfLockTake((void *)(rw_mutex.u64[0]), "rw mutex take r");
|
||||
}
|
||||
|
||||
internal void
|
||||
os_rw_mutex_drop_r(OS_Handle rw_mutex){
|
||||
os_rw_mutex_drop_r_(rw_mutex);
|
||||
ProfLockDrop((void *)(rw_mutex.u64[0]));
|
||||
}
|
||||
|
||||
internal void
|
||||
os_rw_mutex_take_w(OS_Handle rw_mutex){
|
||||
ProfBeginLockWait((void *)(rw_mutex.u64[0]), "rw mutex take rw");
|
||||
os_rw_mutex_take_w_(rw_mutex);
|
||||
ProfEndLockWait();
|
||||
ProfLockTake((void *)(rw_mutex.u64[0]), "rw mutex take rw");
|
||||
}
|
||||
|
||||
internal void
|
||||
os_rw_mutex_drop_w(OS_Handle rw_mutex){
|
||||
os_rw_mutex_drop_w_(rw_mutex);
|
||||
ProfLockDrop((void *)(rw_mutex.u64[0]));
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us){
|
||||
ProfLockDrop((void *)(mutex.u64[0]));
|
||||
B32 result = os_condition_variable_wait_(cv, mutex, endt_us);
|
||||
ProfLockTake((void *)(mutex.u64[0]), "wait cv");
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us){
|
||||
ProfLockDrop((void *)(mutex_rw.u64[0]));
|
||||
B32 result = os_condition_variable_wait_rw_r_(cv, mutex_rw, endt_us);
|
||||
ProfLockTake((void *)(mutex_rw.u64[0]), "wait cv rw r");
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us){
|
||||
ProfLockDrop((void *)(mutex_rw.u64[0]));
|
||||
B32 result = os_condition_variable_wait_rw_w_(cv, mutex_rw, endt_us);
|
||||
ProfLockTake((void *)(mutex_rw.u64[0]), "wait cv rw w");
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
os_condition_variable_signal(OS_Handle cv){
|
||||
os_condition_variable_signal_(cv);
|
||||
}
|
||||
|
||||
internal void
|
||||
os_condition_variable_broadcast(OS_Handle cv){
|
||||
os_condition_variable_broadcast_(cv);
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_string_from_guid(Arena *arena, OS_Guid guid)
|
||||
{
|
||||
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
guid.data1,
|
||||
guid.data2,
|
||||
guid.data3,
|
||||
guid.data4[0],
|
||||
guid.data4[1],
|
||||
guid.data4[2],
|
||||
guid.data4[3],
|
||||
guid.data4[4],
|
||||
guid.data4[5],
|
||||
guid.data4[6],
|
||||
guid.data4[7]);
|
||||
return result;
|
||||
}
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
|
||||
|
||||
internal OS_Handle
|
||||
os_handle_zero(void)
|
||||
{
|
||||
OS_Handle handle = {0};
|
||||
return handle;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_handle_match(OS_Handle a, OS_Handle b)
|
||||
{
|
||||
return a.u64[0] == b.u64[0];
|
||||
}
|
||||
|
||||
internal void
|
||||
os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle)
|
||||
{
|
||||
OS_HandleNode *n = push_array(arena, OS_HandleNode, 1);
|
||||
n->v = handle;
|
||||
SLLQueuePush(handles->first, handles->last, n);
|
||||
handles->count += 1;
|
||||
}
|
||||
|
||||
internal OS_HandleArray
|
||||
os_handle_array_from_list(Arena *arena, OS_HandleList *list)
|
||||
{
|
||||
OS_HandleArray result = {0};
|
||||
result.count = list->count;
|
||||
result.v = push_array_no_zero(arena, OS_Handle, result.count);
|
||||
U64 idx = 0;
|
||||
for(OS_HandleNode *n = list->first; n != 0; n = n->next, idx += 1)
|
||||
{
|
||||
result.v[idx] = n->v;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
||||
|
||||
internal String8List
|
||||
os_string_list_from_argcv(Arena *arena, int argc, char **argv)
|
||||
{
|
||||
String8List result = {0};
|
||||
for(int i = 0; i < argc; i += 1)
|
||||
{
|
||||
String8 str = str8_cstring(argv[i]);
|
||||
str8_list_push(arena, &result, str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8
|
||||
os_data_from_file_path(Arena *arena, String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
|
||||
FileProperties props = os_properties_from_file(file);
|
||||
String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size));
|
||||
os_file_close(file);
|
||||
return data;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_write_data_to_file_path(String8 path, String8 data)
|
||||
{
|
||||
B32 good = 0;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
good = 1;
|
||||
os_file_write(file, r1u64(0, data.size), data.str);
|
||||
os_file_close(file);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_write_data_list_to_file_path(String8 path, String8List list)
|
||||
{
|
||||
B32 good = 0;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
good = 1;
|
||||
U64 off = 0;
|
||||
for(String8Node *n = list.first; n != 0; n = n->next)
|
||||
{
|
||||
os_file_write(file, r1u64(off, off+n->string.size), n->string.str);
|
||||
off += n->string.size;
|
||||
}
|
||||
os_file_close(file);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_append_data_to_file_path(String8 path, String8 data)
|
||||
{
|
||||
B32 good = 0;
|
||||
if(data.size != 0)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
good = 1;
|
||||
U64 pos = os_properties_from_file(file).size;
|
||||
os_file_write(file, r1u64(pos, pos+data.size), data.str);
|
||||
os_file_close(file);
|
||||
}
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal OS_FileID
|
||||
os_id_from_file_path(String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
|
||||
OS_FileID id = os_id_from_file(file);
|
||||
os_file_close(file);
|
||||
return id;
|
||||
}
|
||||
|
||||
internal S64
|
||||
os_file_id_compare(OS_FileID a, OS_FileID b)
|
||||
{
|
||||
S64 cmp = MemoryCompare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v));
|
||||
return cmp;
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
|
||||
{
|
||||
U64 pre_pos = arena_pos(arena);
|
||||
String8 result;
|
||||
result.size = dim_1u64(range);
|
||||
result.str = push_array_no_zero(arena, U8, result.size);
|
||||
U64 actual_read_size = os_file_read(file, range, result.str);
|
||||
if(actual_read_size < result.size)
|
||||
{
|
||||
arena_pop_to(arena, pre_pos + actual_read_size);
|
||||
result.size = actual_read_size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: GUID Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8
|
||||
os_string_from_guid(Arena *arena, OS_Guid guid)
|
||||
{
|
||||
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
guid.data1,
|
||||
guid.data2,
|
||||
guid.data3,
|
||||
guid.data4[0],
|
||||
guid.data4[1],
|
||||
guid.data4[2],
|
||||
guid.data4[3],
|
||||
guid.data4[4],
|
||||
guid.data4[5],
|
||||
guid.data4[6],
|
||||
guid.data4[7]);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,365 +1,336 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_H
|
||||
#define OS_CORE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Access Flags
|
||||
|
||||
typedef U32 OS_AccessFlags;
|
||||
enum
|
||||
{
|
||||
OS_AccessFlag_Read = (1<<0),
|
||||
OS_AccessFlag_Write = (1<<1),
|
||||
OS_AccessFlag_Execute = (1<<2),
|
||||
OS_AccessFlag_Shared = (1<<3),
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ allen: Files
|
||||
|
||||
typedef U32 OS_FileIterFlags;
|
||||
enum
|
||||
{
|
||||
OS_FileIterFlag_SkipFolders = (1 << 0),
|
||||
OS_FileIterFlag_SkipFiles = (1 << 1),
|
||||
OS_FileIterFlag_SkipHiddenFiles = (1 << 2),
|
||||
OS_FileIterFlag_Done = (1 << 31),
|
||||
};
|
||||
|
||||
typedef struct OS_FileIter OS_FileIter;
|
||||
struct OS_FileIter
|
||||
{
|
||||
OS_FileIterFlags flags;
|
||||
U8 memory[600];
|
||||
};
|
||||
|
||||
typedef struct OS_FileInfo OS_FileInfo;
|
||||
struct OS_FileInfo
|
||||
{
|
||||
String8 name;
|
||||
FileProperties props;
|
||||
};
|
||||
|
||||
// nick: on-disk file identifier
|
||||
typedef struct OS_FileID OS_FileID;
|
||||
struct OS_FileID
|
||||
{
|
||||
U64 v[3];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: System Paths
|
||||
|
||||
typedef enum OS_SystemPath
|
||||
{
|
||||
OS_SystemPath_Binary,
|
||||
OS_SystemPath_Initial,
|
||||
OS_SystemPath_Current,
|
||||
OS_SystemPath_UserProgramData,
|
||||
OS_SystemPath_ModuleLoad,
|
||||
}
|
||||
OS_SystemPath;
|
||||
|
||||
typedef enum OS_PathFromUserKind
|
||||
{
|
||||
OS_PathFromUserKind_Save,
|
||||
OS_PathFromUserKind_Load,
|
||||
}
|
||||
OS_PathFromUserKind;
|
||||
|
||||
typedef struct OS_PathFromUser OS_PathFromUser;
|
||||
struct OS_PathFromUser
|
||||
{
|
||||
OS_PathFromUserKind kind;
|
||||
String8 path;
|
||||
U64 filter_count;
|
||||
String8 *filter_extensions;
|
||||
String8 *filter_names;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ allen: Launch Input
|
||||
|
||||
typedef struct OS_LaunchOptions OS_LaunchOptions;
|
||||
struct OS_LaunchOptions
|
||||
{
|
||||
String8List cmd_line;
|
||||
String8 path;
|
||||
String8List env;
|
||||
B32 inherit_env;
|
||||
B32 consoleless;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type
|
||||
|
||||
typedef struct OS_Handle OS_Handle;
|
||||
struct OS_Handle
|
||||
{
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
typedef struct OS_HandleNode OS_HandleNode;
|
||||
struct OS_HandleNode
|
||||
{
|
||||
OS_HandleNode *next;
|
||||
OS_Handle v;
|
||||
};
|
||||
|
||||
typedef struct OS_HandleList OS_HandleList;
|
||||
struct OS_HandleList
|
||||
{
|
||||
OS_HandleNode *first;
|
||||
OS_HandleNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct OS_HandleArray OS_HandleArray;
|
||||
struct OS_HandleArray
|
||||
{
|
||||
OS_Handle *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// Time
|
||||
|
||||
#define OS_UNIX_TIME_MAX max_U32
|
||||
typedef U32 OS_UnixTime;
|
||||
|
||||
////////////////////////////////
|
||||
// Global Unique ID
|
||||
|
||||
typedef struct OS_Guid
|
||||
{
|
||||
U32 data1;
|
||||
U16 data2;
|
||||
U16 data3;
|
||||
U8 data4[8];
|
||||
} OS_Guid;
|
||||
StaticAssert(sizeof(OS_Guid) == 16, os_guid_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Types
|
||||
|
||||
typedef void OS_ThreadFunctionType(void *ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
|
||||
|
||||
internal OS_Handle os_handle_zero(void);
|
||||
internal B32 os_handle_match(OS_Handle a, OS_Handle b);
|
||||
internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle);
|
||||
internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: System Path Helper (Helper, Implemented Once)
|
||||
|
||||
internal String8 os_string_from_system_path(Arena *arena, OS_SystemPath path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
||||
|
||||
internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Helpers (Helper, Implemented Once)
|
||||
|
||||
internal void os_relaunch_self(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8 os_data_from_file_path(Arena *arena, String8 path);
|
||||
internal B32 os_write_data_to_file_path(String8 path, String8 data);
|
||||
internal B32 os_write_data_list_to_file_path(String8 path, String8List list);
|
||||
internal FileProperties os_properties_from_file_path(String8 path);
|
||||
internal OS_FileID os_id_from_file_path(String8 path);
|
||||
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
|
||||
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Synchronization Primitive Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal void os_mutex_take(OS_Handle mutex);
|
||||
internal void os_mutex_drop(OS_Handle mutex);
|
||||
internal void os_rw_mutex_take_r(OS_Handle rw_mutex);
|
||||
internal void os_rw_mutex_drop_r(OS_Handle rw_mutex);
|
||||
internal void os_rw_mutex_take_w(OS_Handle rw_mutex);
|
||||
internal void os_rw_mutex_drop_w(OS_Handle rw_mutex);
|
||||
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
||||
internal B32 os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us);
|
||||
internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle rw_mutex, U64 endt_us);
|
||||
internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle rw_mutex, U64 endt_us);
|
||||
internal void os_condition_variable_signal(OS_Handle cv);
|
||||
internal void os_condition_variable_broadcast(OS_Handle cv);
|
||||
|
||||
#define OS_MutexScope(mutex) DeferLoop(os_mutex_take(mutex), os_mutex_drop(mutex))
|
||||
#define OS_MutexScopeR(mutex) DeferLoop(os_rw_mutex_take_r(mutex), os_rw_mutex_drop_r(mutex))
|
||||
#define OS_MutexScopeW(mutex) DeferLoop(os_rw_mutex_take_w(mutex), os_rw_mutex_drop_w(mutex))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Main Initialization API (Implemented Per-OS)
|
||||
|
||||
internal void os_init(int argc, char **argv);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
|
||||
|
||||
internal void* os_reserve(U64 size);
|
||||
internal B32 os_commit(void *ptr, U64 size);
|
||||
internal void* os_reserve_large(U64 size);
|
||||
internal B32 os_commit_large(void *ptr, U64 size);
|
||||
internal void os_decommit(void *ptr, U64 size);
|
||||
internal void os_release(void *ptr, U64 size);
|
||||
|
||||
internal B32 os_set_large_pages(B32 flag);
|
||||
internal B32 os_large_pages_enabled(void);
|
||||
internal U64 os_large_page_size(void);
|
||||
|
||||
internal void* os_alloc_ring_buffer(U64 size, U64 *actual_size_out);
|
||||
internal void os_free_ring_buffer(void *ring_buffer, U64 actual_size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks System Info (Implemented Per-OS)
|
||||
|
||||
internal String8 os_machine_name(void);
|
||||
internal U64 os_page_size(void);
|
||||
internal U64 os_allocation_granularity(void);
|
||||
internal U64 os_logical_core_count(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Process Info (Implemented Per-OS)
|
||||
|
||||
internal String8List os_get_command_line_arguments(void);
|
||||
internal S32 os_get_pid(void);
|
||||
internal S32 os_get_tid(void);
|
||||
internal String8List os_get_environment(void);
|
||||
internal U64 os_string_list_from_system_path(Arena *arena, OS_SystemPath path, String8List *out);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Process Control (Implemented Per-OS)
|
||||
|
||||
internal void os_exit_process(S32 exit_code);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks File System (Implemented Per-OS)
|
||||
|
||||
//- rjf: files
|
||||
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
|
||||
internal void os_file_close(OS_Handle file);
|
||||
internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
|
||||
internal void os_file_write(OS_Handle file, Rng1U64 rng, void *data);
|
||||
internal B32 os_file_set_times(OS_Handle file, DateTime time);
|
||||
internal FileProperties os_properties_from_file(OS_Handle file);
|
||||
internal OS_FileID os_id_from_file(OS_Handle file);
|
||||
internal B32 os_delete_file_at_path(String8 path);
|
||||
internal B32 os_copy_file_path(String8 dst, String8 src);
|
||||
internal String8 os_full_path_from_path(Arena *arena, String8 path);
|
||||
internal B32 os_file_path_exists(String8 path);
|
||||
|
||||
//- rjf: file maps
|
||||
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file);
|
||||
internal void os_file_map_close(OS_Handle map);
|
||||
internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range);
|
||||
internal void os_file_map_view_close(OS_Handle map, void *ptr);
|
||||
|
||||
//- rjf: directory iteration
|
||||
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags);
|
||||
internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out);
|
||||
internal void os_file_iter_end(OS_FileIter *iter);
|
||||
|
||||
//- rjf: directory creation
|
||||
internal B32 os_make_directory(String8 path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Shared Memory (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_shared_memory_alloc(U64 size, String8 name);
|
||||
internal OS_Handle os_shared_memory_open(String8 name);
|
||||
internal void os_shared_memory_close(OS_Handle handle);
|
||||
internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range);
|
||||
internal void os_shared_memory_view_close(OS_Handle handle, void *ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Time (Implemented Per-OS)
|
||||
|
||||
internal OS_UnixTime os_now_unix(void);
|
||||
internal DateTime os_now_universal_time(void);
|
||||
internal DateTime os_universal_time_from_local_time(DateTime *local_time);
|
||||
internal DateTime os_local_time_from_universal_time(DateTime *universal_time);
|
||||
internal U64 os_now_microseconds(void);
|
||||
internal void os_sleep_milliseconds(U32 msec);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Child Processes (Implemented Per-OS)
|
||||
|
||||
internal B32 os_launch_process(OS_LaunchOptions *options, OS_Handle *handle_out);
|
||||
internal B32 os_process_wait(OS_Handle handle, U64 endt_us);
|
||||
internal void os_process_release_handle(OS_Handle handle);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Threads (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_launch_thread(OS_ThreadFunctionType *func, void *ptr, void *params);
|
||||
internal void os_release_thread_handle(OS_Handle thread);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
|
||||
|
||||
// NOTE(allen): Mutexes are recursive - support counted acquire/release nesting
|
||||
// on a single thread
|
||||
|
||||
//- rjf: recursive mutexes
|
||||
internal OS_Handle os_mutex_alloc(void);
|
||||
internal void os_mutex_release(OS_Handle mutex);
|
||||
internal void os_mutex_take_(OS_Handle mutex);
|
||||
internal void os_mutex_drop_(OS_Handle mutex);
|
||||
|
||||
//- rjf: reader/writer mutexes
|
||||
internal OS_Handle os_rw_mutex_alloc(void);
|
||||
internal void os_rw_mutex_release(OS_Handle rw_mutex);
|
||||
internal void os_rw_mutex_take_r_(OS_Handle mutex);
|
||||
internal void os_rw_mutex_drop_r_(OS_Handle mutex);
|
||||
internal void os_rw_mutex_take_w_(OS_Handle mutex);
|
||||
internal void os_rw_mutex_drop_w_(OS_Handle mutex);
|
||||
|
||||
//- rjf: condition variables
|
||||
internal OS_Handle os_condition_variable_alloc(void);
|
||||
internal void os_condition_variable_release(OS_Handle cv);
|
||||
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
||||
internal B32 os_condition_variable_wait_(OS_Handle cv, OS_Handle mutex, U64 endt_us);
|
||||
internal B32 os_condition_variable_wait_rw_r_(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
||||
internal B32 os_condition_variable_wait_rw_w_(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
||||
internal void os_condition_variable_signal_(OS_Handle cv);
|
||||
internal void os_condition_variable_broadcast_(OS_Handle cv);
|
||||
|
||||
//- rjf: cross-process semaphores
|
||||
internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name);
|
||||
internal void os_semaphore_release(OS_Handle semaphore);
|
||||
internal OS_Handle os_semaphore_open(String8 name);
|
||||
internal void os_semaphore_close(OS_Handle semaphore);
|
||||
internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us);
|
||||
internal void os_semaphore_drop(OS_Handle semaphore);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_library_open(String8 path);
|
||||
internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name);
|
||||
internal void os_library_close(OS_Handle lib);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
|
||||
|
||||
internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
|
||||
|
||||
internal OS_Guid os_make_guid(void);
|
||||
internal String8 os_string_from_guid(Arena *arena, OS_Guid guid);
|
||||
|
||||
#endif // OS_CORE_H
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_H
|
||||
#define OS_CORE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: System Info
|
||||
|
||||
typedef struct OS_SystemInfo OS_SystemInfo;
|
||||
struct OS_SystemInfo
|
||||
{
|
||||
U32 logical_processor_count;
|
||||
U64 page_size;
|
||||
U64 large_page_size;
|
||||
U64 allocation_granularity;
|
||||
String8 machine_name;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Info
|
||||
|
||||
typedef struct OS_ProcessInfo OS_ProcessInfo;
|
||||
struct OS_ProcessInfo
|
||||
{
|
||||
U32 pid;
|
||||
String8 binary_path;
|
||||
String8 initial_path;
|
||||
String8 user_program_data_path;
|
||||
String8List module_load_paths;
|
||||
String8List environment;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Access Flags
|
||||
|
||||
typedef U32 OS_AccessFlags;
|
||||
enum
|
||||
{
|
||||
OS_AccessFlag_Read = (1<<0),
|
||||
OS_AccessFlag_Write = (1<<1),
|
||||
OS_AccessFlag_Execute = (1<<2),
|
||||
OS_AccessFlag_Append = (1<<3),
|
||||
OS_AccessFlag_ShareRead = (1<<4),
|
||||
OS_AccessFlag_ShareWrite = (1<<5),
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Files
|
||||
|
||||
typedef U32 OS_FileIterFlags;
|
||||
enum
|
||||
{
|
||||
OS_FileIterFlag_SkipFolders = (1 << 0),
|
||||
OS_FileIterFlag_SkipFiles = (1 << 1),
|
||||
OS_FileIterFlag_SkipHiddenFiles = (1 << 2),
|
||||
OS_FileIterFlag_Done = (1 << 31),
|
||||
};
|
||||
|
||||
typedef struct OS_FileIter OS_FileIter;
|
||||
struct OS_FileIter
|
||||
{
|
||||
OS_FileIterFlags flags;
|
||||
U8 memory[800];
|
||||
};
|
||||
|
||||
typedef struct OS_FileInfo OS_FileInfo;
|
||||
struct OS_FileInfo
|
||||
{
|
||||
String8 name;
|
||||
FileProperties props;
|
||||
};
|
||||
|
||||
// nick: on-disk file identifier
|
||||
typedef struct OS_FileID OS_FileID;
|
||||
struct OS_FileID
|
||||
{
|
||||
U64 v[3];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Launch Parameters
|
||||
|
||||
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
|
||||
struct OS_ProcessLaunchParams
|
||||
{
|
||||
String8List cmd_line;
|
||||
String8 path;
|
||||
String8List env;
|
||||
B32 inherit_env;
|
||||
B32 consoleless;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type
|
||||
|
||||
typedef struct OS_Handle OS_Handle;
|
||||
struct OS_Handle
|
||||
{
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
typedef struct OS_HandleNode OS_HandleNode;
|
||||
struct OS_HandleNode
|
||||
{
|
||||
OS_HandleNode *next;
|
||||
OS_Handle v;
|
||||
};
|
||||
|
||||
typedef struct OS_HandleList OS_HandleList;
|
||||
struct OS_HandleList
|
||||
{
|
||||
OS_HandleNode *first;
|
||||
OS_HandleNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct OS_HandleArray OS_HandleArray;
|
||||
struct OS_HandleArray
|
||||
{
|
||||
OS_Handle *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globally Unique IDs
|
||||
|
||||
typedef struct OS_Guid OS_Guid;
|
||||
struct OS_Guid
|
||||
{
|
||||
U32 data1;
|
||||
U16 data2;
|
||||
U16 data3;
|
||||
U8 data4[8];
|
||||
};
|
||||
StaticAssert(sizeof(OS_Guid) == 16, os_guid_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Types
|
||||
|
||||
typedef void OS_ThreadFunctionType(void *ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
|
||||
|
||||
internal OS_Handle os_handle_zero(void);
|
||||
internal B32 os_handle_match(OS_Handle a, OS_Handle b);
|
||||
internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle);
|
||||
internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
||||
|
||||
internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8 os_data_from_file_path(Arena *arena, String8 path);
|
||||
internal B32 os_write_data_to_file_path(String8 path, String8 data);
|
||||
internal B32 os_write_data_list_to_file_path(String8 path, String8List list);
|
||||
internal B32 os_append_data_to_file_path(String8 path, String8 data);
|
||||
internal OS_FileID os_id_from_file_path(String8 path);
|
||||
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
|
||||
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: GUID Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8 os_string_from_guid(Arena *arena, OS_Guid guid);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
|
||||
|
||||
internal OS_SystemInfo *os_get_system_info(void);
|
||||
internal OS_ProcessInfo *os_get_process_info(void);
|
||||
internal String8 os_get_current_path(Arena *arena);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
|
||||
|
||||
//- rjf: basic
|
||||
internal void *os_reserve(U64 size);
|
||||
internal B32 os_commit(void *ptr, U64 size);
|
||||
internal void os_decommit(void *ptr, U64 size);
|
||||
internal void os_release(void *ptr, U64 size);
|
||||
|
||||
//- rjf: large pages
|
||||
internal void *os_reserve_large(U64 size);
|
||||
internal B32 os_commit_large(void *ptr, U64 size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Thread Info (Implemented Per-OS)
|
||||
|
||||
internal U32 os_tid(void);
|
||||
internal void os_set_thread_name(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Aborting (Implemented Per-OS)
|
||||
|
||||
internal void os_abort(S32 exit_code);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks File System (Implemented Per-OS)
|
||||
|
||||
//- rjf: files
|
||||
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
|
||||
internal void os_file_close(OS_Handle file);
|
||||
internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
|
||||
internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data);
|
||||
internal B32 os_file_set_times(OS_Handle file, DateTime time);
|
||||
internal FileProperties os_properties_from_file(OS_Handle file);
|
||||
internal OS_FileID os_id_from_file(OS_Handle file);
|
||||
internal B32 os_delete_file_at_path(String8 path);
|
||||
internal B32 os_copy_file_path(String8 dst, String8 src);
|
||||
internal String8 os_full_path_from_path(Arena *arena, String8 path);
|
||||
internal B32 os_file_path_exists(String8 path);
|
||||
internal FileProperties os_properties_from_file_path(String8 path);
|
||||
|
||||
//- rjf: file maps
|
||||
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file);
|
||||
internal void os_file_map_close(OS_Handle map);
|
||||
internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range);
|
||||
internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range);
|
||||
|
||||
//- rjf: directory iteration
|
||||
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags);
|
||||
internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out);
|
||||
internal void os_file_iter_end(OS_FileIter *iter);
|
||||
|
||||
//- rjf: directory creation
|
||||
internal B32 os_make_directory(String8 path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Shared Memory (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_shared_memory_alloc(U64 size, String8 name);
|
||||
internal OS_Handle os_shared_memory_open(String8 name);
|
||||
internal void os_shared_memory_close(OS_Handle handle);
|
||||
internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range);
|
||||
internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Time (Implemented Per-OS)
|
||||
|
||||
internal U64 os_now_microseconds(void);
|
||||
internal U32 os_now_unix(void);
|
||||
internal DateTime os_now_universal_time(void);
|
||||
internal DateTime os_universal_time_from_local(DateTime *local_time);
|
||||
internal DateTime os_local_time_from_universal(DateTime *universal_time);
|
||||
internal void os_sleep_milliseconds(U32 msec);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Child Processes (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params);
|
||||
internal B32 os_process_join(OS_Handle handle, U64 endt_us);
|
||||
internal void os_process_detach(OS_Handle handle);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Threads (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params);
|
||||
internal B32 os_thread_join(OS_Handle handle, U64 endt_us);
|
||||
internal void os_thread_detach(OS_Handle handle);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
|
||||
|
||||
//- rjf: recursive mutexes
|
||||
internal OS_Handle os_mutex_alloc(void);
|
||||
internal void os_mutex_release(OS_Handle mutex);
|
||||
internal void os_mutex_take(OS_Handle mutex);
|
||||
internal void os_mutex_drop(OS_Handle mutex);
|
||||
|
||||
//- rjf: reader/writer mutexes
|
||||
internal OS_Handle os_rw_mutex_alloc(void);
|
||||
internal void os_rw_mutex_release(OS_Handle rw_mutex);
|
||||
internal void os_rw_mutex_take_r(OS_Handle mutex);
|
||||
internal void os_rw_mutex_drop_r(OS_Handle mutex);
|
||||
internal void os_rw_mutex_take_w(OS_Handle mutex);
|
||||
internal void os_rw_mutex_drop_w(OS_Handle mutex);
|
||||
|
||||
//- rjf: condition variables
|
||||
internal OS_Handle os_condition_variable_alloc(void);
|
||||
internal void os_condition_variable_release(OS_Handle cv);
|
||||
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
||||
internal B32 os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us);
|
||||
internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
||||
internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
||||
internal void os_condition_variable_signal(OS_Handle cv);
|
||||
internal void os_condition_variable_broadcast(OS_Handle cv);
|
||||
|
||||
//- rjf: cross-process semaphores
|
||||
internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name);
|
||||
internal void os_semaphore_release(OS_Handle semaphore);
|
||||
internal OS_Handle os_semaphore_open(String8 name);
|
||||
internal void os_semaphore_close(OS_Handle semaphore);
|
||||
internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us);
|
||||
internal void os_semaphore_drop(OS_Handle semaphore);
|
||||
|
||||
//- rjf: scope macros
|
||||
#define OS_MutexScope(mutex) DeferLoop(os_mutex_take(mutex), os_mutex_drop(mutex))
|
||||
#define OS_MutexScopeR(mutex) DeferLoop(os_rw_mutex_take_r(mutex), os_rw_mutex_drop_r(mutex))
|
||||
#define OS_MutexScopeW(mutex) DeferLoop(os_rw_mutex_take_w(mutex), os_rw_mutex_drop_w(mutex))
|
||||
#define OS_MutexScopeRWPromote(mutex) DeferLoop((os_rw_mutex_drop_r(mutex), os_rw_mutex_take_w(mutex)), (os_rw_mutex_drop_w(mutex), os_rw_mutex_take_r(mutex)))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_library_open(String8 path);
|
||||
internal void os_library_close(OS_Handle lib);
|
||||
internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
|
||||
|
||||
internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
|
||||
|
||||
internal OS_Guid os_make_guid(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Entry Points (Implemented Per-OS)
|
||||
|
||||
// NOTE(rjf): The implementation of `os_core` will define low-level entry
|
||||
// points if BUILD_ENTRY_DEFINING_UNIT is defined to 1. These will call
|
||||
// into the standard codebase program entry points, named "entry_point".
|
||||
|
||||
#if BUILD_ENTRY_DEFINING_UNIT
|
||||
internal void entry_point(CmdLine *cmdline);
|
||||
#endif
|
||||
|
||||
#endif // OS_CORE_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,91 +1,122 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef WIN32_H
|
||||
#define WIN32_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Negotiate the windows header include order
|
||||
|
||||
#if OS_FEATURE_SOCKET
|
||||
#include <WinSock2.h>
|
||||
#endif
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Shlobj.h>
|
||||
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
#include <shellscalingapi.h>
|
||||
#endif
|
||||
|
||||
#if OS_FEATURE_SOCKET
|
||||
#include <WS2tcpip.h>
|
||||
#include <Mswsock.h>
|
||||
#endif
|
||||
|
||||
#include <processthreadsapi.h>
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): File Iterator
|
||||
|
||||
typedef struct W32_FileIter W32_FileIter;
|
||||
struct W32_FileIter
|
||||
{
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAW find_data;
|
||||
};
|
||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(W32_FileIter), file_iter_memory_size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Threading Entities
|
||||
|
||||
typedef enum W32_EntityKind
|
||||
{
|
||||
W32_EntityKind_Null,
|
||||
W32_EntityKind_Thread,
|
||||
W32_EntityKind_Mutex,
|
||||
W32_EntityKind_RWMutex,
|
||||
W32_EntityKind_ConditionVariable,
|
||||
}
|
||||
W32_EntityKind;
|
||||
|
||||
typedef struct W32_Entity W32_Entity;
|
||||
struct W32_Entity
|
||||
{
|
||||
W32_Entity *next;
|
||||
W32_EntityKind kind;
|
||||
volatile U32 reference_mask;
|
||||
union{
|
||||
struct{
|
||||
OS_ThreadFunctionType *func;
|
||||
void *ptr;
|
||||
HANDLE handle;
|
||||
DWORD tid;
|
||||
} thread;
|
||||
CRITICAL_SECTION mutex;
|
||||
SRWLOCK rw_mutex;
|
||||
CONDITION_VARIABLE cv;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
//- rjf: files
|
||||
internal FilePropertyFlags w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes);
|
||||
internal void w32_file_properties_from_attributes(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes);
|
||||
|
||||
//- rjf: time
|
||||
internal void w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in);
|
||||
internal void w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in);
|
||||
internal void w32_dense_time_from_file_time(DenseTime *out, FILETIME *in);
|
||||
internal U32 w32_sleep_ms_from_endt_us(U64 endt_us);
|
||||
|
||||
//- rjf: entities
|
||||
internal W32_Entity* w32_alloc_entity(W32_EntityKind kind);
|
||||
internal void w32_free_entity(W32_Entity *entity);
|
||||
|
||||
//- rjf: threads
|
||||
internal DWORD w32_thread_base(void *ptr);
|
||||
|
||||
#endif //WIN32_H
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_WIN32_H
|
||||
#define OS_CORE_WIN32_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes / Libraries
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <timeapi.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <Shlobj.h>
|
||||
#include <processthreadsapi.h>
|
||||
#pragma comment(lib, "user32")
|
||||
#pragma comment(lib, "winmm")
|
||||
#pragma comment(lib, "shell32")
|
||||
#pragma comment(lib, "advapi32")
|
||||
#pragma comment(lib, "rpcrt4")
|
||||
#pragma comment(lib, "shlwapi")
|
||||
#pragma comment(lib, "comctl32")
|
||||
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") // this is required for loading correct comctl32 dll file
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: File Iterator Types
|
||||
|
||||
typedef struct OS_W32_FileIter OS_W32_FileIter;
|
||||
struct OS_W32_FileIter
|
||||
{
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAW find_data;
|
||||
B32 is_volume_iter;
|
||||
String8Array drive_strings;
|
||||
U64 drive_strings_iter_idx;
|
||||
};
|
||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_W32_FileIter), file_iter_memory_size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Types
|
||||
|
||||
typedef enum OS_W32_EntityKind
|
||||
{
|
||||
OS_W32_EntityKind_Null,
|
||||
OS_W32_EntityKind_Thread,
|
||||
OS_W32_EntityKind_Mutex,
|
||||
OS_W32_EntityKind_RWMutex,
|
||||
OS_W32_EntityKind_ConditionVariable,
|
||||
}
|
||||
OS_W32_EntityKind;
|
||||
|
||||
typedef struct OS_W32_Entity OS_W32_Entity;
|
||||
struct OS_W32_Entity
|
||||
{
|
||||
OS_W32_Entity *next;
|
||||
OS_W32_EntityKind kind;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
OS_ThreadFunctionType *func;
|
||||
void *ptr;
|
||||
HANDLE handle;
|
||||
DWORD tid;
|
||||
} thread;
|
||||
CRITICAL_SECTION mutex;
|
||||
SRWLOCK rw_mutex;
|
||||
CONDITION_VARIABLE cv;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: State
|
||||
|
||||
typedef struct OS_W32_State OS_W32_State;
|
||||
struct OS_W32_State
|
||||
{
|
||||
Arena *arena;
|
||||
|
||||
// rjf: info
|
||||
OS_SystemInfo system_info;
|
||||
OS_ProcessInfo process_info;
|
||||
U64 microsecond_resolution;
|
||||
|
||||
// rjf: entity storage
|
||||
CRITICAL_SECTION entity_mutex;
|
||||
Arena *entity_arena;
|
||||
OS_W32_Entity *entity_free;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global OS_W32_State os_w32_state = {0};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: File Info Conversion Helpers
|
||||
|
||||
internal FilePropertyFlags os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes);
|
||||
internal void os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Time Conversion Helpers
|
||||
|
||||
internal void os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in);
|
||||
internal void os_w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in);
|
||||
internal void os_w32_dense_time_from_file_time(DenseTime *out, FILETIME *in);
|
||||
internal U32 os_w32_sleep_ms_from_endt_us(U64 endt_us);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Functions
|
||||
|
||||
internal OS_W32_Entity *os_w32_entity_alloc(OS_W32_EntityKind kind);
|
||||
internal void os_w32_entity_release(OS_W32_Entity *entity);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Entry Point
|
||||
|
||||
internal DWORD os_w32_thread_entry_point(void *ptr);
|
||||
|
||||
#endif // OS_CORE_WIN32_H
|
||||
|
||||
@@ -1,29 +1,12 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Include OS features for extra features and target OS
|
||||
|
||||
#include "core/metagen_os_core.c"
|
||||
|
||||
#if OS_FEATURE_SOCKET
|
||||
#include "socket/metagen_os_socket.c"
|
||||
#endif
|
||||
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
#include "gfx/metagen_os_gfx.c"
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "core/win32/metagen_os_core_win32.c"
|
||||
# if OS_FEATURE_SOCKET
|
||||
# include "socket/win32/metagen_os_socket_win32.c"
|
||||
# endif
|
||||
# if OS_FEATURE_GRAPHICAL
|
||||
# include "gfx/win32/metagen_os_gfx_win32.c"
|
||||
# endif
|
||||
#elif OS_LINUX
|
||||
# include "core/linux/metagen_os_core_linux.c"
|
||||
#else
|
||||
# error no OS layer setup
|
||||
#endif
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "metagen/metagen_os/core/metagen_os_core.c"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "metagen/metagen_os/core/win32/metagen_os_core_win32.c"
|
||||
#elif OS_LINUX
|
||||
# include "metagen/metagen_os/core/linux/metagen_os_core_linux.c"
|
||||
#else
|
||||
# error OS core layer not implemented for this operating system.
|
||||
#endif
|
||||
|
||||
@@ -4,36 +4,22 @@
|
||||
#ifndef OS_INC_H
|
||||
#define OS_INC_H
|
||||
|
||||
#if !defined(OS_FEATURE_SOCKET)
|
||||
# define OS_FEATURE_SOCKET 0
|
||||
#endif
|
||||
|
||||
#if !defined(OS_FEATURE_GRAPHICAL)
|
||||
# define OS_FEATURE_GRAPHICAL 0
|
||||
#endif
|
||||
|
||||
#include "core/metagen_os_core.h"
|
||||
|
||||
#if OS_FEATURE_SOCKET
|
||||
#include "socket/metagen_os_socket.h"
|
||||
#if !defined(OS_GFX_STUB)
|
||||
# define OS_GFX_STUB 0
|
||||
#endif
|
||||
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
#include "gfx/metagen_os_gfx.h"
|
||||
#endif
|
||||
#include "metagen/metagen_os/core/metagen_os_core.h"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "core/win32/metagen_os_core_win32.h"
|
||||
# if OS_FEATURE_SOCKET
|
||||
# include "socket/win32/metagen_os_socket_win32.h"
|
||||
# endif
|
||||
# if OS_FEATURE_GRAPHICAL
|
||||
# include "gfx/win32/metagen_os_gfx_win32.h"
|
||||
# endif
|
||||
# include "metagen/metagen_os/core/win32/metagen_os_core_win32.h"
|
||||
#elif OS_LINUX
|
||||
# include "core/linux/metagen_os_core_linux.h"
|
||||
# include "metagen/metagen_os/core/linux/metagen_os_core_linux.h"
|
||||
#else
|
||||
# error no OS layer setup
|
||||
# error OS core layer not implemented for this operating system.
|
||||
#endif
|
||||
|
||||
#endif // OS_INC_H
|
||||
|
||||
Reference in New Issue
Block a user