From b198f0b421dabff307461601d502d701bf258d76 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 12 May 2026 20:02:35 -0700 Subject: [PATCH] just move metagen onto regular base layer - in theory this causes cycles (metagen w/ bug -> generates busted base layer code -> can't build metagen!) but we do not currently generate anything in base, and we also can just revert in that case. --- src/metagen/metagen_base/metagen_base_arena.c | 248 -- src/metagen/metagen_base/metagen_base_arena.h | 91 - .../metagen_base/metagen_base_command_line.c | 250 -- .../metagen_base/metagen_base_command_line.h | 56 - .../metagen_base_context_cracking.h | 247 -- src/metagen/metagen_base/metagen_base_core.c | 648 ----- src/metagen/metagen_base/metagen_base_core.h | 899 ------ .../metagen_base/metagen_base_entry_point.c | 130 - .../metagen_base/metagen_base_entry_point.h | 12 - src/metagen/metagen_base/metagen_base_inc.c | 20 - src/metagen/metagen_base/metagen_base_inc.h | 24 - src/metagen/metagen_base/metagen_base_log.c | 103 - src/metagen/metagen_base/metagen_base_log.h | 65 - .../metagen_base/metagen_base_markup.c | 21 - .../metagen_base/metagen_base_markup.h | 12 - src/metagen/metagen_base/metagen_base_math.c | 659 ----- src/metagen/metagen_base/metagen_base_math.h | 675 ----- src/metagen/metagen_base/metagen_base_meta.c | 422 --- src/metagen/metagen_base/metagen_base_meta.h | 298 -- .../metagen_base/metagen_base_profile.c | 2 - .../metagen_base/metagen_base_profile.h | 97 - .../metagen_base/metagen_base_strings.c | 2446 ----------------- .../metagen_base/metagen_base_strings.h | 412 --- .../metagen_base_thread_context.c | 87 - .../metagen_base_thread_context.h | 41 - src/metagen/metagen_main.c | 22 +- .../core/linux/metagen_os_core_linux.c | 1337 --------- .../core/linux/metagen_os_core_linux.h | 136 - src/metagen/metagen_os/core/metagen_os_core.c | 240 -- src/metagen/metagen_os/core/metagen_os_core.h | 335 --- .../core/win32/metagen_os_core_win32.c | 1785 ------------ .../core/win32/metagen_os_core_win32.h | 121 - src/metagen/metagen_os/metagen_os_inc.c | 12 - src/metagen/metagen_os/metagen_os_inc.h | 21 - 34 files changed, 10 insertions(+), 11964 deletions(-) delete mode 100644 src/metagen/metagen_base/metagen_base_arena.c delete mode 100644 src/metagen/metagen_base/metagen_base_arena.h delete mode 100644 src/metagen/metagen_base/metagen_base_command_line.c delete mode 100644 src/metagen/metagen_base/metagen_base_command_line.h delete mode 100644 src/metagen/metagen_base/metagen_base_context_cracking.h delete mode 100644 src/metagen/metagen_base/metagen_base_core.c delete mode 100644 src/metagen/metagen_base/metagen_base_core.h delete mode 100644 src/metagen/metagen_base/metagen_base_entry_point.c delete mode 100644 src/metagen/metagen_base/metagen_base_entry_point.h delete mode 100644 src/metagen/metagen_base/metagen_base_inc.c delete mode 100644 src/metagen/metagen_base/metagen_base_inc.h delete mode 100644 src/metagen/metagen_base/metagen_base_log.c delete mode 100644 src/metagen/metagen_base/metagen_base_log.h delete mode 100644 src/metagen/metagen_base/metagen_base_markup.c delete mode 100644 src/metagen/metagen_base/metagen_base_markup.h delete mode 100644 src/metagen/metagen_base/metagen_base_math.c delete mode 100644 src/metagen/metagen_base/metagen_base_math.h delete mode 100644 src/metagen/metagen_base/metagen_base_meta.c delete mode 100644 src/metagen/metagen_base/metagen_base_meta.h delete mode 100644 src/metagen/metagen_base/metagen_base_profile.c delete mode 100644 src/metagen/metagen_base/metagen_base_profile.h delete mode 100644 src/metagen/metagen_base/metagen_base_strings.c delete mode 100644 src/metagen/metagen_base/metagen_base_strings.h delete mode 100644 src/metagen/metagen_base/metagen_base_thread_context.c delete mode 100644 src/metagen/metagen_base/metagen_base_thread_context.h delete mode 100644 src/metagen/metagen_os/core/linux/metagen_os_core_linux.c delete mode 100644 src/metagen/metagen_os/core/linux/metagen_os_core_linux.h delete mode 100644 src/metagen/metagen_os/core/metagen_os_core.c delete mode 100644 src/metagen/metagen_os/core/metagen_os_core.h delete mode 100644 src/metagen/metagen_os/core/win32/metagen_os_core_win32.c delete mode 100644 src/metagen/metagen_os/core/win32/metagen_os_core_win32.h delete mode 100644 src/metagen/metagen_os/metagen_os_inc.c delete mode 100644 src/metagen/metagen_os/metagen_os_inc.h diff --git a/src/metagen/metagen_base/metagen_base_arena.c b/src/metagen/metagen_base/metagen_base_arena.c deleted file mode 100644 index 68ad2544..00000000 --- a/src/metagen/metagen_base/metagen_base_arena.c +++ /dev/null @@ -1,248 +0,0 @@ -// 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 = 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; -#if ARENA_FREE_LIST - arena->free_size = 0; - arena->free_last = 0; -#endif - 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)) - { - Arena *new_block = 0; - -#if ARENA_FREE_LIST - Arena *prev_block; - for(new_block = arena->free_last, prev_block = 0; new_block != 0; prev_block = new_block, new_block = new_block->prev) - { - if(new_block->res >= AlignPow2(size, align)) - { - if(prev_block) - { - prev_block->prev = new_block->prev; - } - else - { - arena->free_last = new_block->prev; - } - arena->free_size -= new_block->res_size; - AsanUnpoisonMemoryRegion((U8*)new_block + ARENA_HEADER_SIZE, new_block->res_size - ARENA_HEADER_SIZE); - break; - } - } -#endif - - if(new_block == 0) - { - U64 res_size = current->res_size; - U64 cmt_size = current->cmt_size; - if(size + ARENA_HEADER_SIZE > res_size) - { - res_size = AlignPow2(size + ARENA_HEADER_SIZE, align); - cmt_size = AlignPow2(size + ARENA_HEADER_SIZE, align); - } - 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_pre + size; - } - - // rjf: commit new pages, if needed - if(current->cmt < pos_pst) - { - U64 cmt_pst_aligned = pos_pst + current->cmt_size-1; - cmt_pst_aligned -= cmt_pst_aligned%current->cmt_size; - U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res); - U64 cmt_size = cmt_pst_clamped - current->cmt; - U8 *cmt_ptr = (U8 *)current + current->cmt; - if(current->flags & ArenaFlag_LargePages) - { - os_commit_large(cmt_ptr, cmt_size); - } - else - { - os_commit(cmt_ptr, 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; - -#if ARENA_FREE_LIST - for(Arena *prev = 0; current->base_pos >= big_pos; current = prev) - { - prev = current->prev; - current->pos = ARENA_HEADER_SIZE; - arena->free_size += current->res_size; - SLLStackPush_N(arena->free_last, current, prev); - AsanPoisonMemoryRegion((U8*)current + ARENA_HEADER_SIZE, current->res_size - ARENA_HEADER_SIZE); - } -#else - for(Arena *prev = 0; current->base_pos >= big_pos; current = prev) - { - prev = current->prev; - os_release(current, current->res); - } -#endif - 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); -} diff --git a/src/metagen/metagen_base/metagen_base_arena.h b/src/metagen/metagen_base/metagen_base_arena.h deleted file mode 100644 index 8696f49f..00000000 --- a/src/metagen/metagen_base/metagen_base_arena.h +++ /dev/null @@ -1,91 +0,0 @@ -// 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 - -//////////////////////////////// -//~ rjf: Types - -typedef U64 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; - U64 cmt_size; - U64 res_size; - U64 base_pos; - U64 pos; - U64 cmt; - U64 res; -#if ARENA_FREE_LIST - U64 free_size; - Arena *free_last; -#endif -}; -StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check); - -typedef struct Temp Temp; -struct Temp -{ - Arena *arena; - U64 pos; -}; - -//////////////////////////////// -//~ rjf: Global Defaults - -global U64 arena_default_reserve_size = MB(64); -global U64 arena_default_commit_size = KB(64); -global ArenaFlags arena_default_flags = 0; - -//////////////////////////////// -//~ rjf: Arena Functions - -//- rjf: arena creation/destruction -internal Arena *arena_alloc_(ArenaParams *params); -#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = arena_default_reserve_size, .commit_size = arena_default_commit_size, .flags = arena_default_flags, __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 diff --git a/src/metagen/metagen_base/metagen_base_command_line.c b/src/metagen/metagen_base/metagen_base_command_line.c deleted file mode 100644 index ec726752..00000000 --- a/src/metagen/metagen_base/metagen_base_command_line.c +++ /dev/null @@ -1,250 +0,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 / (only on Windows) 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 if(operating_system_from_context() == OperatingSystem_Windows && - 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; - } - } - - // rjf: fill argc/argv - parsed.argc = command_line.node_count; - parsed.argv = push_array(arena, char *, parsed.argc); - { - U64 idx = 0; - for(String8Node *n = command_line.first; n != 0; n = n->next) - { - parsed.argv[idx] = (char *)push_str8_copy(arena, n->string).str; - idx += 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); -} diff --git a/src/metagen/metagen_base/metagen_base_command_line.h b/src/metagen/metagen_base/metagen_base_command_line.h deleted file mode 100644 index acd7f17b..00000000 --- a/src/metagen/metagen_base/metagen_base_command_line.h +++ /dev/null @@ -1,56 +0,0 @@ -// 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; - U64 argc; - char **argv; -}; - -//////////////////////////////// -//~ 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 diff --git a/src/metagen/metagen_base/metagen_base_context_cracking.h b/src/metagen/metagen_base/metagen_base_context_cracking.h deleted file mode 100644 index bac701dd..00000000 --- a/src/metagen/metagen_base/metagen_base_context_cracking.h +++ /dev/null @@ -1,247 +0,0 @@ -// 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 9 -#endif - -#if !defined(BUILD_VERSION_PATCH) -# define BUILD_VERSION_PATCH 14 -#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/EpicGamesExt/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 diff --git a/src/metagen/metagen_base/metagen_base_core.c b/src/metagen/metagen_base/metagen_base_core.c deleted file mode 100644 index d024c6e9..00000000 --- a/src/metagen/metagen_base/metagen_base_core.c +++ /dev/null @@ -1,648 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Safe Casts - -internal U16 -safe_cast_u16(U32 x) -{ - AssertAlways(x <= max_U16); - U16 result = (U16)x; - return result; -} - -internal U32 -safe_cast_u32(U64 x) -{ - AssertAlways(x <= max_U32); - U32 result = (U32)x; - return result; -} - -internal S32 -safe_cast_s32(S64 x) -{ - AssertAlways(x <= max_S32); - S32 result = (S32)x; - return result; -} - -//////////////////////////////// -//~ rjf: Large Base Type Functions - -internal U128 -u128_zero(void) -{ - U128 v = {0}; - return v; -} - -internal U128 -u128_make(U64 v0, U64 v1) -{ - U128 v = {v0, v1}; - return v; -} - -internal B32 -u128_match(U128 a, U128 b) -{ - return MemoryMatchStruct(&a, &b); -} - -//////////////////////////////// -//~ rjf: Bit Patterns - -internal U32 -u32_from_u64_saturate(U64 x){ - U32 x32 = (x > max_U32)?max_U32:(U32)x; - return(x32); -} - -internal U64 -u64_up_to_pow2(U64 x){ - if (x == 0){ - x = 1; - } - else{ - x -= 1; - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - x |= (x >> 32); - x += 1; - } - return(x); -} - -internal S32 -extend_sign32(U32 x, U32 size){ - U32 high_bit = size * 8; - U32 shift = 32 - high_bit; - S32 result = ((S32)x << shift) >> shift; - return result; -} - -internal S64 -extend_sign64(U64 x, U64 size){ - U64 high_bit = size * 8; - U64 shift = 64 - high_bit; - S64 result = ((S64)x << shift) >> shift; - return result; -} - -internal F32 -inf32(void){ - union { U32 u; F32 f; } x; - x.u = exponent32; - return(x.f); -} - -internal F32 -neg_inf32(void){ - union { U32 u; F32 f; } x; - x.u = sign32 | exponent32; - return(x.f); -} - -internal U16 -bswap_u16(U16 x) -{ - U16 result = (((x & 0xFF00) >> 8) | - ((x & 0x00FF) << 8)); - return result; -} - -internal U32 -bswap_u32(U32 x) -{ - U32 result = (((x & 0xFF000000) >> 24) | - ((x & 0x00FF0000) >> 8) | - ((x & 0x0000FF00) << 8) | - ((x & 0x000000FF) << 24)); - return result; -} - -internal U64 -bswap_u64(U64 x) -{ - // TODO(nick): naive bswap, replace with something that is faster like an intrinsic - U64 result = (((x & 0xFF00000000000000ULL) >> 56) | - ((x & 0x00FF000000000000ULL) >> 40) | - ((x & 0x0000FF0000000000ULL) >> 24) | - ((x & 0x000000FF00000000ULL) >> 8) | - ((x & 0x00000000FF000000ULL) << 8) | - ((x & 0x0000000000FF0000ULL) << 24) | - ((x & 0x000000000000FF00ULL) << 40) | - ((x & 0x00000000000000FFULL) << 56)); - return result; -} - -#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) - -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_set32(U32 val) -{ - return __builtin_popcount(val); -} - -internal U64 -count_bits_set64(U64 val) -{ - return __builtin_popcountll(val); -} - -internal U64 -ctz32(U32 val) -{ - return __builtin_ctz(val); -} - -internal U64 -clz32(U32 val) -{ - return __builtin_clz(val); -} - -internal U64 -ctz64(U64 val) -{ - return __builtin_ctzll(val); -} - -internal U64 -clz64(U64 val) -{ - return __builtin_clzll(val); -} - -#else -# error "Bit intrinsic functions not defined for this compiler." -#endif - -//////////////////////////////// -//~ rjf: Enum -> Sign - -internal S32 -sign_from_side_S32(Side side){ - return((side == Side_Min)?-1:1); -} - -internal F32 -sign_from_side_F32(Side side){ - return((side == Side_Min)?-1.f:1.f); -} - -//////////////////////////////// -//~ rjf: Memory Functions - -internal B32 -memory_is_zero(void *ptr, U64 size){ - B32 result = 1; - - // break down size - U64 extra = (size&0x7); - U64 count8 = (size >> 3); - - // check with 8-byte stride - U64 *p64 = (U64*)ptr; - if(result) - { - for (U64 i = 0; i < count8; i += 1, p64 += 1){ - if (*p64 != 0){ - result = 0; - goto done; - } - } - } - - // check extra - if(result) - { - U8 *p8 = (U8*)p64; - for (U64 i = 0; i < extra; i += 1, p8 += 1){ - if (*p8 != 0){ - result = 0; - goto done; - } - } - } - - done:; - return(result); -} - -internal void UBSAN_NO_ALIGN -memory_write16(void *ptr, U16 v) -{ - MemoryCopy(ptr, &v, sizeof(v)); -} - -internal void UBSAN_NO_ALIGN -memory_write32(void *ptr, U32 v) -{ - MemoryCopy(ptr, &v, sizeof(v)); -} - -internal U8 UBSAN_NO_ALIGN -memory_read8(void *ptr) -{ - U8 result; - MemoryCopy(&result, ptr, sizeof(result)); - return result; -} - -internal U16 UBSAN_NO_ALIGN -memory_read16(void *ptr) -{ - U16 result; - MemoryCopy(&result, ptr, sizeof(result)); - return result; -} - -internal U32 UBSAN_NO_ALIGN -memory_read32(void *ptr) -{ - U32 result; - MemoryCopy(&result, ptr, sizeof(result)); - return result; -} - -internal U64 UBSAN_NO_ALIGN -memory_read64(void *ptr) -{ - U64 result; - MemoryCopy(&result, ptr, sizeof(result)); - return result; -} - -//////////////////////////////// -//~ rjf: Text 2D Coordinate/Range Functions - -internal TxtPt -txt_pt(S64 line, S64 column) -{ - TxtPt p = {0}; - p.line = line; - p.column = column; - return p; -} - -internal B32 -txt_pt_match(TxtPt a, TxtPt b) -{ - return a.line == b.line && a.column == b.column; -} - -internal B32 -txt_pt_less_than(TxtPt a, TxtPt b) -{ - B32 result = 0; - if(a.line < b.line) - { - result = 1; - } - else if(a.line == b.line) - { - result = a.column < b.column; - } - return result; -} - -internal TxtPt -txt_pt_min(TxtPt a, TxtPt b) -{ - TxtPt result = b; - if(txt_pt_less_than(a, b)) - { - result = a; - } - return result; -} - -internal TxtPt -txt_pt_max(TxtPt a, TxtPt b) -{ - TxtPt result = a; - if(txt_pt_less_than(a, b)) - { - result = b; - } - return result; -} - -internal TxtRng -txt_rng(TxtPt min, TxtPt max) -{ - TxtRng range = {0}; - if(txt_pt_less_than(min, max)) - { - range.min = min; - range.max = max; - } - else - { - range.min = max; - range.max = min; - } - return range; -} - -internal TxtRng -txt_rng_intersect(TxtRng a, TxtRng b) -{ - TxtRng result = {0}; - result.min = txt_pt_max(a.min, b.min); - result.max = txt_pt_min(a.max, b.max); - if(txt_pt_less_than(result.max, result.min)) - { - MemoryZeroStruct(&result); - } - return result; -} - -internal TxtRng -txt_rng_union(TxtRng a, TxtRng b) -{ - TxtRng result = {0}; - result.min = txt_pt_min(a.min, b.min); - result.max = txt_pt_max(a.max, b.max); - return result; -} - -internal B32 -txt_rng_contains(TxtRng r, TxtPt pt) -{ - B32 result = ((txt_pt_less_than(r.min, pt) || txt_pt_match(r.min, pt)) && - txt_pt_less_than(pt, r.max)); - return result; -} - -//////////////////////////////// -//~ rjf: Toolchain/Environment Enum Functions - -internal U64 -bit_size_from_arch(Arch arch) -{ - // TODO(rjf): metacode - U64 arch_bitsize = 0; - switch(arch) - { - case Arch_x64: arch_bitsize = 64; break; - case Arch_x86: arch_bitsize = 32; break; - case Arch_arm64: arch_bitsize = 64; break; - case Arch_arm32: arch_bitsize = 32; break; - default: break; - } - return arch_bitsize; -} - -internal U64 -max_instruction_size_from_arch(Arch arch) -{ - // TODO(rjf): make this real - return 64; -} - -internal OperatingSystem -operating_system_from_context(void){ - OperatingSystem os = OperatingSystem_Null; -#if OS_WINDOWS - os = OperatingSystem_Windows; -#elif OS_LINUX - os = OperatingSystem_Linux; -#elif OS_MAC - os = OperatingSystem_Mac; -#endif - return os; -} - -internal Arch -arch_from_context(void){ - Arch arch = Arch_Null; -#if ARCH_X64 - arch = Arch_x64; -#elif ARCH_X86 - arch = Arch_x86; -#elif ARCH_ARM64 - arch = Arch_arm64; -#elif ARCH_ARM32 - arch = Arch_arm32; -#endif - return arch; -} - -internal Compiler -compiler_from_context(void){ - Compiler compiler = Compiler_Null; -#if COMPILER_MSVC - compiler = Compiler_msvc; -#elif COMPILER_GCC - compiler = Compiler_gcc; -#elif COMPILER_CLANG - compiler = Compiler_clang; -#endif - return compiler; -} - -//////////////////////////////// -//~ rjf: Time Functions - -internal DenseTime -dense_time_from_date_time(DateTime date_time){ - DenseTime result = 0; - result += date_time.year; - result *= 12; - result += date_time.mon; - result *= 31; - result += date_time.day; - result *= 24; - result += date_time.hour; - result *= 60; - result += date_time.min; - result *= 61; - result += date_time.sec; - result *= 1000; - result += date_time.msec; - return(result); -} - -internal DateTime -date_time_from_dense_time(DenseTime time){ - DateTime result = {0}; - result.msec = time%1000; - time /= 1000; - result.sec = time%61; - time /= 61; - result.min = time%60; - time /= 60; - result.hour = time%24; - time /= 24; - result.day = time%31; - time /= 31; - result.mon = time%12; - time /= 12; - Assert(time <= max_U32); - result.year = (U32)time; - return(result); -} - -internal DateTime -date_time_from_micro_seconds(U64 time){ - DateTime result = {0}; - result.micro_sec = time%1000; - time /= 1000; - result.msec = time%1000; - time /= 1000; - result.sec = time%60; - time /= 60; - result.min = time%60; - time /= 60; - result.hour = time%24; - time /= 24; - result.day = time%31; - time /= 31; - result.mon = time%12; - time /= 12; - Assert(time <= max_U32); - result.year = (U32)time; - return(result); -} - -internal DateTime -date_time_from_unix_time(U64 unix_time) -{ - DateTime date = {0}; - date.year = 1970; - date.day = 1 + (unix_time / 86400); - date.sec = (U32)unix_time % 60; - date.min = (U32)(unix_time / 60) % 60; - date.hour = (U32)(unix_time / 3600) % 24; - - for(;;) - { - for(date.month = 0; date.month < 12; ++date.month) - { - U64 c = 0; - switch(date.month) - { - case Month_Jan: c = 31; break; - case Month_Feb: - { - if((date.year % 4 == 0) && ((date.year % 100) != 0 || (date.year % 400) == 0)) - { - c = 29; - } - else - { - c = 28; - } - } break; - case Month_Mar: c = 31; break; - case Month_Apr: c = 30; break; - case Month_May: c = 31; break; - case Month_Jun: c = 30; break; - case Month_Jul: c = 31; break; - case Month_Aug: c = 31; break; - case Month_Sep: c = 30; break; - case Month_Oct: c = 31; break; - case Month_Nov: c = 30; break; - case Month_Dec: c = 31; break; - default: InvalidPath; - } - if(date.day <= c) - { - goto exit; - } - date.day -= c; - } - ++date.year; - } - exit:; - - return date; -} - -//////////////////////////////// -//~ rjf: Non-Fancy Ring Buffer Reads/Writes - -internal U64 -ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size) -{ - Assert(src_data_size <= ring_size); - { - U64 ring_off = ring_pos%ring_size; - U64 bytes_before_split = ring_size-ring_off; - U64 pre_split_bytes = Min(bytes_before_split, src_data_size); - U64 pst_split_bytes = src_data_size-pre_split_bytes; - void *pre_split_data = src_data; - void *pst_split_data = ((U8 *)src_data + pre_split_bytes); - MemoryCopy(ring_base+ring_off, pre_split_data, pre_split_bytes); - MemoryCopy(ring_base+0, pst_split_data, pst_split_bytes); - } - return src_data_size; -} - -internal U64 -ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size) -{ - Assert(read_size <= ring_size); - { - U64 ring_off = ring_pos%ring_size; - U64 bytes_before_split = ring_size-ring_off; - U64 pre_split_bytes = Min(bytes_before_split, read_size); - U64 pst_split_bytes = read_size-pre_split_bytes; - MemoryCopy(dst_data, ring_base+ring_off, pre_split_bytes); - MemoryCopy((U8 *)dst_data + pre_split_bytes, ring_base+0, pst_split_bytes); - } - return read_size; -} diff --git a/src/metagen/metagen_base/metagen_base_core.h b/src/metagen/metagen_base/metagen_base_core.h deleted file mode 100644 index f76e2693..00000000 --- a/src/metagen/metagen_base/metagen_base_core.h +++ /dev/null @@ -1,899 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#ifndef BASE_CORE_H -#define BASE_CORE_H - -//////////////////////////////// -//~ rjf: Foreign Includes - -#include -#include -#include -#include -#include - -//////////////////////////////// -//~ rjf: Codebase Keywords - -#define internal static -#define global static -#define local_persist static - -#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) -# pragma section(".rdata$", read) -# define read_only __declspec(allocate(".rdata$")) -#elif (COMPILER_CLANG && OS_LINUX) -# define read_only __attribute__((section(".rodata"))) -#else -// NOTE(rjf): I don't know of a useful way to do this in GCC land. -// __attribute__((section(".rodata"))) looked promising, but it introduces a -// strange warning about malformed section attributes, and it doesn't look -// like writing to that section reliably produces access violations, strangely -// enough. (It does on Clang) -# define read_only -#endif - -#if COMPILER_MSVC -# define thread_static __declspec(thread) -#elif COMPILER_CLANG || COMPILER_GCC -# define thread_static __thread -#endif - -#if COMPILER_MSVC -# define force_inline __forceinline -#elif COMPILER_CLANG || COMPILER_GCC -# define force_inline __attribute__((always_inline)) -#endif - -//////////////////////////////// -//~ rjf: Linkage Keyword Macros - -#if OS_WINDOWS -# define shared_function C_LINKAGE __declspec(dllexport) -#else -# define shared_function C_LINKAGE -#endif - -#if LANG_CPP -# define C_LINKAGE_BEGIN extern "C"{ -# define C_LINKAGE_END } -# define C_LINKAGE extern "C" -#else -# define C_LINKAGE_BEGIN -# define C_LINKAGE_END -# define C_LINKAGE -#endif - -//////////////////////////////// -//~ rjf: Units - -#define KB(n) (((U64)(n)) << 10) -#define MB(n) (((U64)(n)) << 20) -#define GB(n) (((U64)(n)) << 30) -#define TB(n) (((U64)(n)) << 40) -#define Thousand(n) ((n)*1000) -#define Million(n) ((n)*1000000) -#define Billion(n) ((n)*1000000000) - -//////////////////////////////// -//~ rjf: Branch Predictor Hints - -#if defined(__clang__) -# define Expect(expr, val) __builtin_expect((expr), (val)) -#else -# define Expect(expr, val) (expr) -#endif - -#define Likely(expr) Expect(expr,1) -#define Unlikely(expr) Expect(expr,0) - -//////////////////////////////// -//~ rjf: Clamps, Mins, Maxes - -#define Min(A,B) (((A)<(B))?(A):(B)) -#define Max(A,B) (((A)>(B))?(A):(B)) -#define ClampTop(A,X) Min(A,X) -#define ClampBot(X,B) Max(X,B) -#define Clamp(A,X,B) (((X)<(A))?(A):((X)>(B))?(B):(X)) - -//////////////////////////////// -//~ rjf: Type -> Alignment - -#if COMPILER_MSVC -# define AlignOf(T) __alignof(T) -#elif COMPILER_CLANG -# define AlignOf(T) __alignof(T) -#elif COMPILER_GCC -# define AlignOf(T) __alignof__(T) -#else -# error AlignOf not defined for this compiler. -#endif - -//////////////////////////////// -//~ rjf: Member Offsets - -#define Member(T,m) (((T*)0)->m) -#define OffsetOf(T,m) IntFromPtr(&Member(T,m)) -#define MemberFromOffset(T,ptr,off) (T)((((U8 *)ptr)+(off))) -#define CastFromMember(T,m,ptr) (T*)(((U8*)ptr) - OffsetOf(T,m)) - -//////////////////////////////// -//~ rjf: For-Loop Construct Macros - -#define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end)) -#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end)) - -#define EachIndex(it, count) (U64 it = 0; it < (count); it += 1) -#define EachElement(it, array) (U64 it = 0; it < ArrayCount(array); it += 1) -#define EachEnumVal(type, it) (type it = (type)0; it < type##_COUNT; it = (type)(it+1)) -#define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1)) - -//////////////////////////////// -//~ rjf: Memory Operation Macros - -#define MemoryCopy(dst, src, size) memmove((dst), (src), (size)) -#define MemorySet(dst, byte, size) memset((dst), (byte), (size)) -#define MemoryCompare(a, b, size) memcmp((a), (b), (size)) -#define MemoryStrlen(ptr) strlen(ptr) - -#define MemoryCopyStruct(d,s) MemoryCopy((d),(s),sizeof(*(d))) -#define MemoryCopyArray(d,s) MemoryCopy((d),(s),sizeof(d)) -#define MemoryCopyTyped(d,s,c) MemoryCopy((d),(s),sizeof(*(d))*(c)) - -#define MemoryZero(s,z) memset((s),0,(z)) -#define MemoryZeroStruct(s) MemoryZero((s),sizeof(*(s))) -#define MemoryZeroArray(a) MemoryZero((a),sizeof(a)) -#define MemoryZeroTyped(m,c) MemoryZero((m),sizeof(*(m))*(c)) - -#define MemoryMatch(a,b,z) (MemoryCompare((a),(b),(z)) == 0) -#define MemoryMatchStruct(a,b) MemoryMatch((a),(b),sizeof(*(a))) -#define MemoryMatchArray(a,b) MemoryMatch((a),(b),sizeof(a)) - -#define MemoryRead(T,p,e) ( ((p)+sizeof(T)<=(e))?(*(T*)(p)):(0) ) -#define MemoryConsume(T,p,e) ( ((p)+sizeof(T)<=(e))?((p)+=sizeof(T),*(T*)((p)-sizeof(T))):((p)=(e),0) ) - -//////////////////////////////// -//~ rjf: Asserts - -#if COMPILER_MSVC -# define Trap() __debugbreak() -#elif COMPILER_CLANG || COMPILER_GCC -# define Trap() __builtin_trap() -#else -# error Unknown trap intrinsic for this compiler. -#endif - -#define AssertAlways(x) do{if(!(x)) {Trap();}}while(0) -#if BUILD_DEBUG -# define Assert(x) AssertAlways(x) -#else -# define Assert(x) (void)(x) -#endif -#define InvalidPath Assert(!"Invalid Path!") -#define NotImplemented Assert(!"Not Implemented!") -#define NoOp ((void)0) -#define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1] - -//////////////////////////////// -//~ rjf: Atomic Operations - -#if COMPILER_MSVC -# include -# if ARCH_X64 -# define ins_atomic_u64_eval(x) *((volatile U64 *)(x)) -# 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) InterlockedAdd64((volatile __int64 *)(x), c) -# define ins_atomic_u64_eval_cond_assign(x,k,c) InterlockedCompareExchange64((volatile __int64 *)(x),(k),(c)) -# define ins_atomic_u32_eval(x) *((volatile U32 *)(x)) -# define ins_atomic_u32_inc_eval(x) InterlockedIncrement((volatile LONG *)x) -# 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_u32_add_eval(x,c) InterlockedAdd((volatile LONG *)(x), c) -# else -# error Atomic intrinsics not defined for this compiler / architecture combination. -# endif -#elif COMPILER_CLANG || COMPILER_GCC -# define ins_atomic_u64_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST) -# define ins_atomic_u64_inc_eval(x) (__atomic_fetch_add((volatile U64 *)(x), 1, __ATOMIC_SEQ_CST) + 1) -# define ins_atomic_u64_dec_eval(x) (__atomic_fetch_sub((volatile U64 *)(x), 1, __ATOMIC_SEQ_CST) - 1) -# define ins_atomic_u64_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST) -# define ins_atomic_u64_add_eval(x,c) (__atomic_fetch_add((volatile U64 *)(x), c, __ATOMIC_SEQ_CST) + (c)) -# define ins_atomic_u64_eval_cond_assign(x,k,c) ({ U64 _new = (c); __atomic_compare_exchange_n((volatile U64 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; }) -# define ins_atomic_u32_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST) -# define ins_atomic_u32_inc_eval(x) (__atomic_fetch_add((volatile U32 *)(x), 1, __ATOMIC_SEQ_CST) + 1) -# define ins_atomic_u32_add_eval(x,c) (__atomic_fetch_add((volatile U32 *)(x), c, __ATOMIC_SEQ_CST) + (c)) -# define ins_atomic_u32_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST) -# define ins_atomic_u32_eval_cond_assign(x,k,c) ({ U32 _new = (c); __atomic_compare_exchange_n((volatile U32 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; }) -#else -# error Atomic intrinsics not defined for this compiler / architecture. -#endif - -#if ARCH_64BIT -# define ins_atomic_ptr_eval_cond_assign(x,k,c) (void*)ins_atomic_u64_eval_cond_assign((volatile U64 *)(x), (U64)(k), (U64)(c)) -# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile U64 *)(x), (U64)(c)) -# define ins_atomic_ptr_eval(x) (void*)ins_atomic_u64_eval((volatile U64 *)x) -#elif ARCH_32BIT -# define ins_atomic_ptr_eval_cond_assign(x,k,c) (void*)ins_atomic_u32_eval_cond_assign((volatile U32 *)(x), (U32)(k), (U32)(c)) -# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u32_eval_assign((volatile U32 *)(x), (U32)(c)) -# define ins_atomic_ptr_eval(x) (void*)ins_atomic_u32_eval((volatile U32 *)x) -#else -# error Atomic intrinsics for pointers not defined for this architecture. -#endif - -//////////////////////////////// -//~ rjf: Linked List Building Macros - -//- rjf: linked list macro helpers -#define CheckNil(nil,p) ((p) == 0 || (p) == nil) -#define SetNil(nil,p) ((p) = nil) - -//- rjf: doubly-linked-lists -#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: singly-linked, doubly-headed lists (queues) -#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: singly-linked, singly-headed lists (stacks) -#define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n)) -#define SLLStackPop_N(f,next) ((f)=(f)->next) - -//- rjf: doubly-linked-list helpers -#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, doubly-headed list helpers -#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, singly-headed list helpers -#define SLLStackPush(f,n) SLLStackPush_N(f,n,next) -#define SLLStackPop(f) SLLStackPop_N(f,next) - -//////////////////////////////// -//~ rjf: Address Sanitizer Markup - -#if COMPILER_MSVC -# if defined(__SANITIZE_ADDRESS__) -# define ASAN_ENABLED 1 -# define ASAN_NO_ADDR __declspec(no_sanitize_address) -# endif -#elif COMPILER_CLANG -# if defined(__has_feature) -# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) -# define ASAN_ENABLED 1 -# endif -# endif -# define ASAN_NO_ADDR __attribute__((no_sanitize("address"))) -# define UBSAN_NO_ALIGN __attribute__((no_sanitize("alignment"))) -#endif - -#ifndef ASAN_NO_ADDR -# define ASAN_NO_ADDR -#endif -#ifndef UBSAN_NO_ALIGN -# define UBSAN_NO_ALIGN -#endif - -#if ASAN_ENABLED -C_LINKAGE void __asan_poison_memory_region(void const volatile *addr, size_t size); -C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t size); -# define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size)) -# define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size)) -#else -# define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) -# define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) -#endif - -//////////////////////////////// -//~ rjf: Misc. Helper Macros - -#define Stringify_(S) #S -#define Stringify(S) Stringify_(S) - -#define Glue_(A,B) A##B -#define Glue(A,B) Glue_(A,B) - -#define ArrayCount(a) (sizeof(a) / sizeof((a)[0])) - -#define CeilIntegerDiv(a,b) (((a) + (b) - 1)/(b)) - -#define Swap(T,a,b) do{T t__ = a; a = b; b = t__;}while(0) - -#if ARCH_64BIT -# define IntFromPtr(ptr) ((U64)(ptr)) -#elif ARCH_32BIT -# define IntFromPtr(ptr) ((U32)(ptr)) -#else -# error Missing pointer-to-integer cast for this architecture. -#endif -#define PtrFromInt(i) (void*)((U8*)0 + (i)) - -#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b)); -#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1))) -#define AlignDownPow2(x,b) ((x)&(~((b) - 1))) -#define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1)) -#define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0) -#define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0) - -#define ExtractBit(word, idx) (((word) >> (idx)) & 1) - -#if LANG_CPP -# define zero_struct {} -#else -# define zero_struct {0} -#endif - -#if COMPILER_MSVC && COMPILER_MSVC_YEAR < 2015 -# define this_function_name "unknown" -#else -# define this_function_name __func__ -#endif - -//////////////////////////////// -//~ rjf: Base Types - -typedef uint8_t U8; -typedef uint16_t U16; -typedef uint32_t U32; -typedef uint64_t U64; -typedef int8_t S8; -typedef int16_t S16; -typedef int32_t S32; -typedef int64_t S64; -typedef S8 B8; -typedef S16 B16; -typedef S32 B32; -typedef S64 B64; -typedef float F32; -typedef double F64; -typedef void VoidProc(void); -typedef struct U128 U128; -struct U128 -{ - U64 u64[2]; -}; - -//////////////////////////////// -//~ rjf: Basic Types & Spaces - -typedef enum Dimension -{ - Dimension_X, - Dimension_Y, - Dimension_Z, - Dimension_W, -} -Dimension; - -typedef enum Side -{ - Side_Invalid = -1, - Side_Min, - Side_Max, - Side_COUNT, -} -Side; -#define side_flip(s) ((Side)(!(s))) - -typedef enum Axis2 -{ - Axis2_Invalid = -1, - Axis2_X, - Axis2_Y, - Axis2_COUNT, -} -Axis2; -#define axis2_flip(a) ((Axis2)(!(a))) - -typedef enum Corner -{ - Corner_Invalid = -1, - Corner_00, - Corner_01, - Corner_10, - Corner_11, - Corner_COUNT -} -Corner; - -typedef enum Dir2 -{ - Dir2_Invalid = -1, - Dir2_Left, - Dir2_Up, - Dir2_Right, - Dir2_Down, - Dir2_COUNT -} -Dir2; -#define axis2_from_dir2(d) (((d) & 1) ? Axis2_Y : Axis2_X) -#define side_from_dir2(d) (((d) < Dir2_Right) ? Side_Min : Side_Max) - -//////////////////////////////// -//~ rjf: Toolchain/Environment Enums - -typedef enum OperatingSystem -{ - OperatingSystem_Null, - OperatingSystem_Windows, - OperatingSystem_Linux, - OperatingSystem_Mac, - OperatingSystem_COUNT, -} -OperatingSystem; - -typedef enum ImageType -{ - Image_Null, - Image_CoffPe, - Image_Elf32, - Image_Elf64, - Image_Macho -} ImageType; - -typedef enum Arch -{ - Arch_Null, - Arch_x64, - Arch_x86, - Arch_arm64, - Arch_arm32, - Arch_COUNT, -} -Arch; - -typedef enum Compiler -{ - Compiler_Null, - Compiler_msvc, - Compiler_gcc, - Compiler_clang, - Compiler_COUNT, -} -Compiler; - -//////////////////////////////// -//~ rjf: Text 2D Coordinates & Ranges - -typedef struct TxtPt TxtPt; -struct TxtPt -{ - S64 line; - S64 column; -}; - -typedef struct TxtRng TxtRng; -struct TxtRng -{ - TxtPt min; - TxtPt max; -}; - -//////////////////////////////// -//~ Globally Unique Ids - -typedef union Guid Guid; -union Guid -{ - struct - { - U32 data1; - U16 data2; - U16 data3; - U8 data4[8]; - }; - U8 v[16]; -}; -StaticAssert(sizeof(Guid) == 16, g_guid_size_check); - -//////////////////////////////// -//~ Arrays - -typedef struct U16Array U16Array; -struct U16Array -{ - U64 count; - U16 *v; -}; -typedef struct U32Array U32Array; -struct U32Array -{ - U64 count; - U32 *v; -}; -typedef struct U64Array U64Array; -struct U64Array -{ - U64 count; - U64 *v; -}; -typedef struct U128Array U128Array; -struct U128Array -{ - U64 count; - U128 *v; -}; - -//////////////////////////////// -//~ NOTE(allen): Constants - -global U32 sign32 = 0x80000000; -global U32 exponent32 = 0x7F800000; -global U32 mantissa32 = 0x007FFFFF; - -global F32 big_golden32 = 1.61803398875f; -global F32 small_golden32 = 0.61803398875f; - -global F32 pi32 = 3.1415926535897f; - -global F64 machine_epsilon64 = 4.94065645841247e-324; - -global U64 max_U64 = 0xffffffffffffffffull; -global U32 max_U32 = 0xffffffff; -global U16 max_U16 = 0xffff; -global U8 max_U8 = 0xff; - -global S64 max_S64 = (S64)0x7fffffffffffffffull; -global S32 max_S32 = (S32)0x7fffffff; -global S16 max_S16 = (S16)0x7fff; -global S8 max_S8 = (S8)0x7f; - -global S64 min_S64 = (S64)0xffffffffffffffffull; -global S32 min_S32 = (S32)0xffffffff; -global S16 min_S16 = (S16)0xffff; -global S8 min_S8 = (S8)0xff; - -global const U32 bitmask1 = 0x00000001; -global const U32 bitmask2 = 0x00000003; -global const U32 bitmask3 = 0x00000007; -global const U32 bitmask4 = 0x0000000f; -global const U32 bitmask5 = 0x0000001f; -global const U32 bitmask6 = 0x0000003f; -global const U32 bitmask7 = 0x0000007f; -global const U32 bitmask8 = 0x000000ff; -global const U32 bitmask9 = 0x000001ff; -global const U32 bitmask10 = 0x000003ff; -global const U32 bitmask11 = 0x000007ff; -global const U32 bitmask12 = 0x00000fff; -global const U32 bitmask13 = 0x00001fff; -global const U32 bitmask14 = 0x00003fff; -global const U32 bitmask15 = 0x00007fff; -global const U32 bitmask16 = 0x0000ffff; -global const U32 bitmask17 = 0x0001ffff; -global const U32 bitmask18 = 0x0003ffff; -global const U32 bitmask19 = 0x0007ffff; -global const U32 bitmask20 = 0x000fffff; -global const U32 bitmask21 = 0x001fffff; -global const U32 bitmask22 = 0x003fffff; -global const U32 bitmask23 = 0x007fffff; -global const U32 bitmask24 = 0x00ffffff; -global const U32 bitmask25 = 0x01ffffff; -global const U32 bitmask26 = 0x03ffffff; -global const U32 bitmask27 = 0x07ffffff; -global const U32 bitmask28 = 0x0fffffff; -global const U32 bitmask29 = 0x1fffffff; -global const U32 bitmask30 = 0x3fffffff; -global const U32 bitmask31 = 0x7fffffff; -global const U32 bitmask32 = 0xffffffff; - -global const U64 bitmask33 = 0x00000001ffffffffull; -global const U64 bitmask34 = 0x00000003ffffffffull; -global const U64 bitmask35 = 0x00000007ffffffffull; -global const U64 bitmask36 = 0x0000000fffffffffull; -global const U64 bitmask37 = 0x0000001fffffffffull; -global const U64 bitmask38 = 0x0000003fffffffffull; -global const U64 bitmask39 = 0x0000007fffffffffull; -global const U64 bitmask40 = 0x000000ffffffffffull; -global const U64 bitmask41 = 0x000001ffffffffffull; -global const U64 bitmask42 = 0x000003ffffffffffull; -global const U64 bitmask43 = 0x000007ffffffffffull; -global const U64 bitmask44 = 0x00000fffffffffffull; -global const U64 bitmask45 = 0x00001fffffffffffull; -global const U64 bitmask46 = 0x00003fffffffffffull; -global const U64 bitmask47 = 0x00007fffffffffffull; -global const U64 bitmask48 = 0x0000ffffffffffffull; -global const U64 bitmask49 = 0x0001ffffffffffffull; -global const U64 bitmask50 = 0x0003ffffffffffffull; -global const U64 bitmask51 = 0x0007ffffffffffffull; -global const U64 bitmask52 = 0x000fffffffffffffull; -global const U64 bitmask53 = 0x001fffffffffffffull; -global const U64 bitmask54 = 0x003fffffffffffffull; -global const U64 bitmask55 = 0x007fffffffffffffull; -global const U64 bitmask56 = 0x00ffffffffffffffull; -global const U64 bitmask57 = 0x01ffffffffffffffull; -global const U64 bitmask58 = 0x03ffffffffffffffull; -global const U64 bitmask59 = 0x07ffffffffffffffull; -global const U64 bitmask60 = 0x0fffffffffffffffull; -global const U64 bitmask61 = 0x1fffffffffffffffull; -global const U64 bitmask62 = 0x3fffffffffffffffull; -global const U64 bitmask63 = 0x7fffffffffffffffull; -global const U64 bitmask64 = 0xffffffffffffffffull; - -global const U32 bit1 = (1<<0); -global const U32 bit2 = (1<<1); -global const U32 bit3 = (1<<2); -global const U32 bit4 = (1<<3); -global const U32 bit5 = (1<<4); -global const U32 bit6 = (1<<5); -global const U32 bit7 = (1<<6); -global const U32 bit8 = (1<<7); -global const U32 bit9 = (1<<8); -global const U32 bit10 = (1<<9); -global const U32 bit11 = (1<<10); -global const U32 bit12 = (1<<11); -global const U32 bit13 = (1<<12); -global const U32 bit14 = (1<<13); -global const U32 bit15 = (1<<14); -global const U32 bit16 = (1<<15); -global const U32 bit17 = (1<<16); -global const U32 bit18 = (1<<17); -global const U32 bit19 = (1<<18); -global const U32 bit20 = (1<<19); -global const U32 bit21 = (1<<20); -global const U32 bit22 = (1<<21); -global const U32 bit23 = (1<<22); -global const U32 bit24 = (1<<23); -global const U32 bit25 = (1<<24); -global const U32 bit26 = (1<<25); -global const U32 bit27 = (1<<26); -global const U32 bit28 = (1<<27); -global const U32 bit29 = (1<<28); -global const U32 bit30 = (1<<29); -global const U32 bit31 = (1<<30); -global const U32 bit32 = (1<<31); - -global const U64 bit33 = (1ull<<32); -global const U64 bit34 = (1ull<<33); -global const U64 bit35 = (1ull<<34); -global const U64 bit36 = (1ull<<35); -global const U64 bit37 = (1ull<<36); -global const U64 bit38 = (1ull<<37); -global const U64 bit39 = (1ull<<38); -global const U64 bit40 = (1ull<<39); -global const U64 bit41 = (1ull<<40); -global const U64 bit42 = (1ull<<41); -global const U64 bit43 = (1ull<<42); -global const U64 bit44 = (1ull<<43); -global const U64 bit45 = (1ull<<44); -global const U64 bit46 = (1ull<<45); -global const U64 bit47 = (1ull<<46); -global const U64 bit48 = (1ull<<47); -global const U64 bit49 = (1ull<<48); -global const U64 bit50 = (1ull<<49); -global const U64 bit51 = (1ull<<50); -global const U64 bit52 = (1ull<<51); -global const U64 bit53 = (1ull<<52); -global const U64 bit54 = (1ull<<53); -global const U64 bit55 = (1ull<<54); -global const U64 bit56 = (1ull<<55); -global const U64 bit57 = (1ull<<56); -global const U64 bit58 = (1ull<<57); -global const U64 bit59 = (1ull<<58); -global const U64 bit60 = (1ull<<59); -global const U64 bit61 = (1ull<<60); -global const U64 bit62 = (1ull<<61); -global const U64 bit63 = (1ull<<62); -global const U64 bit64 = (1ull<<63); - -//////////////////////////////// -//~ allen: Time - -typedef enum WeekDay -{ - WeekDay_Sun, - WeekDay_Mon, - WeekDay_Tue, - WeekDay_Wed, - WeekDay_Thu, - WeekDay_Fri, - WeekDay_Sat, - WeekDay_COUNT, -} -WeekDay; - -typedef enum Month -{ - Month_Jan, - Month_Feb, - Month_Mar, - Month_Apr, - Month_May, - Month_Jun, - Month_Jul, - Month_Aug, - Month_Sep, - Month_Oct, - Month_Nov, - Month_Dec, - Month_COUNT, -} -Month; - -typedef struct DateTime DateTime; -struct DateTime -{ - U16 micro_sec; // [0,999] - U16 msec; // [0,999] - U16 sec; // [0,60] - U16 min; // [0,59] - U16 hour; // [0,24] - U16 day; // [0,30] - union - { - WeekDay week_day; - U32 wday; - }; - union - { - Month month; - U32 mon; - }; - U32 year; // 1 = 1 CE, 0 = 1 BC -}; - -typedef U64 DenseTime; - -//////////////////////////////// -//~ allen: Files - -typedef U32 FilePropertyFlags; -enum -{ - FilePropertyFlag_IsFolder = (1 << 0), -}; - -typedef struct FileProperties FileProperties; -struct FileProperties -{ - U64 size; - DenseTime modified; - DenseTime created; - FilePropertyFlags flags; -}; - -//////////////////////////////// -//~ rjf: Safe Casts - -internal U16 safe_cast_u16(U32 x); -internal U32 safe_cast_u32(U64 x); -internal S32 safe_cast_s32(S64 x); - -//////////////////////////////// -//~ rjf: Large Base Type Functions - -internal U128 u128_zero(void); -internal U128 u128_make(U64 v0, U64 v1); -internal B32 u128_match(U128 a, U128 b); - -//////////////////////////////// -//~ rjf: Bit Patterns - -internal U32 u32_from_u64_saturate(U64 x); -internal U64 u64_up_to_pow2(U64 x); -internal S32 extend_sign32(U32 x, U32 size); -internal S64 extend_sign64(U64 x, U64 size); - -internal F32 inf32(void); -internal F32 neg_inf32(void); - -internal U16 bswap_u16(U16 x); -internal U32 bswap_u32(U32 x); -internal U64 bswap_u64(U64 x); - -#if ARCH_LITTLE_ENDIAN -# define from_be_u16(x) bswap_u16(x) -# define from_be_u32(x) bswap_u32(x) -# define from_be_u64(x) bswap_u64(x) -#else -# define from_be_u16(x) (x) -# define from_be_u32(x) (x) -# define from_be_u64(x) (x) -#endif - -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); - -//////////////////////////////// -//~ rjf: Enum -> Sign - -internal S32 sign_from_side_S32(Side side); -internal F32 sign_from_side_F32(Side side); - -//////////////////////////////// -//~ rjf: Memory Functions - -internal B32 memory_is_zero(void *ptr, U64 size); - -internal void memory_write16(void *ptr, U16 v); -internal void memory_write32(void *ptr, U32 v); - -internal U8 memory_read8(void *ptr); -internal U16 memory_read16(void *ptr); -internal U32 memory_read32(void *ptr); -internal U64 memory_read64(void *ptr); - -//////////////////////////////// -//~ rjf: Text 2D Coordinate/Range Functions - -internal TxtPt txt_pt(S64 line, S64 column); -internal B32 txt_pt_match(TxtPt a, TxtPt b); -internal B32 txt_pt_less_than(TxtPt a, TxtPt b); -internal TxtPt txt_pt_min(TxtPt a, TxtPt b); -internal TxtPt txt_pt_max(TxtPt a, TxtPt b); -internal TxtRng txt_rng(TxtPt min, TxtPt max); -internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b); -internal TxtRng txt_rng_union(TxtRng a, TxtRng b); -internal B32 txt_rng_contains(TxtRng r, TxtPt pt); - -//////////////////////////////// -//~ rjf: Toolchain/Environment Enum Functions - -internal U64 bit_size_from_arch(Arch arch); -internal U64 max_instruction_size_from_arch(Arch arch); - -internal OperatingSystem operating_system_from_context(void); -internal Arch arch_from_context(void); -internal Compiler compiler_from_context(void); - -//////////////////////////////// -//~ rjf: Time Functions - -internal DenseTime dense_time_from_date_time(DateTime date_time); -internal DateTime date_time_from_dense_time(DenseTime time); -internal DateTime date_time_from_micro_seconds(U64 time); -internal DateTime date_time_from_unix_time(U64 unix_time); - -//////////////////////////////// -//~ rjf: Non-Fancy Ring Buffer Reads/Writes - -internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size); -internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size); -#define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr))) -#define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr))) - -//////////////////////////////// -//~ rjf: Sorts - -#define quick_sort(ptr, count, element_size, cmp_function) qsort((ptr), (count), (element_size), (int (*)(const void *, const void *))(cmp_function)) - -#endif // BASE_CORE_H diff --git a/src/metagen/metagen_base/metagen_base_entry_point.c b/src/metagen/metagen_base/metagen_base_entry_point.c deleted file mode 100644 index 21bbc363..00000000 --- a/src/metagen/metagen_base/metagen_base_entry_point.c +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -global U64 global_update_tick_idx = 0; - -internal void -main_thread_base_entry_point(int arguments_count, char **arguments) -{ - Temp scratch = scratch_begin(0, 0); - ThreadNameF("[main thread]"); - - //- rjf: set up telemetry -#if PROFILE_TELEMETRY - local_persist char tm_data[MB(64)]; - tmLoadLibrary(TM_RELEASE); - tmSetMaxThreadCount(256); - tmInitialize(sizeof(tm_data), tm_data); -#endif - - //- rjf: parse command line - String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, arguments_count, arguments); - CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings); - - //- rjf: begin captures - B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture")); - if(capture) - { - ProfBeginCapture(arguments[0]); - } - -#if PROFILE_TELEMETRY - tmMessage(0, TMMF_ICON_NOTE, BUILD_TITLE); -#endif - - //- rjf: initialize all included layers -#if defined(ASYNC_H) && !defined(ASYNC_INIT_MANUAL) - async_init(&cmdline); -#endif -#if defined(RDI_FROM_PDB_H) && !defined(P2R_INIT_MANUAL) - p2r_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(DBGI_H) && !defined(DI_INIT_MANUAL) - di_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_GFX_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(FNT_INIT_MANUAL) - fnt_init(); -#endif -#if defined(DBG_ENGINE_CORE_H) && !defined(D_INIT_MANUAL) - d_init(); -#endif -#if defined(RADDBG_CORE_H) && !defined(RD_INIT_MANUAL) - rd_init(&cmdline); -#endif - - //- rjf: call into entry point - entry_point(&cmdline); - - //- rjf: end captures - 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(); -} - -internal U64 -update_tick_idx(void) -{ - U64 result = ins_atomic_u64_eval(&global_update_tick_idx); - return result; -} - -internal B32 -update(void) -{ - ProfTick(0); - ins_atomic_u64_inc_eval(&global_update_tick_idx); -#if OS_FEATURE_GRAPHICAL - B32 result = frame(); -#else - B32 result = 0; -#endif - return result; -} diff --git a/src/metagen/metagen_base/metagen_base_entry_point.h b/src/metagen/metagen_base/metagen_base_entry_point.h deleted file mode 100644 index 318f8d9f..00000000 --- a/src/metagen/metagen_base/metagen_base_entry_point.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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(int argc, char **argv); -internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params); -internal U64 update_tick_idx(void); -internal B32 update(void); - -#endif // BASE_ENTRY_POINT_H diff --git a/src/metagen/metagen_base/metagen_base_inc.c b/src/metagen/metagen_base/metagen_base_inc.c deleted file mode 100644 index 57aa2113..00000000 --- a/src/metagen/metagen_base/metagen_base_inc.c +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Base Includes - -#undef MARKUP_LAYER_COLOR -#define MARKUP_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_meta.c" -#include "metagen_base_log.c" -#include "metagen_base_entry_point.c" diff --git a/src/metagen/metagen_base/metagen_base_inc.h b/src/metagen/metagen_base/metagen_base_inc.h deleted file mode 100644 index 55e2ebe7..00000000 --- a/src/metagen/metagen_base/metagen_base_inc.h +++ /dev/null @@ -1,24 +0,0 @@ -// 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_meta.h" -#include "metagen_base_log.h" -#include "metagen_base_entry_point.h" - -#endif // BASE_INC_H diff --git a/src/metagen/metagen_base/metagen_base_log.c b/src/metagen/metagen_base/metagen_base_log.c deleted file mode 100644 index 1c2a05f8..00000000 --- a/src/metagen/metagen_base/metagen_base_log.c +++ /dev/null @@ -1,103 +0,0 @@ -// 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; -} diff --git a/src/metagen/metagen_base/metagen_base_log.h b/src/metagen/metagen_base/metagen_base_log.h deleted file mode 100644 index 3687390e..00000000 --- a/src/metagen/metagen_base/metagen_base_log.h +++ /dev/null @@ -1,65 +0,0 @@ -// 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 diff --git a/src/metagen/metagen_base/metagen_base_markup.c b/src/metagen/metagen_base/metagen_base_markup.c deleted file mode 100644 index 5ad47ef5..00000000 --- a/src/metagen/metagen_base/metagen_base_markup.c +++ /dev/null @@ -1,21 +0,0 @@ -// 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); -} diff --git a/src/metagen/metagen_base/metagen_base_markup.h b/src/metagen/metagen_base/metagen_base_markup.h deleted file mode 100644 index fd291375..00000000 --- a/src/metagen/metagen_base/metagen_base_markup.h +++ /dev/null @@ -1,12 +0,0 @@ -// 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 diff --git a/src/metagen/metagen_base/metagen_base_math.c b/src/metagen/metagen_base/metagen_base_math.c deleted file mode 100644 index 2c6201f3..00000000 --- a/src/metagen/metagen_base/metagen_base_math.c +++ /dev/null @@ -1,659 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Scalar Ops - -internal F32 -mix_1f32(F32 a, F32 b, F32 t) -{ - F32 c = (a + (b-a) * Clamp(0.f, t, 1.f)); - return c; -} - -internal F64 -mix_1f64(F64 a, F64 b, F64 t) -{ - F64 c = (a + (b-a) * Clamp(0.0, t, 1.0)); - return c; -} - -//////////////////////////////// -//~ rjf: Vector Ops - -internal Vec2F32 vec_2f32(F32 x, F32 y) {Vec2F32 v = {x, y}; return v;} -internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x+b.x, a.y+b.y}; return c;} -internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x-b.x, a.y-b.y}; return c;} -internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x*b.x, a.y*b.y}; return c;} -internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x/b.x, a.y/b.y}; return c;} -internal Vec2F32 scale_2f32(Vec2F32 v, F32 s) {Vec2F32 c = {v.x*s, v.y*s}; return c;} -internal F32 dot_2f32(Vec2F32 a, Vec2F32 b) {F32 c = a.x*b.x + a.y*b.y; return c;} -internal F32 length_squared_2f32(Vec2F32 v) {F32 c = v.x*v.x + v.y*v.y; return c;} -internal F32 length_2f32(Vec2F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y); return c;} -internal Vec2F32 normalize_2f32(Vec2F32 v) {v = scale_2f32(v, 1.f/length_2f32(v)); return v;} -internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t) {Vec2F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t)}; return c;} - -internal Vec2S64 vec_2s64(S64 x, S64 y) {Vec2S64 v = {x, y}; return v;} -internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x+b.x, a.y+b.y}; return c;} -internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x-b.x, a.y-b.y}; return c;} -internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x*b.x, a.y*b.y}; return c;} -internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x/b.x, a.y/b.y}; return c;} -internal Vec2S64 scale_2s64(Vec2S64 v, S64 s) {Vec2S64 c = {v.x*s, v.y*s}; return c;} -internal S64 dot_2s64(Vec2S64 a, Vec2S64 b) {S64 c = a.x*b.x + a.y*b.y; return c;} -internal S64 length_squared_2s64(Vec2S64 v) {S64 c = v.x*v.x + v.y*v.y; return c;} -internal S64 length_2s64(Vec2S64 v) {S64 c = (S64)sqrt_f64((F64)(v.x*v.x + v.y*v.y)); return c;} -internal Vec2S64 normalize_2s64(Vec2S64 v) {v = scale_2s64(v, (S64)(1.f/length_2s64(v))); return v;} -internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t) {Vec2S64 c = {(S64)mix_1f32((F32)a.x, (F32)b.x, t), (S64)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} - -internal Vec2S32 vec_2s32(S32 x, S32 y) {Vec2S32 v = {x, y}; return v;} -internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x+b.x, a.y+b.y}; return c;} -internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x-b.x, a.y-b.y}; return c;} -internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x*b.x, a.y*b.y}; return c;} -internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x/b.x, a.y/b.y}; return c;} -internal Vec2S32 scale_2s32(Vec2S32 v, S32 s) {Vec2S32 c = {v.x*s, v.y*s}; return c;} -internal S32 dot_2s32(Vec2S32 a, Vec2S32 b) {S32 c = a.x*b.x + a.y*b.y; return c;} -internal S32 length_squared_2s32(Vec2S32 v) {S32 c = v.x*v.x + v.y*v.y; return c;} -internal S32 length_2s32(Vec2S32 v) {S32 c = (S32)sqrt_f32((F32)v.x*(F32)v.x + (F32)v.y*(F32)v.y); return c;} -internal Vec2S32 normalize_2s32(Vec2S32 v) {v = scale_2s32(v, (S32)(1.f/length_2s32(v))); return v;} -internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t) {Vec2S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} - -internal Vec2S16 vec_2s16(S16 x, S16 y) {Vec2S16 v = {x, y}; return v;} -internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x+b.x), (S16)(a.y+b.y)}; return c;} -internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x-b.x), (S16)(a.y-b.y)}; return c;} -internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x*b.x), (S16)(a.y*b.y)}; return c;} -internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x/b.x), (S16)(a.y/b.y)}; return c;} -internal Vec2S16 scale_2s16(Vec2S16 v, S16 s) {Vec2S16 c = {(S16)(v.x*s), (S16)(v.y*s)}; return c;} -internal S16 dot_2s16(Vec2S16 a, Vec2S16 b) {S16 c = a.x*b.x + a.y*b.y; return c;} -internal S16 length_squared_2s16(Vec2S16 v) {S16 c = v.x*v.x + v.y*v.y; return c;} -internal S16 length_2s16(Vec2S16 v) {S16 c = (S16)sqrt_f32((F32)(v.x*v.x + v.y*v.y)); return c;} -internal Vec2S16 normalize_2s16(Vec2S16 v) {v = scale_2s16(v, (S16)(1.f/length_2s16(v))); return v;} -internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t) {Vec2S16 c = {(S16)mix_1f32((F32)a.x, (F32)b.x, t), (S16)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} - -internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z) {Vec3F32 v = {x, y, z}; return v;} -internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;} -internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;} -internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;} -internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;} -internal Vec3F32 scale_3f32(Vec3F32 v, F32 s) {Vec3F32 c = {v.x*s, v.y*s, v.z*s}; return c;} -internal F32 dot_3f32(Vec3F32 a, Vec3F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;} -internal F32 length_squared_3f32(Vec3F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;} -internal F32 length_3f32(Vec3F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z); return c;} -internal Vec3F32 normalize_3f32(Vec3F32 v) {v = scale_3f32(v, 1.f/length_3f32(v)); return v;} -internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t) {Vec3F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t)}; return c;} -internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;} - -internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z) {Vec3S32 v = {x, y, z}; return v;} -internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;} -internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;} -internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;} -internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;} -internal Vec3S32 scale_3s32(Vec3S32 v, S32 s) {Vec3S32 c = {v.x*s, v.y*s, v.z*s}; return c;} -internal S32 dot_3s32(Vec3S32 a, Vec3S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;} -internal S32 length_squared_3s32(Vec3S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;} -internal S32 length_3s32(Vec3S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z)); return c;} -internal Vec3S32 normalize_3s32(Vec3S32 v) {v = scale_3s32(v, (S32)(1.f/length_3s32(v))); return v;} -internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t) {Vec3S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t)}; return c;} -internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;} - -internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w) {Vec4F32 v = {x, y, z, w}; return v;} -internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;} -internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;} -internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;} -internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;} -internal Vec4F32 scale_4f32(Vec4F32 v, F32 s) {Vec4F32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;} -internal F32 dot_4f32(Vec4F32 a, Vec4F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;} -internal F32 length_squared_4f32(Vec4F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;} -internal F32 length_4f32(Vec4F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w); return c;} -internal Vec4F32 normalize_4f32(Vec4F32 v) {v = scale_4f32(v, 1.f/length_4f32(v)); return v;} -internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t) {Vec4F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t), mix_1f32(a.w, b.w, t)}; return c;} - -internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w) {Vec4S32 v = {x, y, z, w}; return v;} -internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;} -internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;} -internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;} -internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;} -internal Vec4S32 scale_4s32(Vec4S32 v, S32 s) {Vec4S32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;} -internal S32 dot_4s32(Vec4S32 a, Vec4S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;} -internal S32 length_squared_4s32(Vec4S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;} -internal S32 length_4s32(Vec4S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w)); return c;} -internal Vec4S32 normalize_4s32(Vec4S32 v) {v = scale_4s32(v, (S32)(1.f/length_4s32(v))); return v;} -internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t) {Vec4S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t), (S32)mix_1f32((F32)a.w, (F32)b.w, t)}; return c;} - -//////////////////////////////// -//~ rjf: Matrix Ops - -internal Mat3x3F32 -mat_3x3f32(F32 diagonal) -{ - Mat3x3F32 result = {0}; - result.v[0][0] = diagonal; - result.v[1][1] = diagonal; - result.v[2][2] = diagonal; - return result; -} - -internal Mat3x3F32 -make_translate_3x3f32(Vec2F32 delta) -{ - Mat3x3F32 mat = mat_3x3f32(1.f); - mat.v[2][0] = delta.x; - mat.v[2][1] = delta.y; - return mat; -} - -internal Mat3x3F32 -make_scale_3x3f32(Vec2F32 scale) -{ - Mat3x3F32 mat = mat_3x3f32(1.f); - mat.v[0][0] = scale.x; - mat.v[1][1] = scale.y; - return mat; -} - -internal Mat3x3F32 -mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b) -{ - Mat3x3F32 c = {0}; - for(int j = 0; j < 3; j += 1) - { - for(int i = 0; i < 3; i += 1) - { - c.v[i][j] = (a.v[0][j]*b.v[i][0] + - a.v[1][j]*b.v[i][1] + - a.v[2][j]*b.v[i][2]); - } - } - return c; -} - -internal Mat4x4F32 -mat_4x4f32(F32 diagonal) -{ - Mat4x4F32 result = {0}; - result.v[0][0] = diagonal; - result.v[1][1] = diagonal; - result.v[2][2] = diagonal; - result.v[3][3] = diagonal; - return result; -} - -internal Mat4x4F32 -make_translate_4x4f32(Vec3F32 delta) -{ - Mat4x4F32 result = mat_4x4f32(1.f); - result.v[3][0] = delta.x; - result.v[3][1] = delta.y; - result.v[3][2] = delta.z; - return result; -} - -internal Mat4x4F32 -make_scale_4x4f32(Vec3F32 scale) -{ - Mat4x4F32 result = mat_4x4f32(1.f); - result.v[0][0] = scale.x; - result.v[1][1] = scale.y; - result.v[2][2] = scale.z; - return result; -} - -internal Mat4x4F32 -make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z) -{ - Mat4x4F32 result = mat_4x4f32(1.f); - F32 tan_theta_over_2 = tan_f32(fov / 2); - result.v[0][0] = 1.f / tan_theta_over_2; - result.v[1][1] = aspect_ratio / tan_theta_over_2; - result.v[2][3] = 1.f; - result.v[2][2] = -(near_z + far_z) / (near_z - far_z); - result.v[3][2] = (2.f * near_z * far_z) / (near_z - far_z); - result.v[3][3] = 0.f; - return result; -} - -internal Mat4x4F32 -make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z) -{ - Mat4x4F32 result = mat_4x4f32(1.f); - - result.v[0][0] = 2.f / (right - left); - result.v[1][1] = 2.f / (top - bottom); - result.v[2][2] = 2.f / (far_z - near_z); - result.v[3][3] = 1.f; - - result.v[3][0] = (left + right) / (left - right); - result.v[3][1] = (bottom + top) / (bottom - top); - result.v[3][2] = (near_z + far_z) / (near_z - far_z); - - return result; -} - -internal Mat4x4F32 -make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up) -{ - Mat4x4F32 result; - Vec3F32 f = normalize_3f32(sub_3f32(eye, center)); - Vec3F32 s = normalize_3f32(cross_3f32(f, up)); - Vec3F32 u = cross_3f32(s, f); - result.v[0][0] = s.x; - result.v[0][1] = u.x; - result.v[0][2] = -f.x; - result.v[0][3] = 0.0f; - result.v[1][0] = s.y; - result.v[1][1] = u.y; - result.v[1][2] = -f.y; - result.v[1][3] = 0.0f; - result.v[2][0] = s.z; - result.v[2][1] = u.z; - result.v[2][2] = -f.z; - result.v[2][3] = 0.0f; - result.v[3][0] = -dot_3f32(s, eye); - result.v[3][1] = -dot_3f32(u, eye); - result.v[3][2] = dot_3f32(f, eye); - result.v[3][3] = 1.0f; - return result; -} - -internal Mat4x4F32 -make_rotate_4x4f32(Vec3F32 axis, F32 turns) -{ - Mat4x4F32 result = mat_4x4f32(1.f); - axis = normalize_3f32(axis); - F32 sin_theta = sin_f32(turns); - F32 cos_theta = cos_f32(turns); - F32 cos_value = 1.f - cos_theta; - result.v[0][0] = (axis.x * axis.x * cos_value) + cos_theta; - result.v[0][1] = (axis.x * axis.y * cos_value) + (axis.z * sin_theta); - result.v[0][2] = (axis.x * axis.z * cos_value) - (axis.y * sin_theta); - result.v[1][0] = (axis.y * axis.x * cos_value) - (axis.z * sin_theta); - result.v[1][1] = (axis.y * axis.y * cos_value) + cos_theta; - result.v[1][2] = (axis.y * axis.z * cos_value) + (axis.x * sin_theta); - result.v[2][0] = (axis.z * axis.x * cos_value) + (axis.y * sin_theta); - result.v[2][1] = (axis.z * axis.y * cos_value) - (axis.x * sin_theta); - result.v[2][2] = (axis.z * axis.z * cos_value) + cos_theta; - return result; -} - -internal Mat4x4F32 -mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b) -{ - Mat4x4F32 c = {0}; - for(int j = 0; j < 4; j += 1) - { - for(int i = 0; i < 4; i += 1) - { - c.v[i][j] = (a.v[0][j]*b.v[i][0] + - a.v[1][j]*b.v[i][1] + - a.v[2][j]*b.v[i][2] + - a.v[3][j]*b.v[i][3]); - } - } - return c; -} - -internal Mat4x4F32 -scale_4x4f32(Mat4x4F32 m, F32 scale) -{ - for(int j = 0; j < 4; j += 1) - { - for(int i = 0; i < 4; i += 1) - { - m.v[i][j] *= scale; - } - } - return m; -} - -internal Mat4x4F32 -inverse_4x4f32(Mat4x4F32 m) -{ - F32 coef00 = m.v[2][2] * m.v[3][3] - m.v[3][2] * m.v[2][3]; - F32 coef02 = m.v[1][2] * m.v[3][3] - m.v[3][2] * m.v[1][3]; - F32 coef03 = m.v[1][2] * m.v[2][3] - m.v[2][2] * m.v[1][3]; - F32 coef04 = m.v[2][1] * m.v[3][3] - m.v[3][1] * m.v[2][3]; - F32 coef06 = m.v[1][1] * m.v[3][3] - m.v[3][1] * m.v[1][3]; - F32 coef07 = m.v[1][1] * m.v[2][3] - m.v[2][1] * m.v[1][3]; - F32 coef08 = m.v[2][1] * m.v[3][2] - m.v[3][1] * m.v[2][2]; - F32 coef10 = m.v[1][1] * m.v[3][2] - m.v[3][1] * m.v[1][2]; - F32 coef11 = m.v[1][1] * m.v[2][2] - m.v[2][1] * m.v[1][2]; - F32 coef12 = m.v[2][0] * m.v[3][3] - m.v[3][0] * m.v[2][3]; - F32 coef14 = m.v[1][0] * m.v[3][3] - m.v[3][0] * m.v[1][3]; - F32 coef15 = m.v[1][0] * m.v[2][3] - m.v[2][0] * m.v[1][3]; - F32 coef16 = m.v[2][0] * m.v[3][2] - m.v[3][0] * m.v[2][2]; - F32 coef18 = m.v[1][0] * m.v[3][2] - m.v[3][0] * m.v[1][2]; - F32 coef19 = m.v[1][0] * m.v[2][2] - m.v[2][0] * m.v[1][2]; - F32 coef20 = m.v[2][0] * m.v[3][1] - m.v[3][0] * m.v[2][1]; - F32 coef22 = m.v[1][0] * m.v[3][1] - m.v[3][0] * m.v[1][1]; - F32 coef23 = m.v[1][0] * m.v[2][1] - m.v[2][0] * m.v[1][1]; - - Vec4F32 fac0 = { coef00, coef00, coef02, coef03 }; - Vec4F32 fac1 = { coef04, coef04, coef06, coef07 }; - Vec4F32 fac2 = { coef08, coef08, coef10, coef11 }; - Vec4F32 fac3 = { coef12, coef12, coef14, coef15 }; - Vec4F32 fac4 = { coef16, coef16, coef18, coef19 }; - Vec4F32 fac5 = { coef20, coef20, coef22, coef23 }; - - Vec4F32 vec0 = { m.v[1][0], m.v[0][0], m.v[0][0], m.v[0][0] }; - Vec4F32 vec1 = { m.v[1][1], m.v[0][1], m.v[0][1], m.v[0][1] }; - Vec4F32 vec2 = { m.v[1][2], m.v[0][2], m.v[0][2], m.v[0][2] }; - Vec4F32 vec3 = { m.v[1][3], m.v[0][3], m.v[0][3], m.v[0][3] }; - - Vec4F32 inv0 = add_4f32(sub_4f32(mul_4f32(vec1, fac0), mul_4f32(vec2, fac1)), mul_4f32(vec3, fac2)); - Vec4F32 inv1 = add_4f32(sub_4f32(mul_4f32(vec0, fac0), mul_4f32(vec2, fac3)), mul_4f32(vec3, fac4)); - Vec4F32 inv2 = add_4f32(sub_4f32(mul_4f32(vec0, fac1), mul_4f32(vec1, fac3)), mul_4f32(vec3, fac5)); - Vec4F32 inv3 = add_4f32(sub_4f32(mul_4f32(vec0, fac2), mul_4f32(vec1, fac4)), mul_4f32(vec2, fac5)); - - Vec4F32 sign_a = { +1, -1, +1, -1 }; - Vec4F32 sign_b = { -1, +1, -1, +1 }; - - Mat4x4F32 inverse; - for(U32 i = 0; i < 4; i += 1) - { - inverse.v[0][i] = inv0.v[i] * sign_a.v[i]; - inverse.v[1][i] = inv1.v[i] * sign_b.v[i]; - inverse.v[2][i] = inv2.v[i] * sign_a.v[i]; - inverse.v[3][i] = inv3.v[i] * sign_b.v[i]; - } - - Vec4F32 row0 = { inverse.v[0][0], inverse.v[1][0], inverse.v[2][0], inverse.v[3][0] }; - Vec4F32 m0 = { m.v[0][0], m.v[0][1], m.v[0][2], m.v[0][3] }; - Vec4F32 dot0 = mul_4f32(m0, row0); - F32 dot1 = (dot0.x + dot0.y) + (dot0.z + dot0.w); - - F32 one_over_det = 1 / dot1; - - return scale_4x4f32(inverse, one_over_det); -} - -internal Mat4x4F32 -derotate_4x4f32(Mat4x4F32 mat) -{ - Vec3F32 scale = - { - length_3f32(v3f32(mat.v[0][0], mat.v[0][1], mat.v[0][2])), - length_3f32(v3f32(mat.v[1][0], mat.v[1][1], mat.v[1][2])), - length_3f32(v3f32(mat.v[2][0], mat.v[2][1], mat.v[2][2])), - }; - mat.v[0][0] = scale.x; - mat.v[1][0] = 0.f; - mat.v[2][0] = 0.f; - mat.v[0][1] = 0.f; - mat.v[1][1] = scale.y; - mat.v[2][1] = 0.f; - mat.v[0][2] = 0.f; - mat.v[1][2] = 0.f; - mat.v[2][2] = scale.z; - return mat; -} - -//////////////////////////////// -//~ rjf: Range Ops - -internal Rng1U32 rng_1u32(U32 min, U32 max) {Rng1U32 r = {min, max}; if(r.min > r.max) { Swap(U32, r.min, r.max); } return r;} -internal Rng1U32 shift_1u32(Rng1U32 r, U32 x) {r.min += x; r.max += x; return r;} -internal Rng1U32 pad_1u32(Rng1U32 r, U32 x) {r.min -= x; r.max += x; return r;} -internal U32 center_1u32(Rng1U32 r) {U32 c = (r.min+r.max)/2; return c;} -internal B32 contains_1u32(Rng1U32 r, U32 x) {B32 c = (r.min <= x && x < r.max); return c;} -internal U32 dim_1u32(Rng1U32 r) {U32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} -internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} -internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} -internal U32 clamp_1u32(Rng1U32 r, U32 v) {v = Clamp(r.min, v, r.max); return v;} - -internal Rng1S32 rng_1s32(S32 min, S32 max) {Rng1S32 r = {min, max}; if(r.min > r.max) { Swap(S32, r.min, r.max); } return r;} -internal Rng1S32 shift_1s32(Rng1S32 r, S32 x) {r.min += x; r.max += x; return r;} -internal Rng1S32 pad_1s32(Rng1S32 r, S32 x) {r.min -= x; r.max += x; return r;} -internal S32 center_1s32(Rng1S32 r) {S32 c = (r.min+r.max)/2; return c;} -internal B32 contains_1s32(Rng1S32 r, S32 x) {B32 c = (r.min <= x && x < r.max); return c;} -internal S32 dim_1s32(Rng1S32 r) {S32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} -internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} -internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} -internal S32 clamp_1s32(Rng1S32 r, S32 v) {v = Clamp(r.min, v, r.max); return v;} - -internal Rng1U64 rng_1u64(U64 min, U64 max) {Rng1U64 r = {min, max}; if(r.min > r.max) { Swap(U64, r.min, r.max); } return r;} -internal Rng1U64 shift_1u64(Rng1U64 r, U64 x) {r.min += x; r.max += x; return r;} -internal Rng1U64 pad_1u64(Rng1U64 r, U64 x) {r.min -= x; r.max += x; return r;} -internal U64 center_1u64(Rng1U64 r) {U64 c = (r.min+r.max)/2; return c;} -internal B32 contains_1u64(Rng1U64 r, U64 x) {B32 c = (r.min <= x && x < r.max); return c;} -internal U64 dim_1u64(Rng1U64 r) {U64 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} -internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} -internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} -internal U64 clamp_1u64(Rng1U64 r, U64 v) {v = Clamp(r.min, v, r.max); return v;} - -internal Rng1S64 rng_1s64(S64 min, S64 max) {Rng1S64 r = {min, max}; if(r.min > r.max) { Swap(S64, r.min, r.max); } return r;} -internal Rng1S64 shift_1s64(Rng1S64 r, S64 x) {r.min += x; r.max += x; return r;} -internal Rng1S64 pad_1s64(Rng1S64 r, S64 x) {r.min -= x; r.max += x; return r;} -internal S64 center_1s64(Rng1S64 r) {S64 c = (r.min+r.max)/2; return c;} -internal B32 contains_1s64(Rng1S64 r, S64 x) {B32 c = (r.min <= x && x < r.max); return c;} -internal S64 dim_1s64(Rng1S64 r) {S64 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} -internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} -internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} -internal S64 clamp_1s64(Rng1S64 r, S64 v) {v = Clamp(r.min, v, r.max); return v;} - -internal Rng1F32 rng_1f32(F32 min, F32 max) {Rng1F32 r = {min, max}; if(r.min > r.max) { Swap(F32, r.min, r.max); } return r;} -internal Rng1F32 shift_1f32(Rng1F32 r, F32 x) {r.min += x; r.max += x; return r;} -internal Rng1F32 pad_1f32(Rng1F32 r, F32 x) {r.min -= x; r.max += x; return r;} -internal F32 center_1f32(Rng1F32 r) {F32 c = (r.min+r.max)/2; return c;} -internal B32 contains_1f32(Rng1F32 r, F32 x) {B32 c = (r.min <= x && x < r.max); return c;} -internal F32 dim_1f32(Rng1F32 r) {F32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} -internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} -internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} -internal F32 clamp_1f32(Rng1F32 r, F32 v) {v = Clamp(r.min, v, r.max); return v;} - -internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max) {Rng2S16 r = {min, max}; return r;} -internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x) {r.min = add_2s16(r.min, x); r.max = add_2s16(r.max, x); return r;} -internal Rng2S16 pad_2s16(Rng2S16 r, S16 x) {Vec2S16 xv = {x, x}; r.min = sub_2s16(r.min, xv); r.max = add_2s16(r.max, xv); return r;} -internal Vec2S16 center_2s16(Rng2S16 r) {Vec2S16 c = {(S16)((r.min.x+r.max.x)/2), (S16)((r.min.y+r.max.y)/2)}; return c;} -internal B32 contains_2s16(Rng2S16 r, Vec2S16 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} -internal Vec2S16 dim_2s16(Rng2S16 r) {Vec2S16 dim = {(S16)(((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0)), (S16)(((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0))}; return dim;} -internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} -internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} -internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} - -internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max) {Rng2S32 r = {min, max}; return r;} -internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x) {r.min = add_2s32(r.min, x); r.max = add_2s32(r.max, x); return r;} -internal Rng2S32 pad_2s32(Rng2S32 r, S32 x) {Vec2S32 xv = {x, x}; r.min = sub_2s32(r.min, xv); r.max = add_2s32(r.max, xv); return r;} -internal Vec2S32 center_2s32(Rng2S32 r) {Vec2S32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} -internal B32 contains_2s32(Rng2S32 r, Vec2S32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} -internal Vec2S32 dim_2s32(Rng2S32 r) {Vec2S32 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} -internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} -internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} -internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} - -internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max) {Rng2S64 r = {min, max}; return r;} -internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x) {r.min = add_2s64(r.min, x); r.max = add_2s64(r.max, x); return r;} -internal Rng2S64 pad_2s64(Rng2S64 r, S64 x) {Vec2S64 xv = {x, x}; r.min = sub_2s64(r.min, xv); r.max = add_2s64(r.max, xv); return r;} -internal Vec2S64 center_2s64(Rng2S64 r) {Vec2S64 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} -internal B32 contains_2s64(Rng2S64 r, Vec2S64 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} -internal Vec2S64 dim_2s64(Rng2S64 r) {Vec2S64 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} -internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} -internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} -internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} - -internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max) {Rng2F32 r = {min, max}; return r;} -internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x) {r.min = add_2f32(r.min, x); r.max = add_2f32(r.max, x); return r;} -internal Rng2F32 pad_2f32(Rng2F32 r, F32 x) {Vec2F32 xv = {x, x}; r.min = sub_2f32(r.min, xv); r.max = add_2f32(r.max, xv); return r;} -internal Vec2F32 center_2f32(Rng2F32 r) {Vec2F32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} -internal B32 contains_2f32(Rng2F32 r, Vec2F32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} -internal Vec2F32 dim_2f32(Rng2F32 r) {Vec2F32 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} -internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} -internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} -internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} - -//////////////////////////////// -//~ rjf: Miscellaneous Ops - -internal Vec3F32 -hsv_from_rgb(Vec3F32 rgb) -{ - F32 c_max = Max(rgb.x, Max(rgb.y, rgb.z)); - F32 c_min = Min(rgb.x, Min(rgb.y, rgb.z)); - F32 delta = c_max - c_min; - F32 h = ((delta == 0.f) ? 0.f : - (c_max == rgb.x) ? mod_f32((rgb.y - rgb.z)/delta + 6.f, 6.f) : - (c_max == rgb.y) ? (rgb.z - rgb.x)/delta + 2.f : - (c_max == rgb.z) ? (rgb.x - rgb.y)/delta + 4.f : - 0.f); - F32 s = (c_max == 0.f) ? 0.f : (delta/c_max); - F32 v = c_max; - Vec3F32 hsv = {h/6.f, s, v}; - return hsv; -} - -internal Vec3F32 -rgb_from_hsv(Vec3F32 hsv) -{ - F32 h = mod_f32(hsv.x * 360.f, 360.f); - F32 s = hsv.y; - F32 v = hsv.z; - - F32 c = v*s; - F32 x = c*(1.f - abs_f32(mod_f32(h/60.f, 2.f) - 1.f)); - F32 m = v - c; - - F32 r = 0; - F32 g = 0; - F32 b = 0; - - if ((h >= 0.f && h < 60.f) || (h >= 360.f && h < 420.f)){ - r = c; - g = x; - b = 0; - } - else if (h >= 60.f && h < 120.f){ - r = x; - g = c; - b = 0; - } - else if (h >= 120.f && h < 180.f){ - r = 0; - g = c; - b = x; - } - else if (h >= 180.f && h < 240.f){ - r = 0; - g = x; - b = c; - } - else if (h >= 240.f && h < 300.f){ - r = x; - g = 0; - b = c; - } - else if ((h >= 300.f && h <= 360.f) || (h >= -60.f && h <= 0.f)){ - r = c; - g = 0; - b = x; - } - - Vec3F32 rgb = {r + m, g + m, b + m}; - return(rgb); -} - -internal Vec4F32 -hsva_from_rgba(Vec4F32 rgba) -{ - Vec3F32 rgb = v3f32(rgba.x, rgba.y, rgba.z); - Vec3F32 hsv = hsv_from_rgb(rgb); - Vec4F32 hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w); - return hsva; -} - -internal Vec4F32 -rgba_from_hsva(Vec4F32 hsva) -{ - Vec3F32 hsv = v3f32(hsva.x, hsva.y, hsva.z); - Vec3F32 rgb = rgb_from_hsv(hsv); - Vec4F32 rgba = v4f32(rgb.x, rgb.y, rgb.z, hsva.w); - return rgba; -} - -internal Vec4F32 -rgba_from_u32(U32 hex) -{ - Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f, - ((hex&0x00ff0000)>>16)/255.f, - ((hex&0x0000ff00)>> 8)/255.f, - ((hex&0x000000ff)>> 0)/255.f); - return result; -} - -internal U32 -u32_from_rgba(Vec4F32 rgba) -{ - U32 result = 0; - result |= ((U32)((U8)(rgba.x*255.f))) << 24; - result |= ((U32)((U8)(rgba.y*255.f))) << 16; - result |= ((U32)((U8)(rgba.z*255.f))) << 8; - result |= ((U32)((U8)(rgba.w*255.f))) << 0; - return result; -} - -//////////////////////////////// -//~ rjf: List Type Functions - -internal void -rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng) -{ - Rng1U64Node *n = push_array(arena, Rng1U64Node, 1); - MemoryCopyStruct(&n->v, &rng); - SLLQueuePush(list->first, list->last, n); - list->count += 1; -} - -internal void -rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat) -{ - if(to_concat->first) - { - if(list->first) - { - list->last->next = to_concat->first; - list->last = to_concat->last; - } - else - { - list->first = to_concat->first; - list->last = to_concat->last; - } - MemoryZeroStruct(to_concat); - } -} - -internal Rng1U64Array -rng1u64_array_from_list(Arena *arena, Rng1U64List *list) -{ - Rng1U64Array arr = {0}; - arr.count = list->count; - arr.v = push_array_no_zero(arena, Rng1U64, arr.count); - U64 idx = 0; - for(Rng1U64Node *n = list->first; n != 0; n = n->next) - { - arr.v[idx] = n->v; - idx += 1; - } - return arr; -} - -internal void -rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng) -{ - Rng1S64Node *n = push_array(arena, Rng1S64Node, 1); - MemoryCopyStruct(&n->v, &rng); - SLLQueuePush(list->first, list->last, n); - list->count += 1; -} - -internal Rng1S64Array -rng1s64_array_from_list(Arena *arena, Rng1S64List *list) -{ - Rng1S64Array arr = {0}; - arr.count = list->count; - arr.v = push_array_no_zero(arena, Rng1S64, arr.count); - U64 idx = 0; - for(Rng1S64Node *n = list->first; n != 0; n = n->next) - { - arr.v[idx] = n->v; - idx += 1; - } - return arr; -} diff --git a/src/metagen/metagen_base/metagen_base_math.h b/src/metagen/metagen_base/metagen_base_math.h deleted file mode 100644 index b6063ad5..00000000 --- a/src/metagen/metagen_base/metagen_base_math.h +++ /dev/null @@ -1,675 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#ifndef BASE_MATH_H -#define BASE_MATH_H - -//////////////////////////////// -//~ rjf: Vector Types - -//- rjf: 2-vectors - -typedef union Vec2F32 Vec2F32; -union Vec2F32 -{ - struct - { - F32 x; - F32 y; - }; - F32 v[2]; -}; - -typedef union Vec2S64 Vec2S64; -union Vec2S64 -{ - struct - { - S64 x; - S64 y; - }; - S64 v[2]; -}; - -typedef union Vec2S32 Vec2S32; -union Vec2S32 -{ - struct - { - S32 x; - S32 y; - }; - S32 v[2]; -}; - -typedef union Vec2S16 Vec2S16; -union Vec2S16 -{ - struct - { - S16 x; - S16 y; - }; - S16 v[2]; -}; - -//- rjf: 3-vectors - -typedef union Vec3F32 Vec3F32; -union Vec3F32 -{ - struct - { - F32 x; - F32 y; - F32 z; - }; - struct - { - Vec2F32 xy; - F32 _z0; - }; - struct - { - F32 _x0; - Vec2F32 yz; - }; - F32 v[3]; -}; - -typedef union Vec3S32 Vec3S32; -union Vec3S32 -{ - struct - { - S32 x; - S32 y; - S32 z; - }; - struct - { - Vec2S32 xy; - S32 _z0; - }; - struct - { - S32 _x0; - Vec2S32 yz; - }; - S32 v[3]; -}; - -//- rjf: 4-vectors - -typedef union Vec4F32 Vec4F32; -union Vec4F32 -{ - struct - { - F32 x; - F32 y; - F32 z; - F32 w; - }; - struct - { - Vec2F32 xy; - Vec2F32 zw; - }; - struct - { - Vec3F32 xyz; - F32 _z0; - }; - struct - { - F32 _x0; - Vec3F32 yzw; - }; - F32 v[4]; -}; - -typedef union Vec4S32 Vec4S32; -union Vec4S32 -{ - struct - { - S32 x; - S32 y; - S32 z; - S32 w; - }; - struct - { - Vec2S32 xy; - Vec2S32 zw; - }; - struct - { - Vec3S32 xyz; - S32 _z0; - }; - struct - { - S32 _x0; - Vec3S32 yzw; - }; - S32 v[4]; -}; - -//////////////////////////////// -//~ rjf: Matrix Types - -typedef struct Mat3x3F32 Mat3x3F32; -struct Mat3x3F32 -{ - F32 v[3][3]; -}; - -typedef struct Mat4x4F32 Mat4x4F32; -struct Mat4x4F32 -{ - F32 v[4][4]; -}; - -//////////////////////////////// -//~ rjf: Range Types - -//- rjf: 1-range - -typedef union Rng1U32 Rng1U32; -union Rng1U32 -{ - struct - { - U32 min; - U32 max; - }; - U32 v[2]; -}; - -typedef union Rng1S32 Rng1S32; -union Rng1S32 -{ - struct - { - S32 min; - S32 max; - }; - S32 v[2]; -}; - -typedef union Rng1U64 Rng1U64; -union Rng1U64 -{ - struct - { - U64 min; - U64 max; - }; - U64 v[2]; -}; - -typedef union Rng1S64 Rng1S64; -union Rng1S64 -{ - struct - { - S64 min; - S64 max; - }; - S64 v[2]; -}; - -typedef union Rng1F32 Rng1F32; -union Rng1F32 -{ - struct - { - F32 min; - F32 max; - }; - F32 v[2]; -}; - -//- rjf: 2-range (rectangles) - -typedef union Rng2S16 Rng2S16; -union Rng2S16 -{ - struct - { - Vec2S16 min; - Vec2S16 max; - }; - struct - { - Vec2S16 p0; - Vec2S16 p1; - }; - struct - { - S16 x0; - S16 y0; - S16 x1; - S16 y1; - }; - Vec2S16 v[2]; -}; - -typedef union Rng2S32 Rng2S32; -union Rng2S32 -{ - struct - { - Vec2S32 min; - Vec2S32 max; - }; - struct - { - Vec2S32 p0; - Vec2S32 p1; - }; - struct - { - S32 x0; - S32 y0; - S32 x1; - S32 y1; - }; - Vec2S32 v[2]; -}; - -typedef union Rng2F32 Rng2F32; -union Rng2F32 -{ - struct - { - Vec2F32 min; - Vec2F32 max; - }; - struct - { - Vec2F32 p0; - Vec2F32 p1; - }; - struct - { - F32 x0; - F32 y0; - F32 x1; - F32 y1; - }; - Vec2F32 v[2]; -}; - -typedef union Rng2S64 Rng2S64; -union Rng2S64 -{ - struct - { - Vec2S64 min; - Vec2S64 max; - }; - struct - { - Vec2S64 p0; - Vec2S64 p1; - }; - struct - { - S64 x0; - S64 y0; - S64 x1; - S64 y1; - }; - Vec2S64 v[2]; -}; - -//////////////////////////////// -//~ rjf: List Types - -typedef struct Rng1U64Node Rng1U64Node; -struct Rng1U64Node -{ - Rng1U64Node *next; - Rng1U64 v; -}; - -typedef struct Rng1U64List Rng1U64List; -struct Rng1U64List -{ - U64 count; - Rng1U64Node *first; - Rng1U64Node *last; -}; - -typedef struct Rng1U64Array Rng1U64Array; -struct Rng1U64Array -{ - Rng1U64 *v; - U64 count; -}; - -typedef struct Rng1S64Node Rng1S64Node; -struct Rng1S64Node -{ - Rng1S64Node *next; - Rng1S64 v; -}; - -typedef struct Rng1S64List Rng1S64List; -struct Rng1S64List -{ - Rng1S64Node *first; - Rng1S64Node *last; - U64 count; -}; - -typedef struct Rng1S64Array Rng1S64Array; -struct Rng1S64Array -{ - Rng1S64 *v; - U64 count; -}; - -//////////////////////////////// -//~ rjf: Scalar Ops - -#define abs_s64(v) (S64)llabs(v) - -#define sqrt_f32(v) sqrtf(v) -#define mod_f32(a, b) fmodf((a), (b)) -#define pow_f32(b, e) powf((b), (e)) -#define ceil_f32(v) ceilf(v) -#define floor_f32(v) floorf(v) -#define round_f32(v) roundf(v) -#define abs_f32(v) fabsf(v) -#define radians_from_turns_f32(v) ((v)*2*3.1415926535897f) -#define turns_from_radians_f32(v) ((v)/2*3.1415926535897f) -#define degrees_from_turns_f32(v) ((v)*360.f) -#define turns_from_degrees_f32(v) ((v)/360.f) -#define degrees_from_radians_f32(v) (degrees_from_turns_f32(turns_from_radians_f32(v))) -#define radians_from_degrees_f32(v) (radians_from_turns_f32(turns_from_degrees_f32(v))) -#define sin_f32(v) sinf(radians_from_turns_f32(v)) -#define cos_f32(v) cosf(radians_from_turns_f32(v)) -#define tan_f32(v) tanf(radians_from_turns_f32(v)) - -#define sqrt_f64(v) sqrt(v) -#define mod_f64(a, b) fmod((a), (b)) -#define pow_f64(b, e) pow((b), (e)) -#define ceil_f64(v) ceil(v) -#define floor_f64(v) floor(v) -#define round_f64(v) round(v) -#define abs_f64(v) fabs(v) -#define radians_from_turns_f64(v) ((v)*2*3.1415926535897) -#define turns_from_radians_f64(v) ((v)/2*3.1415926535897) -#define degrees_from_turns_f64(v) ((v)*360.0) -#define turns_from_degrees_f64(v) ((v)/360.0) -#define degrees_from_radians_f64(v) (degrees_from_turns_f64(turns_from_radians_f64(v))) -#define radians_from_degrees_f64(v) (radians_from_turns_f64(turns_from_degrees_f64(v))) -#define sin_f64(v) sin(radians_from_turns_f64(v)) -#define cos_f64(v) cos(radians_from_turns_f64(v)) -#define tan_f64(v) tan(radians_from_turns_f64(v)) - -internal F32 mix_1f32(F32 a, F32 b, F32 t); -internal F64 mix_1f64(F64 a, F64 b, F64 t); - -//////////////////////////////// -//~ rjf: Vector Ops - -#define v2f32(x, y) vec_2f32((x), (y)) -internal Vec2F32 vec_2f32(F32 x, F32 y); -internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b); -internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b); -internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b); -internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b); -internal Vec2F32 scale_2f32(Vec2F32 v, F32 s); -internal F32 dot_2f32(Vec2F32 a, Vec2F32 b); -internal F32 length_squared_2f32(Vec2F32 v); -internal F32 length_2f32(Vec2F32 v); -internal Vec2F32 normalize_2f32(Vec2F32 v); -internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t); - -#define v2s64(x, y) vec_2s64((x), (y)) -internal Vec2S64 vec_2s64(S64 x, S64 y); -internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b); -internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b); -internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b); -internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b); -internal Vec2S64 scale_2s64(Vec2S64 v, S64 s); -internal S64 dot_2s64(Vec2S64 a, Vec2S64 b); -internal S64 length_squared_2s64(Vec2S64 v); -internal S64 length_2s64(Vec2S64 v); -internal Vec2S64 normalize_2s64(Vec2S64 v); -internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t); - -#define v2s32(x, y) vec_2s32((x), (y)) -internal Vec2S32 vec_2s32(S32 x, S32 y); -internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b); -internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b); -internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b); -internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b); -internal Vec2S32 scale_2s32(Vec2S32 v, S32 s); -internal S32 dot_2s32(Vec2S32 a, Vec2S32 b); -internal S32 length_squared_2s32(Vec2S32 v); -internal S32 length_2s32(Vec2S32 v); -internal Vec2S32 normalize_2s32(Vec2S32 v); -internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t); - -#define v2s16(x, y) vec_2s16((x), (y)) -internal Vec2S16 vec_2s16(S16 x, S16 y); -internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b); -internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b); -internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b); -internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b); -internal Vec2S16 scale_2s16(Vec2S16 v, S16 s); -internal S16 dot_2s16(Vec2S16 a, Vec2S16 b); -internal S16 length_squared_2s16(Vec2S16 v); -internal S16 length_2s16(Vec2S16 v); -internal Vec2S16 normalize_2s16(Vec2S16 v); -internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t); - -#define v3f32(x, y, z) vec_3f32((x), (y), (z)) -internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z); -internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b); -internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b); -internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b); -internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b); -internal Vec3F32 scale_3f32(Vec3F32 v, F32 s); -internal F32 dot_3f32(Vec3F32 a, Vec3F32 b); -internal F32 length_squared_3f32(Vec3F32 v); -internal F32 length_3f32(Vec3F32 v); -internal Vec3F32 normalize_3f32(Vec3F32 v); -internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t); -internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b); - -#define v3s32(x, y, z) vec_3s32((x), (y), (z)) -internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z); -internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b); -internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b); -internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b); -internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b); -internal Vec3S32 scale_3s32(Vec3S32 v, S32 s); -internal S32 dot_3s32(Vec3S32 a, Vec3S32 b); -internal S32 length_squared_3s32(Vec3S32 v); -internal S32 length_3s32(Vec3S32 v); -internal Vec3S32 normalize_3s32(Vec3S32 v); -internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t); -internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b); - -#define v4f32(x, y, z, w) vec_4f32((x), (y), (z), (w)) -internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w); -internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b); -internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b); -internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b); -internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b); -internal Vec4F32 scale_4f32(Vec4F32 v, F32 s); -internal F32 dot_4f32(Vec4F32 a, Vec4F32 b); -internal F32 length_squared_4f32(Vec4F32 v); -internal F32 length_4f32(Vec4F32 v); -internal Vec4F32 normalize_4f32(Vec4F32 v); -internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t); - -#define v4s32(x, y, z, w) vec_4s32((x), (y), (z), (w)) -internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w); -internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b); -internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b); -internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b); -internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b); -internal Vec4S32 scale_4s32(Vec4S32 v, S32 s); -internal S32 dot_4s32(Vec4S32 a, Vec4S32 b); -internal S32 length_squared_4s32(Vec4S32 v); -internal S32 length_4s32(Vec4S32 v); -internal Vec4S32 normalize_4s32(Vec4S32 v); -internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t); - -//////////////////////////////// -//~ rjf: Matrix Ops - -internal Mat3x3F32 mat_3x3f32(F32 diagonal); -internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta); -internal Mat3x3F32 make_scale_3x3f32(Vec2F32 scale); -internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b); - -internal Mat4x4F32 mat_4x4f32(F32 diagonal); -internal Mat4x4F32 make_translate_4x4f32(Vec3F32 delta); -internal Mat4x4F32 make_scale_4x4f32(Vec3F32 scale); -internal Mat4x4F32 make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z); -internal Mat4x4F32 make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z); -internal Mat4x4F32 make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up); -internal Mat4x4F32 make_rotate_4x4f32(Vec3F32 axis, F32 turns); -internal Mat4x4F32 mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b); -internal Mat4x4F32 scale_4x4f32(Mat4x4F32 m, F32 scale); -internal Mat4x4F32 inverse_4x4f32(Mat4x4F32 m); -internal Mat4x4F32 derotate_4x4f32(Mat4x4F32 mat); - -//////////////////////////////// -//~ rjf: Range Ops - -#define r1u32(min, max) rng_1u32((min), (max)) -internal Rng1U32 rng_1u32(U32 min, U32 max); -internal Rng1U32 shift_1u32(Rng1U32 r, U32 x); -internal Rng1U32 pad_1u32(Rng1U32 r, U32 x); -internal U32 center_1u32(Rng1U32 r); -internal B32 contains_1u32(Rng1U32 r, U32 x); -internal U32 dim_1u32(Rng1U32 r); -internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b); -internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b); -internal U32 clamp_1u32(Rng1U32 r, U32 v); - -#define r1s32(min, max) rng_1s32((min), (max)) -internal Rng1S32 rng_1s32(S32 min, S32 max); -internal Rng1S32 shift_1s32(Rng1S32 r, S32 x); -internal Rng1S32 pad_1s32(Rng1S32 r, S32 x); -internal S32 center_1s32(Rng1S32 r); -internal B32 contains_1s32(Rng1S32 r, S32 x); -internal S32 dim_1s32(Rng1S32 r); -internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b); -internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b); -internal S32 clamp_1s32(Rng1S32 r, S32 v); - -#define r1u64(min, max) rng_1u64((min), (max)) -internal Rng1U64 rng_1u64(U64 min, U64 max); -internal Rng1U64 shift_1u64(Rng1U64 r, U64 x); -internal Rng1U64 pad_1u64(Rng1U64 r, U64 x); -internal U64 center_1u64(Rng1U64 r); -internal B32 contains_1u64(Rng1U64 r, U64 x); -internal U64 dim_1u64(Rng1U64 r); -internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b); -internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b); -internal U64 clamp_1u64(Rng1U64 r, U64 v); - -#define r1s64(min, max) rng_1s64((min), (max)) -internal Rng1S64 rng_1s64(S64 min, S64 max); -internal Rng1S64 shift_1s64(Rng1S64 r, S64 x); -internal Rng1S64 pad_1s64(Rng1S64 r, S64 x); -internal S64 center_1s64(Rng1S64 r); -internal B32 contains_1s64(Rng1S64 r, S64 x); -internal S64 dim_1s64(Rng1S64 r); -internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b); -internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b); -internal S64 clamp_1s64(Rng1S64 r, S64 v); - -#define r1f32(min, max) rng_1f32((min), (max)) -internal Rng1F32 rng_1f32(F32 min, F32 max); -internal Rng1F32 shift_1f32(Rng1F32 r, F32 x); -internal Rng1F32 pad_1f32(Rng1F32 r, F32 x); -internal F32 center_1f32(Rng1F32 r); -internal B32 contains_1f32(Rng1F32 r, F32 x); -internal F32 dim_1f32(Rng1F32 r); -internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b); -internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b); -internal F32 clamp_1f32(Rng1F32 r, F32 v); - -#define r2s16(min, max) rng_2s16((min), (max)) -#define r2s16p(x, y, z, w) r2s16(v2s16((x), (y)), v2s16((z), (w))) -internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max); -internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x); -internal Rng2S16 pad_2s16(Rng2S16 r, S16 x); -internal Vec2S16 center_2s16(Rng2S16 r); -internal B32 contains_2s16(Rng2S16 r, Vec2S16 x); -internal Vec2S16 dim_2s16(Rng2S16 r); -internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b); -internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b); -internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v); - -#define r2s32(min, max) rng_2s32((min), (max)) -#define r2s32p(x, y, z, w) r2s32(v2s32((x), (y)), v2s32((z), (w))) -internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max); -internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x); -internal Rng2S32 pad_2s32(Rng2S32 r, S32 x); -internal Vec2S32 center_2s32(Rng2S32 r); -internal B32 contains_2s32(Rng2S32 r, Vec2S32 x); -internal Vec2S32 dim_2s32(Rng2S32 r); -internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b); -internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b); -internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v); - -#define r2s64(min, max) rng_2s64((min), (max)) -#define r2s64p(x, y, z, w) r2s64(v2s64((x), (y)), v2s64((z), (w))) -internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max); -internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x); -internal Rng2S64 pad_2s64(Rng2S64 r, S64 x); -internal Vec2S64 center_2s64(Rng2S64 r); -internal B32 contains_2s64(Rng2S64 r, Vec2S64 x); -internal Vec2S64 dim_2s64(Rng2S64 r); -internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b); -internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b); -internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v); - -#define r2f32(min, max) rng_2f32((min), (max)) -#define r2f32p(x, y, z, w) r2f32(v2f32((x), (y)), v2f32((z), (w))) -internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max); -internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x); -internal Rng2F32 pad_2f32(Rng2F32 r, F32 x); -internal Vec2F32 center_2f32(Rng2F32 r); -internal B32 contains_2f32(Rng2F32 r, Vec2F32 x); -internal Vec2F32 dim_2f32(Rng2F32 r); -internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b); -internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b); -internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v); - -//////////////////////////////// -//~ rjf: Miscellaneous Ops - -internal Vec3F32 hsv_from_rgb(Vec3F32 rgb); -internal Vec3F32 rgb_from_hsv(Vec3F32 hsv); -internal Vec4F32 hsva_from_rgba(Vec4F32 rgba); -internal Vec4F32 rgba_from_hsva(Vec4F32 hsva); -internal Vec4F32 rgba_from_u32(U32 hex); -internal U32 u32_from_rgba(Vec4F32 rgba); - -#define rgba_from_u32_lit_comp(h) { (((h)&0xff000000)>>24)/255.f, (((h)&0x00ff0000)>>16)/255.f, (((h)&0x0000ff00)>> 8)/255.f, (((h)&0x000000ff)>> 0)/255.f } - -//////////////////////////////// -//~ rjf: List Type Functions - -internal void rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng); -internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat); -internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list); - -internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng); -internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list); - -#endif // BASE_MATH_H diff --git a/src/metagen/metagen_base/metagen_base_meta.c b/src/metagen/metagen_base/metagen_base_meta.c deleted file mode 100644 index c60dc237..00000000 --- a/src/metagen/metagen_base/metagen_base_meta.c +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Type Info Lookups - -internal Member * -member_from_name(Type *type, String8 name) -{ - Member *member = &member_nil; - if(type->members != 0 && name.size != 0) - { - for(U64 idx = 0; idx < type->count; idx += 1) - { - if(str8_match(type->members[idx].name, name, 0)) - { - member = &type->members[idx]; - break; - } - } - } - return member; -} - -//////////////////////////////// -//~ rjf: Type Info * Instance Operations - -internal void -typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr) -{ - Temp scratch = scratch_begin(0, 0); - typedef struct RebaseTypeTask RebaseTypeTask; - struct RebaseTypeTask - { - RebaseTypeTask *next; - Type *type; - U8 *ptr; - }; - RebaseTypeTask start_task = {0, type, data.str}; - RebaseTypeTask *first_task = &start_task; - RebaseTypeTask *last_task = first_task; - for(RebaseTypeTask *t = first_task; t != 0; t = t->next) - { - switch(t->type->kind) - { - default:{}break; - case TypeKind_Ptr: - if(!(t->type->flags & TypeFlag_IsExternal)) - { - *(U64 *)t->ptr = ((U64)(*(U8 **)t->ptr - (U8 *)base_ptr)); - }break; - case TypeKind_Array: - { - for(U64 idx = 0; idx < t->type->count; idx += 1) - { - RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1); - task->type = t->type->direct; - task->ptr = t->ptr + t->type->direct->size * idx; - SLLQueuePush(first_task, last_task, task); - } - }break; - case TypeKind_Struct: - { - for(U64 idx = 0; idx < t->type->count; idx += 1) - { - Member *member = &t->type->members[idx]; - RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1); - task->type = member->type; - task->ptr = t->ptr + member->value; - SLLQueuePush(first_task, last_task, task); - } - }break; - } - } - scratch_end(scratch); -} - -internal String8 -serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List strings = {0}; - str8_serial_begin(scratch.arena, &strings); - { - typedef struct SerializeTypeTask SerializeTypeTask; - struct SerializeTypeTask - { - SerializeTypeTask *next; - Type *type; - U64 count; - U8 *src; - Type *containing_type; - U8 *containing_ptr; - B32 is_post_header; - }; - SerializeTypeTask start_task = {0, type, 1, data.str}; - SerializeTypeTask *first_task = &start_task; - SerializeTypeTask *last_task = first_task; - for(SerializeTypeTask *t = first_task; t != 0; t = t->next) - { - switch(t->type->kind) - { - //- rjf: leaf -> just copy the data directly - default: - if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf) - { - str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count)); - }break; - - //- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise just write as plain data - case TypeKind_Ptr: - { - // rjf: unpack info about this pointer - TypeSerializePtrRefInfo *ptr_ref_info = 0; - for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1) - { - if(params->ptr_ref_infos[idx].type == t->type->direct) - { - ptr_ref_info = ¶ms->ptr_ref_infos[idx]; - break; - } - } - - // rjf: indexification -> subtract base, divide direct size, write index - if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0) - { - U64 ptr_value = 0; - MemoryCopy(&ptr_value, t->src, sizeof(ptr_value)); - U64 ptr_write_value = ((U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->indexify_base)/t->type->direct->size); - str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value); - } - - // rjf: offsetification -> subtract base, write offsets - else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0) - { - U64 ptr_value = 0; - MemoryCopy(&ptr_value, t->src, sizeof(ptr_value)); - U64 ptr_write_value = (U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->offsetify_base); - str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value); - } - - // rjf: size-by-member (pre-header): still potentially dependent on other members which - // delimit our size, so push a new post-header task for pointer. - else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header) - { - SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); - task->type = t->type; - task->count = t->count; - task->src = t->src; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - task->is_post_header = 1; - SLLQueuePush(first_task, last_task, task); - } - - // rjf: size-by-member (post-header): all flat parts of containing struct have been - // iterated, so now we can read the size, & descend to new task to read pointer - // destination contents - else if(t->type->count_delimiter_name.size != 0 && t->is_post_header) - { - // rjf: determine count of this pointer - U64 count = 0; - { - Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); - MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size); - } - - // rjf: push task - SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); - task->type = t->type->direct; - task->count = count; - task->src = *(void **)t->src; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - SLLQueuePush(first_task, last_task, task); - } - - // rjf: catch-all: write pointer value - else - { - str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count)); - } - }break; - - //- rjf: arrays -> descend to underlying type, + count - case TypeKind_Array: - { - SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); - task->type = t->type->direct; - task->count = t->type->count; - task->src = t->src; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - SLLQueuePush(first_task, last_task, task); - }break; - - //- rjf: struct -> descend to members - case TypeKind_Struct: - { - U64 off = 0; - for(U64 idx = 0; idx < t->count; idx += 1) - { - for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1) - { - if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize) - { - continue; - } - SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); - task->type = t->type->members[member_idx].type; - task->count = 1; - task->src = t->src + idx*t->type->size + t->type->members[member_idx].value; - task->containing_type = t->type; - task->containing_ptr = t->src; - SLLQueuePush(first_task, last_task, task); - } - } - }break; - - //- rjf: enum -> descend to basic type interpretation - case TypeKind_Enum: - { - SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); - task->type = t->type->direct; - task->count = t->count; - task->src = t->src; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - SLLQueuePush(first_task, last_task, task); - }break; - } - } - } - String8 result = str8_serial_end(arena, &strings); - scratch_end(scratch); - return result; -} - -internal String8 -deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) -{ - String8 result = {0}; - result.size = type->size; - result.str = push_array(arena, U8, result.size); - { - Temp scratch = scratch_begin(&arena, 1); - typedef struct DeserializeTypeTask DeserializeTypeTask; - struct DeserializeTypeTask - { - DeserializeTypeTask *next; - Type *type; - U64 count; - U8 *dst; - Type *containing_type; - U8 *containing_ptr; - B32 is_post_header; - }; - U64 read_off = 0; - DeserializeTypeTask start_task = {0, type, 1, result.str}; - DeserializeTypeTask *first_task = &start_task; - DeserializeTypeTask *last_task = first_task; - for(DeserializeTypeTask *t = first_task; t != 0; t = t->next) - { - U8 *t_src = data.str + read_off; - switch(t->type->kind) - { - //- rjf: leaf -> copy the data directly - default: - if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf) - { - MemoryCopy(t->dst, t_src, t->type->size*t->count); - read_off += t->type->size*t->count; - }break; - - //- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise skip - case TypeKind_Ptr: - { - // rjf: unpack info about this pointer - TypeSerializePtrRefInfo *ptr_ref_info = 0; - for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1) - { - if(params->ptr_ref_infos[idx].type == t->type->direct) - { - ptr_ref_info = ¶ms->ptr_ref_infos[idx]; - break; - } - } - - // rjf: indexification -> add base, multiply direct size - if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0) - { - U64 ptr_value = 0; - MemoryCopy(&ptr_value, t_src, sizeof(ptr_value)); - U64 ptr_write_value = (ptr_value + (U64)ptr_ref_info->indexify_base) * t->type->direct->size; - MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value)); - read_off += sizeof(ptr_value); - } - - // rjf: offsetification -> subtract base, write offsets - else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0) - { - U64 ptr_value = 0; - MemoryCopy(&ptr_value, t_src, sizeof(ptr_value)); - U64 ptr_write_value = ptr_value + (U64)ptr_ref_info->offsetify_base; - MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value)); - read_off += sizeof(ptr_value); - } - - // rjf: size-by-member (pre-header): still potentially dependent on other members which - // delimit our size, so push a new post-header task for pointer. - else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header) - { - DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); - task->type = t->type; - task->count = t->count; - task->dst = t->dst; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - task->is_post_header = 1; - SLLQueuePush(first_task, last_task, task); - } - - // rjf: size-by-member (post-header): all flat parts of containing struct have been - // iterated, so now we can read the size, & descend to new task to read pointer - // destination contents - else if(t->type->count_delimiter_name.size != 0 && t->is_post_header) - { - // rjf: determine count of this pointer - U64 count = 0; - { - Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); - MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size); - } - - // rjf: allocate buffer for pointer destination; write address into pointer value slot - U64 ptr_dest_buffer_size = (count+1)*t->type->direct->size; - U8 *ptr_dest_buffer = push_array(arena, U8, ptr_dest_buffer_size); - MemoryCopy(t->dst, &ptr_dest_buffer, sizeof(ptr_dest_buffer)); - - // rjf: push task - DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); - task->type = t->type->direct; - task->count = count; - task->dst = ptr_dest_buffer; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - SLLQueuePush(first_task, last_task, task); - } - - // rjf: catch-all: read pointer value - else - { - MemoryCopy(t->dst, t_src, t->type->size*t->count); - read_off += t->type->size*t->count; - } - }break; - - //- rjf: arrays -> descend to underlying type, + count - case TypeKind_Array: - { - DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); - task->type = t->type->direct; - task->count = t->type->count; - task->dst = t->dst; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - SLLQueuePush(first_task, last_task, task); - }break; - - //- rjf: struct -> descend to members - case TypeKind_Struct: - { - for(U64 idx = 0; idx < t->count; idx += 1) - { - for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1) - { - if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize) - { - continue; - } - DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); - task->type = t->type->members[member_idx].type; - task->count = 1; - task->dst = t->dst + idx*t->type->size + t->type->members[member_idx].value; - task->containing_type = t->type; - task->containing_ptr = t->dst; - SLLQueuePush(first_task, last_task, task); - } - } - }break; - - //- rjf: enum -> descend to basic type interpretation - case TypeKind_Enum: - { - DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); - task->type = t->type->direct; - task->count = t->count; - task->dst = t->dst; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - SLLQueuePush(first_task, last_task, task); - }break; - } - } - if(params->advance_out != 0) - { - params->advance_out[0] = read_off; - } - scratch_end(scratch); - } - return result; -} - -internal String8 -deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) -{ - Temp scratch = scratch_begin(&arena, 1); - String8 data_srlz = serialized_from_typed_data(scratch.arena, type, data, params); - String8 data_copy = deserialized_from_typed_data(arena, type, data_srlz, params); - scratch_end(scratch); - return data_copy; -} diff --git a/src/metagen/metagen_base/metagen_base_meta.h b/src/metagen/metagen_base/metagen_base_meta.h deleted file mode 100644 index 45d01e72..00000000 --- a/src/metagen/metagen_base/metagen_base_meta.h +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#ifndef BASE_META_H -#define BASE_META_H - -//////////////////////////////// -//~ rjf: Meta Markup Features - -#define EmbedFile(name, path) -#define TweakB32(name, default) (TWEAK_##name) -#define TweakF32(name, default, min, max) (TWEAK_##name) - -//////////////////////////////// -//~ rjf: Tweak Info Tables - -typedef struct TweakB32Info TweakB32Info; -struct TweakB32Info -{ - String8 name; - B32 default_value; - B32 *value_ptr; -}; - -typedef struct TweakF32Info TweakF32Info; -struct TweakF32Info -{ - String8 name; - F32 default_value; - Rng1F32 value_range; - F32 *value_ptr; -}; - -typedef struct TweakB32InfoTable TweakB32InfoTable; -struct TweakB32InfoTable -{ - TweakB32Info *v; - U64 count; -}; - -typedef struct TweakF32InfoTable TweakF32InfoTable; -struct TweakF32InfoTable -{ - TweakF32Info *v; - U64 count; -}; - -typedef struct EmbedInfo EmbedInfo; -struct EmbedInfo -{ - String8 name; - String8 *data; - U128 *hash; -}; - -typedef struct EmbedInfoTable EmbedInfoTable; -struct EmbedInfoTable -{ - EmbedInfo *v; - U64 count; -}; - -//////////////////////////////// -//~ rjf: Type Info Types - -typedef enum TypeKind -{ - TypeKind_Null, - - // rjf: leaves - TypeKind_Void, TypeKind_FirstLeaf = TypeKind_Void, - TypeKind_U8, - TypeKind_U16, - TypeKind_U32, - TypeKind_U64, - TypeKind_S8, - TypeKind_S16, - TypeKind_S32, - TypeKind_S64, - TypeKind_B8, - TypeKind_B16, - TypeKind_B32, - TypeKind_B64, - TypeKind_F32, - TypeKind_F64, TypeKind_LastLeaf = TypeKind_F64, - - // rjf: operators - TypeKind_Ptr, - TypeKind_Array, - - // rjf: user-defined-types - TypeKind_Struct, - TypeKind_Union, - TypeKind_Enum, - - TypeKind_COUNT -} -TypeKind; - -typedef U32 TypeFlags; -enum -{ - TypeFlag_IsExternal = (1<<0), - TypeFlag_IsPlainText = (1<<1), - TypeFlag_IsCodeText = (1<<2), - TypeFlag_IsPathText = (1<<3), -}; - -typedef U32 MemberFlags; -enum -{ - MemberFlag_DoNotSerialize = (1<<0), -}; - -typedef struct Type Type; -typedef struct Member Member; -struct Member -{ - String8 name; - String8 pretty_name; - Type *type; - U64 value; - MemberFlags flags; -}; - -typedef struct Type Type; -struct Type -{ - TypeKind kind; - TypeFlags flags; - U64 size; - Type *direct; - String8 name; - String8 count_delimiter_name; // gathered from surrounding members, turns *->[1] into *->[N] - U64 count; - Member *members; -}; - -//////////////////////////////// -//~ rjf: Type Serialization Parameters - -typedef struct TypeSerializePtrRefInfo TypeSerializePtrRefInfo; -struct TypeSerializePtrRefInfo -{ - Type *type; // pointers to this - void *indexify_base; // can be indexified using this - void *offsetify_base; // can be offsetified using this - void *nil_ptr; // is terminal if matching 0 or this -}; - -typedef struct TypeSerializeParams TypeSerializeParams; -struct TypeSerializeParams -{ - U64 *advance_out; - TypeSerializePtrRefInfo *ptr_ref_infos; - U64 ptr_ref_infos_count; -}; - -//////////////////////////////// -//~ rjf: Type Name -> Type Info - -#define type(T) (&T##__type) - -//////////////////////////////// -//~ rjf: Type Info Table Initializer Helpers - -#define member_lit_comp(S, ti, m, ...) {str8_lit_comp(#m), {0}, (ti), OffsetOf(S, m), __VA_ARGS__} -#define struct_members(S) read_only global Member S##__members[] = -#define struct_type(S, ...) read_only global Type S##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#S), {0}, ArrayCount(S##__members), S##__members, __VA_ARGS__} -#define named_struct_type(name, S, ...) read_only global Type name##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#name), {0}, ArrayCount(name##__members), name##__members, __VA_ARGS__} -#define ptr_type(name, ti, ...) read_only global Type name = {TypeKind_Ptr, 0, sizeof(void *), (ti), __VA_ARGS__} - -//////////////////////////////// -//~ rjf: Globals - -read_only global Type type_nil = {TypeKind_Null, 0, 0, &type_nil}; -read_only global Member member_nil = {{0}, {0}, &type_nil}; - -//////////////////////////////// -//~ rjf: Built-In Types - -//- rjf: leaves -read_only global Type void__type = {TypeKind_Void, 0, 0, &type_nil, str8_lit_comp("void")}; -read_only global Type U8__type = {TypeKind_U8, 0, sizeof(U8), &type_nil, str8_lit_comp("U8")}; -read_only global Type U16__type = {TypeKind_U16, 0, sizeof(U16), &type_nil, str8_lit_comp("U16")}; -read_only global Type U32__type = {TypeKind_U32, 0, sizeof(U32), &type_nil, str8_lit_comp("U32")}; -read_only global Type U64__type = {TypeKind_U64, 0, sizeof(U64), &type_nil, str8_lit_comp("U64")}; -read_only global Type S8__type = {TypeKind_S8, 0, sizeof(S8), &type_nil, str8_lit_comp("S8")}; -read_only global Type S16__type = {TypeKind_S16, 0, sizeof(S16), &type_nil, str8_lit_comp("S16")}; -read_only global Type S32__type = {TypeKind_S32, 0, sizeof(S32), &type_nil, str8_lit_comp("S32")}; -read_only global Type S64__type = {TypeKind_S64, 0, sizeof(S64), &type_nil, str8_lit_comp("S64")}; -read_only global Type B8__type = {TypeKind_B8, 0, sizeof(B8), &type_nil, str8_lit_comp("B8")}; -read_only global Type B16__type = {TypeKind_B16, 0, sizeof(B16), &type_nil, str8_lit_comp("B16")}; -read_only global Type B32__type = {TypeKind_B32, 0, sizeof(B32), &type_nil, str8_lit_comp("B32")}; -read_only global Type B64__type = {TypeKind_B64, 0, sizeof(B64), &type_nil, str8_lit_comp("B64")}; -read_only global Type F32__type = {TypeKind_F32, 0, sizeof(F32), &type_nil, str8_lit_comp("F32")}; -read_only global Type F64__type = {TypeKind_F64, 0, sizeof(F64), &type_nil, str8_lit_comp("F64")}; -read_only global Type *type_kind_type_table[] = -{ - &type_nil, - type(void), - type(U8), - type(U16), - type(U32), - type(U64), - type(S8), - type(S16), - type(S32), - type(S64), - type(B8), - type(B16), - type(B32), - type(B64), - type(F32), - type(F64), - &type_nil, - &type_nil, - &type_nil, - &type_nil, - &type_nil, -}; - -//- rjf: Rng1U64 -struct_members(Rng1U64) -{ - member_lit_comp(Rng1U64, type(U64), min), - member_lit_comp(Rng1U64, type(U64), max), -}; -struct_type(Rng1U64); - -//- rjf: String8 -ptr_type(String8__str_ptr_type, type(U8), str8_lit_comp("size")); -struct_members(String8) -{ - member_lit_comp(String8, &String8__str_ptr_type, str), - member_lit_comp(String8, type(U64), size), -}; -struct_type(String8); - -//- rjf: String8Node -extern Type String8Node__type; -Type String8Node__ptr_type = {TypeKind_Ptr, 0, sizeof(void *), &String8Node__type}; -Member String8Node__members[] = -{ - {str8_lit_comp("next"), {0}, &String8Node__ptr_type, OffsetOf(String8Node, next)}, - {str8_lit_comp("string"), {0}, type(String8), OffsetOf(String8Node, string)}, -}; -Type String8Node__type = -{ - TypeKind_Struct, - 0, - sizeof(String8Node), - &type_nil, - str8_lit_comp("String8Node"), - {0}, - ArrayCount(String8Node__members), - String8Node__members, -}; - -//- rjf: String8List -Member String8List__members[] = -{ - {str8_lit_comp("first"), {0}, &String8Node__ptr_type, OffsetOf(String8List, first)}, - {str8_lit_comp("last"), {0}, &String8Node__ptr_type, OffsetOf(String8List, last), MemberFlag_DoNotSerialize}, - {str8_lit_comp("node_count"), {0}, type(U64), OffsetOf(String8List, node_count)}, - {str8_lit_comp("total_size"), {0}, type(U64), OffsetOf(String8List, total_size)}, -}; -Type String8List__type = -{ - TypeKind_Struct, - 0, - sizeof(String8List), - &type_nil, - str8_lit_comp("String8List"), - {0}, - ArrayCount(String8List__members), - String8List__members, -}; - -//////////////////////////////// -//~ rjf: Type Info Lookups - -internal Member *member_from_name(Type *type, String8 name); -#define EachMember(T, it) (Member *it = (type(T))->members; it != 0 && it < (type(T))->members + (type(T))->count; it += 1) - -//////////////////////////////// -//~ rjf: Type Info * Instance Operations - -internal void typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr); -internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); -internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); -internal String8 deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); -#define struct_rebase_ptrs(T, ptr, base) typed_data_rebase_ptrs(type(T), str8_struct(ptr), (base)) -#define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}) -#define struct_from_serialized(arena, T, string, ...) (T *)deserialized_from_typed_data((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str -#define deep_copy_from_struct(arena, T, ptr, ...) (T *)deep_copy_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str - -#endif // BASE_META_H diff --git a/src/metagen/metagen_base/metagen_base_profile.c b/src/metagen/metagen_base/metagen_base_profile.c deleted file mode 100644 index 8ac6bce5..00000000 --- a/src/metagen/metagen_base/metagen_base_profile.c +++ /dev/null @@ -1,2 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) diff --git a/src/metagen/metagen_base/metagen_base_profile.h b/src/metagen/metagen_base/metagen_base_profile.h deleted file mode 100644 index 1e0d938b..00000000 --- a/src/metagen/metagen_base/metagen_base_profile.h +++ /dev/null @@ -1,97 +0,0 @@ -// 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, "ws2_32.lib") -# 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) -# define ProfBeginV(...) \ -if (TM_API_PTR) { \ -static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \ -Temp scratch = scratch_begin(0,0); \ -String8 string = push_str8f(scratch.arena, __VA_ARGS__); \ -tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \ -hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \ -TM_API_PTR->_tmEnterZoneFast_Core(0, 0, file_id, __LINE__, hash); \ -scratch_end(scratch); \ -} -# define ProfNoteV(...) \ -if (TM_API_PTR) { \ -static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \ -Temp scratch = scratch_begin(0,0); \ -String8 string = push_str8f(scratch.arena, __VA_ARGS__); \ -tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \ -hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \ -TM_API_PTR->_tmMessageFast_Core(0, TMMF_ICON_NOTE, file_id, __LINE__, hash); \ -scratch_end(scratch); \ -} -#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) -# define ProfBeginV(...) (0) -# define ProfNoteV(...) (0) -#endif - -//////////////////////////////// -//~ rjf: Helper Wrappers - -#define ProfBeginFunction(...) ProfBegin(this_function_name) -#define ProfScope(...) DeferLoop(ProfBeginDynamic(__VA_ARGS__), ProfEnd()) - -#endif // BASE_PROFILE_H diff --git a/src/metagen/metagen_base/metagen_base_strings.c b/src/metagen/metagen_base/metagen_base_strings.c deleted file mode 100644 index 9e42e0cd..00000000 --- a/src/metagen/metagen_base/metagen_base_strings.c +++ /dev/null @@ -1,2446 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Third Party Includes - -#if !BUILD_SUPPLEMENTARY_UNIT -# define STB_SPRINTF_IMPLEMENTATION -# define STB_SPRINTF_STATIC -# include "third_party/stb/stb_sprintf.h" -#endif - -//////////////////////////////// -//~ NOTE(allen): String <-> Integer Tables - -read_only global U8 integer_symbols[16] = { - '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', -}; - -// NOTE(allen): Includes reverses for uppercase and lowercase hex. -read_only global U8 integer_symbol_reverse[128] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -}; - -read_only global U8 base64[64] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '_', '$', -}; - -read_only global U8 base64_reverse[128] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0x00, - 0xFF,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32, - 0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0xFF,0xFF,0xFF,0xFF,0x3E, - 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, - 0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0xFF,0xFF,0xFF,0xFF,0xFF, -}; - -//////////////////////////////// -//~ rjf: Character Classification & Conversion Functions - -internal B32 -char_is_space(U8 c){ - return(c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f' || c == '\v'); -} - -internal B32 -char_is_upper(U8 c){ - return('A' <= c && c <= 'Z'); -} - -internal B32 -char_is_lower(U8 c){ - return('a' <= c && c <= 'z'); -} - -internal B32 -char_is_alpha(U8 c){ - return(char_is_upper(c) || char_is_lower(c)); -} - -internal B32 -char_is_slash(U8 c){ - return(c == '/' || c == '\\'); -} - -internal B32 -char_is_digit(U8 c, U32 base){ - B32 result = 0; - if (0 < base && base <= 16){ - U8 val = integer_symbol_reverse[c]; - if (val < base){ - result = 1; - } - } - return(result); -} - -internal U8 -char_to_lower(U8 c){ - if (char_is_upper(c)){ - c += ('a' - 'A'); - } - return(c); -} - -internal U8 -char_to_upper(U8 c){ - if (char_is_lower(c)){ - c += ('A' - 'a'); - } - return(c); -} - -internal U8 -char_to_correct_slash(U8 c){ - if(char_is_slash(c)){ - c = '/'; - } - return(c); -} - -//////////////////////////////// -//~ rjf: C-String Measurement - -internal U64 -cstring8_length(U8 *c){ - U8 *p = c; - for (;*p != 0; p += 1); - return(p - c); -} - -internal U64 -cstring16_length(U16 *c){ - U16 *p = c; - for (;*p != 0; p += 1); - return(p - c); -} - -internal U64 -cstring32_length(U32 *c){ - U32 *p = c; - for (;*p != 0; p += 1); - return(p - c); -} - -//////////////////////////////// -//~ rjf: String Constructors - -internal String8 -str8(U8 *str, U64 size){ - String8 result = {str, size}; - return(result); -} - -internal String8 -str8_range(U8 *first, U8 *one_past_last){ - String8 result = {first, (U64)(one_past_last - first)}; - return(result); -} - -internal String8 -str8_zero(void){ - String8 result = {0}; - return(result); -} - -internal String16 -str16(U16 *str, U64 size){ - String16 result = {str, size}; - return(result); -} - -internal String16 -str16_range(U16 *first, U16 *one_past_last){ - String16 result = {first, (U64)(one_past_last - first)}; - return(result); -} - -internal String16 -str16_zero(void){ - String16 result = {0}; - return(result); -} - -internal String32 -str32(U32 *str, U64 size){ - String32 result = {str, size}; - return(result); -} - -internal String32 -str32_range(U32 *first, U32 *one_past_last){ - String32 result = {first, (U64)(one_past_last - first)}; - return(result); -} - -internal String32 -str32_zero(void){ - String32 result = {0}; - return(result); -} - -internal String8 -str8_cstring(char *c){ - String8 result = {(U8*)c, cstring8_length((U8*)c)}; - return(result); -} - -internal String16 -str16_cstring(U16 *c){ - String16 result = {(U16*)c, cstring16_length((U16*)c)}; - return(result); -} - -internal String32 -str32_cstring(U32 *c){ - String32 result = {(U32*)c, cstring32_length((U32*)c)}; - return(result); -} - -internal String8 -str8_cstring_capped(void *cstr, void *cap) -{ - char *ptr = (char *)cstr; - char *opl = (char *)cap; - for (;ptr < opl && *ptr != 0; ptr += 1); - U64 size = (U64)(ptr - (char *)cstr); - String8 result = str8((U8*)cstr, size); - return result; -} - -internal String16 -str16_cstring_capped(void *cstr, void *cap) -{ - U16 *ptr = (U16 *)cstr; - U16 *opl = (U16 *)cap; - for (;ptr < opl && *ptr != 0; ptr += 1); - U64 size = (U64)(ptr - (U16 *)cstr); - String16 result = str16(cstr, size); - return result; -} - -internal String8 -str8_cstring_capped_reverse(void *raw_start, void *raw_cap) -{ - U8 *start = raw_start; - U8 *ptr = raw_cap; - for(; ptr > start; ) - { - ptr -= 1; - - if (*ptr == '\0') - { - break; - } - } - U64 size = (U64)(ptr - start); - String8 result = str8(start, size); - return result; -} - -//////////////////////////////// -//~ rjf: String Stylization - -internal String8 -upper_from_str8(Arena *arena, String8 string) -{ - string = push_str8_copy(arena, string); - for(U64 idx = 0; idx < string.size; idx += 1) - { - string.str[idx] = char_to_upper(string.str[idx]); - } - return string; -} - -internal String8 -lower_from_str8(Arena *arena, String8 string) -{ - string = push_str8_copy(arena, string); - for(U64 idx = 0; idx < string.size; idx += 1) - { - string.str[idx] = char_to_lower(string.str[idx]); - } - return string; -} - -internal String8 -backslashed_from_str8(Arena *arena, String8 string) -{ - string = push_str8_copy(arena, string); - for(U64 idx = 0; idx < string.size; idx += 1) - { - string.str[idx] = char_is_slash(string.str[idx]) ? '\\' : string.str[idx]; - } - return string; -} - -//////////////////////////////// -//~ rjf: String Matching - -internal B32 -str8_match(String8 a, String8 b, StringMatchFlags flags) -{ - B32 result = 0; - if(a.size == b.size && flags == 0) - { - result = MemoryMatch(a.str, b.str, b.size); - } - else if(a.size == b.size || (flags & StringMatchFlag_RightSideSloppy)) - { - B32 case_insensitive = (flags & StringMatchFlag_CaseInsensitive); - B32 slash_insensitive = (flags & StringMatchFlag_SlashInsensitive); - U64 size = Min(a.size, b.size); - result = 1; - for(U64 i = 0; i < size; i += 1) - { - U8 at = a.str[i]; - U8 bt = b.str[i]; - if(case_insensitive) - { - at = char_to_upper(at); - bt = char_to_upper(bt); - } - if(slash_insensitive) - { - at = char_to_correct_slash(at); - bt = char_to_correct_slash(bt); - } - if(at != bt) - { - result = 0; - break; - } - } - } - return result; -} - -internal U64 -str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags){ - U8 *p = string.str + start_pos; - U64 stop_offset = Max(string.size + 1, needle.size) - needle.size; - U8 *stop_p = string.str + stop_offset; - if (needle.size > 0){ - U8 *string_opl = string.str + string.size; - String8 needle_tail = str8_skip(needle, 1); - StringMatchFlags adjusted_flags = flags | StringMatchFlag_RightSideSloppy; - U8 needle_first_char_adjusted = needle.str[0]; - if(adjusted_flags & StringMatchFlag_CaseInsensitive){ - needle_first_char_adjusted = char_to_upper(needle_first_char_adjusted); - } - for (;p < stop_p; p += 1){ - U8 haystack_char_adjusted = *p; - if(adjusted_flags & StringMatchFlag_CaseInsensitive){ - haystack_char_adjusted = char_to_upper(haystack_char_adjusted); - } - if (haystack_char_adjusted == needle_first_char_adjusted){ - if (str8_match(str8_range(p + 1, string_opl), needle_tail, adjusted_flags)){ - break; - } - } - } - } - U64 result = string.size; - if (p < stop_p){ - result = (U64)(p - string.str); - } - return(result); -} - -internal U64 -str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags) -{ - U64 result = 0; - for(S64 i = string.size - start_pos - needle.size; i >= 0; --i) - { - String8 haystack = str8_substr(string, rng_1u64(i, i + needle.size)); - if(str8_match(haystack, needle, flags)) - { - result = (U64)i + needle.size; - break; - } - } - return result; -} - -internal B32 -str8_ends_with(String8 string, String8 end, StringMatchFlags flags){ - String8 postfix = str8_postfix(string, end.size); - B32 is_match = str8_match(end, postfix, flags); - return is_match; -} - -//////////////////////////////// -//~ rjf: String Slicing - -internal String8 -str8_substr(String8 str, Rng1U64 range){ - range.min = ClampTop(range.min, str.size); - range.max = ClampTop(range.max, str.size); - str.str += range.min; - str.size = dim_1u64(range); - return(str); -} - -internal String8 -str8_prefix(String8 str, U64 size){ - str.size = ClampTop(size, str.size); - return(str); -} - -internal String8 -str8_skip(String8 str, U64 amt){ - amt = ClampTop(amt, str.size); - str.str += amt; - str.size -= amt; - return(str); -} - -internal String8 -str8_postfix(String8 str, U64 size){ - size = ClampTop(size, str.size); - str.str = (str.str + str.size) - size; - str.size = size; - return(str); -} - -internal String8 -str8_chop(String8 str, U64 amt){ - amt = ClampTop(amt, str.size); - str.size -= amt; - return(str); -} - -internal String8 -str8_skip_chop_whitespace(String8 string){ - U8 *first = string.str; - U8 *opl = first + string.size; - for (;first < opl; first += 1){ - if (!char_is_space(*first)){ - break; - } - } - for (;opl > first;){ - opl -= 1; - if (!char_is_space(*opl)){ - opl += 1; - break; - } - } - String8 result = str8_range(first, opl); - return(result); -} - -//////////////////////////////// -//~ rjf: String Formatting & Copying - -internal String8 -push_str8_cat(Arena *arena, String8 s1, String8 s2){ - String8 str; - str.size = s1.size + s2.size; - str.str = push_array_no_zero(arena, U8, str.size + 1); - MemoryCopy(str.str, s1.str, s1.size); - MemoryCopy(str.str + s1.size, s2.str, s2.size); - str.str[str.size] = 0; - return(str); -} - -internal String8 -push_str8_copy(Arena *arena, String8 s){ - String8 str; - str.size = s.size; - str.str = push_array_no_zero(arena, U8, str.size + 1); - MemoryCopy(str.str, s.str, s.size); - str.str[str.size] = 0; - return(str); -} - -internal String8 -push_str8fv(Arena *arena, char *fmt, va_list args){ - va_list args2; - va_copy(args2, args); - U32 needed_bytes = raddbg_vsnprintf(0, 0, fmt, args) + 1; - String8 result = {0}; - result.str = push_array_no_zero(arena, U8, needed_bytes); - result.size = raddbg_vsnprintf((char*)result.str, needed_bytes, fmt, args2); - result.str[result.size] = 0; - va_end(args2); - return(result); -} - -internal String8 -push_str8f(Arena *arena, char *fmt, ...){ - va_list args; - va_start(args, fmt); - String8 result = push_str8fv(arena, fmt, args); - va_end(args); - return(result); -} - -//////////////////////////////// -//~ rjf: String <=> Integer Conversions - -//- rjf: string -> integer - -internal S64 -sign_from_str8(String8 string, String8 *string_tail){ - // count negative signs - U64 neg_count = 0; - U64 i = 0; - for (; i < string.size; i += 1){ - if (string.str[i] == '-'){ - neg_count += 1; - } - else if (string.str[i] != '+'){ - break; - } - } - - // output part of string after signs - *string_tail = str8_skip(string, i); - - // output integer sign - S64 sign = (neg_count & 1)?-1:+1; - return(sign); -} - -internal B32 -str8_is_integer(String8 string, U32 radix){ - B32 result = 0; - if (string.size > 0){ - if (1 < radix && radix <= 16){ - result = 1; - for (U64 i = 0; i < string.size; i += 1){ - U8 c = string.str[i]; - if (!(c < 0x80) || integer_symbol_reverse[c] >= radix){ - result = 0; - break; - } - } - } - } - return(result); -} - -internal U64 -u64_from_str8(String8 string, U32 radix){ - U64 x = 0; - if (1 < radix && radix <= 16){ - for (U64 i = 0; i < string.size; i += 1){ - x *= radix; - x += integer_symbol_reverse[string.str[i]&0x7F]; - } - } - return(x); -} - -internal S64 -s64_from_str8(String8 string, U32 radix){ - S64 sign = sign_from_str8(string, &string); - S64 x = (S64)u64_from_str8(string, radix) * sign; - return(x); -} - -internal U32 -u32_from_str8(String8 string, U32 radix) -{ - U64 x64 = u64_from_str8(string, radix); - U32 x32 = safe_cast_u32(x64); - return x32; -} - -internal S32 -s32_from_str8(String8 string, U32 radix) -{ - S64 x64 = s64_from_str8(string, radix); - S32 x32 = safe_cast_s32(x64); - return x32; -} - -internal B32 -try_u64_from_str8_c_rules(String8 string, U64 *x){ - B32 is_integer = 0; - if (str8_is_integer(string, 10)){ - is_integer = 1; - *x = u64_from_str8(string, 10); - } - else{ - String8 hex_string = str8_skip(string, 2); - if (str8_match(str8_prefix(string, 2), str8_lit("0x"), 0) && - str8_is_integer(hex_string, 0x10)){ - is_integer = 1; - *x = u64_from_str8(hex_string, 0x10); - } - else if (str8_match(str8_prefix(string, 2), str8_lit("0b"), 0) && - str8_is_integer(hex_string, 2)){ - is_integer = 1; - *x = u64_from_str8(hex_string, 2); - } - else{ - String8 oct_string = str8_skip(string, 1); - if (str8_match(str8_prefix(string, 1), str8_lit("0"), 0) && - str8_is_integer(hex_string, 010)){ - is_integer = 1; - *x = u64_from_str8(oct_string, 010); - } - } - } - return(is_integer); -} - -internal B32 -try_s64_from_str8_c_rules(String8 string, S64 *x){ - String8 string_tail = {0}; - S64 sign = sign_from_str8(string, &string_tail); - U64 x_u64 = 0; - B32 is_integer = try_u64_from_str8_c_rules(string_tail, &x_u64); - *x = x_u64*sign; - return(is_integer); -} - -//- rjf: integer -> string - -internal String8 -str8_from_memory_size(Arena *arena, U64 size) -{ - String8 result; - - if(size < KB(1)) - { - result = push_str8f(arena, "%llu Bytes", size); - } - else if(size < MB(1)) - { - result = push_str8f(arena, "%llu.%02llu KiB", size / KB(1), ((size * 100) / KB(1)) % 100); - } - else if(size < GB(1)) - { - result = push_str8f(arena, "%llu.%02llu MiB", size / MB(1), ((size * 100) / MB(1)) % 100); - } - else if(size < TB(1)) - { - result = push_str8f(arena, "%llu.%02llu GiB", size / GB(1), ((size * 100) / GB(1)) % 100); - } - else - { - result = push_str8f(arena, "%llu.%02llu TiB", size / TB(1), ((size * 100) / TB(1)) % 100); - } - - return result; -} - -internal String8 -str8_from_count(Arena *arena, U64 count) -{ - String8 result; - - if(count < 1 * 1000) - { - result = push_str8f(arena, "%llu", count); - } - else if(count < 1000000) - { - U64 frac = ((count * 100) / 1000) % 100; - if(frac > 0) - { - result = push_str8f(arena, "%llu.%02lluK", count / 1000, frac); - } - else - { - result = push_str8f(arena, "%lluK", count / 1000); - } - } - else if(count < 1000000000) - { - U64 frac = ((count * 100) / 1000000) % 100; - if(frac > 0) - { - result = push_str8f(arena, "%llu.%02lluM", count / 1000000, frac); - } - else - { - result = push_str8f(arena, "%lluM", count / 1000000); - } - } - else - { - U64 frac = ((count * 100) * 1000000000) % 100; - if(frac > 0) - { - result = push_str8f(arena, "%llu.%02lluB", count / 1000000000, frac); - } - else - { - result = push_str8f(arena, "%lluB", count / 1000000000, frac); - } - } - - return result; -} - -internal String8 -str8_from_bits_u32(Arena *arena, U32 x) -{ - U8 c0 = 'a' + ((x >> 28) & 0xf); - U8 c1 = 'a' + ((x >> 24) & 0xf); - U8 c2 = 'a' + ((x >> 20) & 0xf); - U8 c3 = 'a' + ((x >> 16) & 0xf); - U8 c4 = 'a' + ((x >> 12) & 0xf); - U8 c5 = 'a' + ((x >> 8) & 0xf); - U8 c6 = 'a' + ((x >> 4) & 0xf); - U8 c7 = 'a' + ((x >> 0) & 0xf); - String8 result = push_str8f(arena, "%c%c%c%c%c%c%c%c", c0, c1, c2, c3, c4, c5, c6, c7); - return result; -} - -internal String8 -str8_from_bits_u64(Arena *arena, U64 x) -{ - U8 c0 = 'a' + ((x >> 60) & 0xf); - U8 c1 = 'a' + ((x >> 56) & 0xf); - U8 c2 = 'a' + ((x >> 52) & 0xf); - U8 c3 = 'a' + ((x >> 48) & 0xf); - U8 c4 = 'a' + ((x >> 44) & 0xf); - U8 c5 = 'a' + ((x >> 40) & 0xf); - U8 c6 = 'a' + ((x >> 36) & 0xf); - U8 c7 = 'a' + ((x >> 32) & 0xf); - U8 c8 = 'a' + ((x >> 28) & 0xf); - U8 c9 = 'a' + ((x >> 24) & 0xf); - U8 ca = 'a' + ((x >> 20) & 0xf); - U8 cb = 'a' + ((x >> 16) & 0xf); - U8 cc = 'a' + ((x >> 12) & 0xf); - U8 cd = 'a' + ((x >> 8) & 0xf); - U8 ce = 'a' + ((x >> 4) & 0xf); - U8 cf = 'a' + ((x >> 0) & 0xf); - String8 result = push_str8f(arena, - "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", - c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf); - return result; -} - -internal String8 -str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator) -{ - String8 result = {0}; - { - // rjf: prefix - String8 prefix = {0}; - switch(radix) - { - case 16:{prefix = str8_lit("0x");}break; - case 8: {prefix = str8_lit("0o");}break; - case 2: {prefix = str8_lit("0b");}break; - } - - // rjf: determine # of chars between separators - U8 digit_group_size = 3; - switch(radix) - { - default:break; - case 2: - case 8: - case 16: - {digit_group_size = 4;}break; - } - - // rjf: prep - U64 needed_leading_0s = 0; - { - U64 needed_digits = 1; - { - U64 u64_reduce = u64; - for(;;) - { - u64_reduce /= radix; - if(u64_reduce == 0) - { - break; - } - needed_digits += 1; - } - } - needed_leading_0s = (min_digits > needed_digits) ? min_digits - needed_digits : 0; - U64 needed_separators = 0; - if(digit_group_separator != 0) - { - needed_separators = (needed_digits+needed_leading_0s)/digit_group_size; - if(needed_separators > 0 && (needed_digits+needed_leading_0s)%digit_group_size == 0) - { - needed_separators -= 1; - } - } - result.size = prefix.size + needed_leading_0s + needed_separators + needed_digits; - result.str = push_array_no_zero(arena, U8, result.size + 1); - result.str[result.size] = 0; - } - - // rjf: fill contents - { - U64 u64_reduce = u64; - U64 digits_until_separator = digit_group_size; - for(U64 idx = 0; idx < result.size; idx += 1) - { - if(digits_until_separator == 0 && digit_group_separator != 0) - { - result.str[result.size - idx - 1] = digit_group_separator; - digits_until_separator = digit_group_size+1; - } - else - { - result.str[result.size - idx - 1] = char_to_lower(integer_symbols[u64_reduce%radix]); - u64_reduce /= radix; - } - digits_until_separator -= 1; - if(u64_reduce == 0) - { - break; - } - } - for(U64 leading_0_idx = 0; leading_0_idx < needed_leading_0s; leading_0_idx += 1) - { - result.str[prefix.size + leading_0_idx] = '0'; - } - } - - // rjf: fill prefix - if(prefix.size != 0) - { - MemoryCopy(result.str, prefix.str, prefix.size); - } - } - return result; -} - -internal String8 -str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator) -{ - String8 result = {0}; - // TODO(rjf): preeeeetty sloppy... - if(s64 < 0) - { - Temp scratch = scratch_begin(&arena, 1); - String8 numeric_part = str8_from_u64(scratch.arena, (U64)(-s64), radix, min_digits, digit_group_separator); - result = push_str8f(arena, "-%S", numeric_part); - scratch_end(scratch); - } - else - { - result = str8_from_u64(arena, (U64)s64, radix, min_digits, digit_group_separator); - } - return result; -} - -//////////////////////////////// -//~ rjf: String <=> Float Conversions - -internal F64 -f64_from_str8(String8 string) -{ - // TODO(rjf): crappy implementation for now that just uses atof. - F64 result = 0; - if(string.size > 0) - { - // rjf: find starting pos of numeric string, as well as sign - F64 sign = +1.0; - if(string.str[0] == '-') - { - sign = -1.0; - } - else if(string.str[0] == '+') - { - sign = 1.0; - } - - // rjf: gather numerics - U64 num_valid_chars = 0; - char buffer[64]; - B32 exp = 0; - for(U64 idx = 0; idx < string.size && num_valid_chars < sizeof(buffer)-1; idx += 1) - { - if(char_is_digit(string.str[idx], 10) || string.str[idx] == '.' || string.str[idx] == 'e' || - (exp && (string.str[idx] == '+' || string.str[idx] == '-'))) - { - buffer[num_valid_chars] = string.str[idx]; - num_valid_chars += 1; - exp = 0; - exp = (string.str[idx] == 'e'); - } - } - - // rjf: null-terminate (the reason for all of this!!!!!!) - buffer[num_valid_chars] = 0; - - // rjf: do final conversion - result = sign * atof(buffer); - } - return result; -} - -//////////////////////////////// -//~ rjf: String List Construction Functions - -internal String8Node* -str8_list_push_node(String8List *list, String8Node *node){ - SLLQueuePush(list->first, list->last, node); - list->node_count += 1; - list->total_size += node->string.size; - return(node); -} - -internal String8Node* -str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string){ - SLLQueuePush(list->first, list->last, node); - list->node_count += 1; - list->total_size += string.size; - node->string = string; - return(node); -} - -internal String8Node* -str8_list_push_node_front(String8List *list, String8Node *node){ - SLLQueuePushFront(list->first, list->last, node); - list->node_count += 1; - list->total_size += node->string.size; - return(node); -} - -internal String8Node* -str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string){ - SLLQueuePushFront(list->first, list->last, node); - list->node_count += 1; - list->total_size += string.size; - node->string = string; - return(node); -} - -internal String8Node* -str8_list_push(Arena *arena, String8List *list, String8 string){ - String8Node *node = push_array_no_zero(arena, String8Node, 1); - str8_list_push_node_set_string(list, node, string); - return(node); -} - -internal String8Node* -str8_list_push_front(Arena *arena, String8List *list, String8 string){ - String8Node *node = push_array_no_zero(arena, String8Node, 1); - str8_list_push_node_front_set_string(list, node, string); - return(node); -} - -internal void -str8_list_concat_in_place(String8List *list, String8List *to_push){ - if(to_push->node_count != 0){ - if (list->last){ - list->node_count += to_push->node_count; - list->total_size += to_push->total_size; - list->last->next = to_push->first; - list->last = to_push->last; - } - else{ - *list = *to_push; - } - MemoryZeroStruct(to_push); - } -} - -internal String8Node* -str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align){ - String8Node *node = push_array_no_zero(arena, String8Node, 1); - U64 new_size = list->total_size + min; - U64 increase_size = 0; - if (align > 1){ - // NOTE(allen): assert is power of 2 - Assert(((align - 1) & align) == 0); - U64 mask = align - 1; - new_size += mask; - new_size &= (~mask); - increase_size = new_size - list->total_size; - } - local_persist const U8 zeroes_buffer[64] = {0}; - Assert(increase_size <= ArrayCount(zeroes_buffer)); - SLLQueuePush(list->first, list->last, node); - list->node_count += 1; - list->total_size = new_size; - node->string.str = (U8*)zeroes_buffer; - node->string.size = increase_size; - return(node); -} - -internal String8Node* -str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...){ - va_list args; - va_start(args, fmt); - String8 string = push_str8fv(arena, fmt, args); - String8Node *result = str8_list_push(arena, list, string); - va_end(args); - return(result); -} - -internal String8Node* -str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...){ - va_list args; - va_start(args, fmt); - String8 string = push_str8fv(arena, fmt, args); - String8Node *result = str8_list_push_front(arena, list, string); - va_end(args); - return(result); -} - -internal String8List -str8_list_copy(Arena *arena, String8List *list){ - String8List result = {0}; - for (String8Node *node = list->first; - node != 0; - node = node->next){ - String8Node *new_node = push_array_no_zero(arena, String8Node, 1); - String8 new_string = push_str8_copy(arena, node->string); - str8_list_push_node_set_string(&result, new_node, new_string); - } - return(result); -} - -internal String8List -str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags){ - String8List list = {0}; - - B32 keep_empties = (flags & StringSplitFlag_KeepEmpties); - - U8 *ptr = string.str; - U8 *opl = string.str + string.size; - for (;ptr < opl;){ - U8 *first = ptr; - for (;ptr < opl; ptr += 1){ - U8 c = *ptr; - B32 is_split = 0; - for (U64 i = 0; i < split_char_count; i += 1){ - if (split_chars[i] == c){ - is_split = 1; - break; - } - } - if (is_split){ - break; - } - } - - String8 string = str8_range(first, ptr); - if (keep_empties || string.size > 0){ - str8_list_push(arena, &list, string); - } - ptr += 1; - } - - return(list); -} - -internal String8List -str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags){ - String8List list = str8_split(arena, string, split_chars.str, split_chars.size, flags); - return list; -} - -internal String8List -str8_list_split_by_string_chars(Arena *arena, String8List list, String8 split_chars, StringSplitFlags flags){ - String8List result = {0}; - for (String8Node *node = list.first; node != 0; node = node->next){ - String8List split = str8_split_by_string_chars(arena, node->string, split_chars, flags); - str8_list_concat_in_place(&result, &split); - } - return result; -} - -internal String8 -str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params){ - StringJoin join = {0}; - if (optional_params != 0){ - MemoryCopyStruct(&join, optional_params); - } - - U64 sep_count = 0; - if (list->node_count > 0){ - sep_count = list->node_count - 1; - } - - String8 result; - result.size = join.pre.size + join.post.size + sep_count*join.sep.size + list->total_size; - U8 *ptr = result.str = push_array_no_zero(arena, U8, result.size + 1); - - MemoryCopy(ptr, join.pre.str, join.pre.size); - ptr += join.pre.size; - for (String8Node *node = list->first; - node != 0; - node = node->next){ - MemoryCopy(ptr, node->string.str, node->string.size); - ptr += node->string.size; - if (node->next != 0){ - MemoryCopy(ptr, join.sep.str, join.sep.size); - ptr += join.sep.size; - } - } - MemoryCopy(ptr, join.post.str, join.post.size); - ptr += join.post.size; - - *ptr = 0; - - return(result); -} - -internal void -str8_list_from_flags(Arena *arena, String8List *list, - U32 flags, String8 *flag_string_table, U32 flag_string_count){ - for (U32 i = 0; i < flag_string_count; i += 1){ - U32 flag = (1 << i); - if (flags & flag){ - str8_list_push(arena, list, flag_string_table[i]); - } - } -} - -//////////////////////////////// -//~ rjf; String Arrays - -internal String8Array -str8_array_from_list(Arena *arena, String8List *list) -{ - String8Array array; - array.count = list->node_count; - array.v = push_array_no_zero(arena, String8, array.count); - U64 idx = 0; - for(String8Node *n = list->first; n != 0; n = n->next, idx += 1) - { - array.v[idx] = n->string; - } - return array; -} - -internal String8Array -str8_array_reserve(Arena *arena, U64 count) -{ - String8Array arr; - arr.count = 0; - arr.v = push_array(arena, String8, count); - return arr; -} - -//////////////////////////////// -//~ rjf: String Path Helpers - -internal String8 -str8_chop_last_slash(String8 string){ - if (string.size > 0){ - U8 *ptr = string.str + string.size - 1; - for (;ptr >= string.str; ptr -= 1){ - if (*ptr == '/' || *ptr == '\\'){ - break; - } - } - if (ptr >= string.str){ - string.size = (U64)(ptr - string.str); - } - else{ - string.size = 0; - } - } - return(string); -} - -internal String8 -str8_skip_last_slash(String8 string){ - if (string.size > 0){ - U8 *ptr = string.str + string.size - 1; - for (;ptr >= string.str; ptr -= 1){ - if (*ptr == '/' || *ptr == '\\'){ - break; - } - } - if (ptr >= string.str){ - ptr += 1; - string.size = (U64)(string.str + string.size - ptr); - string.str = ptr; - } - } - return(string); -} - -internal String8 -str8_chop_last_dot(String8 string) -{ - String8 result = string; - U64 p = string.size; - for (;p > 0;){ - p -= 1; - if (string.str[p] == '.'){ - result = str8_prefix(string, p); - break; - } - } - return(result); -} - -internal String8 -str8_skip_last_dot(String8 string){ - String8 result = string; - U64 p = string.size; - for (;p > 0;){ - p -= 1; - if (string.str[p] == '.'){ - result = str8_skip(string, p + 1); - break; - } - } - return(result); -} - -internal PathStyle -path_style_from_str8(String8 string){ - PathStyle result = PathStyle_Relative; - if (string.size >= 1 && string.str[0] == '/'){ - result = PathStyle_UnixAbsolute; - } - else if (string.size >= 2 && - char_is_alpha(string.str[0]) && - string.str[1] == ':'){ - if (string.size == 2 || - char_is_slash(string.str[2])){ - result = PathStyle_WindowsAbsolute; - } - } - return(result); -} - -internal String8List -str8_split_path(Arena *arena, String8 string){ - String8List result = str8_split(arena, string, (U8*)"/\\", 2, 0); - return(result); -} - -internal void -str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style){ - Temp scratch = scratch_begin(0, 0); - - String8MetaNode *stack = 0; - String8MetaNode *free_meta_node = 0; - String8Node *first = path->first; - - MemoryZeroStruct(path); - for (String8Node *node = first, *next = 0; - node != 0; - node = next){ - // save next now - next = node->next; - - // cases: - if (node == first && style == PathStyle_WindowsAbsolute){ - goto save_without_stack; - } - if (node->string.size == 1 && node->string.str[0] == '.'){ - goto do_nothing; - } - if (node->string.size == 2 && node->string.str[0] == '.' && node->string.str[1] == '.'){ - if (stack != 0){ - goto eliminate_stack_top; - } - else{ - goto save_without_stack; - } - } - goto save_with_stack; - - - // handlers: - save_with_stack: - { - str8_list_push_node(path, node); - - String8MetaNode *stack_node = free_meta_node; - if (stack_node != 0){ - SLLStackPop(free_meta_node); - } - else{ - stack_node = push_array_no_zero(scratch.arena, String8MetaNode, 1); - } - SLLStackPush(stack, stack_node); - stack_node->node = node; - - continue; - } - - save_without_stack: - { - str8_list_push_node(path, node); - - continue; - } - - eliminate_stack_top: - { - path->node_count -= 1; - path->total_size -= stack->node->string.size; - - SLLStackPop(stack); - - if (stack == 0){ - path->last = path->first; - } - else{ - path->last = stack->node; - } - continue; - } - - do_nothing: continue; - } - scratch_end(scratch); -} - -internal String8 -str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style){ - StringJoin params = {0}; - switch(style) - { - case PathStyle_Null:{}break; - case PathStyle_Relative: - case PathStyle_WindowsAbsolute: - { - params.sep = str8_lit("/"); - }break; - - case PathStyle_UnixAbsolute: - { - params.pre = str8_lit("/"); - params.sep = str8_lit("/"); - }break; - } - String8 result = str8_list_join(arena, path, ¶ms); - return result; -} - -internal String8TxtPtPair -str8_txt_pt_pair_from_string(String8 string) -{ - String8TxtPtPair pair = {0}; - { - String8 file_part = {0}; - String8 line_part = {0}; - String8 col_part = {0}; - - // rjf: grab file part - for(U64 idx = 0; idx <= string.size; idx += 1) - { - U8 byte = (idx < string.size) ? (string.str[idx]) : 0; - U8 next_byte = ((idx+1 < string.size) ? (string.str[idx+1]) : 0); - if(byte == ':' && next_byte != '/' && next_byte != '\\') - { - file_part = str8_prefix(string, idx); - line_part = str8_skip(string, idx+1); - break; - } - else if(byte == 0) - { - file_part = string; - break; - } - } - - // rjf: grab line/column - { - U64 colon_pos = str8_find_needle(line_part, 0, str8_lit(":"), 0); - if(colon_pos < line_part.size) - { - col_part = str8_skip(line_part, colon_pos+1); - line_part = str8_prefix(line_part, colon_pos); - } - } - - // rjf: convert line/column strings to numerics - U64 line = 0; - U64 column = 0; - try_u64_from_str8_c_rules(line_part, &line); - try_u64_from_str8_c_rules(col_part, &column); - - // rjf: fill - pair.string = file_part; - pair.pt = txt_pt((S64)line, (S64)column); - if(pair.pt.line == 0) { pair.pt.line = 1; } - if(pair.pt.column == 0) { pair.pt.column = 1; } - } - return pair; -} - -//////////////////////////////// -//~ rjf: UTF-8 & UTF-16 Decoding/Encoding - -read_only global U8 utf8_class[32] = { - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5, -}; - -internal UnicodeDecode -utf8_decode(U8 *str, U64 max){ - UnicodeDecode result = {1, max_U32}; - U8 byte = str[0]; - U8 byte_class = utf8_class[byte >> 3]; - switch (byte_class) - { - case 1: - { - result.codepoint = byte; - }break; - case 2: - { - if (2 < max) - { - U8 cont_byte = str[1]; - if (utf8_class[cont_byte >> 3] == 0) - { - result.codepoint = (byte & bitmask5) << 6; - result.codepoint |= (cont_byte & bitmask6); - result.inc = 2; - } - } - }break; - case 3: - { - if (2 < max) - { - U8 cont_byte[2] = {str[1], str[2]}; - if (utf8_class[cont_byte[0] >> 3] == 0 && - utf8_class[cont_byte[1] >> 3] == 0) - { - result.codepoint = (byte & bitmask4) << 12; - result.codepoint |= ((cont_byte[0] & bitmask6) << 6); - result.codepoint |= (cont_byte[1] & bitmask6); - result.inc = 3; - } - } - }break; - case 4: - { - if (3 < max) - { - U8 cont_byte[3] = {str[1], str[2], str[3]}; - if (utf8_class[cont_byte[0] >> 3] == 0 && - utf8_class[cont_byte[1] >> 3] == 0 && - utf8_class[cont_byte[2] >> 3] == 0) - { - result.codepoint = (byte & bitmask3) << 18; - result.codepoint |= ((cont_byte[0] & bitmask6) << 12); - result.codepoint |= ((cont_byte[1] & bitmask6) << 6); - result.codepoint |= (cont_byte[2] & bitmask6); - result.inc = 4; - } - } - } - } - return(result); -} - -internal UnicodeDecode -utf16_decode(U16 *str, U64 max){ - UnicodeDecode result = {1, max_U32}; - result.codepoint = str[0]; - result.inc = 1; - if (max > 1 && 0xD800 <= str[0] && str[0] < 0xDC00 && 0xDC00 <= str[1] && str[1] < 0xE000){ - result.codepoint = ((str[0] - 0xD800) << 10) | ((str[1] - 0xDC00) + 0x10000); - result.inc = 2; - } - return(result); -} - -internal U32 -utf8_encode(U8 *str, U32 codepoint){ - U32 inc = 0; - if (codepoint <= 0x7F){ - str[0] = (U8)codepoint; - inc = 1; - } - else if (codepoint <= 0x7FF){ - str[0] = (bitmask2 << 6) | ((codepoint >> 6) & bitmask5); - str[1] = bit8 | (codepoint & bitmask6); - inc = 2; - } - else if (codepoint <= 0xFFFF){ - str[0] = (bitmask3 << 5) | ((codepoint >> 12) & bitmask4); - str[1] = bit8 | ((codepoint >> 6) & bitmask6); - str[2] = bit8 | ( codepoint & bitmask6); - inc = 3; - } - else if (codepoint <= 0x10FFFF){ - str[0] = (bitmask4 << 4) | ((codepoint >> 18) & bitmask3); - str[1] = bit8 | ((codepoint >> 12) & bitmask6); - str[2] = bit8 | ((codepoint >> 6) & bitmask6); - str[3] = bit8 | ( codepoint & bitmask6); - inc = 4; - } - else{ - str[0] = '?'; - inc = 1; - } - return(inc); -} - -internal U32 -utf16_encode(U16 *str, U32 codepoint){ - U32 inc = 1; - if (codepoint == max_U32){ - str[0] = (U16)'?'; - } - else if (codepoint < 0x10000){ - str[0] = (U16)codepoint; - } - else{ - U32 v = codepoint - 0x10000; - str[0] = safe_cast_u16(0xD800 + (v >> 10)); - str[1] = safe_cast_u16(0xDC00 + (v & bitmask10)); - inc = 2; - } - return(inc); -} - -internal U32 -utf8_from_utf32_single(U8 *buffer, U32 character){ - return(utf8_encode(buffer, character)); -} - -//////////////////////////////// -//~ rjf: Unicode String Conversions - -internal String8 -str8_from_16(Arena *arena, String16 in) -{ - String8 result = str8_zero(); - if(in.size) - { - U64 cap = in.size*3; - U8 *str = push_array_no_zero(arena, U8, cap + 1); - U16 *ptr = in.str; - U16 *opl = ptr + in.size; - U64 size = 0; - UnicodeDecode consume; - for(;ptr < opl; ptr += consume.inc) - { - consume = utf16_decode(ptr, opl - ptr); - size += utf8_encode(str + size, consume.codepoint); - } - str[size] = 0; - arena_pop(arena, (cap - size)); - result = str8(str, size); - } - return result; -} - -internal String16 -str16_from_8(Arena *arena, String8 in) -{ - String16 result = str16_zero(); - if(in.size) - { - U64 cap = in.size*2; - U16 *str = push_array_no_zero(arena, U16, cap + 1); - U8 *ptr = in.str; - U8 *opl = ptr + in.size; - U64 size = 0; - UnicodeDecode consume; - for(;ptr < opl; ptr += consume.inc) - { - consume = utf8_decode(ptr, opl - ptr); - size += utf16_encode(str + size, consume.codepoint); - } - str[size] = 0; - arena_pop(arena, (cap - size)*2); - result = str16(str, size); - } - return result; -} - -internal String8 -str8_from_32(Arena *arena, String32 in) -{ - String8 result = str8_zero(); - if(in.size) - { - U64 cap = in.size*4; - U8 *str = push_array_no_zero(arena, U8, cap + 1); - U32 *ptr = in.str; - U32 *opl = ptr + in.size; - U64 size = 0; - for(;ptr < opl; ptr += 1) - { - size += utf8_encode(str + size, *ptr); - } - str[size] = 0; - arena_pop(arena, (cap - size)); - result = str8(str, size); - } - return result; -} - -internal String32 -str32_from_8(Arena *arena, String8 in) -{ - String32 result = str32_zero(); - if(in.size) - { - U64 cap = in.size; - U32 *str = push_array_no_zero(arena, U32, cap + 1); - U8 *ptr = in.str; - U8 *opl = ptr + in.size; - U64 size = 0; - UnicodeDecode consume; - for(;ptr < opl; ptr += consume.inc) - { - consume = utf8_decode(ptr, opl - ptr); - str[size] = consume.codepoint; - size += 1; - } - str[size] = 0; - arena_pop(arena, (cap - size)*4); - result = str32(str, size); - } - return result; -} - -//////////////////////////////// -//~ String -> Enum Conversions - -read_only global struct -{ - String8 string; - OperatingSystem os; -} g_os_enum_map[] = -{ - { str8_lit_comp(""), OperatingSystem_Null }, - { str8_lit_comp("Windows"), OperatingSystem_Windows, }, - { str8_lit_comp("Linux"), OperatingSystem_Linux, }, - { str8_lit_comp("Mac"), OperatingSystem_Mac, }, -}; -StaticAssert(ArrayCount(g_os_enum_map) == OperatingSystem_COUNT, g_os_enum_map_count_check); - -internal OperatingSystem -operating_system_from_string(String8 string) -{ - for(U64 i = 0; i < ArrayCount(g_os_enum_map); ++i) - { - if(str8_match(g_os_enum_map[i].string, string, StringMatchFlag_CaseInsensitive)) - { - return g_os_enum_map[i].os; - } - } - return OperatingSystem_Null; -} - -//////////////////////////////// -//~ rjf: Basic Types & Space Enum -> String Conversions - -internal String8 -string_from_dimension(Dimension dimension){ - local_persist String8 strings[] = { - str8_lit_comp("X"), - str8_lit_comp("Y"), - str8_lit_comp("Z"), - str8_lit_comp("W"), - }; - String8 result = str8_lit("error"); - if ((U32)dimension < 4){ - result = strings[dimension]; - } - return(result); -} - -internal String8 -string_from_side(Side side){ - local_persist String8 strings[] = { - str8_lit_comp("Min"), - str8_lit_comp("Max"), - }; - String8 result = str8_lit("error"); - if ((U32)side < 2){ - result = strings[side]; - } - return(result); -} - -internal String8 -string_from_operating_system(OperatingSystem os) -{ - String8 result = g_os_enum_map[OperatingSystem_Null].string; - if(os < ArrayCount(g_os_enum_map)) - { - result = g_os_enum_map[os].string; - } - return result; -} - -internal String8 -string_from_arch(Arch arch){ - local_persist String8 strings[] = { - str8_lit_comp("Null"), - str8_lit_comp("x64"), - str8_lit_comp("x86"), - str8_lit_comp("arm64"), - str8_lit_comp("arm32"), - }; - String8 result = str8_lit("error"); - if (arch < Arch_COUNT){ - result = strings[arch]; - } - return(result); -} - -//////////////////////////////// -//~ rjf: Time Types -> String - -internal String8 -string_from_week_day(WeekDay week_day){ - local_persist String8 strings[] = { - str8_lit_comp("Sun"), - str8_lit_comp("Mon"), - str8_lit_comp("Tue"), - str8_lit_comp("Wed"), - str8_lit_comp("Thu"), - str8_lit_comp("Fri"), - str8_lit_comp("Sat"), - }; - String8 result = str8_lit("Err"); - if ((U32)week_day < WeekDay_COUNT){ - result = strings[week_day]; - } - return(result); -} - -internal String8 -string_from_month(Month month){ - local_persist String8 strings[] = { - str8_lit_comp("Jan"), - str8_lit_comp("Feb"), - str8_lit_comp("Mar"), - str8_lit_comp("Apr"), - str8_lit_comp("May"), - str8_lit_comp("Jun"), - str8_lit_comp("Jul"), - str8_lit_comp("Aug"), - str8_lit_comp("Sep"), - str8_lit_comp("Oct"), - str8_lit_comp("Nov"), - str8_lit_comp("Dec"), - }; - String8 result = str8_lit("Err"); - if ((U32)month < Month_COUNT){ - result = strings[month]; - } - return(result); -} - -internal String8 -push_date_time_string(Arena *arena, DateTime *date_time){ - char *mon_str = (char*)string_from_month(date_time->month).str; - U32 adjusted_hour = date_time->hour%12; - if (adjusted_hour == 0){ - adjusted_hour = 12; - } - char *ampm = "am"; - if (date_time->hour >= 12){ - ampm = "pm"; - } - String8 result = push_str8f(arena, "%d %s %d, %02d:%02d:%02d %s", - date_time->day, mon_str, date_time->year, - adjusted_hour, date_time->min, date_time->sec, ampm); - return(result); -} - -internal String8 -push_file_name_date_time_string(Arena *arena, DateTime *date_time){ - char *mon_str = (char*)string_from_month(date_time->month).str; - String8 result = push_str8f(arena, "%d-%s-%0d--%02d-%02d-%02d", - date_time->year, mon_str, date_time->day, - date_time->hour, date_time->min, date_time->sec); - return(result); -} - -internal String8 -string_from_elapsed_time(Arena *arena, DateTime dt){ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; - if (dt.year){ - str8_list_pushf(scratch.arena, &list, "%dy", dt.year); - str8_list_pushf(scratch.arena, &list, "%um", dt.mon); - str8_list_pushf(scratch.arena, &list, "%ud", dt.day); - } else if (dt.mon){ - str8_list_pushf(scratch.arena, &list, "%um", dt.mon); - str8_list_pushf(scratch.arena, &list, "%ud", dt.day); - } else if (dt.day){ - str8_list_pushf(scratch.arena, &list, "%ud", dt.day); - } - str8_list_pushf(scratch.arena, &list, "%u:%u:%u:%u ms", dt.hour, dt.min, dt.sec, dt.msec); - StringJoin join = { str8_lit_comp(""), str8_lit_comp(" "), str8_lit_comp("") }; - String8 result = str8_list_join(arena, &list, &join); - scratch_end(scratch); - return(result); -} - -//////////////////////////////// -//~ Globally UNique Ids - -internal String8 -string_from_guid(Arena *arena, 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; -} - -internal B32 -try_guid_from_string(String8 string, Guid *guid_out) -{ - Temp scratch = scratch_begin(0,0); - B32 is_parsed = 0; - String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("-"), StringSplitFlag_KeepEmpties); - if(list.node_count == 5) - { - String8 data1_str = list.first->string; - String8 data2_str = list.first->next->string; - String8 data3_str = list.first->next->next->string; - String8 data4_hi_str = list.first->next->next->next->string; - String8 data4_lo_str = list.first->next->next->next->next->string; - if(str8_is_integer(data1_str, 16) && - str8_is_integer(data2_str, 16) && - str8_is_integer(data3_str, 16) && - str8_is_integer(data4_hi_str, 16) && - str8_is_integer(data4_lo_str, 16)) - { - U64 data1 = u64_from_str8(data1_str, 16); - U64 data2 = u64_from_str8(data2_str, 16); - U64 data3 = u64_from_str8(data3_str, 16); - U64 data4_hi = u64_from_str8(data4_hi_str, 16); - U64 data4_lo = u64_from_str8(data4_lo_str, 16); - if(data1 <= max_U32 && - data2 <= max_U16 && - data3 <= max_U16 && - data4_hi <= max_U16 && - data4_lo <= 0xffffffffffff) - { - guid_out->data1 = (U32)data1; - guid_out->data2 = (U16)data2; - guid_out->data3 = (U16)data3; - U64 data4 = (data4_hi << 48) | data4_lo; - MemoryCopy(&guid_out->data4[0], &data4, sizeof(data4)); - is_parsed = 1; - } - } - } - scratch_end(scratch); - return is_parsed; -} - -internal Guid -guid_from_string(String8 string) -{ - Guid guid = {0}; - try_guid_from_string(string, &guid); - return guid; -} - -//////////////////////////////// -//~ rjf: Basic Text Indentation - -internal String8 -indented_from_string(Arena *arena, String8 string) -{ - Temp scratch = scratch_begin(&arena, 1); - read_only local_persist U8 indentation_bytes[] = " "; - String8List indented_strings = {0}; - S64 depth = 0; - S64 next_depth = 0; - U64 line_begin_off = 0; - for(U64 off = 0; off <= string.size; off += 1) - { - U8 byte = off width_this_line){ - String8 line = str8_substr(string, line_range); - if (wrapped_indent_level > 0){ - line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); - } - str8_list_push(arena, &list, line); - line_range = r1u64(line_range.max+1, candidate_line_range.max); - wrapped_indent_level = ClampTop(64, wrap_indent); - } - else{ - line_range = candidate_line_range; - } - } - } - if (line_range.min < string.size && line_range.max > line_range.min){ - String8 line = str8_substr(string, line_range); - if (wrapped_indent_level > 0){ - line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); - } - str8_list_push(arena, &list, line); - } - return list; -} - -//////////////////////////////// -//~ rjf: String <-> Color - -internal String8 -hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba) -{ - String8 hex_string = push_str8f(arena, "%02x%02x%02x%02x", (U8)(rgba.x*255.f), (U8)(rgba.y*255.f), (U8)(rgba.z*255.f), (U8)(rgba.w*255.f)); - return hex_string; -} - -internal Vec4F32 -rgba_from_hex_string_4f32(String8 hex_string) -{ - U8 byte_text[8] = {0}; - U64 byte_text_idx = 0; - for(U64 idx = 0; idx < hex_string.size && byte_text_idx < ArrayCount(byte_text); idx += 1) - { - if(char_is_digit(hex_string.str[idx], 16)) - { - byte_text[byte_text_idx] = char_to_lower(hex_string.str[idx]); - byte_text_idx += 1; - } - } - U8 byte_vals[4] = {0}; - for(U64 idx = 0; idx < 4; idx += 1) - { - byte_vals[idx] = (U8)u64_from_str8(str8(&byte_text[idx*2], 2), 16); - } - Vec4F32 rgba = v4f32(byte_vals[0]/255.f, byte_vals[1]/255.f, byte_vals[2]/255.f, byte_vals[3]/255.f); - return rgba; -} - -//////////////////////////////// -//~ rjf: String Fuzzy Matching - -internal FuzzyMatchRangeList -fuzzy_match_find(Arena *arena, String8 needle, String8 haystack) -{ - FuzzyMatchRangeList result = {0}; - Temp scratch = scratch_begin(&arena, 1); - String8List needles = str8_split(scratch.arena, needle, (U8*)" ", 1, 0); - result.needle_part_count = needles.node_count; - for(String8Node *needle_n = needles.first; needle_n != 0; needle_n = needle_n->next) - { - U64 find_pos = 0; - for(;find_pos < haystack.size;) - { - find_pos = str8_find_needle(haystack, find_pos, needle_n->string, StringMatchFlag_CaseInsensitive); - B32 is_in_gathered_ranges = 0; - for(FuzzyMatchRangeNode *n = result.first; n != 0; n = n->next) - { - if(n->range.min <= find_pos && find_pos < n->range.max) - { - is_in_gathered_ranges = 1; - find_pos = n->range.max; - break; - } - } - if(!is_in_gathered_ranges) - { - break; - } - } - if(find_pos < haystack.size) - { - Rng1U64 range = r1u64(find_pos, find_pos+needle_n->string.size); - FuzzyMatchRangeNode *n = push_array(arena, FuzzyMatchRangeNode, 1); - n->range = range; - SLLQueuePush(result.first, result.last, n); - result.count += 1; - result.total_dim += dim_1u64(range); - } - } - scratch_end(scratch); - return result; -} - -internal FuzzyMatchRangeList -fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src) -{ - FuzzyMatchRangeList dst = {0}; - for(FuzzyMatchRangeNode *src_n = src->first; src_n != 0; src_n = src_n->next) - { - FuzzyMatchRangeNode *dst_n = push_array(arena, FuzzyMatchRangeNode, 1); - SLLQueuePush(dst.first, dst.last, dst_n); - dst_n->range = src_n->range; - } - dst.count = src->count; - dst.needle_part_count = src->needle_part_count; - dst.total_dim = src->total_dim; - return dst; -} - -//////////////////////////////// -//~ NOTE(allen): Serialization Helpers - -internal void -str8_serial_begin(Arena *arena, String8List *srl){ - String8Node *node = push_array(arena, String8Node, 1); - node->string.str = push_array_no_zero(arena, U8, 0); - srl->first = srl->last = node; - srl->node_count = 1; - srl->total_size = 0; -} - -internal String8 -str8_serial_end(Arena *arena, String8List *srl){ - U64 size = srl->total_size; - U8 *out = push_array_no_zero(arena, U8, size); - str8_serial_write_to_dst(srl, out); - String8 result = str8(out, size); - return result; -} - -internal void -str8_serial_write_to_dst(String8List *srl, void *out){ - U8 *ptr = (U8*)out; - for (String8Node *node = srl->first; - node != 0; - node = node->next){ - U64 size = node->string.size; - MemoryCopy(ptr, node->string.str, size); - ptr += size; - } -} - -internal U64 -str8_serial_push_align(Arena *arena, String8List *srl, U64 align){ - Assert(IsPow2(align)); - - U64 pos = srl->total_size; - U64 new_pos = AlignPow2(pos, align); - U64 size = (new_pos - pos); - - if(size != 0) - { - U8 *buf = push_array(arena, U8, size); - - String8 *str = &srl->last->string; - if (str->str + str->size == buf){ - srl->last->string.size += size; - srl->total_size += size; - } - else{ - str8_list_push(arena, srl, str8(buf, size)); - } - } - return size; -} - -internal void * -str8_serial_push_size(Arena *arena, String8List *srl, U64 size) -{ - void *result = 0; - if(size != 0) - { - U8 *buf = push_array_no_zero(arena, U8, size); - String8 *str = &srl->last->string; - if (str->str + str->size == buf){ - srl->last->string.size += size; - srl->total_size += size; - } - else{ - str8_list_push(arena, srl, str8(buf, size)); - } - result = buf; - } - return result; -} - -internal void * -str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size){ - void *result = str8_serial_push_size(arena, srl, size); - if(result != 0) - { - MemoryCopy(result, data, size); - } - return result; -} - -internal void -str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first){ - for (String8Node *node = first; - node != 0; - node = node->next){ - str8_serial_push_data(arena, srl, node->string.str, node->string.size); - } -} - -internal void -str8_serial_push_u64(Arena *arena, String8List *srl, U64 x){ - U8 *buf = push_array_no_zero(arena, U8, 8); - MemoryCopy(buf, &x, 8); - String8 *str = &srl->last->string; - if (str->str + str->size == buf){ - srl->last->string.size += 8; - srl->total_size += 8; - } - else{ - str8_list_push(arena, srl, str8(buf, 8)); - } -} - -internal void -str8_serial_push_u32(Arena *arena, String8List *srl, U32 x){ - U8 *buf = push_array_no_zero(arena, U8, 4); - MemoryCopy(buf, &x, 4); - String8 *str = &srl->last->string; - if (str->str + str->size == buf){ - srl->last->string.size += 4; - srl->total_size += 4; - } - else{ - str8_list_push(arena, srl, str8(buf, 4)); - } -} - -internal void -str8_serial_push_u16(Arena *arena, String8List *srl, U16 x){ - str8_serial_push_data(arena, srl, &x, sizeof(x)); -} - -internal void -str8_serial_push_u8(Arena *arena, String8List *srl, U8 x){ - str8_serial_push_data(arena, srl, &x, sizeof(x)); -} - -internal void -str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str){ - str8_serial_push_data(arena, srl, str.str, str.size); - str8_serial_push_u8(arena, srl, 0); -} - -internal void -str8_serial_push_string(Arena *arena, String8List *srl, String8 str){ - str8_serial_push_data(arena, srl, str.str, str.size); -} - -//////////////////////////////// -//~ rjf: Deserialization Helpers - -internal U64 -str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity) -{ - U64 bytes_left = string.size-Min(off, string.size); - U64 actually_readable_size = Min(bytes_left, read_size); - U64 legally_readable_size = actually_readable_size - actually_readable_size%granularity; - if(legally_readable_size > 0) - { - MemoryCopy(read_dst, string.str+off, legally_readable_size); - } - return legally_readable_size; -} - -internal U64 -str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val) -{ - U64 cursor = off; - for (;;) { - U16 val = 0; - str8_deserial_read_struct(string, cursor, &val); - if (val == scan_val) { - break; - } - cursor += sizeof(val); - } - return cursor; -} - -internal void * -str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size) -{ - void *raw_ptr = 0; - if (off + size <= string.size) { - raw_ptr = string.str + off; - } - return raw_ptr; -} - -internal U64 -str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out) -{ - U64 cstr_size = 0; - if (off < string.size) { - U8 *ptr = string.str + off; - U8 *cap = string.str + string.size; - *cstr_out = str8_cstring_capped(ptr, cap); - cstr_size = (cstr_out->size + 1); - } - return cstr_size; -} - -internal U64 -str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out) -{ - U64 null_off = str8_deserial_find_first_match(string, off, 0); - U64 size = null_off - off; - U16 *str = (U16 *)str8_deserial_get_raw_ptr(string, off, size); - U64 count = size / sizeof(*str); - *str_out = str16(str, count); - - U64 read_size_with_null = size + sizeof(*str); - return read_size_with_null; -} - -internal U64 -str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out) -{ - Rng1U64 range = rng_1u64(off, off + size); - *block_out = str8_substr(string, range); - return block_out->size; -} - -internal U64 -str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out) -{ - U64 value = 0; - U64 shift = 0; - U64 cursor = off; - for(;;) - { - U8 byte = 0; - U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte); - - if(bytes_read != sizeof(byte)) - { - break; - } - - U8 val = byte & 0x7fu; - value |= ((U64)val) << shift; - - cursor += bytes_read; - shift += 7u; - - if((byte & 0x80u) == 0) - { - break; - } - } - if(value_out != 0) - { - *value_out = value; - } - U64 bytes_read = cursor - off; - return bytes_read; -} - -internal U64 -str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out) -{ - U64 value = 0; - U64 shift = 0; - U64 cursor = off; - for(;;) - { - U8 byte; - U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte); - if(bytes_read != sizeof(byte)) - { - break; - } - - U8 val = byte & 0x7fu; - value |= ((U64)val) << shift; - - cursor += bytes_read; - shift += 7u; - - if((byte & 0x80u) == 0) - { - if(shift < sizeof(value) * 8 && (byte & 0x40u) != 0) - { - value |= -(S64)(1ull << shift); - } - break; - } - } - if(value_out != 0) - { - *value_out = value; - } - U64 bytes_read = cursor - off; - return bytes_read; -} - diff --git a/src/metagen/metagen_base/metagen_base_strings.h b/src/metagen/metagen_base/metagen_base_strings.h deleted file mode 100644 index fc946dd8..00000000 --- a/src/metagen/metagen_base/metagen_base_strings.h +++ /dev/null @@ -1,412 +0,0 @@ -// 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_Null, - 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); -internal String16 str16_cstring_capped(void *cstr, void *cap); -internal String8 str8_cstring_capped_reverse(void *raw_start, void *raw_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 U64 str8_find_needle_reverse(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 U32 u32_from_str8(String8 string, U32 radix); -internal S32 s32_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 size); -internal String8 str8_from_count(Arena *arena, U64 count); -internal String8 str8_from_bits_u32(Arena *arena, U32 x); -internal String8 str8_from_bits_u64(Arena *arena, U64 x); -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); - -//////////////////////////////// -//~ String -> Enum Conversions - -internal OperatingSystem operating_system_from_string(String8 string); - -//////////////////////////////// -//~ 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_arch(Arch 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); - -//////////////////////////////// -//~ Globally Unique Ids - -internal String8 string_from_guid(Arena *arena, Guid guid); -internal B32 try_guid_from_string(String8 string, Guid *guid_out); -internal Guid guid_from_string(String8 string); - -//////////////////////////////// -//~ rjf: Basic Text Indentation - -internal String8 indented_from_string(Arena *arena, String8 string); - -//////////////////////////////// -//~ rjf: Text Escaping - -internal String8 escaped_from_raw_str8(Arena *arena, String8 string); -internal String8 raw_from_escaped_str8(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); -internal U64 str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out); -internal U64 str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_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_array(string, off, ptr, 1) - -#endif // BASE_STRINGS_H diff --git a/src/metagen/metagen_base/metagen_base_thread_context.c b/src/metagen/metagen_base/metagen_base_thread_context.c deleted file mode 100644 index 1a3f84ed..00000000 --- a/src/metagen/metagen_base/metagen_base_thread_context.c +++ /dev/null @@ -1,87 +0,0 @@ -// 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; -} diff --git a/src/metagen/metagen_base/metagen_base_thread_context.h b/src/metagen/metagen_base/metagen_base_thread_context.h deleted file mode 100644 index b2515c93..00000000 --- a/src/metagen/metagen_base/metagen_base_thread_context.h +++ /dev/null @@ -1,41 +0,0 @@ -// 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 countt); - -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 diff --git a/src/metagen/metagen_main.c b/src/metagen/metagen_main.c index 1c19ac5d..9d9a1e78 100644 --- a/src/metagen/metagen_main.c +++ b/src/metagen/metagen_main.c @@ -10,14 +10,12 @@ //~ rjf: Includes //- rjf: headers -#include "metagen/metagen_base/metagen_base_inc.h" -#include "metagen/metagen_os/metagen_os_inc.h" +#include "base/base_inc.h" #include "mdesk/mdesk.h" #include "metagen.h" //- rjf: impls -#include "metagen/metagen_base/metagen_base_inc.c" -#include "metagen/metagen_os/metagen_os_inc.c" +#include "base/base_inc.c" #include "mdesk/mdesk.c" #include "metagen.c" @@ -39,9 +37,9 @@ entry_point(CmdLine *cmdline) ////////////////////////////// //- rjf: extract paths // - String8 build_dir_path = os_get_process_info()->binary_path; + String8 build_dir_path = get_process_info()->binary_path; String8 project_dir_path = str8_chop_last_slash(build_dir_path); - String8 code_dir_path = push_str8f(mg_arena, "%S/src", project_dir_path); + String8 code_dir_path = str8f(mg_arena, "%S/src", project_dir_path); ////////////////////////////// //- rjf: search code directories for all files to consider @@ -60,8 +58,8 @@ entry_point(CmdLine *cmdline) Task *last_task = &start_task; for(Task *task = first_task; task != 0; task = task->next) { - OS_FileIter *it = os_file_iter_begin(mg_arena, task->path, 0); - for(OS_FileInfo info = {0}; os_file_iter_next(mg_arena, it, &info);) + FileIter *it = file_iter_begin(mg_arena, task->path, 0); + for(FileInfo info = {0}; file_iter_next(mg_arena, it, &info);) { String8 file_path = push_str8f(mg_arena, "%S/%S", task->path, info.name); if(info.props.flags & FilePropertyFlag_IsFolder) @@ -75,7 +73,7 @@ entry_point(CmdLine *cmdline) str8_list_push(mg_arena, &file_paths, file_path); } } - os_file_iter_end(it); + file_iter_end(it); } } @@ -91,7 +89,7 @@ entry_point(CmdLine *cmdline) String8 file_ext = str8_skip_last_dot(file_path); if(str8_match(file_ext, str8_lit("mdesk"), 0)) { - String8 data = os_data_from_file_path(mg_arena, file_path); + String8 data = data_from_file_path(mg_arena, file_path); MD_TokenizeResult tokenize = md_tokenize_from_text(mg_arena, data); MD_ParseResult parse = md_parse_from_text_tokens(mg_arena, file_path, data, tokenize.tokens); for(MD_Msg *m = parse.msgs.first; m != 0; m = m->next) @@ -421,7 +419,7 @@ entry_point(CmdLine *cmdline) { String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); - String8 data = os_data_from_file_path(mg_arena, node->first->string); + String8 data = data_from_file_path(mg_arena, node->first->string); String8 embed_string = mg_c_array_literal_contents_from_data(data); str8_list_pushf(mg_arena, &layer->h_tables, "read_only global U8 %S__data[] =\n{\n", node->string); str8_list_push (mg_arena, &layer->h_tables, embed_string); @@ -517,7 +515,7 @@ entry_point(CmdLine *cmdline) String8 gen_folder = str8_lit("generated"); layer_generated_folder = push_str8f(mg_arena, "%S/%S/%S", code_dir_path, layer->key, gen_folder); } - if(os_make_directory(layer_generated_folder)) + if(make_directory(layer_generated_folder)) { String8List layer_key_parts = str8_split_path(mg_arena, layer->key); StringJoin join = {0}; diff --git a/src/metagen/metagen_os/core/linux/metagen_os_core_linux.c b/src/metagen/metagen_os/core/linux/metagen_os_core_linux.c deleted file mode 100644 index 23ec77cf..00000000 --- a/src/metagen/metagen_os/core/linux/metagen_os_core_linux.c +++ /dev/null @@ -1,1337 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Helpers - -internal DateTime -os_lnx_date_time_from_tm(tm in, U32 msec) -{ - DateTime dt = {0}; - dt.sec = in.tm_sec; - dt.min = in.tm_min; - dt.hour = in.tm_hour; - dt.day = in.tm_mday-1; - dt.mon = in.tm_mon; - dt.year = in.tm_year+1900; - dt.msec = msec; - return dt; -} - -internal tm -os_lnx_tm_from_date_time(DateTime dt) -{ - tm result = {0}; - result.tm_sec = dt.sec; - result.tm_min = dt.min; - result.tm_hour= dt.hour; - result.tm_mday= dt.day+1; - result.tm_mon = dt.mon; - result.tm_year= dt.year-1900; - return result; -} - -internal timespec -os_lnx_timespec_from_date_time(DateTime dt) -{ - tm tm_val = os_lnx_tm_from_date_time(dt); - time_t seconds = timegm(&tm_val); - timespec result = {0}; - result.tv_sec = seconds; - return result; -} - -internal DenseTime -os_lnx_dense_time_from_timespec(timespec in) -{ - DenseTime result = 0; - { - struct tm tm_time = {0}; - gmtime_r(&in.tv_sec, &tm_time); - DateTime date_time = os_lnx_date_time_from_tm(tm_time, in.tv_nsec/Million(1)); - result = dense_time_from_date_time(date_time); - } - return result; -} - -internal FileProperties -os_lnx_file_properties_from_stat(struct stat *s) -{ - FileProperties props = {0}; - props.size = s->st_size; - props.created = os_lnx_dense_time_from_timespec(s->st_ctim); - props.modified = os_lnx_dense_time_from_timespec(s->st_mtim); - if(s->st_mode & S_IFDIR) - { - props.flags |= FilePropertyFlag_IsFolder; - } - return props; -} - -internal void -os_lnx_safe_call_sig_handler(int x) -{ - OS_LNX_SafeCallChain *chain = os_lnx_safe_call_chain; - if(chain != 0 && chain->fail_handler != 0) - { - chain->fail_handler(chain->ptr); - } - abort(); -} - -//////////////////////////////// -//~ rjf: Entities - -internal OS_LNX_Entity * -os_lnx_entity_alloc(OS_LNX_EntityKind kind) -{ - OS_LNX_Entity *entity = 0; - DeferLoop(pthread_mutex_lock(&os_lnx_state.entity_mutex), - pthread_mutex_unlock(&os_lnx_state.entity_mutex)) - { - entity = os_lnx_state.entity_free; - if(entity) - { - SLLStackPop(os_lnx_state.entity_free); - } - else - { - entity = push_array_no_zero(os_lnx_state.entity_arena, OS_LNX_Entity, 1); - } - } - MemoryZeroStruct(entity); - entity->kind = kind; - return entity; -} - -internal void -os_lnx_entity_release(OS_LNX_Entity *entity) -{ - DeferLoop(pthread_mutex_lock(&os_lnx_state.entity_mutex), - pthread_mutex_unlock(&os_lnx_state.entity_mutex)) - { - SLLStackPush(os_lnx_state.entity_free, entity); - } -} - -//////////////////////////////// -//~ rjf: Thread Entry Point - -internal void * -os_lnx_thread_entry_point(void *ptr) -{ - OS_LNX_Entity *entity = (OS_LNX_Entity *)ptr; - OS_ThreadFunctionType *func = entity->thread.func; - void *thread_ptr = entity->thread.ptr; - TCTX tctx_; - tctx_init_and_equip(&tctx_); - func(thread_ptr); - tctx_release(); - return 0; -} - -//////////////////////////////// -//~ rjf: @os_hooks System/Process Info (Implemented Per-OS) - -internal OS_SystemInfo * -os_get_system_info(void) -{ - return &os_lnx_state.system_info; -} - -internal OS_ProcessInfo * -os_get_process_info(void) -{ - return &os_lnx_state.process_info; -} - -internal String8 -os_get_current_path(Arena *arena) -{ - char *cwdir = getcwd(0, 0); - String8 string = push_str8_copy(arena, str8_cstring(cwdir)); - free(cwdir); - return string; -} - -internal U32 -os_get_process_start_time_unix(void) -{ - Temp scratch = scratch_begin(0,0); - U64 start_time = 0; - pid_t pid = getpid(); - String8 path = push_str8f(scratch.arena, "/proc/%u", pid); - struct stat st; - int err = stat((char*)path.str, &st); - if(err == 0) - { - start_time = st.st_mtime; - } - scratch_end(scratch); - return (U32)start_time; -} - -//////////////////////////////// -//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) - -//- rjf: basic - -internal void * -os_reserve(U64 size) -{ - void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - if(result == MAP_FAILED) - { - result = 0; - } - return result; -} - -internal B32 -os_commit(void *ptr, U64 size) -{ - mprotect(ptr, size, PROT_READ|PROT_WRITE); - return 1; -} - -internal void -os_decommit(void *ptr, U64 size) -{ - madvise(ptr, size, MADV_DONTNEED); - mprotect(ptr, size, PROT_NONE); -} - -internal void -os_release(void *ptr, U64 size) -{ - munmap(ptr, size); -} - -//- rjf: large pages - -internal void * -os_reserve_large(U64 size) -{ - void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0); - if(result == MAP_FAILED) - { - result = 0; - } - return result; -} - -internal B32 -os_commit_large(void *ptr, U64 size) -{ - mprotect(ptr, size, PROT_READ|PROT_WRITE); - return 1; -} - -//////////////////////////////// -//~ rjf: @os_hooks Thread Info (Implemented Per-OS) - -internal U32 -os_tid(void) -{ - U32 result = gettid(); - return result; -} - -internal void -os_set_thread_name(String8 name) -{ - Temp scratch = scratch_begin(0, 0); - String8 name_copy = push_str8_copy(scratch.arena, name); - pthread_t current_thread = pthread_self(); - pthread_setname_np(current_thread, (char *)name_copy.str); - scratch_end(scratch); -} - -//////////////////////////////// -//~ rjf: @os_hooks Aborting (Implemented Per-OS) - -internal void -os_abort(S32 exit_code) -{ - exit(exit_code); -} - -//////////////////////////////// -//~ rjf: @os_hooks File System (Implemented Per-OS) - -//- rjf: files - -internal OS_Handle -os_file_open(OS_AccessFlags flags, String8 path) -{ - Temp scratch = scratch_begin(0, 0); - String8 path_copy = push_str8_copy(scratch.arena, path); - int lnx_flags = 0; - if(flags & OS_AccessFlag_Read && flags & OS_AccessFlag_Write) - { - lnx_flags = O_RDWR; - } - else if(flags & OS_AccessFlag_Write) - { - lnx_flags = O_WRONLY; - } - else if(flags & OS_AccessFlag_Read) - { - lnx_flags = O_RDONLY; - } - if(flags & OS_AccessFlag_Append) - { - lnx_flags |= O_APPEND; - } - if(flags & (OS_AccessFlag_Write|OS_AccessFlag_Append)) - { - lnx_flags |= O_CREAT; - } - int fd = open((char *)path_copy.str, lnx_flags, 0755); - OS_Handle handle = {0}; - if(fd != -1) - { - handle.u64[0] = fd; - } - scratch_end(scratch); - return handle; -} - -internal void -os_file_close(OS_Handle file) -{ - if(os_handle_match(file, os_handle_zero())) { return; } - int fd = (int)file.u64[0]; - close(fd); -} - -internal U64 -os_file_read(OS_Handle file, Rng1U64 rng, void *out_data) -{ - if(os_handle_match(file, os_handle_zero())) { return 0; } - int fd = (int)file.u64[0]; - U64 total_num_bytes_to_read = dim_1u64(rng); - U64 total_num_bytes_read = 0; - U64 total_num_bytes_left_to_read = total_num_bytes_to_read; - for(;total_num_bytes_left_to_read > 0;) - { - int read_result = pread(fd, (U8 *)out_data + total_num_bytes_read, total_num_bytes_left_to_read, rng.min + total_num_bytes_read); - if(read_result >= 0) - { - total_num_bytes_read += read_result; - total_num_bytes_left_to_read -= read_result; - } - else if(errno != EINTR) - { - break; - } - } - return total_num_bytes_read; -} - -internal U64 -os_file_write(OS_Handle file, Rng1U64 rng, void *data) -{ - if(os_handle_match(file, os_handle_zero())) { return 0; } - int fd = (int)file.u64[0]; - U64 total_num_bytes_to_write = dim_1u64(rng); - U64 total_num_bytes_written = 0; - U64 total_num_bytes_left_to_write = total_num_bytes_to_write; - for(;total_num_bytes_left_to_write > 0;) - { - int write_result = pwrite(fd, (U8 *)data + total_num_bytes_written, total_num_bytes_left_to_write, rng.min + total_num_bytes_written); - if(write_result >= 0) - { - total_num_bytes_written += write_result; - total_num_bytes_left_to_write -= write_result; - } - else if(errno != EINTR) - { - break; - } - } - return total_num_bytes_written; -} - -internal B32 -os_file_set_times(OS_Handle file, DateTime date_time) -{ - if(os_handle_match(file, os_handle_zero())) { return 0; } - int fd = (int)file.u64[0]; - timespec time = os_lnx_timespec_from_date_time(date_time); - timespec times[2] = {time, time}; - int futimens_result = futimens(fd, times); - B32 good = (futimens_result != -1); - return good; -} - -internal FileProperties -os_properties_from_file(OS_Handle file) -{ - if(os_handle_match(file, os_handle_zero())) { return (FileProperties){0}; } - int fd = (int)file.u64[0]; - struct stat fd_stat = {0}; - int fstat_result = fstat(fd, &fd_stat); - FileProperties props = {0}; - if(fstat_result != -1) - { - props = os_lnx_file_properties_from_stat(&fd_stat); - } - return props; -} - -internal OS_FileID -os_id_from_file(OS_Handle file) -{ - if(os_handle_match(file, os_handle_zero())) { return (OS_FileID){0}; } - int fd = (int)file.u64[0]; - struct stat fd_stat = {0}; - int fstat_result = fstat(fd, &fd_stat); - OS_FileID id = {0}; - if(fstat_result != -1) - { - id.v[0] = fd_stat.st_dev; - id.v[1] = fd_stat.st_ino; - } - return id; -} - -internal B32 -os_delete_file_at_path(String8 path) -{ - Temp scratch = scratch_begin(0, 0); - B32 result = 0; - String8 path_copy = push_str8_copy(scratch.arena, path); - if(remove((char*)path_copy.str) != -1) - { - result = 1; - } - scratch_end(scratch); - return result; -} - -internal B32 -os_copy_file_path(String8 dst, String8 src) -{ - B32 result = 0; - OS_Handle src_h = os_file_open(OS_AccessFlag_Read, src); - OS_Handle dst_h = os_file_open(OS_AccessFlag_Write, dst); - if(!os_handle_match(src_h, os_handle_zero()) && - !os_handle_match(dst_h, os_handle_zero())) - { - int src_fd = (int)src_h.u64[0]; - int dst_fd = (int)dst_h.u64[0]; - FileProperties src_props = os_properties_from_file(src_h); - U64 size = src_props.size; - U64 total_bytes_copied = 0; - U64 bytes_left_to_copy = size; - for(;bytes_left_to_copy > 0;) - { - off_t sendfile_off = total_bytes_copied; - int send_result = sendfile(dst_fd, src_fd, &sendfile_off, bytes_left_to_copy); - if(send_result <= 0) - { - break; - } - U64 bytes_copied = (U64)send_result; - bytes_left_to_copy -= bytes_copied; - total_bytes_copied += bytes_copied; - } - } - os_file_close(src_h); - os_file_close(dst_h); - return result; -} - -internal B32 -os_move_file_path(String8 dst, String8 src) -{ - // TODO(rjf) - return 0; -} - -internal String8 -os_full_path_from_path(Arena *arena, String8 path) -{ - Temp scratch = scratch_begin(&arena, 1); - String8 path_copy = push_str8_copy(scratch.arena, path); - char buffer[PATH_MAX] = {0}; - realpath((char *)path_copy.str, buffer); - String8 result = push_str8_copy(arena, str8_cstring(buffer)); - scratch_end(scratch); - return result; -} - -internal B32 -os_file_path_exists(String8 path) -{ - Temp scratch = scratch_begin(0, 0); - String8 path_copy = push_str8_copy(scratch.arena, path); - int access_result = access((char *)path_copy.str, F_OK); - B32 result = 0; - if(access_result == 0) - { - result = 1; - } - scratch_end(scratch); - return result; -} - -internal B32 -os_folder_path_exists(String8 path) -{ - Temp scratch = scratch_begin(0, 0); - B32 exists = 0; - String8 path_copy = push_str8_copy(scratch.arena, path); - DIR *handle = opendir((char*)path_copy.str); - if(handle) - { - closedir(handle); - exists = 1; - } - scratch_end(scratch); - return exists; -} - -internal FileProperties -os_properties_from_file_path(String8 path) -{ - Temp scratch = scratch_begin(0, 0); - String8 path_copy = push_str8_copy(scratch.arena, path); - struct stat f_stat = {0}; - int stat_result = stat((char *)path_copy.str, &f_stat); - FileProperties props = {0}; - if(stat_result != -1) - { - props = os_lnx_file_properties_from_stat(&f_stat); - } - scratch_end(scratch); - return props; -} - -//- rjf: file maps - -internal OS_Handle -os_file_map_open(OS_AccessFlags flags, OS_Handle file) -{ - OS_Handle map = file; - return map; -} - -internal void -os_file_map_close(OS_Handle map) -{ - // NOTE(rjf): nothing to do; `map` handles are the same as `file` handles in - // the linux implementation (on Windows they require separate handles) -} - -internal void * -os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range) -{ - if(os_handle_match(map, os_handle_zero())) { return 0; } - int fd = (int)map.u64[0]; - int prot_flags = 0; - if(flags & OS_AccessFlag_Write) { prot_flags |= PROT_WRITE; } - if(flags & OS_AccessFlag_Read) { prot_flags |= PROT_READ; } - int map_flags = MAP_PRIVATE; - void *base = mmap(0, dim_1u64(range), prot_flags, map_flags, fd, range.min); - if(base == MAP_FAILED) - { - base = 0; - } - return base; -} - -internal void -os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range) -{ - munmap(ptr, dim_1u64(range)); -} - -//- rjf: directory iteration - -internal OS_FileIter * -os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) -{ - OS_FileIter *base_iter = push_array(arena, OS_FileIter, 1); - base_iter->flags = flags; - OS_LNX_FileIter *iter = (OS_LNX_FileIter *)base_iter->memory; - { - String8 path_copy = push_str8_copy(arena, path); - iter->dir = opendir((char *)path_copy.str); - iter->path = path_copy; - } - return base_iter; -} - -internal B32 -os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out) -{ - B32 good = 0; - OS_LNX_FileIter *lnx_iter = (OS_LNX_FileIter *)iter->memory; - for(;;) - { - // rjf: get next entry - lnx_iter->dp = readdir(lnx_iter->dir); - good = (lnx_iter->dp != 0); - - // rjf: unpack entry info - struct stat st = {0}; - int stat_result = 0; - if(good) - { - Temp scratch = scratch_begin(&arena, 1); - String8 full_path = push_str8f(scratch.arena, "%S/%s", lnx_iter->path, lnx_iter->dp->d_name); - stat_result = stat((char *)full_path.str, &st); - scratch_end(scratch); - } - - // rjf: determine if filtered - B32 filtered = 0; - if(good) - { - filtered = ((st.st_mode == S_IFDIR && iter->flags & OS_FileIterFlag_SkipFolders) || - (st.st_mode == S_IFREG && iter->flags & OS_FileIterFlag_SkipFiles) || - (lnx_iter->dp->d_name[0] == '.' && lnx_iter->dp->d_name[1] == 0) || - (lnx_iter->dp->d_name[0] == '.' && lnx_iter->dp->d_name[1] == '.' && lnx_iter->dp->d_name[2] == 0)); - } - - // rjf: output & exit, if good & unfiltered - if(good && !filtered) - { - info_out->name = push_str8_copy(arena, str8_cstring(lnx_iter->dp->d_name)); - if(stat_result != -1) - { - info_out->props = os_lnx_file_properties_from_stat(&st); - } - break; - } - - // rjf: exit if not good - if(!good) - { - break; - } - } - return good; -} - -internal void -os_file_iter_end(OS_FileIter *iter) -{ - OS_LNX_FileIter *lnx_iter = (OS_LNX_FileIter *)iter->memory; - closedir(lnx_iter->dir); -} - -//- rjf: directory creation - -internal B32 -os_make_directory(String8 path) -{ - Temp scratch = scratch_begin(0, 0); - B32 result = 0; - String8 path_copy = push_str8_copy(scratch.arena, path); - if(mkdir((char*)path_copy.str, 0755) != -1) - { - result = 1; - } - scratch_end(scratch); - return result; -} - -//////////////////////////////// -//~ rjf: @os_hooks Shared Memory (Implemented Per-OS) - -internal OS_Handle -os_shared_memory_alloc(U64 size, String8 name) -{ - Temp scratch = scratch_begin(0, 0); - String8 name_copy = push_str8_copy(scratch.arena, name); - int id = shm_open((char *)name_copy.str, O_RDWR, 0); - ftruncate(id, size); - OS_Handle result = {(U64)id}; - scratch_end(scratch); - return result; -} - -internal OS_Handle -os_shared_memory_open(String8 name) -{ - Temp scratch = scratch_begin(0, 0); - String8 name_copy = push_str8_copy(scratch.arena, name); - int id = shm_open((char *)name_copy.str, O_RDWR, 0); - OS_Handle result = {(U64)id}; - scratch_end(scratch); - return result; -} - -internal void -os_shared_memory_close(OS_Handle handle) -{ - if(os_handle_match(handle, os_handle_zero())){return;} - int id = (int)handle.u64[0]; - close(id); -} - -internal void * -os_shared_memory_view_open(OS_Handle handle, Rng1U64 range) -{ - if(os_handle_match(handle, os_handle_zero())){return 0;} - int id = (int)handle.u64[0]; - void *base = mmap(0, dim_1u64(range), PROT_READ|PROT_WRITE, MAP_SHARED, id, range.min); - if(base == MAP_FAILED) - { - base = 0; - } - return base; -} - -internal void -os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range) -{ - if(os_handle_match(handle, os_handle_zero())){return;} - munmap(ptr, dim_1u64(range)); -} - -//////////////////////////////// -//~ rjf: @os_hooks Time (Implemented Per-OS) - -internal U64 -os_now_microseconds(void) -{ - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - U64 result = t.tv_sec*Million(1) + (t.tv_nsec/Thousand(1)); - return result; -} - -internal U32 -os_now_unix(void) -{ - time_t t = time(0); - return (U32)t; -} - -internal DateTime -os_now_universal_time(void) -{ - time_t t = 0; - time(&t); - struct tm universal_tm = {0}; - gmtime_r(&t, &universal_tm); - DateTime result = os_lnx_date_time_from_tm(universal_tm, 0); - return result; -} - -internal DateTime -os_universal_time_from_local(DateTime *date_time) -{ - // rjf: local DateTime -> universal time_t - tm local_tm = os_lnx_tm_from_date_time(*date_time); - local_tm.tm_isdst = -1; - time_t universal_t = mktime(&local_tm); - - // rjf: universal time_t -> DateTime - tm universal_tm = {0}; - gmtime_r(&universal_t, &universal_tm); - DateTime result = os_lnx_date_time_from_tm(universal_tm, 0); - return result; -} - -internal DateTime -os_local_time_from_universal(DateTime *date_time) -{ - // rjf: universal DateTime -> local time_t - tm universal_tm = os_lnx_tm_from_date_time(*date_time); - universal_tm.tm_isdst = -1; - time_t universal_t = timegm(&universal_tm); - tm local_tm = {0}; - localtime_r(&universal_t, &local_tm); - - // rjf: local tm -> DateTime - DateTime result = os_lnx_date_time_from_tm(local_tm, 0); - return result; -} - -internal void -os_sleep_milliseconds(U32 msec) -{ - usleep(msec*Thousand(1)); -} - -//////////////////////////////// -//~ rjf: @os_hooks Child Processes (Implemented Per-OS) - -internal OS_Handle -os_process_launch(OS_ProcessLaunchParams *params) -{ - NotImplemented; -} - -internal B32 -os_process_join(OS_Handle handle, U64 endt_us) -{ - NotImplemented; -} - -internal void -os_process_detach(OS_Handle handle) -{ - NotImplemented; -} - -//////////////////////////////// -//~ rjf: @os_hooks Threads (Implemented Per-OS) - -internal OS_Handle -os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params) -{ - OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Thread); - entity->thread.func = func; - entity->thread.ptr = ptr; - { - int pthread_result = pthread_create(&entity->thread.handle, 0, os_lnx_thread_entry_point, entity); - if(pthread_result == -1) - { - os_lnx_entity_release(entity); - entity = 0; - } - } - OS_Handle handle = {(U64)entity}; - return handle; -} - -internal B32 -os_thread_join(OS_Handle handle, U64 endt_us) -{ - if(os_handle_match(handle, os_handle_zero())) { return 0; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)handle.u64[0]; - int join_result = pthread_join(entity->thread.handle, 0); - B32 result = (join_result == 0); - os_lnx_entity_release(entity); - return result; -} - -internal void -os_thread_detach(OS_Handle handle) -{ - if(os_handle_match(handle, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)handle.u64[0]; - os_lnx_entity_release(entity); -} - -//////////////////////////////// -//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) - -//- rjf: mutexes - -internal OS_Handle -os_mutex_alloc(void) -{ - OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Mutex); - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - int init_result = pthread_mutex_init(&entity->mutex_handle, &attr); - pthread_mutexattr_destroy(&attr); - if(init_result == -1) - { - os_lnx_entity_release(entity); - entity = 0; - } - OS_Handle handle = {(U64)entity}; - return handle; -} - -internal void -os_mutex_release(OS_Handle mutex) -{ - if(os_handle_match(mutex, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; - pthread_mutex_destroy(&entity->mutex_handle); - os_lnx_entity_release(entity); -} - -internal void -os_mutex_take(OS_Handle mutex) -{ - if(os_handle_match(mutex, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; - pthread_mutex_lock(&entity->mutex_handle); -} - -internal void -os_mutex_drop(OS_Handle mutex) -{ - if(os_handle_match(mutex, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; - pthread_mutex_unlock(&entity->mutex_handle); -} - -//- rjf: reader/writer mutexes - -internal OS_Handle -os_rw_mutex_alloc(void) -{ - OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_RWMutex); - int init_result = pthread_rwlock_init(&entity->rwmutex_handle, 0); - if(init_result == -1) - { - os_lnx_entity_release(entity); - entity = 0; - } - OS_Handle handle = {(U64)entity}; - return handle; -} - -internal void -os_rw_mutex_release(OS_Handle rw_mutex) -{ - if(os_handle_match(rw_mutex, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; - pthread_rwlock_destroy(&entity->rwmutex_handle); - os_lnx_entity_release(entity); -} - -internal void -os_rw_mutex_take_r(OS_Handle rw_mutex) -{ - if(os_handle_match(rw_mutex, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; - pthread_rwlock_rdlock(&entity->rwmutex_handle); -} - -internal void -os_rw_mutex_drop_r(OS_Handle rw_mutex) -{ - if(os_handle_match(rw_mutex, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; - pthread_rwlock_unlock(&entity->rwmutex_handle); -} - -internal void -os_rw_mutex_take_w(OS_Handle rw_mutex) -{ - if(os_handle_match(rw_mutex, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; - pthread_rwlock_wrlock(&entity->rwmutex_handle); -} - -internal void -os_rw_mutex_drop_w(OS_Handle rw_mutex) -{ - if(os_handle_match(rw_mutex, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; - pthread_rwlock_unlock(&entity->rwmutex_handle); -} - -//- rjf: condition variables - -internal OS_Handle -os_condition_variable_alloc(void) -{ - OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_ConditionVariable); - int init_result = pthread_cond_init(&entity->cv.cond_handle, 0); - if(init_result == -1) - { - os_lnx_entity_release(entity); - entity = 0; - } - int init2_result = 0; - if(entity) - { - init2_result = pthread_mutex_init(&entity->cv.rwlock_mutex_handle, 0); - } - if(init2_result == -1) - { - pthread_cond_destroy(&entity->cv.cond_handle); - os_lnx_entity_release(entity); - entity = 0; - } - OS_Handle handle = {(U64)entity}; - return handle; -} - -internal void -os_condition_variable_release(OS_Handle cv) -{ - if(os_handle_match(cv, os_handle_zero())) { return; } - OS_LNX_Entity *entity = (OS_LNX_Entity *)cv.u64[0]; - pthread_cond_destroy(&entity->cv.cond_handle); - pthread_mutex_destroy(&entity->cv.rwlock_mutex_handle); - os_lnx_entity_release(entity); -} - -internal B32 -os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us) -{ - if(os_handle_match(cv, os_handle_zero())) { return 0; } - if(os_handle_match(mutex, os_handle_zero())) { return 0; } - OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; - OS_LNX_Entity *mutex_entity = (OS_LNX_Entity *)mutex.u64[0]; - struct timespec endt_timespec; - endt_timespec.tv_sec = endt_us/Million(1); - endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1)); - int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &mutex_entity->mutex_handle, &endt_timespec); - B32 result = (wait_result != ETIMEDOUT); - return result; -} - -internal B32 -os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) -{ - // TODO(rjf): because pthread does not supply cv/rw natively, I had to hack - // this together, but this would probably just be a lot better if we just - // implemented the primitives ourselves with e.g. futexes - // - if(os_handle_match(cv, os_handle_zero())) { return 0; } - if(os_handle_match(mutex_rw, os_handle_zero())) { return 0; } - OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; - OS_LNX_Entity *rw_mutex_entity = (OS_LNX_Entity *)mutex_rw.u64[0]; - struct timespec endt_timespec; - endt_timespec.tv_sec = endt_us/Million(1); - endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1)); - B32 result = 0; - for(;;) - { - pthread_mutex_lock(&cv_entity->cv.rwlock_mutex_handle); - int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &cv_entity->cv.rwlock_mutex_handle, &endt_timespec); - if(wait_result != ETIMEDOUT) - { - pthread_rwlock_rdlock(&rw_mutex_entity->rwmutex_handle); - pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); - result = 1; - break; - } - pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); - if(wait_result == ETIMEDOUT) - { - break; - } - } - return result; -} - -internal B32 -os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) -{ - // TODO(rjf): because pthread does not supply cv/rw natively, I had to hack - // this together, but this would probably just be a lot better if we just - // implemented the primitives ourselves with e.g. futexes - // - if(os_handle_match(cv, os_handle_zero())) { return 0; } - if(os_handle_match(mutex_rw, os_handle_zero())) { return 0; } - OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; - OS_LNX_Entity *rw_mutex_entity = (OS_LNX_Entity *)mutex_rw.u64[0]; - struct timespec endt_timespec; - endt_timespec.tv_sec = endt_us/Million(1); - endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1)); - B32 result = 0; - for(;;) - { - pthread_mutex_lock(&cv_entity->cv.rwlock_mutex_handle); - int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &cv_entity->cv.rwlock_mutex_handle, &endt_timespec); - if(wait_result != ETIMEDOUT) - { - pthread_rwlock_wrlock(&rw_mutex_entity->rwmutex_handle); - pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); - result = 1; - break; - } - pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); - if(wait_result == ETIMEDOUT) - { - break; - } - } - return result; -} - -internal void -os_condition_variable_signal(OS_Handle cv) -{ - if(os_handle_match(cv, os_handle_zero())) { return; } - OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; - pthread_cond_signal(&cv_entity->cv.cond_handle); -} - -internal void -os_condition_variable_broadcast(OS_Handle cv) -{ - if(os_handle_match(cv, os_handle_zero())) { return; } - OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; - pthread_cond_broadcast(&cv_entity->cv.cond_handle); -} - -//- rjf: cross-process semaphores - -internal OS_Handle -os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) -{ - OS_Handle result = {0}; - if (name.size > 0) { - // TODO: we need to allocate shared memory to store sem_t - NotImplemented; - } else { - sem_t *s = mmap(0, sizeof(*s), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - AssertAlways(s != MAP_FAILED); - int err = sem_init(s, 0, initial_count); - if (err == 0) { - result.u64[0] = (U64)s; - } - } - return result; -} - -internal void -os_semaphore_release(OS_Handle semaphore) -{ - int err = munmap((void*)semaphore.u64[0], sizeof(sem_t)); - AssertAlways(err == 0); -} - -internal OS_Handle -os_semaphore_open(String8 name) -{ - NotImplemented; -} - -internal void -os_semaphore_close(OS_Handle semaphore) -{ - NotImplemented; -} - -internal B32 -os_semaphore_take(OS_Handle semaphore, U64 endt_us) -{ - AssertAlways(endt_us == max_U64); - for (;;) { - int err = sem_wait((sem_t*)semaphore.u64[0]); - if (err == 0) { - break; - } else { - if (errno == EAGAIN) { - continue; - } - } - InvalidPath; - break; - } - return 1; -} - -internal void -os_semaphore_drop(OS_Handle semaphore) -{ - for (;;) { - int err = sem_post((sem_t*)semaphore.u64[0]); - if (err == 0) { - break; - } else { - if (errno == EAGAIN) { - continue; - } - } - InvalidPath; - break; - } -} - -//////////////////////////////// -//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) - -internal OS_Handle -os_library_open(String8 path) -{ - Temp scratch = scratch_begin(0, 0); - char *path_cstr = (char *)push_str8_copy(scratch.arena, path).str; - void *so = dlopen(path_cstr, RTLD_LAZY|RTLD_LOCAL); - OS_Handle lib = { (U64)so }; - scratch_end(scratch); - return lib; -} - -internal VoidProc* -os_library_load_proc(OS_Handle lib, String8 name) -{ - Temp scratch = scratch_begin(0, 0); - void *so = (void *)lib.u64; - char *name_cstr = (char *)push_str8_copy(scratch.arena, name).str; - VoidProc *proc = (VoidProc *)dlsym(so, name_cstr); - scratch_end(scratch); - return proc; -} - -internal void -os_library_close(OS_Handle lib) -{ - void *so = (void *)lib.u64; - dlclose(so); -} - -//////////////////////////////// -//~ rjf: @os_hooks Safe Calls (Implemented Per-OS) - -internal void -os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr) -{ - // rjf: push handler to chain - OS_LNX_SafeCallChain chain = {0}; - SLLStackPush(os_lnx_safe_call_chain, &chain); - chain.fail_handler = fail_handler; - chain.ptr = ptr; - - // rjf: set up sig handler info - struct sigaction new_act = {0}; - new_act.sa_handler = os_lnx_safe_call_sig_handler; - int signals_to_handle[] = - { - SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, - }; - struct sigaction og_act[ArrayCount(signals_to_handle)] = {0}; - - // rjf: attach handler info for all signals - for(U32 i = 0; i < ArrayCount(signals_to_handle); i += 1) - { - sigaction(signals_to_handle[i], &new_act, &og_act[i]); - } - - // rjf: call function - func(ptr); - - // rjf: reset handler info for all signals - for(U32 i = 0; i < ArrayCount(signals_to_handle); i += 1) - { - sigaction(signals_to_handle[i], &og_act[i], 0); - } -} - -//////////////////////////////// -//~ rjf: @os_hooks GUIDs (Implemented Per-OS) - -internal Guid -os_make_guid(void) -{ - Guid guid = {0}; - getrandom(guid.v, sizeof(guid.v), 0); - guid.data3 &= 0x0fff; - guid.data3 |= (4 << 12); - guid.data4[0] &= 0x3f; - guid.data4[0] |= 0x80; - return guid; -} - -//////////////////////////////// -//~ rjf: @os_hooks Entry Points (Implemented Per-OS) - -int -main(int argc, char **argv) -{ - //- rjf: set up OS layer - { - //- rjf: get statically-allocated system/process info - { - OS_SystemInfo *info = &os_lnx_state.system_info; - info->logical_processor_count = (U32)get_nprocs(); - info->page_size = (U64)getpagesize(); - info->large_page_size = MB(2); - info->allocation_granularity = info->page_size; - } - { - OS_ProcessInfo *info = &os_lnx_state.process_info; - info->pid = (U32)getpid(); - } - - //- rjf: set up thread context - local_persist TCTX tctx; - tctx_init_and_equip(&tctx); - - //- rjf: set up dynamically allocated state - os_lnx_state.arena = arena_alloc(); - os_lnx_state.entity_arena = arena_alloc(); - pthread_mutex_init(&os_lnx_state.entity_mutex, 0); - - //- rjf: grab dynamically allocated system info - { - Temp scratch = scratch_begin(0, 0); - OS_SystemInfo *info = &os_lnx_state.system_info; - - // rjf: get machine name - B32 got_final_result = 0; - U8 *buffer = 0; - int size = 0; - for(S64 cap = 4096, r = 0; r < 4; cap *= 2, r += 1) - { - scratch_end(scratch); - buffer = push_array_no_zero(scratch.arena, U8, cap); - size = gethostname((char*)buffer, cap); - if(size < cap) - { - got_final_result = 1; - break; - } - } - - // rjf: save name to info - if(got_final_result && size > 0) - { - info->machine_name.size = size; - info->machine_name.str = push_array_no_zero(os_lnx_state.arena, U8, info->machine_name.size + 1); - MemoryCopy(info->machine_name.str, buffer, info->machine_name.size); - info->machine_name.str[info->machine_name.size] = 0; - } - - scratch_end(scratch); - } - - //- rjf: grab dynamically allocated process info - { - Temp scratch = scratch_begin(0, 0); - OS_ProcessInfo *info = &os_lnx_state.process_info; - - // rjf: grab binary path - { - // rjf: get self string - B32 got_final_result = 0; - U8 *buffer = 0; - int size = 0; - for(S64 cap = PATH_MAX, r = 0; r < 4; cap *= 2, r += 1) - { - scratch_end(scratch); - buffer = push_array_no_zero(scratch.arena, U8, cap); - size = readlink("/proc/self/exe", (char*)buffer, cap); - if(size < cap) - { - got_final_result = 1; - break; - } - } - - // rjf: save - if(got_final_result && size > 0) - { - String8 full_name = str8(buffer, size); - String8 name_chopped = str8_chop_last_slash(full_name); - info->binary_path = push_str8_copy(os_lnx_state.arena, name_chopped); - } - } - - // rjf: grab initial directory - { - info->initial_path = os_get_current_path(os_lnx_state.arena); - } - - // rjf: grab home directory - { - char *home = getenv("HOME"); - info->user_program_data_path = str8_cstring(home); - } - - scratch_end(scratch); - } - } - - //- rjf: call into "real" entry point - main_thread_base_entry_point(argc, argv); -} diff --git a/src/metagen/metagen_os/core/linux/metagen_os_core_linux.h b/src/metagen/metagen_os/core/linux/metagen_os_core_linux.h deleted file mode 100644 index c939f2bd..00000000 --- a/src/metagen/metagen_os/core/linux/metagen_os_core_linux.h +++ /dev/null @@ -1,136 +0,0 @@ -// 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -pid_t gettid(void); -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 diff --git a/src/metagen/metagen_os/core/metagen_os_core.c b/src/metagen/metagen_os/core/metagen_os_core.c deleted file mode 100644 index 21a0a413..00000000 --- a/src/metagen/metagen_os/core/metagen_os_core.c +++ /dev/null @@ -1,240 +0,0 @@ -// 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: Process Launcher Helpers - -internal OS_Handle -os_cmd_line_launch(String8 string) -{ - Temp scratch = scratch_begin(0, 0); - U8 split_chars[] = {' '}; - String8List parts = str8_split(scratch.arena, string, split_chars, ArrayCount(split_chars), 0); - OS_Handle handle = {0}; - if(parts.node_count != 0) - { - // rjf: unpack exe part - String8 exe = parts.first->string; - String8 exe_folder = str8_chop_last_slash(exe); - if(exe_folder.size == 0) - { - exe_folder = os_get_current_path(scratch.arena); - } - - // rjf: find stdout delimiter - String8Node *stdout_delimiter_n = 0; - for(String8Node *n = parts.first; n != 0; n = n->next) - { - if(str8_match(n->string, str8_lit(">"), 0)) - { - stdout_delimiter_n = n; - break; - } - } - - // rjf: read stdout path - String8 stdout_path = {0}; - if(stdout_delimiter_n && stdout_delimiter_n->next) - { - stdout_path = stdout_delimiter_n->next->string; - } - - // rjf: open stdout handle - OS_Handle stdout_handle = {0}; - if(stdout_path.size != 0) - { - OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Read, stdout_path); - os_file_close(file); - stdout_handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, stdout_path); - } - - // rjf: form command line - String8List cmdline = {0}; - for(String8Node *n = parts.first; n != stdout_delimiter_n && n != 0; n = n->next) - { - str8_list_push(scratch.arena, &cmdline, n->string); - } - - // rjf: launch - OS_ProcessLaunchParams params = {0}; - params.cmd_line = cmdline; - params.path = exe_folder; - params.inherit_env = 1; - params.stdout_file = stdout_handle; - handle = os_process_launch(¶ms); - - // rjf: close stdout handle - { - if(stdout_path.size != 0) - { - os_file_close(stdout_handle); - } - } - } - scratch_end(scratch); - return handle; -} - -internal OS_Handle -os_cmd_line_launchf(char *fmt, ...) -{ - Temp scratch = scratch_begin(0, 0); - va_list args; - va_start(args, fmt); - String8 string = push_str8fv(scratch.arena, fmt, args); - OS_Handle result = os_cmd_line_launch(string); - va_end(args); - scratch_end(scratch); - return result; -} - diff --git a/src/metagen/metagen_os/core/metagen_os_core.h b/src/metagen/metagen_os/core/metagen_os_core.h deleted file mode 100644 index e3a02048..00000000 --- a/src/metagen/metagen_os/core/metagen_os_core.h +++ /dev/null @@ -1,335 +0,0 @@ -// 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; - B32 large_pages_allowed; - 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), - OS_AccessFlag_Inherited = (1<<6), -}; - -//////////////////////////////// -//~ 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: 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: Process Launch Parameters - -typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams; -struct OS_ProcessLaunchParams -{ - String8List cmd_line; - String8 path; - String8List env; - B32 inherit_env; - B32 debug_subprocesses; - B32 consoleless; - OS_Handle stdout_file; - OS_Handle stderr_file; - OS_Handle stdin_file; -}; - -//////////////////////////////// -//~ 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: Process Launcher Helpers - -internal OS_Handle os_cmd_line_launch(String8 string); -internal OS_Handle os_cmd_line_launchf(char *fmt, ...); - -//////////////////////////////// -//~ 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); -internal U32 os_get_process_start_time_unix(void); - -//////////////////////////////// -//~ 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); -#define os_file_read_struct(f, off, ptr) os_file_read((f), r1u64((off), (off)+sizeof(*(ptr))), (ptr)) -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_file_reserve_size(OS_Handle file, U64 size); -internal B32 os_delete_file_at_path(String8 path); -internal B32 os_copy_file_path(String8 dst, String8 src); -internal B32 os_move_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 B32 os_folder_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 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 diff --git a/src/metagen/metagen_os/core/win32/metagen_os_core_win32.c b/src/metagen/metagen_os/core/win32/metagen_os_core_win32.c deleted file mode 100644 index 6cc494f0..00000000 --- a/src/metagen/metagen_os/core/win32/metagen_os_core_win32.c +++ /dev/null @@ -1,1785 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Modern Windows SDK Functions -// -// (We must dynamically link to them, since they can be missing in older SDKs) - -typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDescription); -global W32_SetThreadDescription_Type *w32_SetThreadDescription_func = 0; - -//////////////////////////////// -//~ rjf: File Info Conversion Helpers - -internal FilePropertyFlags -os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes) -{ - FilePropertyFlags flags = 0; - if(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - flags |= FilePropertyFlag_IsFolder; - } - return flags; -} - -internal void -os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes) -{ - properties->size = Compose64Bit(attributes->nFileSizeHigh, attributes->nFileSizeLow); - os_w32_dense_time_from_file_time(&properties->created, &attributes->ftCreationTime); - os_w32_dense_time_from_file_time(&properties->modified, &attributes->ftLastWriteTime); - properties->flags = os_w32_file_property_flags_from_dwFileAttributes(attributes->dwFileAttributes); -} - -//////////////////////////////// -//~ rjf: Time Conversion Helpers - -internal void -os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in) -{ - out->year = in->wYear; - out->mon = in->wMonth - 1; - out->wday = in->wDayOfWeek; - out->day = in->wDay; - out->hour = in->wHour; - out->min = in->wMinute; - out->sec = in->wSecond; - out->msec = in->wMilliseconds; -} - -internal void -os_w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in) -{ - out->wYear = (WORD)(in->year); - out->wMonth = in->mon + 1; - out->wDay = in->day; - out->wHour = in->hour; - out->wMinute = in->min; - out->wSecond = in->sec; - out->wMilliseconds = in->msec; -} - -internal void -os_w32_dense_time_from_file_time(DenseTime *out, FILETIME *in) -{ - SYSTEMTIME systime = {0}; - FileTimeToSystemTime(in, &systime); - DateTime date_time = {0}; - os_w32_date_time_from_system_time(&date_time, &systime); - *out = dense_time_from_date_time(date_time); -} - -internal U32 -os_w32_sleep_ms_from_endt_us(U64 endt_us) -{ - U32 sleep_ms = 0; - if(endt_us == max_U64) - { - sleep_ms = INFINITE; - } - else - { - U64 begint = os_now_microseconds(); - if(begint < endt_us) - { - U64 sleep_us = endt_us - begint; - sleep_ms = (U32)((sleep_us + 999)/1000); - } - } - return sleep_ms; -} - -internal U32 -os_w32_unix_time_from_file_time(FILETIME file_time) -{ - U64 win32_time = ((U64)file_time.dwHighDateTime << 32) | file_time.dwLowDateTime; - U64 unix_time64 = ((win32_time - 0x19DB1DED53E8000ULL) / 10000000); - - Assert(unix_time64 <= max_U32); - U32 unix_time32 = (U32)unix_time64; - - return unix_time32; -} - -//////////////////////////////// -//~ rjf: Entity Functions - -internal OS_W32_Entity * -os_w32_entity_alloc(OS_W32_EntityKind kind) -{ - OS_W32_Entity *result = 0; - EnterCriticalSection(&os_w32_state.entity_mutex); - { - result = os_w32_state.entity_free; - if(result) - { - SLLStackPop(os_w32_state.entity_free); - } - else - { - result = push_array_no_zero(os_w32_state.entity_arena, OS_W32_Entity, 1); - } - MemoryZeroStruct(result); - } - LeaveCriticalSection(&os_w32_state.entity_mutex); - result->kind = kind; - return result; -} - -internal void -os_w32_entity_release(OS_W32_Entity *entity) -{ - entity->kind = OS_W32_EntityKind_Null; - EnterCriticalSection(&os_w32_state.entity_mutex); - SLLStackPush(os_w32_state.entity_free, entity); - LeaveCriticalSection(&os_w32_state.entity_mutex); -} - -//////////////////////////////// -//~ rjf: Thread Entry Point - -internal DWORD -os_w32_thread_entry_point(void *ptr) -{ - OS_W32_Entity *entity = (OS_W32_Entity *)ptr; - OS_ThreadFunctionType *func = entity->thread.func; - void *thread_ptr = entity->thread.ptr; - TCTX tctx_; - tctx_init_and_equip(&tctx_); - func(thread_ptr); - tctx_release(); - return 0; -} - -//////////////////////////////// -//~ rjf: @os_hooks System/Process Info (Implemented Per-OS) - -internal OS_SystemInfo * -os_get_system_info(void) -{ - return &os_w32_state.system_info; -} - -internal OS_ProcessInfo * -os_get_process_info(void) -{ - return &os_w32_state.process_info; -} - -internal String8 -os_get_current_path(Arena *arena) -{ - Temp scratch = scratch_begin(&arena, 1); - DWORD length = GetCurrentDirectoryW(0, 0); - U16 *memory = push_array_no_zero(scratch.arena, U16, length + 1); - length = GetCurrentDirectoryW(length + 1, (WCHAR*)memory); - String8 name = str8_from_16(arena, str16(memory, length)); - scratch_end(scratch); - return name; -} - -internal U32 -os_get_process_start_time_unix(void) -{ - HANDLE handle = GetCurrentProcess(); - FILETIME start_time = {0}; - FILETIME exit_time; - FILETIME kernel_time; - FILETIME user_time; - if(GetProcessTimes(handle, &start_time, &exit_time, &kernel_time, &user_time)) - { - return os_w32_unix_time_from_file_time(start_time); - } - return 0; -} - -//////////////////////////////// -//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) - -//- rjf: basic - -internal void * -os_reserve(U64 size) -{ - void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); - return result; -} - -internal B32 -os_commit(void *ptr, U64 size) -{ - B32 result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); - return result; -} - -internal void -os_decommit(void *ptr, U64 size) -{ - VirtualFree(ptr, size, MEM_DECOMMIT); -} - -internal void -os_release(void *ptr, U64 size) -{ - // NOTE(rjf): size not used - not necessary on Windows, but necessary for other OSes. - VirtualFree(ptr, 0, MEM_RELEASE); -} - -//- rjf: large pages - -internal void * -os_reserve_large(U64 size) -{ - // we commit on reserve because windows - void *result = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_LARGE_PAGES, PAGE_READWRITE); - return result; -} - -internal B32 -os_commit_large(void *ptr, U64 size) -{ - return 1; -} - -//////////////////////////////// -//~ rjf: @os_hooks Thread Info (Implemented Per-OS) - -internal U32 -os_tid(void) -{ - DWORD id = GetCurrentThreadId(); - return (U32)id; -} - -internal void -os_set_thread_name(String8 name) -{ - Temp scratch = scratch_begin(0, 0); - - // rjf: windows 10 style - if(w32_SetThreadDescription_func) - { - String16 name16 = str16_from_8(scratch.arena, name); - HRESULT hr = w32_SetThreadDescription_func(GetCurrentThread(), (WCHAR*)name16.str); - } - - // rjf: raise-exception style - { - String8 name_copy = push_str8_copy(scratch.arena, name); -#pragma pack(push,8) - typedef struct THREADNAME_INFO THREADNAME_INFO; - struct THREADNAME_INFO - { - U32 dwType; // Must be 0x1000. - char *szName; // Pointer to name (in user addr space). - U32 dwThreadID; // Thread ID (-1=caller thread). - U32 dwFlags; // Reserved for future use, must be zero. - }; -#pragma pack(pop) - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = (char *)name_copy.str; - info.dwThreadID = os_tid(); - info.dwFlags = 0; -#pragma warning(push) -#pragma warning(disable: 6320 6322) - __try - { - RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } -#pragma warning(pop) - } - - scratch_end(scratch); -} - -//////////////////////////////// -//~ rjf: @os_hooks Aborting (Implemented Per-OS) - -internal void -os_abort(S32 exit_code) -{ - ExitProcess(exit_code); -} - -//////////////////////////////// -//~ rjf: @os_hooks File System (Implemented Per-OS) - -//- rjf: files - -internal OS_Handle -os_file_open(OS_AccessFlags flags, String8 path) -{ - OS_Handle result = {0}; - Temp scratch = scratch_begin(0, 0); - String16 path16 = str16_from_8(scratch.arena, path); - DWORD access_flags = 0; - DWORD share_mode = 0; - DWORD creation_disposition = OPEN_EXISTING; - SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0}; - if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;} - if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;} - if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;} - if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;} - if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;} - if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;} - if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS; access_flags |= FILE_APPEND_DATA; } - if(flags & OS_AccessFlag_Inherited) - { - security_attributes.bInheritHandle = 1; - } - HANDLE file = CreateFileW((WCHAR *)path16.str, access_flags, share_mode, &security_attributes, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0); - if(file != INVALID_HANDLE_VALUE) - { - result.u64[0] = (U64)file; - } - scratch_end(scratch); - return result; -} - -internal void -os_file_close(OS_Handle file) -{ - if(os_handle_match(file, os_handle_zero())) { return; } - HANDLE handle = (HANDLE)file.u64[0]; - BOOL result = CloseHandle(handle); - (void)result; -} - -internal U64 -os_file_read(OS_Handle file, Rng1U64 rng, void *out_data) -{ - if(os_handle_match(file, os_handle_zero())) { return 0; } - HANDLE handle = (HANDLE)file.u64[0]; - - // rjf: clamp range by file size - U64 size = 0; - GetFileSizeEx(handle, (LARGE_INTEGER *)&size); - Rng1U64 rng_clamped = r1u64(ClampTop(rng.min, size), ClampTop(rng.max, size)); - U64 total_read_size = 0; - - // rjf: read loop - { - U64 to_read = dim_1u64(rng_clamped); - for(U64 off = rng.min; total_read_size < to_read;) - { - U64 amt64 = to_read - total_read_size; - U32 amt32 = u32_from_u64_saturate(amt64); - DWORD read_size = 0; - OVERLAPPED overlapped = {0}; - overlapped.Offset = (off&0x00000000ffffffffull); - overlapped.OffsetHigh = (off&0xffffffff00000000ull) >> 32; - ReadFile(handle, (U8 *)out_data + total_read_size, amt32, &read_size, &overlapped); - off += read_size; - total_read_size += read_size; - if(read_size != amt32) - { - break; - } - } - } - - return total_read_size; -} - -internal U64 -os_file_write(OS_Handle file, Rng1U64 rng, void *data) -{ - if(os_handle_match(file, os_handle_zero())) { return 0; } - HANDLE win_handle = (HANDLE)file.u64[0]; - U64 src_off = 0; - U64 dst_off = rng.min; - U64 total_write_size = dim_1u64(rng); - for(;;) - { - void *bytes_src = (U8 *)data + src_off; - U64 bytes_left = total_write_size - src_off; - DWORD write_size = Min(MB(1), bytes_left); - DWORD bytes_written = 0; - OVERLAPPED overlapped = {0}; - overlapped.Offset = (dst_off&0x00000000ffffffffull); - overlapped.OffsetHigh = (dst_off&0xffffffff00000000ull) >> 32; - BOOL success = WriteFile(win_handle, bytes_src, write_size, &bytes_written, &overlapped); - if(success == 0) - { - break; - } - src_off += bytes_written; - dst_off += bytes_written; - if(bytes_left == 0) - { - break; - } - } - return src_off; -} - -internal B32 -os_file_set_time(OS_Handle file, DateTime time) -{ - if(os_handle_match(file, os_handle_zero())) { return 0; } - B32 result = 0; - HANDLE handle = (HANDLE)file.u64[0]; - SYSTEMTIME system_time = {0}; - os_w32_system_time_from_date_time(&system_time, &time); - FILETIME file_time = {0}; - result = (SystemTimeToFileTime(&system_time, &file_time) && - SetFileTime(handle, &file_time, &file_time, &file_time)); - return result; -} - -internal FileProperties -os_properties_from_file(OS_Handle file) -{ - if(os_handle_match(file, os_handle_zero())) { FileProperties r = {0}; return r; } - FileProperties props = {0}; - HANDLE handle = (HANDLE)file.u64[0]; - BY_HANDLE_FILE_INFORMATION info; - BOOL info_good = GetFileInformationByHandle(handle, &info); - if(info_good) - { - U32 size_lo = info.nFileSizeLow; - U32 size_hi = info.nFileSizeHigh; - props.size = (U64)size_lo | (((U64)size_hi)<<32); - os_w32_dense_time_from_file_time(&props.modified, &info.ftLastWriteTime); - os_w32_dense_time_from_file_time(&props.created, &info.ftCreationTime); - props.flags = os_w32_file_property_flags_from_dwFileAttributes(info.dwFileAttributes); - } - return props; -} - -internal OS_FileID -os_id_from_file(OS_Handle file) -{ - if(os_handle_match(file, os_handle_zero())) { OS_FileID r = {0}; return r; } - OS_FileID result = {0}; - HANDLE handle = (HANDLE)file.u64[0]; - BY_HANDLE_FILE_INFORMATION info; - BOOL is_ok = GetFileInformationByHandle(handle, &info); - if(is_ok) - { - result.v[0] = info.dwVolumeSerialNumber; - result.v[1] = info.nFileIndexLow; - result.v[2] = info.nFileIndexHigh; - } - return result; -} - -internal B32 -os_file_reserve_size(OS_Handle file, U64 size) -{ - HANDLE handle = (HANDLE)file.u64[0]; - - FILE_ALLOCATION_INFO alloc_info = {0}; - alloc_info.AllocationSize.LowPart = size & max_U32; - alloc_info.AllocationSize.HighPart = (size >> 32) & max_U32; - - BOOL is_reserved = SetFileInformationByHandle(handle, FileAllocationInfo, &alloc_info, sizeof(alloc_info)); - return is_reserved; -} - -internal B32 -os_delete_file_at_path(String8 path) -{ - Temp scratch = scratch_begin(0, 0); - String16 path16 = str16_from_8(scratch.arena, path); - B32 result = DeleteFileW((WCHAR*)path16.str); - scratch_end(scratch); - return result; -} - -internal B32 -os_copy_file_path(String8 dst, String8 src) -{ - Temp scratch = scratch_begin(0, 0); - String16 dst16 = str16_from_8(scratch.arena, dst); - String16 src16 = str16_from_8(scratch.arena, src); - B32 result = CopyFileW((WCHAR*)src16.str, (WCHAR*)dst16.str, 0); - scratch_end(scratch); - return result; -} - -internal B32 -os_move_file_path(String8 dst, String8 src) -{ - Temp scratch = scratch_begin(0, 0); - String16 dst16 = str16_from_8(scratch.arena, dst); - String16 src16 = str16_from_8(scratch.arena, src); - B32 result = MoveFileW((WCHAR*)src16.str, (WCHAR*)dst16.str); - scratch_end(scratch); - return result; -} - -internal String8 -os_full_path_from_path(Arena *arena, String8 path) -{ - Temp scratch = scratch_begin(&arena, 1); - DWORD buffer_size = Max(MAX_PATH, path.size * 2) + 1; - String16 path16 = str16_from_8(scratch.arena, path); - WCHAR *buffer = push_array_no_zero(scratch.arena, WCHAR, buffer_size); - DWORD path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, buffer, NULL); - if(path16_size > buffer_size) - { - arena_pop(scratch.arena, buffer_size); - buffer_size = path16_size + 1; - buffer = push_array_no_zero(scratch.arena, WCHAR, buffer_size); - path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, buffer, NULL); - } - String8 full_path = str8_from_16(arena, str16((U16*)buffer, path16_size)); - scratch_end(scratch); - return full_path; -} - -internal B32 -os_file_path_exists(String8 path) -{ - Temp scratch = scratch_begin(0,0); - String16 path16 = str16_from_8(scratch.arena, path); - DWORD attributes = GetFileAttributesW((WCHAR *)path16.str); - B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && !!(~attributes & FILE_ATTRIBUTE_DIRECTORY); - scratch_end(scratch); - return exists; -} - -internal B32 -os_folder_path_exists(String8 path) -{ - Temp scratch = scratch_begin(0,0); - String16 path16 = str16_from_8(scratch.arena, path); - DWORD attributes = GetFileAttributesW((WCHAR *)path16.str); - B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY); - scratch_end(scratch); - return exists; -} - -internal FileProperties -os_properties_from_file_path(String8 path) -{ - WIN32_FIND_DATAW find_data = {0}; - Temp scratch = scratch_begin(0, 0); - String16 path16 = str16_from_8(scratch.arena, path); - HANDLE handle = FindFirstFileW((WCHAR *)path16.str, &find_data); - FileProperties props = {0}; - if(handle != INVALID_HANDLE_VALUE) - { - props.size = Compose64Bit(find_data.nFileSizeHigh, find_data.nFileSizeLow); - os_w32_dense_time_from_file_time(&props.created, &find_data.ftCreationTime); - os_w32_dense_time_from_file_time(&props.modified, &find_data.ftLastWriteTime); - props.flags = os_w32_file_property_flags_from_dwFileAttributes(find_data.dwFileAttributes); - } - else - { - Temp scratch = scratch_begin(0, 0); - WCHAR buffer[512] = {0}; - DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer); - U64 last_slash_pos = 0; - for(;last_slash_pos < path.size; last_slash_pos = str8_find_needle(path, last_slash_pos+1, str8_lit("/"), StringMatchFlag_SlashInsensitive)); - String8 path_trimmed = str8_prefix(path, last_slash_pos); - for(U64 off = 0; off < (U64)length;) - { - String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off); - off += next_drive_string_16.size+1; - String8 next_drive_string = str8_from_16(scratch.arena, next_drive_string_16); - next_drive_string = str8_chop_last_slash(next_drive_string); - if(str8_match(path_trimmed, next_drive_string, StringMatchFlag_CaseInsensitive)) - { - props.flags |= FilePropertyFlag_IsFolder; - break; - } - } - scratch_end(scratch); - } - FindClose(handle); - scratch_end(scratch); - return props; -} - -//- rjf: file maps - -internal OS_Handle -os_file_map_open(OS_AccessFlags flags, OS_Handle file) -{ - OS_Handle map = {0}; - { - HANDLE file_handle = (HANDLE)file.u64[0]; - DWORD protect_flags = 0; - { - switch(flags) - { - default:{}break; - case OS_AccessFlag_Read: - {protect_flags = PAGE_READONLY;}break; - case OS_AccessFlag_Write: - case OS_AccessFlag_Read|OS_AccessFlag_Write: - {protect_flags = PAGE_READWRITE;}break; - case OS_AccessFlag_Execute: - case OS_AccessFlag_Read|OS_AccessFlag_Execute: - {protect_flags = PAGE_EXECUTE_READ;}break; - case OS_AccessFlag_Execute|OS_AccessFlag_Write|OS_AccessFlag_Read: - case OS_AccessFlag_Execute|OS_AccessFlag_Write: - {protect_flags = PAGE_EXECUTE_READWRITE;}break; - } - } - HANDLE map_handle = CreateFileMappingA(file_handle, 0, protect_flags, 0, 0, 0); - map.u64[0] = (U64)map_handle; - } - return map; -} - -internal void -os_file_map_close(OS_Handle map) -{ - HANDLE handle = (HANDLE)map.u64[0]; - BOOL result = CloseHandle(handle); - (void)result; -} - -internal void * -os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range) -{ - HANDLE handle = (HANDLE)map.u64[0]; - U32 off_lo = (U32)((range.min&0x00000000ffffffffull)>>0); - U32 off_hi = (U32)((range.min&0xffffffff00000000ull)>>32); - U64 size = dim_1u64(range); - DWORD access_flags = 0; - { - switch(flags) - { - default:{}break; - case OS_AccessFlag_Read: - { - access_flags = FILE_MAP_READ; - }break; - case OS_AccessFlag_Write: - { - access_flags = FILE_MAP_WRITE; - }break; - case OS_AccessFlag_Read|OS_AccessFlag_Write: - { - access_flags = FILE_MAP_ALL_ACCESS; - }break; - case OS_AccessFlag_Execute: - case OS_AccessFlag_Read|OS_AccessFlag_Execute: - case OS_AccessFlag_Write|OS_AccessFlag_Execute: - case OS_AccessFlag_Read|OS_AccessFlag_Write|OS_AccessFlag_Execute: - { - access_flags = FILE_MAP_ALL_ACCESS|FILE_MAP_EXECUTE; - }break; - } - } - void *result = MapViewOfFile(handle, access_flags, off_hi, off_lo, size); - return result; -} - -internal void -os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range) -{ - BOOL result = UnmapViewOfFile(ptr); - (void)result; -} - -//- rjf: directory iteration - -internal OS_FileIter * -os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8 path_with_wildcard = push_str8_cat(scratch.arena, path, str8_lit("\\*")); - String16 path16 = str16_from_8(scratch.arena, path_with_wildcard); - OS_FileIter *iter = push_array(arena, OS_FileIter, 1); - iter->flags = flags; - OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; - if(path.size == 0) - { - w32_iter->is_volume_iter = 1; - WCHAR buffer[512] = {0}; - DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer); - String8List drive_strings = {0}; - for(U64 off = 0; off < (U64)length;) - { - String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off); - off += next_drive_string_16.size+1; - String8 next_drive_string = str8_from_16(arena, next_drive_string_16); - next_drive_string = str8_chop_last_slash(next_drive_string); - str8_list_push(scratch.arena, &drive_strings, next_drive_string); - } - w32_iter->drive_strings = str8_array_from_list(arena, &drive_strings); - w32_iter->drive_strings_iter_idx = 0; - } - else - { - w32_iter->handle = FindFirstFileW((WCHAR*)path16.str, &w32_iter->find_data); - } - scratch_end(scratch); - return iter; -} - -internal B32 -os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out) -{ - B32 result = 0; - OS_FileIterFlags flags = iter->flags; - OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; - switch(w32_iter->is_volume_iter) - { - //- rjf: file iteration - default: - case 0: - { - if (!(flags & OS_FileIterFlag_Done) && w32_iter->handle != INVALID_HANDLE_VALUE) - { - do - { - // check is usable - B32 usable_file = 1; - - WCHAR *file_name = w32_iter->find_data.cFileName; - DWORD attributes = w32_iter->find_data.dwFileAttributes; - if (file_name[0] == '.'){ - if (flags & OS_FileIterFlag_SkipHiddenFiles){ - usable_file = 0; - } - else if (file_name[1] == 0){ - usable_file = 0; - } - else if (file_name[1] == '.' && file_name[2] == 0){ - usable_file = 0; - } - } - if (attributes & FILE_ATTRIBUTE_DIRECTORY){ - if (flags & OS_FileIterFlag_SkipFolders){ - usable_file = 0; - } - } - else{ - if (flags & OS_FileIterFlag_SkipFiles){ - usable_file = 0; - } - } - - // emit if usable - if (usable_file){ - info_out->name = str8_from_16(arena, str16_cstring((U16*)file_name)); - info_out->props.size = (U64)w32_iter->find_data.nFileSizeLow | (((U64)w32_iter->find_data.nFileSizeHigh)<<32); - os_w32_dense_time_from_file_time(&info_out->props.created, &w32_iter->find_data.ftCreationTime); - os_w32_dense_time_from_file_time(&info_out->props.modified, &w32_iter->find_data.ftLastWriteTime); - info_out->props.flags = os_w32_file_property_flags_from_dwFileAttributes(attributes); - result = 1; - if (!FindNextFileW(w32_iter->handle, &w32_iter->find_data)){ - iter->flags |= OS_FileIterFlag_Done; - } - break; - } - }while(FindNextFileW(w32_iter->handle, &w32_iter->find_data)); - } - }break; - - //- rjf: volume iteration - case 1: - { - result = w32_iter->drive_strings_iter_idx < w32_iter->drive_strings.count; - if(result != 0) - { - MemoryZeroStruct(info_out); - info_out->name = w32_iter->drive_strings.v[w32_iter->drive_strings_iter_idx]; - info_out->props.flags |= FilePropertyFlag_IsFolder; - w32_iter->drive_strings_iter_idx += 1; - } - }break; - } - if(!result) - { - iter->flags |= OS_FileIterFlag_Done; - } - return result; -} - -internal void -os_file_iter_end(OS_FileIter *iter) -{ - OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; - HANDLE zero_handle; - MemoryZeroStruct(&zero_handle); - if(!MemoryMatchStruct(&zero_handle, &w32_iter->handle)) - { - FindClose(w32_iter->handle); - } -} - -//- rjf: directory creation - -internal B32 -os_make_directory(String8 path) -{ - B32 result = 0; - Temp scratch = scratch_begin(0, 0); - String16 name16 = str16_from_8(scratch.arena, path); - WIN32_FILE_ATTRIBUTE_DATA attributes = {0}; - GetFileAttributesExW((WCHAR*)name16.str, GetFileExInfoStandard, &attributes); - if(attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - result = 1; - } - else if(CreateDirectoryW((WCHAR*)name16.str, 0)) - { - result = 1; - } - scratch_end(scratch); - return(result); -} - -//////////////////////////////// -//~ rjf: @os_hooks Shared Memory (Implemented Per-OS) - -internal OS_Handle -os_shared_memory_alloc(U64 size, String8 name) -{ - Temp scratch = scratch_begin(0, 0); - String16 name16 = str16_from_8(scratch.arena, name); - HANDLE file = CreateFileMappingW(INVALID_HANDLE_VALUE, - 0, - PAGE_READWRITE, - (U32)((size & 0xffffffff00000000) >> 32), - (U32)((size & 0x00000000ffffffff)), - (WCHAR *)name16.str); - OS_Handle result = {(U64)file}; - scratch_end(scratch); - return result; -} - -internal OS_Handle -os_shared_memory_open(String8 name) -{ - Temp scratch = scratch_begin(0, 0); - String16 name16 = str16_from_8(scratch.arena, name); - HANDLE file = OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, (WCHAR *)name16.str); - OS_Handle result = {(U64)file}; - scratch_end(scratch); - return result; -} - -internal void -os_shared_memory_close(OS_Handle handle) -{ - HANDLE file = (HANDLE)(handle.u64[0]); - CloseHandle(file); -} - -internal void * -os_shared_memory_view_open(OS_Handle handle, Rng1U64 range) -{ - HANDLE file = (HANDLE)(handle.u64[0]); - U64 offset = range.min; - U64 size = range.max-range.min; - void *ptr = MapViewOfFile(file, FILE_MAP_ALL_ACCESS, - (U32)((offset & 0xffffffff00000000) >> 32), - (U32)((offset & 0x00000000ffffffff)), - size); - return ptr; -} - -internal void -os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range) -{ - UnmapViewOfFile(ptr); -} - -//////////////////////////////// -//~ rjf: @os_hooks Time (Implemented Per-OS) - -internal U64 -os_now_microseconds(void) -{ - U64 result = 0; - LARGE_INTEGER large_int_counter; - if(QueryPerformanceCounter(&large_int_counter)) - { - result = (large_int_counter.QuadPart*Million(1))/os_w32_state.microsecond_resolution; - } - return result; -} - -internal U32 -os_now_unix(void) -{ - FILETIME file_time; - GetSystemTimeAsFileTime(&file_time); - U32 unix_time = os_w32_unix_time_from_file_time(file_time); - return unix_time; -} - -internal DateTime -os_now_universal_time(void) -{ - SYSTEMTIME systime = {0}; - GetSystemTime(&systime); - DateTime result = {0}; - os_w32_date_time_from_system_time(&result, &systime); - return result; -} - -internal DateTime -os_universal_time_from_local(DateTime *date_time) -{ - SYSTEMTIME systime = {0}; - os_w32_system_time_from_date_time(&systime, date_time); - FILETIME ftime = {0}; - SystemTimeToFileTime(&systime, &ftime); - FILETIME ftime_local = {0}; - LocalFileTimeToFileTime(&ftime, &ftime_local); - FileTimeToSystemTime(&ftime_local, &systime); - DateTime result = {0}; - os_w32_date_time_from_system_time(&result, &systime); - return result; -} - -internal DateTime -os_local_time_from_universal(DateTime *date_time) -{ - SYSTEMTIME systime = {0}; - os_w32_system_time_from_date_time(&systime, date_time); - FILETIME ftime = {0}; - SystemTimeToFileTime(&systime, &ftime); - FILETIME ftime_local = {0}; - FileTimeToLocalFileTime(&ftime, &ftime_local); - FileTimeToSystemTime(&ftime_local, &systime); - DateTime result = {0}; - os_w32_date_time_from_system_time(&result, &systime); - return result; -} - -internal void -os_sleep_milliseconds(U32 msec) -{ - Sleep(msec); -} - -//////////////////////////////// -//~ rjf: @os_hooks Child Processes (Implemented Per-OS) - -internal OS_Handle -os_process_launch(OS_ProcessLaunchParams *params) -{ - OS_Handle result = {0}; - Temp scratch = scratch_begin(0, 0); - - //- rjf: form full command string - String8 cmd = {0}; - { - StringJoin join_params = {0}; - join_params.pre = str8_lit("\""); - join_params.sep = str8_lit("\" \""); - join_params.post = str8_lit("\""); - cmd = str8_list_join(scratch.arena, ¶ms->cmd_line, &join_params); - } - - //- rjf: form environment - B32 use_null_env_arg = 0; - String8 env = {0}; - { - StringJoin join_params2 = {0}; - join_params2.sep = str8_lit("\0"); - join_params2.post = str8_lit("\0"); - String8List all_opts = params->env; - if(params->inherit_env != 0) - { - if(all_opts.node_count != 0) - { - MemoryZeroStruct(&all_opts); - for(String8Node *n = params->env.first; n != 0; n = n->next) - { - str8_list_push(scratch.arena, &all_opts, n->string); - } - for(String8Node *n = os_w32_state.process_info.environment.first; n != 0; n = n->next) - { - str8_list_push(scratch.arena, &all_opts, n->string); - } - } - else - { - use_null_env_arg = 1; - } - } - if(use_null_env_arg == 0) - { - env = str8_list_join(scratch.arena, &all_opts, &join_params2); - } - } - - //- rjf: utf-8 -> utf-16 - String16 cmd16 = str16_from_8(scratch.arena, cmd); - String16 dir16 = str16_from_8(scratch.arena, params->path); - String16 env16 = {0}; - if(use_null_env_arg == 0) - { - env16 = str16_from_8(scratch.arena, env); - } - - //- rjf: determine creation flags - DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT; - if(params->consoleless) - { - creation_flags |= CREATE_NO_WINDOW; - } - - //- rjf: launch - BOOL inherit_handles = 0; - STARTUPINFOW startup_info = {sizeof(startup_info)}; - if(!os_handle_match(params->stdout_file, os_handle_zero())) - { - HANDLE stdout_handle = (HANDLE)params->stdout_file.u64[0]; - startup_info.hStdOutput = stdout_handle; - startup_info.dwFlags |= STARTF_USESTDHANDLES; - inherit_handles = 1; - } - if(!os_handle_match(params->stderr_file, os_handle_zero())) - { - HANDLE stderr_handle = (HANDLE)params->stderr_file.u64[0]; - startup_info.hStdError = stderr_handle; - startup_info.dwFlags |= STARTF_USESTDHANDLES; - inherit_handles = 1; - } - if(!os_handle_match(params->stdin_file, os_handle_zero())) - { - HANDLE stdin_handle = (HANDLE)params->stdin_file.u64[0]; - startup_info.hStdInput = stdin_handle; - startup_info.dwFlags |= STARTF_USESTDHANDLES; - inherit_handles = 1; - } - PROCESS_INFORMATION process_info = {0}; - if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, inherit_handles, creation_flags, use_null_env_arg ? 0 : (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info)) - { - result.u64[0] = (U64)process_info.hProcess; - CloseHandle(process_info.hThread); - } - - scratch_end(scratch); - return result; -} - -internal B32 -os_process_join(OS_Handle handle, U64 endt_us) -{ - HANDLE process = (HANDLE)(handle.u64[0]); - DWORD sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); - DWORD result = WaitForSingleObject(process, sleep_ms); - return (result == WAIT_OBJECT_0); -} - -internal void -os_process_detach(OS_Handle handle) -{ - HANDLE process = (HANDLE)(handle.u64[0]); - CloseHandle(process); -} - -//////////////////////////////// -//~ rjf: @os_hooks Threads (Implemented Per-OS) - -internal OS_Handle -os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params) -{ - OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_Thread); - entity->thread.func = func; - entity->thread.ptr = ptr; - entity->thread.handle = CreateThread(0, 0, os_w32_thread_entry_point, entity, 0, &entity->thread.tid); - OS_Handle result = {IntFromPtr(entity)}; - return result; -} - -internal B32 -os_thread_join(OS_Handle handle, U64 endt_us) -{ - DWORD sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); - OS_W32_Entity *entity = (OS_W32_Entity *)PtrFromInt(handle.u64[0]); - DWORD wait_result = WAIT_OBJECT_0; - if(entity != 0) - { - wait_result = WaitForSingleObject(entity->thread.handle, sleep_ms); - CloseHandle(entity->thread.handle); - os_w32_entity_release(entity); - } - return (wait_result == WAIT_OBJECT_0); -} - -internal void -os_thread_detach(OS_Handle thread) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(thread.u64[0]); - if(entity != 0) - { - CloseHandle(entity->thread.handle); - os_w32_entity_release(entity); - } -} - -//////////////////////////////// -//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) - -//- rjf: mutexes - -internal OS_Handle -os_mutex_alloc(void) -{ - OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_Mutex); - InitializeCriticalSection(&entity->mutex); - OS_Handle result = {IntFromPtr(entity)}; - return result; -} - -internal void -os_mutex_release(OS_Handle mutex) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); - os_w32_entity_release(entity); -} - -internal void -os_mutex_take(OS_Handle mutex) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); - EnterCriticalSection(&entity->mutex); -} - -internal void -os_mutex_drop(OS_Handle mutex) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); - LeaveCriticalSection(&entity->mutex); -} - -//- rjf: reader/writer mutexes - -internal OS_Handle -os_rw_mutex_alloc(void) -{ - OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_RWMutex); - InitializeSRWLock(&entity->rw_mutex); - OS_Handle result = {IntFromPtr(entity)}; - return result; -} - -internal void -os_rw_mutex_release(OS_Handle rw_mutex) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); - os_w32_entity_release(entity); -} - -internal void -os_rw_mutex_take_r(OS_Handle rw_mutex) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); - AcquireSRWLockShared(&entity->rw_mutex); -} - -internal void -os_rw_mutex_drop_r(OS_Handle rw_mutex) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); - ReleaseSRWLockShared(&entity->rw_mutex); -} - -internal void -os_rw_mutex_take_w(OS_Handle rw_mutex) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); - AcquireSRWLockExclusive(&entity->rw_mutex); -} - -internal void -os_rw_mutex_drop_w(OS_Handle rw_mutex) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); - ReleaseSRWLockExclusive(&entity->rw_mutex); -} - -//- rjf: condition variables - -internal OS_Handle -os_condition_variable_alloc(void) -{ - OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_ConditionVariable); - InitializeConditionVariable(&entity->cv); - OS_Handle result = {IntFromPtr(entity)}; - return result; -} - -internal void -os_condition_variable_release(OS_Handle cv) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - os_w32_entity_release(entity); -} - -internal B32 -os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us) -{ - U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); - BOOL result = 0; - if(sleep_ms > 0) - { - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - OS_W32_Entity *mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); - result = SleepConditionVariableCS(&entity->cv, &mutex_entity->mutex, sleep_ms); - } - return result; -} - -internal B32 -os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) -{ - U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); - BOOL result = 0; - if(sleep_ms > 0) - { - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - OS_W32_Entity *mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex_rw.u64[0]); - result = SleepConditionVariableSRW(&entity->cv, &mutex_entity->rw_mutex, sleep_ms, - CONDITION_VARIABLE_LOCKMODE_SHARED); - } - return result; -} - -internal B32 -os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) -{ - U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); - BOOL result = 0; - if(sleep_ms > 0) - { - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - OS_W32_Entity *mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex_rw.u64[0]); - result = SleepConditionVariableSRW(&entity->cv, &mutex_entity->rw_mutex, sleep_ms, 0); - } - return result; -} - -internal void -os_condition_variable_signal(OS_Handle cv) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - WakeConditionVariable(&entity->cv); -} - -internal void -os_condition_variable_broadcast(OS_Handle cv) -{ - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - WakeAllConditionVariable(&entity->cv); -} - -//- rjf: cross-process semaphores - -internal OS_Handle -os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) -{ - Temp scratch = scratch_begin(0, 0); - String16 name16 = str16_from_8(scratch.arena, name); - HANDLE handle = CreateSemaphoreW(0, initial_count, max_count, (WCHAR *)name16.str); - OS_Handle result = {(U64)handle}; - scratch_end(scratch); - return result; -} - -internal void -os_semaphore_release(OS_Handle semaphore) -{ - HANDLE handle = (HANDLE)semaphore.u64[0]; - CloseHandle(handle); -} - -internal OS_Handle -os_semaphore_open(String8 name) -{ - Temp scratch = scratch_begin(0, 0); - String16 name16 = str16_from_8(scratch.arena, name); - HANDLE handle = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS , 0, (WCHAR *)name16.str); - OS_Handle result = {(U64)handle}; - scratch_end(scratch); - return result; -} - -internal void -os_semaphore_close(OS_Handle semaphore) -{ - HANDLE handle = (HANDLE)semaphore.u64[0]; - CloseHandle(handle); -} - -internal B32 -os_semaphore_take(OS_Handle semaphore, U64 endt_us) -{ - U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); - HANDLE handle = (HANDLE)semaphore.u64[0]; - DWORD wait_result = WaitForSingleObject(handle, sleep_ms); - B32 result = (wait_result == WAIT_OBJECT_0); - return result; -} - -internal void -os_semaphore_drop(OS_Handle semaphore) -{ - HANDLE handle = (HANDLE)semaphore.u64[0]; - ReleaseSemaphore(handle, 1, 0); -} - -//////////////////////////////// -//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) - -internal OS_Handle -os_library_open(String8 path) -{ - Temp scratch = scratch_begin(0, 0); - String16 path16 = str16_from_8(scratch.arena, path); - HMODULE mod = LoadLibraryW((LPCWSTR)path16.str); - OS_Handle result = { (U64)mod }; - scratch_end(scratch); - return result; -} - -internal VoidProc* -os_library_load_proc(OS_Handle lib, String8 name) -{ - Temp scratch = scratch_begin(0, 0); - HMODULE mod = (HMODULE)lib.u64[0]; - name = push_str8_copy(scratch.arena, name); - VoidProc *result = (VoidProc*)GetProcAddress(mod, (LPCSTR)name.str); - scratch_end(scratch); - return result; -} - -internal void -os_library_close(OS_Handle lib) -{ - HMODULE mod = (HMODULE)lib.u64[0]; - FreeLibrary(mod); -} - -//////////////////////////////// -//~ rjf: @os_hooks Safe Calls (Implemented Per-OS) - -internal void -os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr) -{ - __try - { - func(ptr); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - if(fail_handler != 0) - { - fail_handler(ptr); - } - ExitProcess(1); - } -} - -//////////////////////////////// -//~ rjf: @os_hooks GUIDs (Implemented Per-OS) - -internal Guid -os_make_guid(void) -{ - Guid result; MemoryZeroStruct(&result); - UUID uuid; - RPC_STATUS rpc_status = UuidCreate(&uuid); - if(rpc_status == RPC_S_OK) - { - result.data1 = uuid.Data1; - result.data2 = uuid.Data2; - result.data3 = uuid.Data3; - MemoryCopyArray(result.data4, uuid.Data4); - } - return result; -} - -//////////////////////////////// -//~ rjf: @os_hooks Entry Points (Implemented Per-OS) - -#include -#undef OS_WINDOWS // shlwapi uses its own OS_WINDOWS include inside -#include - -internal B32 win32_g_is_quiet = 0; - -internal HRESULT WINAPI -win32_dialog_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LONG_PTR data) -{ - if(msg == TDN_HYPERLINK_CLICKED) - { - ShellExecuteW(NULL, L"open", (LPWSTR)lparam, NULL, NULL, SW_SHOWNORMAL); - } - return S_OK; -} - -internal LONG WINAPI -win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs) -{ - if(win32_g_is_quiet) - { - ExitProcess(1); - } - - static volatile LONG first = 0; - if(InterlockedCompareExchange(&first, 1, 0) != 0) - { - // prevent failures in other threads to popup same message box - // this handler just shows first thread that crashes - // we are terminating afterwards anyway - for (;;) Sleep(1000); - } - - WCHAR buffer[4096] = {0}; - int buflen = 0; - - DWORD exception_code = exception_ptrs->ExceptionRecord->ExceptionCode; - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"A fatal exception (code 0x%x) occurred. The process is terminating.\n", exception_code); - - // load dbghelp dynamically just in case if it is missing - HMODULE dbghelp = LoadLibraryA("dbghelp.dll"); - if(dbghelp) - { - DWORD (WINAPI *dbg_SymSetOptions)(DWORD SymOptions); - BOOL (WINAPI *dbg_SymInitializeW)(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess); - BOOL (WINAPI *dbg_StackWalk64)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, - LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, - PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, - PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); - PVOID (WINAPI *dbg_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase); - DWORD64 (WINAPI *dbg_SymGetModuleBase64)(HANDLE hProcess, DWORD64 qwAddr); - BOOL (WINAPI *dbg_SymFromAddrW)(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFOW Symbol); - BOOL (WINAPI *dbg_SymGetLineFromAddrW64)(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line); - BOOL (WINAPI *dbg_SymGetModuleInfoW64)(HANDLE hProcess, DWORD64 qwAddr, PIMAGEHLP_MODULEW64 ModuleInfo); - - *(FARPROC*)&dbg_SymSetOptions = GetProcAddress(dbghelp, "SymSetOptions"); - *(FARPROC*)&dbg_SymInitializeW = GetProcAddress(dbghelp, "SymInitializeW"); - *(FARPROC*)&dbg_StackWalk64 = GetProcAddress(dbghelp, "StackWalk64"); - *(FARPROC*)&dbg_SymFunctionTableAccess64 = GetProcAddress(dbghelp, "SymFunctionTableAccess64"); - *(FARPROC*)&dbg_SymGetModuleBase64 = GetProcAddress(dbghelp, "SymGetModuleBase64"); - *(FARPROC*)&dbg_SymFromAddrW = GetProcAddress(dbghelp, "SymFromAddrW"); - *(FARPROC*)&dbg_SymGetLineFromAddrW64 = GetProcAddress(dbghelp, "SymGetLineFromAddrW64"); - *(FARPROC*)&dbg_SymGetModuleInfoW64 = GetProcAddress(dbghelp, "SymGetModuleInfoW64"); - - if(dbg_SymSetOptions && dbg_SymInitializeW && dbg_StackWalk64 && dbg_SymFunctionTableAccess64 && dbg_SymGetModuleBase64 && dbg_SymFromAddrW && dbg_SymGetLineFromAddrW64 && dbg_SymGetModuleInfoW64) - { - HANDLE process = GetCurrentProcess(); - HANDLE thread = GetCurrentThread(); - CONTEXT* context = exception_ptrs->ContextRecord; - - WCHAR module_path[MAX_PATH]; - GetModuleFileNameW(NULL, module_path, ArrayCount(module_path)); - PathRemoveFileSpecW(module_path); - - dbg_SymSetOptions(SYMOPT_EXACT_SYMBOLS | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); - if(dbg_SymInitializeW(process, module_path, TRUE)) - { - // check that raddbg.pdb file is good - B32 raddbg_pdb_valid = 0; - { - IMAGEHLP_MODULEW64 module = {0}; - module.SizeOfStruct = sizeof(module); - if(dbg_SymGetModuleInfoW64(process, (DWORD64)&win32_exception_filter, &module)) - { - raddbg_pdb_valid = (module.SymType == SymPdb); - } - } - - if(!raddbg_pdb_valid) - { - buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, - L"\nThe PDB debug information file for this executable is not valid or was not found. Please rebuild binary to get the call stack.\n"); - } - else - { - STACKFRAME64 frame = {0}; - DWORD image_type; -#if defined(_M_AMD64) - image_type = IMAGE_FILE_MACHINE_AMD64; - frame.AddrPC.Offset = context->Rip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrFrame.Offset = context->Rbp; - frame.AddrFrame.Mode = AddrModeFlat; - frame.AddrStack.Offset = context->Rsp; - frame.AddrStack.Mode = AddrModeFlat; -#elif defined(_M_ARM64) - image_type = IMAGE_FILE_MACHINE_ARM64; - frame.AddrPC.Offset = context->Pc; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrFrame.Offset = context->Fp; - frame.AddrFrame.Mode = AddrModeFlat; - frame.AddrStack.Offset = context->Sp; - frame.AddrStack.Mode = AddrModeFlat; -#else -# error Arch not supported! -#endif - - for(U32 idx=0; ;idx++) - { - const U32 max_frames = 32; - if(idx == max_frames) - { - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"..."); - break; - } - - if(!dbg_StackWalk64(image_type, process, thread, &frame, context, 0, dbg_SymFunctionTableAccess64, dbg_SymGetModuleBase64, 0)) - { - break; - } - - U64 address = frame.AddrPC.Offset; - if(address == 0) - { - break; - } - - if(idx==0) - { -#if BUILD_CONSOLE_INTERFACE - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nCreate a new issue with this report at %S.\n\n", BUILD_ISSUES_LINK_STRING_LITERAL); -#else - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, - L"\nPress Ctrl+C to copy this text to clipboard, then create a new issue at\n" - L"%S\n\n", BUILD_ISSUES_LINK_STRING_LITERAL, BUILD_ISSUES_LINK_STRING_LITERAL); -#endif - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"Call stack:\n"); - } - - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"%u. [0x%I64x]", idx + 1, address); - - struct { - SYMBOL_INFOW info; - WCHAR name[MAX_SYM_NAME]; - } symbol = {0}; - - symbol.info.SizeOfStruct = sizeof(symbol.info); - symbol.info.MaxNameLen = MAX_SYM_NAME; - - DWORD64 displacement = 0; - if(dbg_SymFromAddrW(process, address, &displacement, &symbol.info)) - { - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L" %s +%u", symbol.info.Name, (DWORD)displacement); - - IMAGEHLP_LINEW64 line = {0}; - line.SizeOfStruct = sizeof(line); - - DWORD line_displacement = 0; - if(dbg_SymGetLineFromAddrW64(process, address, &line_displacement, &line)) - { - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L", %s line %u", PathFindFileNameW(line.FileName), line.LineNumber); - } - } - else - { - IMAGEHLP_MODULEW64 module = {0}; - module.SizeOfStruct = sizeof(module); - if(dbg_SymGetModuleInfoW64(process, address, &module)) - { - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L" %s", module.ModuleName); - } - } - - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\n"); - } - } - } - } - } - - buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nVersion: %S%S", BUILD_VERSION_STRING_LITERAL, BUILD_GIT_HASH_STRING_LITERAL_APPEND); - -#if BUILD_CONSOLE_INTERFACE - fwprintf(stderr, L"\n--- Fatal Exception ---\n"); - fwprintf(stderr, L"%s\n\n", buffer); -#else - TASKDIALOGCONFIG dialog = {0}; - dialog.cbSize = sizeof(dialog); - dialog.dwFlags = TDF_SIZE_TO_CONTENT | TDF_ENABLE_HYPERLINKS | TDF_ALLOW_DIALOG_CANCELLATION; - dialog.pszMainIcon = TD_ERROR_ICON; - dialog.dwCommonButtons = TDCBF_CLOSE_BUTTON; - dialog.pszWindowTitle = L"Fatal Exception"; - dialog.pszContent = buffer; - dialog.pfCallback = &win32_dialog_callback; - TaskDialogIndirect(&dialog, 0, 0, 0); -#endif - - ExitProcess(1); -} - -#undef OS_WINDOWS // shlwapi uses its own OS_WINDOWS include inside -#define OS_WINDOWS 1 - -internal void -w32_entry_point_caller(int argc, WCHAR **wargv) -{ - SetUnhandledExceptionFilter(&win32_exception_filter); - - //- rjf: dynamically load windows functions which are not guaranteed - // in all SDKs - { - HMODULE module = LoadLibraryA("kernel32.dll"); - w32_SetThreadDescription_func = (W32_SetThreadDescription_Type *)GetProcAddress(module, "SetThreadDescription"); - FreeLibrary(module); - } - - //- rjf: try to allow large pages if we can - B32 large_pages_allowed = 0; - { - HANDLE token; - if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) - { - LUID luid; - if(LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid)) - { - TOKEN_PRIVILEGES priv; - priv.PrivilegeCount = 1; - priv.Privileges[0].Luid = luid; - priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - large_pages_allowed = !!AdjustTokenPrivileges(token, 0, &priv, sizeof(priv), 0, 0); - } - CloseHandle(token); - } - } - - //- rjf: get system info - SYSTEM_INFO sysinfo = {0}; - GetSystemInfo(&sysinfo); - - //- rjf: set up non-dynamically-alloc'd state - // - // (we need to set up some basics before this layer can supply - // memory allocation primitives) - { - os_w32_state.microsecond_resolution = 1; - LARGE_INTEGER large_int_resolution; - if(QueryPerformanceFrequency(&large_int_resolution)) - { - os_w32_state.microsecond_resolution = large_int_resolution.QuadPart; - } - } - { - OS_SystemInfo *info = &os_w32_state.system_info; - info->logical_processor_count = (U64)sysinfo.dwNumberOfProcessors; - info->page_size = sysinfo.dwPageSize; - info->large_page_size = GetLargePageMinimum(); - info->allocation_granularity = sysinfo.dwAllocationGranularity; - } - { - OS_ProcessInfo *info = &os_w32_state.process_info; - info->large_pages_allowed = large_pages_allowed; - info->pid = GetCurrentProcessId(); - } - - //- rjf: extract arguments - Arena *args_arena = arena_alloc(.reserve_size = MB(1), .commit_size = KB(32)); - char **argv = push_array(args_arena, char *, argc); - for(int i = 0; i < argc; i += 1) - { - String16 arg16 = str16_cstring((U16 *)wargv[i]); - String8 arg8 = str8_from_16(args_arena, arg16); - if(str8_match(arg8, str8_lit("--quiet"), StringMatchFlag_CaseInsensitive) || - str8_match(arg8, str8_lit("-quiet"), StringMatchFlag_CaseInsensitive)) - { - win32_g_is_quiet = 1; - } - if(str8_match(arg8, str8_lit("--large_pages"), StringMatchFlag_CaseInsensitive) || - str8_match(arg8, str8_lit("-large_pages"), StringMatchFlag_CaseInsensitive)) - { - arena_default_flags = ArenaFlag_LargePages; - arena_default_reserve_size = Max(MB(64), os_w32_state.system_info.large_page_size); - arena_default_commit_size = arena_default_reserve_size; - } - argv[i] = (char *)arg8.str; - } - - //- rjf: set up thread context - local_persist TCTX tctx; - tctx_init_and_equip(&tctx); - - //- rjf: set up dynamically-alloc'd state - Arena *arena = arena_alloc(); - { - os_w32_state.arena = arena; - { - OS_SystemInfo *info = &os_w32_state.system_info; - U8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0}; - DWORD size = MAX_COMPUTERNAME_LENGTH + 1; - if(GetComputerNameA((char*)buffer, &size)) - { - info->machine_name = push_str8_copy(arena, str8(buffer, size)); - } - } - } - { - OS_ProcessInfo *info = &os_w32_state.process_info; - { - Temp scratch = scratch_begin(0, 0); - DWORD size = KB(32); - U16 *buffer = push_array_no_zero(scratch.arena, U16, size); - DWORD length = GetModuleFileNameW(0, (WCHAR*)buffer, size); - String8 name8 = str8_from_16(scratch.arena, str16(buffer, length)); - String8 name_chopped = str8_chop_last_slash(name8); - info->binary_path = push_str8_copy(arena, name_chopped); - scratch_end(scratch); - } - info->initial_path = os_get_current_path(arena); - { - Temp scratch = scratch_begin(0, 0); - U64 size = KB(32); - U16 *buffer = push_array_no_zero(scratch.arena, U16, size); - if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, 0, 0, (WCHAR*)buffer))) - { - info->user_program_data_path = str8_from_16(arena, str16_cstring(buffer)); - } - scratch_end(scratch); - } - { - WCHAR *this_proc_env = GetEnvironmentStringsW(); - U64 start_idx = 0; - for(U64 idx = 0;; idx += 1) - { - if(this_proc_env[idx] == 0) - { - if(start_idx == idx) - { - break; - } - else - { - String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx); - String8 string = str8_from_16(arena, string16); - str8_list_push(arena, &info->environment, string); - start_idx = idx+1; - } - } - } - } - } - - //- rjf: set up entity storage - InitializeCriticalSection(&os_w32_state.entity_mutex); - os_w32_state.entity_arena = arena_alloc(); - - //- rjf: call into "real" entry point - main_thread_base_entry_point(argc, argv); -} - -#if BUILD_CONSOLE_INTERFACE -int wmain(int argc, WCHAR **argv) -{ - w32_entry_point_caller(argc, argv); - return 0; -} -#else -int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) -{ - w32_entry_point_caller(__argc, __wargv); - return 0; -} -#endif diff --git a/src/metagen/metagen_os/core/win32/metagen_os_core_win32.h b/src/metagen/metagen_os/core/win32/metagen_os_core_win32.h deleted file mode 100644 index 9a8f0d12..00000000 --- a/src/metagen/metagen_os/core/win32/metagen_os_core_win32.h +++ /dev/null @@ -1,121 +0,0 @@ -// 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 - -#include -#include -#include -#include -#include -#include -#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 diff --git a/src/metagen/metagen_os/metagen_os_inc.c b/src/metagen/metagen_os/metagen_os_inc.c deleted file mode 100644 index 70bb1565..00000000 --- a/src/metagen/metagen_os/metagen_os_inc.c +++ /dev/null @@ -1,12 +0,0 @@ -// 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 diff --git a/src/metagen/metagen_os/metagen_os_inc.h b/src/metagen/metagen_os/metagen_os_inc.h deleted file mode 100644 index b2d96f02..00000000 --- a/src/metagen/metagen_os/metagen_os_inc.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#ifndef OS_INC_H -#define OS_INC_H - -#if !defined(OS_FEATURE_GRAPHICAL) -# define OS_FEATURE_GRAPHICAL 0 -#endif - -#include "metagen/metagen_os/core/metagen_os_core.h" - -#if OS_WINDOWS -# include "metagen/metagen_os/core/win32/metagen_os_core_win32.h" -#elif OS_LINUX -# include "metagen/metagen_os/core/linux/metagen_os_core_linux.h" -#else -# error OS core layer not implemented for this operating system. -#endif - -#endif // OS_INC_H