progress on os (on files)

This commit is contained in:
ed
2025-02-07 19:05:04 -05:00
parent 475dd029e0
commit a4f915d27d
10 changed files with 564 additions and 552 deletions
+5 -1
View File
@@ -47,7 +47,11 @@
"thread": "c", "thread": "c",
"cmath": "c", "cmath": "c",
"string.h": "c", "string.h": "c",
"time.h": "c" "time.h": "c",
"sstream": "c",
"os_win32.h": "c",
"windows.h": "c",
"base.h": "c"
}, },
"workbench.colorCustomizations": { "workbench.colorCustomizations": {
"activityBar.activeBackground": "#713fb8", "activityBar.activeBackground": "#713fb8",
+1 -14
View File
@@ -10,20 +10,7 @@
# include <intrin.h> # include <intrin.h>
# include <tmmintrin.h> # include <tmmintrin.h>
# include <wmmintrin.h> # include <wmmintrin.h>
# ifndef WIN32_LEAN_AND_MEAN
# ifndef NOMINMAX
# define NOMINMAX
# endif
#
# define WIN32_LEAN_AND_MEAN
# define WIN32_MEAN_AND_LEAN
# define VC_EXTRALEAN
# include <Windows.h>
# endif
# undef NOMINMAX
# undef WIN32_LEAN_AND_MEAN
# undef WIN32_MEAN_AND_LEAN
# undef VC_EXTRALEAN
#endif #endif
#if LANG_C #if LANG_C
+10 -4
View File
@@ -21,12 +21,12 @@
//////////////////////////////// ////////////////////////////////
//~ NOTE(allen): String <-> Integer Tables //~ NOTE(allen): String <-> Integer Tables
read_only global U8 integer_symbols[16] = { MD_API_C read_only global U8 integer_symbols[16] = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', '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. // NOTE(allen): Includes reverses for uppercase and lowercase hex.
read_only global U8 integer_symbol_reverse[128] = { MD_API_C 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, 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,
@@ -37,7 +37,7 @@ 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,
}; };
read_only global U8 base64[64] = { MD_API_C read_only global U8 base64[64] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', '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', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
@@ -46,7 +46,7 @@ read_only global U8 base64[64] = {
'_', '$', '_', '$',
}; };
read_only global U8 base64_reverse[128] = { MD_API_C 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,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, 0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
@@ -574,6 +574,7 @@ str8_from_alloctor_s64(AllocatorInfo ainfo, S64 s64, U32 radix, U8 min_digits, U
{ {
String8 result = {0}; String8 result = {0};
if(s64 < 0) { if(s64 < 0) {
// TODO(Ed): Review, we should just keep using thread scratch arenas (and provide them to teh context)
U8 bytes[KB(8)]; U8 bytes[KB(8)];
FArena scratch = farena_from_memory(bytes, size_of(bytes)); FArena scratch = farena_from_memory(bytes, size_of(bytes));
String8 numeric_part = str8_from_allocator_u64(farena_allocator(scratch), (U64)(-s64), radix, min_digits, digit_group_separator); String8 numeric_part = str8_from_allocator_u64(farena_allocator(scratch), (U64)(-s64), radix, min_digits, digit_group_separator);
@@ -969,6 +970,7 @@ path_style_from_str8(String8 string) {
void void
str8_path_list_resolve_dots_in_place(String8List* path, PathStyle style) str8_path_list_resolve_dots_in_place(String8List* path, PathStyle style)
{ {
// TODO(Ed): Review
TempArena scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
String8MetaNode* stack = 0; String8MetaNode* stack = 0;
String8MetaNode* free_meta_node = 0; String8MetaNode* free_meta_node = 0;
@@ -1605,6 +1607,7 @@ indented_from_string(Arena* arena, String8 string)
String8 String8
indented_from_string_alloc(AllocatorInfo ainfo, String8 string) indented_from_string_alloc(AllocatorInfo ainfo, String8 string)
{ {
// TODO(Ed): Review, we should just keep using thread scratch arenas (and provide them to teh context)
Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1)); Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1));
TempArena scratch = scratch_begin(&arena, 1); TempArena scratch = scratch_begin(&arena, 1);
@@ -1697,6 +1700,7 @@ escaped_from_raw_str8(Arena* arena, String8 string)
String8 String8
escaped_from_raw_str8_alloc(AllocatorInfo ainfo, String8 string) escaped_from_raw_str8_alloc(AllocatorInfo ainfo, String8 string)
{ {
// TODO(Ed): Review, we should just keep using thread scratch arenas (and provide them to teh context)
Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1)); Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1));
TempArena scratch = scratch_begin(&arena, 1); TempArena scratch = scratch_begin(&arena, 1);
@@ -1796,6 +1800,7 @@ raw_from_escaped_str8(Arena* arena, String8 string)
String8 String8
raw_from_escaped_str8_alloc(AllocatorInfo ainfo, String8 string) raw_from_escaped_str8_alloc(AllocatorInfo ainfo, String8 string)
{ {
// TODO(Ed): Review, we should just keep using thread scratch arenas (and provide them to teh context)
Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1)); Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1));
TempArena scratch = scratch_begin(&arena, 1); TempArena scratch = scratch_begin(&arena, 1);
@@ -2054,6 +2059,7 @@ fuzzy_match_find(Arena *arena, String8 needle, String8 haystack)
FuzzyMatchRangeList FuzzyMatchRangeList
fuzzy_match_find_alloc(AllocatorInfo ainfo, String8 needle, String8 haystack) fuzzy_match_find_alloc(AllocatorInfo ainfo, String8 needle, String8 haystack)
{ {
// TODO(Ed): Review, we should just keep using thread scratch arenas (and provide them to teh context)
Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1)); Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1));
TempArena scratch = temp_begin(&arena, 1); TempArena scratch = temp_begin(&arena, 1);
+2 -2
View File
@@ -9,10 +9,10 @@
//////////////////////////////// ////////////////////////////////
// NOTE(allen): Thread Context Functions // NOTE(allen): Thread Context Functions
thread_static TCTX* tctx_thread_local; MD_API_C thread_static TCTX* tctx_thread_local;
#if ! MD_BUILD_SUPPLEMENTARY_UNIT #if ! MD_BUILD_SUPPLEMENTARY_UNIT
thread_static TCTX* tctx_thread_local = 0; MD_API_C thread_static TCTX* tctx_thread_local = 0;
#endif #endif
void void
-194
View File
@@ -1,194 +0,0 @@
#ifdef INTELLISENSE_DIRECTIVES
# include "os.h"
#endif
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
OS_Handle
os_handle_zero(void)
{
OS_Handle handle = {0};
return handle;
}
B32
os_handle_match(OS_Handle a, OS_Handle b)
{
return a.u64[0] == b.u64[0];
}
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;
}
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)
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)
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;
}
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;
}
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;
}
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;
}
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;
}
S64
os_file_id_compare(OS_FileID a, OS_FileID b)
{
S64 cmp = memory_compare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v));
return cmp;
}
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;
}
String8
os_string_from_file_range_alloc(AllocatorInfo ainfo, OS_Handle file, Rng1U64 range) {
String8 result;
result.size = dim_1u64(range);
result.str = alloc_array_no_zero(ainfo, U8, result.size);
U64 actual_read_size = os_file_read(file, range, result.str);
if(actual_read_size < result.size)
{
// TODO(Ed): It may be better to actually wrap the alloation in an arena and then rewind it.
// This would ensure resize isn't doing an expensive shrink (from a bad heap realloc, or something else)
// That or we just leave it up to the user to make sure to pass in an arena.
resize(ainfo, result.str, result.size, result.str + actual_read_size);
result.size = actual_read_size;
}
return result;
}
////////////////////////////////
//~ rjf: GUID Helpers (Helpers, Implemented Once)
internal String8
os_string_from_guid(Arena *arena, OS_Guid guid)
{
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.data1,
guid.data2,
guid.data3,
guid.data4[0],
guid.data4[1],
guid.data4[2],
guid.data4[3],
guid.data4[4],
guid.data4[5],
guid.data4[6],
guid.data4[7]);
return result;
}
+3 -4
View File
@@ -1,7 +1,6 @@
#ifdef INTELLISENSE_DIRECTIVES #ifdef INTELLISENSE_DIRECTIVES
#pragma once # pragma once
#include "base/macros.h" # include "base/base.h"
#include "base/base_types.h"
#endif #endif
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
@@ -45,7 +44,7 @@ struct OS_LNX_FileIter
struct dirent* dp; struct dirent* dp;
String8 path; String8 path;
}; };
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check); md_assert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check);
//////////////////////////////// ////////////////////////////////
//~ rjf: Safe Call Handler Chain //~ rjf: Safe Call Handler Chain
+93
View File
@@ -0,0 +1,93 @@
#ifdef INTELLISENSE_DIRECTIVES
# include "os.h"
#endif
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
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;
}
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;
}
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;
}
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;
}
String8
os_string_from_file_range_alloc(AllocatorInfo ainfo, OS_Handle file, Rng1U64 range) {
String8 result;
result.size = dim_1u64(range);
result.str = alloc_array_no_zero(ainfo, U8, result.size);
U64 actual_read_size = os_file_read(file, range, result.str);
if(actual_read_size < result.size)
{
// TODO(Ed): It may be better to actually wrap the alloation in an arena and then rewind it.
// This would ensure resize isn't doing an expensive shrink (from a bad heap realloc, or something else)
// That or we just leave it up to the user to make sure to pass in an arena.
resize(ainfo, result.str, result.size, result.str + actual_read_size);
result.size = actual_read_size;
}
return result;
}
+128 -17
View File
@@ -19,7 +19,6 @@
# error OS core layer not implemented for this operating system. # error OS core layer not implemented for this operating system.
#endif #endif
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
@@ -162,31 +161,144 @@ typedef void OS_ThreadFunctionType(void *ptr);
//////////////////////////////// ////////////////////////////////
//~ rjf: Handle Type Functions (Helpers, Implemented Once) //~ rjf: Handle Type Functions (Helpers, Implemented Once)
OS_Handle os_handle_zero (void); force_inline OS_Handle os_handle_zero (void) { OS_Handle handle = {0}; return handle; }
B32 os_handle_match (OS_Handle a, OS_Handle b); force_inline B32 os_handle_match(OS_Handle a, OS_Handle b) { return a.u64[0] == b.u64[0]; }
void os_handle_list_push (Arena* arena, OS_HandleList* handles, OS_Handle handle); void os_handle_list_push (Arena* arena, OS_HandleList* handles, OS_Handle handle);
OS_HandleArray os_handle_array_from_list(Arena* arena, OS_HandleList* list); void os_handle_list_alloc (AllocatorInfo ainfo, OS_HandleList* handles, OS_Handle handle);
OS_HandleArray os_handle_array_from_list (Arena* arena, OS_HandleList* list);
OS_HandleArray os_handle_array_from_list_alloc(AllocatorInfo ainfo, OS_HandleList* list);
inline void
os_handle_list_push(Arena* arena, OS_HandleList* handles, OS_Handle handle) {
#if MD_DONT_MAP_ARENA_TO_ALLOCATOR_IMPL
OS_HandleNode* n = push_array(arena, OS_HandleNode, 1);
n->v = handle;
sll_queue_push(handles->first, handles->last, n);
handles->count += 1;
#else
return os_handle_list_alloc(arena_allocator(arena), handles, handle);
#endif
}
inline OS_HandleArray
os_handle_array_from_list(Arena* arena, OS_HandleList* list) {
#if MD_DONT_MAP_ARENA_TO_ALLOCATOR_IMPL
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;
#else
return os_handle_array_from_list_alloc(arena_allocator(arena), list);
#endif
}
inline void
os_handle_list_alloc(AllocatorInfo ainfo, OS_HandleList* handles, OS_Handle handle) {
OS_HandleNode* n = alloc_array(ainfo, OS_HandleNode, 1);
n->v = handle;
sll_queue_push(handles->first, handles->last, n);
handles->count += 1;
}
inline OS_HandleArray
os_handle_array_from_list_alloc(AllocatorInfo ainfo, OS_HandleList* list) {
OS_HandleArray result = {0};
result.count = list->count;
result.v = alloc_array_no_zero(ainfo, 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) //~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv); inline 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) //~ rjf: Filesystem Helpers (Helpers, Implemented Once)
internal String8 os_data_from_file_path(Arena *arena, String8 path); MD_API B32 os_write_data_to_file_path (String8 path, String8 data);
internal B32 os_write_data_to_file_path(String8 path, String8 data); MD_API B32 os_write_data_list_to_file_path(String8 path, String8List list);
internal B32 os_write_data_list_to_file_path(String8 path, String8List list); MD_API B32 os_append_data_to_file_path (String8 path, String8 data);
internal B32 os_append_data_to_file_path(String8 path, String8 data); OS_FileID os_id_from_file_path (String8 path);
internal OS_FileID os_id_from_file_path(String8 path); S64 os_file_id_compare (OS_FileID a, OS_FileID b);
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); String8 os_data_from_file_path (Arena* arena, String8 path);
String8 os_data_from_file_path_alloc (AllocatorInfo ainfo, String8 path);
MD_API String8 os_string_from_file_range (Arena* arena, OS_Handle file, Rng1U64 range);
MD_API String8 os_string_from_file_range_alloc(AllocatorInfo ainfo, OS_Handle file, Rng1U64 range);
inline String8
os_data_from_file_path(Arena* arena, String8 path)
{
#if MD_DONT_MAP_ARENA_TO_ALLOCATOR_IMPL
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;
#else
return os_data_from_file_path_alloc(arena_allocator(arena), path);
#endif
}
inline String8
os_data_from_file_path_alloc(AllocatorInfo ainfo, 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_alloc(ainfo, file, r1u64(0, props.size));
os_file_close(file);
return data;
}
inline 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;
}
inline S64 os_file_id_compare(OS_FileID a, OS_FileID b) { S64 cmp = memory_compare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v)); return cmp; }
//////////////////////////////// ////////////////////////////////
//~ rjf: GUID Helpers (Helpers, Implemented Once) //~ rjf: GUID Helpers (Helpers, Implemented Once)
internal String8 os_string_from_guid(Arena *arena, OS_Guid guid); inline String8
os_string_from_guid(Arena* arena, OS_Guid guid) {
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.data1,
guid.data2,
guid.data3,
guid.data4[0],
guid.data4[1],
guid.data4[2],
guid.data4[3],
guid.data4[4],
guid.data4[5],
guid.data4[6],
guid.data4[7]);
return result;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS) //~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
@@ -239,11 +351,11 @@ internal FileProperties os_properties_from_file_path(String8 path);
//- rjf: file maps //- rjf: file maps
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file); 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_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_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range);
internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range); internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range);
//- rjf: directory iteration //- rjf: directory iteration
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags); 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 B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out);
internal void os_file_iter_end(OS_FileIter *iter); internal void os_file_iter_end(OS_FileIter *iter);
@@ -256,7 +368,7 @@ internal B32 os_make_directory(String8 path);
internal OS_Handle os_shared_memory_alloc(U64 size, String8 name); internal OS_Handle os_shared_memory_alloc(U64 size, String8 name);
internal OS_Handle os_shared_memory_open(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_close(OS_Handle handle);
internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range); 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); internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range);
//////////////////////////////// ////////////////////////////////
@@ -351,4 +463,3 @@ internal OS_Guid os_make_guid(void);
#if BUILD_ENTRY_DEFINING_UNIT #if BUILD_ENTRY_DEFINING_UNIT
internal void entry_point(CmdLine *cmdline); internal void entry_point(CmdLine *cmdline);
#endif #endif
+69 -189
View File
@@ -1,88 +1,38 @@
#ifdef INTELLISENSE_DIRECTIVES
# include "os_win32.h"
# include "os/os.h"
#endif
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
MD_API global OS_W32_State os_w32_state = {0};
//////////////////////////////// ////////////////////////////////
//~ rjf: Modern Windows SDK Functions //~ rjf: Modern Windows SDK Functions
// //
// (We must dynamically link to them, since they can be missing in older SDKs) // (We must dynamically link to them, since they can be missing in older SDKs)
typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDescription); typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDescription);
global W32_SetThreadDescription_Type *w32_SetThreadDescription_func = 0; MD_API_C global W32_SetThreadDescription_Type* w32_SetThreadDescription_func = 0;
//////////////////////////////// ////////////////////////////////
//~ rjf: File Info Conversion Helpers //~ 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 //~ rjf: Time Conversion Helpers
internal void U32
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) os_w32_sleep_ms_from_endt_us(U64 endt_us)
{ {
U32 sleep_ms = 0; U32 sleep_ms = 0;
if(endt_us == max_U64) if (endt_us == MAX_U64) {
{
sleep_ms = INFINITE; sleep_ms = INFINITE;
} }
else else
{ {
U64 begint = os_now_microseconds(); U64 begint = os_now_microseconds();
if(begint < endt_us) if (begint < endt_us) {
{
U64 sleep_us = endt_us - begint; U64 sleep_us = endt_us - begint;
sleep_ms = (U32)((sleep_us + 999)/1000); sleep_ms = (U32)((sleep_us + 999)/1000);
} }
@@ -93,7 +43,7 @@ os_w32_sleep_ms_from_endt_us(U64 endt_us)
//////////////////////////////// ////////////////////////////////
//~ rjf: Entity Functions //~ rjf: Entity Functions
internal OS_W32_Entity * OS_W32_Entity*
os_w32_entity_alloc(OS_W32_EntityKind kind) os_w32_entity_alloc(OS_W32_EntityKind kind)
{ {
OS_W32_Entity *result = 0; OS_W32_Entity *result = 0;
@@ -102,37 +52,38 @@ os_w32_entity_alloc(OS_W32_EntityKind kind)
result = os_w32_state.entity_free; result = os_w32_state.entity_free;
if(result) if(result)
{ {
SLLStackPop(os_w32_state.entity_free); sll_stack_pop(os_w32_state.entity_free);
} }
else else
{ {
result = push_array_no_zero(os_w32_state.entity_arena, OS_W32_Entity, 1); result = push_array_no_zero(os_w32_state.entity_arena, OS_W32_Entity, 1);
} }
MemoryZeroStruct(result); memory_zero_struct(result);
} }
LeaveCriticalSection(&os_w32_state.entity_mutex); LeaveCriticalSection(&os_w32_state.entity_mutex);
result->kind = kind; result->kind = kind;
return result; return result;
} }
internal void void
os_w32_entity_release(OS_W32_Entity *entity) os_w32_entity_release(OS_W32_Entity *entity)
{ {
entity->kind = OS_W32_EntityKind_Null; entity->kind = OS_W32_EntityKind_Null;
EnterCriticalSection(&os_w32_state.entity_mutex); EnterCriticalSection(&os_w32_state.entity_mutex);
SLLStackPush(os_w32_state.entity_free, entity); sll_stack_push(os_w32_state.entity_free, entity);
LeaveCriticalSection(&os_w32_state.entity_mutex); LeaveCriticalSection(&os_w32_state.entity_mutex);
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: Thread Entry Point //~ rjf: Thread Entry Point
internal DWORD DWORD
os_w32_thread_entry_point(void *ptr) os_w32_thread_entry_point(void *ptr)
{ {
OS_W32_Entity *entity = (OS_W32_Entity *)ptr; OS_W32_Entity* entity = (OS_W32_Entity*)ptr;
OS_ThreadFunctionType *func = entity->thread.func; OS_ThreadFunctionType* func = entity->thread.func;
void *thread_ptr = entity->thread.ptr; void* thread_ptr = entity->thread.ptr;
TCTX tctx_; TCTX tctx_;
tctx_init_and_equip(&tctx_); tctx_init_and_equip(&tctx_);
func(thread_ptr); func(thread_ptr);
@@ -143,95 +94,26 @@ os_w32_thread_entry_point(void *ptr)
//////////////////////////////// ////////////////////////////////
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS) //~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
internal OS_SystemInfo * OS_SystemInfo*
os_get_system_info(void) os_get_system_info(void) {
{
return &os_w32_state.system_info; return &os_w32_state.system_info;
} }
internal OS_ProcessInfo * OS_ProcessInfo*
os_get_process_info(void) os_get_process_info(void) {
{
return &os_w32_state.process_info; 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;
}
////////////////////////////////
//~ 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) //~ rjf: @os_hooks Thread Info (Implemented Per-OS)
internal U32 void
os_tid(void)
{
DWORD id = GetCurrentThreadId();
return (U32)id;
}
internal void
os_set_thread_name(String8 name) os_set_thread_name(String8 name)
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
// rjf: windows 10 style // rjf: windows 10 style
if(w32_SetThreadDescription_func) if (w32_SetThreadDescription_func)
{ {
String16 name16 = str16_from_8(scratch.arena, name); String16 name16 = str16_from_8(scratch.arena, name);
HRESULT hr = w32_SetThreadDescription_func(GetCurrentThread(), (WCHAR*)name16.str); HRESULT hr = w32_SetThreadDescription_func(GetCurrentThread(), (WCHAR*)name16.str);
@@ -240,23 +122,26 @@ os_set_thread_name(String8 name)
// rjf: raise-exception style // rjf: raise-exception style
{ {
String8 name_copy = push_str8_copy(scratch.arena, name); String8 name_copy = push_str8_copy(scratch.arena, name);
#pragma pack(push,8)
#pragma pack(push,8)
typedef struct THREADNAME_INFO THREADNAME_INFO; typedef struct THREADNAME_INFO THREADNAME_INFO;
struct THREADNAME_INFO struct THREADNAME_INFO
{ {
U32 dwType; // Must be 0x1000. U32 dwType; // Must be 0x1000.
char *szName; // Pointer to name (in user addr space). char* szName; // Pointer to name (in user addr space).
U32 dwThreadID; // Thread ID (-1=caller thread). U32 dwThreadID; // Thread ID (-1=caller thread).
U32 dwFlags; // Reserved for future use, must be zero. U32 dwFlags; // Reserved for future use, must be zero.
}; };
#pragma pack(pop) #pragma pack(pop)
THREADNAME_INFO info; THREADNAME_INFO info;
info.dwType = 0x1000; info.dwType = 0x1000;
info.szName = (char *)name_copy.str; info.szName = (char *)name_copy.str;
info.dwThreadID = os_tid(); info.dwThreadID = os_tid();
info.dwFlags = 0; info.dwFlags = 0;
#pragma warning(push)
#pragma warning(disable: 6320 6322) #pragma warning(push)
#pragma warning(disable: 6320 6322)
__try __try
{ {
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info);
@@ -264,55 +149,50 @@ os_set_thread_name(String8 name)
__except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_EXECUTE_HANDLER)
{ {
} }
#pragma warning(pop) #pragma warning(pop)
} }
scratch_end(scratch); 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: @os_hooks File System (Implemented Per-OS)
//- rjf: files //- rjf: files
internal OS_Handle OS_Handle
os_file_open(OS_AccessFlags flags, String8 path) os_file_open(OS_AccessFlags flags, String8 path)
{ {
OS_Handle result = {0}; OS_Handle result = {0};
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
{
String16 path16 = str16_from_8(scratch.arena, path); String16 path16 = str16_from_8(scratch.arena, path);
DWORD access_flags = 0; DWORD access_flags = 0;
DWORD share_mode = 0; DWORD share_mode = 0;
DWORD creation_disposition = OPEN_EXISTING; DWORD creation_disposition = OPEN_EXISTING;
if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;}
if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;} if (flags & OS_AccessFlag_Read) { access_flags |= GENERIC_READ; }
if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;} if (flags & OS_AccessFlag_Write) { access_flags |= GENERIC_WRITE; }
if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;} if (flags & OS_AccessFlag_Execute) { access_flags |= GENERIC_EXECUTE; }
if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;} if (flags & OS_AccessFlag_ShareRead) { share_mode |= FILE_SHARE_READ; }
if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;} if (flags & OS_AccessFlag_ShareWrite) { share_mode |= FILE_SHARE_WRITE | FILE_SHARE_DELETE; }
if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS;} if (flags & OS_AccessFlag_Write) { creation_disposition = CREATE_ALWAYS; }
HANDLE file = CreateFileW((WCHAR *)path16.str, access_flags, share_mode, 0, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0); if (flags & OS_AccessFlag_Append) { creation_disposition = OPEN_ALWAYS; }
if(file != INVALID_HANDLE_VALUE)
{ HANDLE file = CreateFileW((WCHAR*)path16.str, access_flags, share_mode, 0, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0);
if (file != INVALID_HANDLE_VALUE) {
result.u64[0] = (U64)file; result.u64[0] = (U64)file;
} }
}
scratch_end(scratch); scratch_end(scratch);
return result; return result;
} }
internal void void
os_file_close(OS_Handle file) os_file_close(OS_Handle file)
{ {
if(os_handle_match(file, os_handle_zero())) { return; } if (os_handle_match(file, os_handle_zero())) { return; }
HANDLE handle = (HANDLE)file.u64[0]; HANDLE handle = (HANDLE)file.u64[0];
BOOL result = CloseHandle(handle); BOOL result = CloseHandle(handle);
(void)result; (void)result;
@@ -438,7 +318,7 @@ os_id_from_file(OS_Handle file)
internal B32 internal B32
os_delete_file_at_path(String8 path) os_delete_file_at_path(String8 path)
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
String16 path16 = str16_from_8(scratch.arena, path); String16 path16 = str16_from_8(scratch.arena, path);
B32 result = DeleteFileW((WCHAR*)path16.str); B32 result = DeleteFileW((WCHAR*)path16.str);
scratch_end(scratch); scratch_end(scratch);
@@ -448,7 +328,7 @@ os_delete_file_at_path(String8 path)
internal B32 internal B32
os_copy_file_path(String8 dst, String8 src) os_copy_file_path(String8 dst, String8 src)
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
String16 dst16 = str16_from_8(scratch.arena, dst); String16 dst16 = str16_from_8(scratch.arena, dst);
String16 src16 = str16_from_8(scratch.arena, src); String16 src16 = str16_from_8(scratch.arena, src);
B32 result = CopyFileW((WCHAR*)src16.str, (WCHAR*)dst16.str, 0); B32 result = CopyFileW((WCHAR*)src16.str, (WCHAR*)dst16.str, 0);
@@ -459,7 +339,7 @@ os_copy_file_path(String8 dst, String8 src)
internal String8 internal String8
os_full_path_from_path(Arena *arena, String8 path) os_full_path_from_path(Arena *arena, String8 path)
{ {
Temp scratch = scratch_begin(&arena, 1); TempArena scratch = scratch_begin(&arena, 1);
DWORD buffer_size = MAX_PATH + 1; DWORD buffer_size = MAX_PATH + 1;
U16 *buffer = push_array_no_zero(scratch.arena, U16, buffer_size); U16 *buffer = push_array_no_zero(scratch.arena, U16, buffer_size);
String16 path16 = str16_from_8(scratch.arena, path); String16 path16 = str16_from_8(scratch.arena, path);
@@ -472,7 +352,7 @@ os_full_path_from_path(Arena *arena, String8 path)
internal B32 internal B32
os_file_path_exists(String8 path) os_file_path_exists(String8 path)
{ {
Temp scratch = scratch_begin(0,0); TempArena scratch = scratch_begin(0,0);
String16 path16 = str16_from_8(scratch.arena, path); String16 path16 = str16_from_8(scratch.arena, path);
DWORD attributes = GetFileAttributesW((WCHAR *)path16.str); DWORD attributes = GetFileAttributesW((WCHAR *)path16.str);
B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && !!(~attributes & FILE_ATTRIBUTE_DIRECTORY); B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && !!(~attributes & FILE_ATTRIBUTE_DIRECTORY);
@@ -484,7 +364,7 @@ internal FileProperties
os_properties_from_file_path(String8 path) os_properties_from_file_path(String8 path)
{ {
WIN32_FIND_DATAW find_data = {0}; WIN32_FIND_DATAW find_data = {0};
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
String16 path16 = str16_from_8(scratch.arena, path); String16 path16 = str16_from_8(scratch.arena, path);
HANDLE handle = FindFirstFileW((WCHAR *)path16.str, &find_data); HANDLE handle = FindFirstFileW((WCHAR *)path16.str, &find_data);
FileProperties props = {0}; FileProperties props = {0};
@@ -589,7 +469,7 @@ os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range)
internal OS_FileIter * internal OS_FileIter *
os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags)
{ {
Temp scratch = scratch_begin(&arena, 1); TempArena scratch = scratch_begin(&arena, 1);
String8 path_with_wildcard = push_str8_cat(scratch.arena, path, str8_lit("\\*")); String8 path_with_wildcard = push_str8_cat(scratch.arena, path, str8_lit("\\*"));
String16 path16 = str16_from_8(scratch.arena, path_with_wildcard); String16 path16 = str16_from_8(scratch.arena, path_with_wildcard);
OS_FileIter *iter = push_array(arena, OS_FileIter, 1); OS_FileIter *iter = push_array(arena, OS_FileIter, 1);
@@ -751,7 +631,7 @@ os_shared_memory_alloc(U64 size, String8 name)
internal OS_Handle internal OS_Handle
os_shared_memory_open(String8 name) os_shared_memory_open(String8 name)
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
String16 name16 = str16_from_8(scratch.arena, name); String16 name16 = str16_from_8(scratch.arena, name);
HANDLE file = OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, (WCHAR *)name16.str); HANDLE file = OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, (WCHAR *)name16.str);
OS_Handle result = {(U64)file}; OS_Handle result = {(U64)file};
@@ -864,7 +744,7 @@ internal OS_Handle
os_process_launch(OS_ProcessLaunchParams *params) os_process_launch(OS_ProcessLaunchParams *params)
{ {
OS_Handle result = {0}; OS_Handle result = {0};
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
//- rjf: form full command string //- rjf: form full command string
String8 cmd = {0}; String8 cmd = {0};
@@ -1150,7 +1030,7 @@ os_condition_variable_broadcast(OS_Handle cv)
internal OS_Handle internal OS_Handle
os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name)
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
String16 name16 = str16_from_8(scratch.arena, name); String16 name16 = str16_from_8(scratch.arena, name);
HANDLE handle = CreateSemaphoreW(0, initial_count, max_count, (WCHAR *)name16.str); HANDLE handle = CreateSemaphoreW(0, initial_count, max_count, (WCHAR *)name16.str);
OS_Handle result = {(U64)handle}; OS_Handle result = {(U64)handle};
@@ -1168,7 +1048,7 @@ os_semaphore_release(OS_Handle semaphore)
internal OS_Handle internal OS_Handle
os_semaphore_open(String8 name) os_semaphore_open(String8 name)
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
String16 name16 = str16_from_8(scratch.arena, name); String16 name16 = str16_from_8(scratch.arena, name);
HANDLE handle = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS , 0, (WCHAR *)name16.str); HANDLE handle = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS , 0, (WCHAR *)name16.str);
OS_Handle result = {(U64)handle}; OS_Handle result = {(U64)handle};
@@ -1206,7 +1086,7 @@ os_semaphore_drop(OS_Handle semaphore)
internal OS_Handle internal OS_Handle
os_library_open(String8 path) os_library_open(String8 path)
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
String16 path16 = str16_from_8(scratch.arena, path); String16 path16 = str16_from_8(scratch.arena, path);
HMODULE mod = LoadLibraryW((LPCWSTR)path16.str); HMODULE mod = LoadLibraryW((LPCWSTR)path16.str);
OS_Handle result = { (U64)mod }; OS_Handle result = { (U64)mod };
@@ -1217,7 +1097,7 @@ os_library_open(String8 path)
internal VoidProc* internal VoidProc*
os_library_load_proc(OS_Handle lib, String8 name) os_library_load_proc(OS_Handle lib, String8 name)
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
HMODULE mod = (HMODULE)lib.u64[0]; HMODULE mod = (HMODULE)lib.u64[0];
name = push_str8_copy(scratch.arena, name); name = push_str8_copy(scratch.arena, name);
VoidProc *result = (VoidProc*)GetProcAddress(mod, (LPCSTR)name.str); VoidProc *result = (VoidProc*)GetProcAddress(mod, (LPCSTR)name.str);
@@ -1565,7 +1445,7 @@ w32_entry_point_caller(int argc, WCHAR **wargv)
{ {
OS_ProcessInfo *info = &os_w32_state.process_info; OS_ProcessInfo *info = &os_w32_state.process_info;
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
DWORD size = KB(32); DWORD size = KB(32);
U16 *buffer = push_array_no_zero(scratch.arena, U16, size); U16 *buffer = push_array_no_zero(scratch.arena, U16, size);
DWORD length = GetModuleFileNameW(0, (WCHAR*)buffer, size); DWORD length = GetModuleFileNameW(0, (WCHAR*)buffer, size);
@@ -1576,7 +1456,7 @@ w32_entry_point_caller(int argc, WCHAR **wargv)
} }
info->initial_path = os_get_current_path(arena); info->initial_path = os_get_current_path(arena);
{ {
Temp scratch = scratch_begin(0, 0); TempArena scratch = scratch_begin(0, 0);
U64 size = KB(32); U64 size = KB(32);
U16 *buffer = push_array_no_zero(scratch.arena, U16, size); U16 *buffer = push_array_no_zero(scratch.arena, U16, size);
if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, 0, 0, (WCHAR*)buffer))) if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, 0, 0, (WCHAR*)buffer)))
+155 -29
View File
@@ -1,13 +1,20 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "base/base.h"
#endif
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef OS_CORE_WIN32_H
#define OS_CORE_WIN32_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Includes / Libraries //~ rjf: Includes / Libraries
#ifndef NOMINMAX
#define NOMINMAX
#endif
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define WIN32_MEAN_AND_LEAN
#define VC_EXTRALEAN
#include <windows.h> #include <windows.h>
#include <windowsx.h> #include <windowsx.h>
#include <timeapi.h> #include <timeapi.h>
@@ -22,6 +29,10 @@
#pragma comment(lib, "shlwapi") #pragma comment(lib, "shlwapi")
#pragma comment(lib, "comctl32") #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 #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
#undef NOMINMAX
#undef WIN32_LEAN_AND_MEAN
#undef WIN32_MEAN_AND_LEAN
#undef VC_EXTRALEAN
//////////////////////////////// ////////////////////////////////
//~ rjf: File Iterator Types //~ rjf: File Iterator Types
@@ -35,35 +46,38 @@ struct OS_W32_FileIter
String8Array drive_strings; String8Array drive_strings;
U64 drive_strings_iter_idx; U64 drive_strings_iter_idx;
}; };
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_W32_FileIter), file_iter_memory_size); md_static_assert(sizeof(member(OS_FileIter, memory)) >= sizeof(OS_W32_FileIter), file_iter_memory_size);
//////////////////////////////// ////////////////////////////////
//~ rjf: Entity Types //~ rjf: Entity Types
typedef enum OS_W32_EntityKind typedef enum OS_W32_EntityKind OS_W32_EntityKind;
enum OS_W32_EntityKind
{ {
OS_W32_EntityKind_Null, OS_W32_EntityKind_Null,
OS_W32_EntityKind_Thread, OS_W32_EntityKind_Thread,
OS_W32_EntityKind_Mutex, OS_W32_EntityKind_Mutex,
OS_W32_EntityKind_RWMutex, OS_W32_EntityKind_RWMutex,
OS_W32_EntityKind_ConditionVariable, OS_W32_EntityKind_ConditionVariable,
} };
OS_W32_EntityKind;
typedef struct OS_W32_EntityThread OS_W32_EntityThread;
struct OS_W32_EntityThread
{
OS_ThreadFunctionType* func;
void* ptr;
HANDLE handle;
DWORD tid;
};
typedef struct OS_W32_Entity OS_W32_Entity; typedef struct OS_W32_Entity OS_W32_Entity;
struct OS_W32_Entity struct OS_W32_Entity
{ {
OS_W32_Entity *next; OS_W32_Entity* next;
OS_W32_EntityKind kind; OS_W32_EntityKind kind;
union union
{ {
struct OS_W32_EntityThread thread;
{
OS_ThreadFunctionType *func;
void *ptr;
HANDLE handle;
DWORD tid;
} thread;
CRITICAL_SECTION mutex; CRITICAL_SECTION mutex;
SRWLOCK rw_mutex; SRWLOCK rw_mutex;
CONDITION_VARIABLE cv; CONDITION_VARIABLE cv;
@@ -76,7 +90,7 @@ struct OS_W32_Entity
typedef struct OS_W32_State OS_W32_State; typedef struct OS_W32_State OS_W32_State;
struct OS_W32_State struct OS_W32_State
{ {
Arena *arena; Arena* arena;
// rjf: info // rjf: info
OS_SystemInfo system_info; OS_SystemInfo system_info;
@@ -85,38 +99,150 @@ struct OS_W32_State
// rjf: entity storage // rjf: entity storage
CRITICAL_SECTION entity_mutex; CRITICAL_SECTION entity_mutex;
Arena *entity_arena; Arena* entity_arena;
OS_W32_Entity *entity_free; OS_W32_Entity* entity_free;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Globals //~ rjf: Globals
global OS_W32_State os_w32_state = {0}; MD_API extern OS_W32_State os_w32_state = {0};
//////////////////////////////// ////////////////////////////////
//~ rjf: File Info Conversion Helpers //~ rjf: File Info Conversion Helpers
internal FilePropertyFlags os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes); inline FilePropertyFlags
internal void os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes); os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes)
{
FilePropertyFlags flags = 0;
if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
flags |= FilePropertyFlag_IsFolder;
}
return flags;
}
inline void
os_w32_file_properties_from_attribute_data(FileProperties* properties, WIN32_FILE_ATTRIBUTE_DATA* attributes) {
properties->size = compose_64bit(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 //~ rjf: Time Conversion Helpers
internal void os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in); 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); 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); void os_w32_dense_time_from_file_time (DenseTime* out, FILETIME* in);
internal U32 os_w32_sleep_ms_from_endt_us(U64 endt_us); MD_API U32 os_w32_sleep_ms_from_endt_us(U64 endt_us);
inline 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;
}
inline 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;
}
inline void
os_w32_dense_time_from_file_time(DenseTime* out, FILETIME* in) {
SYSTEMTIME systime = {0};
DateTime date_time = {0};
FileTimeToSystemTime(in, &systime);
os_w32_date_time_from_system_time(&date_time, &systime);
*out = dense_time_from_date_time(date_time);
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Entity Functions //~ rjf: Entity Functions
internal OS_W32_Entity *os_w32_entity_alloc(OS_W32_EntityKind kind); MD_API OS_W32_Entity* os_w32_entity_alloc (OS_W32_EntityKind kind);
internal void os_w32_entity_release(OS_W32_Entity *entity); MD_API void os_w32_entity_release(OS_W32_Entity* entity);
inline void
os_w32_entity_release(OS_W32_Entity *entity) {
entity->kind = OS_W32_EntityKind_Null;
EnterCriticalSection(&os_w32_state.entity_mutex);
sll_stack_push(os_w32_state.entity_free, entity);
LeaveCriticalSection(&os_w32_state.entity_mutex);
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Thread Entry Point //~ rjf: Thread Entry Point
internal DWORD os_w32_thread_entry_point(void *ptr); MD_API DWORD os_w32_thread_entry_point(void* ptr);
////////////////////////////////
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
inline String8
os_get_current_path(Arena* arena) {
String8 name;
TempArena 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);
name = str8_from_16(arena, str16(memory, length));
}
scratch_end(scratch);
return name;
}
////////////////////////////////
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
//- rjf: basic
force_inline void* os_reserve ( U64 size) { void* result = VirtualAlloc( 0, size, MEM_RESERVE, PAGE_READWRITE); return result; }
force_inline B32 os_commit (void* ptr, U64 size) { B32 result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); return result; }
force_inline void os_decommit(void* ptr, U64 size) { VirtualFree (ptr, size, MEM_DECOMMIT); }
inline 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
inline 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;
}
inline B32 os_commit_large(void *ptr, U64 size) { return 1; }
////////////////////////////////
//~ rjf: @os_hooks Thread Info (Implemented Per-OS)
inline U32 os_tid(void) { DWORD id = GetCurrentThreadId(); return (U32)id; }
////////////////////////////////
//~ rjf: @os_hooks Aborting (Implemented Per-OS)
inline void os_abort(S32 exit_code) { ExitProcess(exit_code); }
#endif // OS_CORE_WIN32_H