Refactoring, add basic file module (Win32)
This commit is contained in:
parent
747f7d92b9
commit
916777c2b5
@ -1,18 +1,18 @@
|
||||
void* internal_alloc (s64 size) {
|
||||
Allocator allocator = get_context_allocator();
|
||||
Allocator allocator = context_allocator();
|
||||
void* result = allocator.proc(Allocator_Mode::ALLOCATE, size, 0, nullptr, allocator.data);
|
||||
return result;
|
||||
}
|
||||
|
||||
// #NOTE: internal_realloc does NOT copy anything! It just hands you new memory to work with!
|
||||
void* internal_realloc (void* memory, s64 size, s64 old_size) {
|
||||
Allocator allocator = get_context_allocator();
|
||||
Allocator allocator = context_allocator();
|
||||
void* result = allocator.proc(Allocator_Mode::RESIZE, size, old_size, memory, allocator.data);
|
||||
return result;
|
||||
}
|
||||
|
||||
void internal_free (void* memory) {
|
||||
Allocator allocator = get_context_allocator();
|
||||
Allocator allocator = context_allocator();
|
||||
allocator.proc(Allocator_Mode::DEALLOCATE, 0, 0, memory, allocator.data);
|
||||
}
|
||||
|
||||
|
||||
@ -204,6 +204,6 @@ s64 arena_usage_bytes (Arena* arena) { return (s64)(arena->current_point - arena
|
||||
s64 arena_usage_committed_bytes (Arena* arena) { return (s64)(arena->first_uncommitted_page - arena->memory_base); }
|
||||
|
||||
// for arena details, I need to setup my string builder first.
|
||||
Allocator get_allocator (Arena* arena) {
|
||||
Allocator allocator (Arena* arena) {
|
||||
return { arena_allocator_proc, arena };
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ s64 arena_usage_committed_bytes (Arena* arena);
|
||||
s64 reserve_size (Arena* arena);
|
||||
s64 reserve_size (Arena_Reserve ar);
|
||||
bool is_valid (Arena* arena);
|
||||
Allocator get_allocator (Arena* arena);
|
||||
Allocator allocator (Arena* arena);
|
||||
|
||||
// Platform-Specific Implementations (forward-declared)
|
||||
void platform_init (Arena* arena, s64 new_reserve);
|
||||
|
||||
@ -19,7 +19,7 @@ struct Array { // downcasts to an ArrayView.
|
||||
|
||||
Array(s64 new_count, bool initialize=false) { // old: NewArray ::, array_new :
|
||||
count = new_count;
|
||||
allocator = get_context_allocator();
|
||||
allocator = context_allocator();
|
||||
data = NewArray<T>(new_count, initialize);
|
||||
allocated = new_count;
|
||||
}
|
||||
@ -29,7 +29,7 @@ struct Array { // downcasts to an ArrayView.
|
||||
count = new_count;
|
||||
data = (T*)new_data;
|
||||
allocated = _allocated;
|
||||
allocator = get_context_allocator();
|
||||
allocator = context_allocator();
|
||||
}
|
||||
|
||||
Array(s64 new_count, void* new_data, s64 _allocated, Allocator _allocator) {
|
||||
@ -124,7 +124,7 @@ void array_reserve (Array<T>& src, s64 desired_items) {
|
||||
|
||||
src.data = nullptr;
|
||||
if (src.allocator.proc == nullptr) {
|
||||
src.allocator = get_context_allocator();
|
||||
src.allocator = context_allocator();
|
||||
}
|
||||
|
||||
Assert(src.allocator.proc != nullptr);
|
||||
@ -249,7 +249,8 @@ struct ArrayView {
|
||||
s64 count;
|
||||
T* data;
|
||||
|
||||
ArrayView(Array<T> array) {
|
||||
// #TODO: Add initializers ArrayView<u8> from string, ArrayView<T> from ArenaArray<T>
|
||||
ArrayView(Array<T> array) { // auto-downcast from Array<T>
|
||||
count = array.count;
|
||||
data = array.data;
|
||||
}
|
||||
@ -266,7 +267,6 @@ struct ArrayView {
|
||||
count = _count;
|
||||
data = _data;
|
||||
}
|
||||
|
||||
T& operator[](s64 index) {
|
||||
#if ARRAY_ENABLE_BOUNDS_CHECKING
|
||||
if (index < 0 || index >= count) { debug_break(); } // index out of bounds
|
||||
@ -275,6 +275,11 @@ struct ArrayView {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> ArrayView<u8> to_byte_view (ArrayView<T> src) {
|
||||
ArrayView<u8> byte_view = { src.count * sizeof(T), src.data };
|
||||
return byte_view;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is_empty (ArrayView<T> src) {
|
||||
if (src.count == 0) return true;
|
||||
|
||||
@ -188,7 +188,46 @@ force_inline s64 Next_Power_Of_Two(s64 v) {
|
||||
#define push_expandable_arena(x) \
|
||||
Push_Expandable_Arena Concat(_push_ex_arena_guard_, __LINE__)(x)
|
||||
#define auto_release_temp() \
|
||||
auto_release(get_temp_allocator());
|
||||
auto_release(temp());
|
||||
#define auto_release(x) \
|
||||
Auto_Release Concat(_auto_release_guard_, __LINE__)(x)
|
||||
|
||||
|
||||
#define thread_context() thread_local_context
|
||||
#define temp() allocator(thread_context()->temp)
|
||||
#define context_allocator() thread_context()->allocator
|
||||
#define context_logger() &thread_context()->logger
|
||||
|
||||
// #TODO #constexpr #MATH - make these constexpr
|
||||
/*
|
||||
TAU :: cast(float32) 6.283185;
|
||||
TAU64 :: 6.28318530717958648;
|
||||
|
||||
PI :: cast(float32) 3.1415927;
|
||||
PI64 :: 3.141592653589793;
|
||||
|
||||
FLOAT16_MAX : float : 65504.0;
|
||||
|
||||
FLOAT32_MIN :: 0h00800000;
|
||||
FLOAT32_MAX :: 0h7F7FFFFF;
|
||||
FLOAT32_INFINITY :: 0h7F800000;
|
||||
FLOAT32_NAN :: 0h7FBFFFFF;
|
||||
|
||||
FLOAT64_MIN :: 0h00100000_00000000;
|
||||
FLOAT64_MAX :: 0h7FEFFFFF_FFFFFFFF;
|
||||
FLOAT64_INFINITY :: 0h7FF00000_00000000;
|
||||
FLOAT64_NAN :: 0h7FF7FFFF_FFFFFFFF;
|
||||
|
||||
S8_MIN :s8: -128;
|
||||
S8_MAX :s8: 127;
|
||||
U8_MAX :u8: 255;
|
||||
S16_MIN :s16: -32768;
|
||||
S16_MAX :s16: 32767;
|
||||
U16_MAX :u16: 0xffff;
|
||||
S32_MIN :s32: 0x8000_0000;
|
||||
S32_MAX :s32: 0x7fff_ffff;
|
||||
U32_MAX :u32: 0xffff_ffff;
|
||||
S64_MIN :s64: 0x8000_0000_0000_0000;
|
||||
S64_MAX :s64: 0x7fff_ffff_ffff_ffff;
|
||||
U64_MAX :u64: 0xffff_ffff_ffff_ffff;
|
||||
*/
|
||||
@ -14,10 +14,10 @@ internal void Bootstrap_Main_Thread_Context () {
|
||||
// #NewContext
|
||||
ExpandableArena* arena_ex = expandable_arena_new(Arena_Reserve::Size_64M, 16);
|
||||
|
||||
thread_local_context = New<Thread_Context>(get_allocator(arena_ex));
|
||||
thread_local_context = New<Thread_Context>(allocator(arena_ex));
|
||||
thread_local_context->temp = expandable_arena_new(Arena_Reserve::Size_2M, 16);
|
||||
thread_local_context->arena = arena_ex;
|
||||
thread_local_context->allocator = get_allocator(arena_ex);
|
||||
thread_local_context->allocator = allocator(arena_ex);
|
||||
thread_local_context->thread_idx = 0;
|
||||
thread_local_context->thread_name = "Main Thread";
|
||||
thread_local_context->log_builder = new_string_builder(Arena_Reserve::Size_64M);
|
||||
@ -32,18 +32,18 @@ struct Push_Arena {
|
||||
|
||||
Push_Arena(ExpandableArena* arena_ex) {
|
||||
Assert(is_valid(arena_ex));
|
||||
context = get_thread_context();
|
||||
context = thread_context();
|
||||
Assert(context != nullptr);
|
||||
original_allocator = context->allocator;
|
||||
context->allocator = get_allocator(arena_ex);
|
||||
context->allocator = allocator(arena_ex);
|
||||
}
|
||||
|
||||
Push_Arena(Arena* arena) {
|
||||
Assert(is_valid(arena));
|
||||
context = get_thread_context();
|
||||
context = thread_context();
|
||||
Assert(context != nullptr);
|
||||
original_allocator = context->allocator;
|
||||
context->allocator = get_allocator(arena);
|
||||
context->allocator = allocator(arena);
|
||||
}
|
||||
|
||||
~Push_Arena() {
|
||||
@ -55,29 +55,12 @@ force_inline void set_thread_context (Thread_Context* new_context) {
|
||||
thread_local_context = new_context;
|
||||
}
|
||||
|
||||
Thread_Context* get_thread_context () {
|
||||
return (Thread_Context*)thread_local_context;
|
||||
}
|
||||
|
||||
Logger* get_context_logger () {
|
||||
return &get_thread_context()->logger;
|
||||
}
|
||||
|
||||
force_inline Allocator get_temp_allocator () {
|
||||
return get_allocator(get_thread_context()->temp);
|
||||
}
|
||||
|
||||
force_inline Allocator get_context_allocator() {
|
||||
Thread_Context* context = get_thread_context();
|
||||
return context->allocator;
|
||||
}
|
||||
|
||||
void temp_reset_keeping_memory() {
|
||||
Thread_Context* context = get_thread_context();
|
||||
Thread_Context* context = thread_context();
|
||||
arena_reset(context->temp, false);
|
||||
}
|
||||
|
||||
void temp_reset() { // alias: reset_temporary_storage.
|
||||
Thread_Context* context = get_thread_context();
|
||||
Thread_Context* context = thread_context();
|
||||
arena_reset(context->temp, true);
|
||||
}
|
||||
@ -25,8 +25,6 @@ struct Thread_Context {
|
||||
// C_LINKAGE thread_static TCTX* tctx_thread_local;
|
||||
thread_static Thread_Context* thread_local_context;
|
||||
|
||||
Thread_Context* get_thread_context ();
|
||||
|
||||
// #TODO #NewContext void create_thread_context (Thread_Context** context, string thread_name, bool is_main_thread);
|
||||
|
||||
internal void Bootstrap_Main_Thread_Context ();
|
||||
@ -36,7 +34,7 @@ struct Push_Allocator {
|
||||
Allocator old_allocator;
|
||||
|
||||
Push_Allocator (Allocator new_allocator) {
|
||||
context = get_thread_context();
|
||||
context = thread_context();
|
||||
old_allocator = context->allocator;
|
||||
context->allocator = new_allocator;
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ u8* expandable_arena_start (ExpandableArena* arena_ex) {
|
||||
return Align(arena_ex->memory_base + sizeof(ExpandableArena), ARENA_DEFAULT_ALIGNMENT);
|
||||
}
|
||||
|
||||
Allocator get_allocator (ExpandableArena* arena_ex) {
|
||||
Allocator allocator (ExpandableArena* arena_ex) {
|
||||
return { expandable_arena_allocator_proc, arena_ex };
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,6 @@ void* expandable_arena_allocator_proc (Allocator_Mode mode, s64 requested_size,
|
||||
bool is_valid (ExpandableArena* arena);
|
||||
void* expandable_arena_alloc (ExpandableArena* arena_ex, s64 byte_count);
|
||||
u8* expandable_arena_start (ExpandableArena* arena_ex);
|
||||
Allocator get_allocator (ExpandableArena* arena_ex);
|
||||
Allocator allocator (ExpandableArena* arena_ex);
|
||||
void arena_reset (ExpandableArena* arena_ex, bool free_extra_pages=true);
|
||||
force_inline void arena_delete (ExpandableArena* arena_ex);
|
||||
|
||||
@ -145,7 +145,7 @@ Allocator GPAllocator () {
|
||||
void* GPAllocator_Proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data) {
|
||||
u16 alignment = 16; // default alignment
|
||||
|
||||
Thread_Context* tctx = get_thread_context();
|
||||
Thread_Context* tctx = thread_context();
|
||||
if (tctx) alignment = tctx->GPAllocator_alignment;
|
||||
|
||||
switch (mode) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
void log (string fmt, ...) {
|
||||
String_Builder* sb = get_thread_context()->log_builder;
|
||||
void log_error (string fmt, ...) {
|
||||
String_Builder* sb = thread_context()->log_builder;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@ -15,13 +15,36 @@ void log (string fmt, ...) {
|
||||
|
||||
string message = string_view(sb);
|
||||
|
||||
Logger* logger = get_context_logger();
|
||||
Logger* logger = context_logger();
|
||||
logger->proc(message, Log_Level::Error, logger->data);
|
||||
|
||||
reset_string_builder(sb);
|
||||
}
|
||||
|
||||
void log (string fmt, ...) {
|
||||
String_Builder* sb = thread_context()->log_builder;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
print_to_builder(sb, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
// Append newline if needed
|
||||
string result = string_view(sb);
|
||||
bool ends_with_newline = (result.data[result.count-1] == '\n');
|
||||
if (!ends_with_newline) {
|
||||
append(sb, "\n");
|
||||
}
|
||||
|
||||
string message = string_view(sb);
|
||||
|
||||
Logger* logger = context_logger();
|
||||
logger->proc(message, Log_Level::None, logger->data);
|
||||
|
||||
reset_string_builder(sb);
|
||||
}
|
||||
|
||||
void print (string message) {
|
||||
Logger* logger = get_context_logger();
|
||||
Logger* logger = context_logger();
|
||||
logger->proc(message, Log_Level::None, logger->data);
|
||||
}
|
||||
|
||||
@ -65,11 +65,7 @@ void default_logger_initialize() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// more hacky forward declares
|
||||
Logger* get_context_logger ();
|
||||
Allocator get_temp_allocator ();
|
||||
Allocator get_context_allocator ();
|
||||
|
||||
void log_error (string fmt, ...);
|
||||
void log (string fmt, ...);
|
||||
void print (string message);
|
||||
|
||||
|
||||
@ -90,7 +90,9 @@ string wide_to_utf8 (u16* source, s32 length) {
|
||||
if (query_result <= 0) return { };
|
||||
|
||||
// Make room for a null terminator:
|
||||
query_result += 1;
|
||||
if (length != -1) {
|
||||
query_result += 1;
|
||||
}
|
||||
|
||||
u8* memory = NewArray<u8>(query_result);
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ bool strings_match (string first_string, string second_string);
|
||||
|
||||
// #Unicode
|
||||
// #TODO: Make a raw version that returns the raw pointer?
|
||||
string wide_to_utf8 (u16* source, s32 length);
|
||||
string wide_to_utf8 (u16* source, s32 length=-1);
|
||||
wstring utf8_to_wide (string source);
|
||||
|
||||
string format_string (char* format, ...);
|
||||
|
||||
@ -121,7 +121,7 @@ void init (Thread_Group* group, s32 group_thread_count, Thread_Group_Proc group_
|
||||
bool enable_work_stealing = false) {
|
||||
// Set allocator if not already set:
|
||||
if (!group->allocator.proc) {
|
||||
group->allocator = get_context_allocator();
|
||||
group->allocator = context_allocator();
|
||||
}
|
||||
|
||||
push_allocator(group->allocator);
|
||||
@ -253,7 +253,7 @@ void add_work (Thread_Group* group, void* work) {
|
||||
|
||||
ArrayView<void*> get_completed_work (Thread_Group* group) {
|
||||
Array<void*> results = Array<void*>();
|
||||
results.allocator = get_temp_allocator();
|
||||
results.allocator = temp();
|
||||
|
||||
push_allocator(group->allocator);
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@ struct timed_block_print {
|
||||
u64 tick_difference = end_tick - start_tick;
|
||||
f64 ticks_f64 = (f64)tick_difference;
|
||||
f64 elapsed_time_seconds = ticks_f64 / (f64)((s64)g_cpu_base_frequency_megahertz * 1000000);
|
||||
push_allocator(get_temp_allocator());
|
||||
push_allocator(temp());
|
||||
log("[Timed_Block %s]: %s (%s)", block_name.data, format_time_seconds(elapsed_time_seconds).data, format_cycles(tick_difference).data);
|
||||
}
|
||||
};
|
||||
@ -124,7 +124,7 @@ struct system_timed_block_print {
|
||||
~system_timed_block_print() {
|
||||
f64 end_time = GetUnixTimestamp();
|
||||
f64 elapsed_time_seconds = end_time - start_time;
|
||||
push_allocator(get_temp_allocator());
|
||||
push_allocator(temp());
|
||||
log("[Timed_Block %s]: %s", block_name.data, format_time_seconds(elapsed_time_seconds).data);
|
||||
}
|
||||
};
|
||||
|
||||
@ -100,7 +100,7 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) {
|
||||
// }
|
||||
// }
|
||||
|
||||
push_arena(get_thread_context()->arena);
|
||||
push_arena(thread_context()->arena);
|
||||
|
||||
{ OS_System_Info* info = &os_state_w32.system_info;
|
||||
info->logical_processor_count = (s32)sysinfo.dwNumberOfProcessors;
|
||||
@ -166,7 +166,7 @@ internal void Win32_Entry_Point (int argc, WCHAR **argv) {
|
||||
{ OS_Process_Info* info = &os_state_w32.process_info;
|
||||
DWORD length = GetCurrentDirectoryW(0, 0);
|
||||
// This can be freed later when we call temp_reset();
|
||||
u16* memory = NewArray<u16>(get_temp_allocator(), length + 1);
|
||||
u16* memory = NewArray<u16>(temp(), length + 1);
|
||||
length = GetCurrentDirectoryW(length + 1, (WCHAR*)memory);
|
||||
info->working_path = wide_to_utf8(memory, length);
|
||||
Assert(is_valid(info->working_path));
|
||||
@ -205,10 +205,10 @@ internal bool thread_init (Thread* thread, Thread_Proc proc, string thread_name=
|
||||
// #NewContext
|
||||
ExpandableArena* arena_ex = expandable_arena_new(Arena_Reserve::Size_64M, 16);
|
||||
|
||||
thread->context = New<Thread_Context>(get_allocator(arena_ex));
|
||||
thread->context = New<Thread_Context>(allocator(arena_ex));
|
||||
thread->context->temp = expandable_arena_new(Arena_Reserve::Size_2M, 16);
|
||||
thread->context->arena = arena_ex;
|
||||
thread->context->allocator = get_allocator(arena_ex);
|
||||
thread->context->allocator = allocator(arena_ex);
|
||||
thread->context->thread_idx = (s32)this_thread_index;
|
||||
thread->context->thread_name = copy_string(thread_name);
|
||||
thread->context->log_builder = new_string_builder(Arena_Reserve::Size_64M);
|
||||
@ -302,6 +302,208 @@ internal void wake_all (Condition_Variable* cv) {
|
||||
WakeAllConditionVariable(&cv->condition_variable);
|
||||
}
|
||||
|
||||
internal string get_error_string (OS_Error_Code error_code) {
|
||||
u16* lpMsgBuf;
|
||||
bool success = (bool)FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPWSTR)&lpMsgBuf, 0, nullptr);
|
||||
if (!success) { return ""; }
|
||||
|
||||
push_allocator(temp());
|
||||
|
||||
string result = wide_to_utf8(lpMsgBuf);
|
||||
|
||||
LocalFree(lpMsgBuf);
|
||||
|
||||
return result; // trim_right(result, "\r\n");
|
||||
}
|
||||
|
||||
internal bool file_is_valid (File file) {
|
||||
if (file.handle == INVALID_HANDLE_VALUE) return false;
|
||||
if (file.handle == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal File file_open (string file_path, bool for_writing, bool keep_existing_content, bool log_errors) {
|
||||
HANDLE handle;
|
||||
|
||||
push_allocator(temp()); // for utf8 -> wide conversions:
|
||||
|
||||
if (for_writing) {
|
||||
u32 creation = (keep_existing_content) ? OPEN_ALWAYS : CREATE_ALWAYS;
|
||||
handle = CreateFileW(
|
||||
(LPCWSTR)utf8_to_wide(file_path).data,
|
||||
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
nullptr, creation, 0, nullptr);
|
||||
} else {
|
||||
u32 creation = OPEN_EXISTING;
|
||||
handle = CreateFileW(
|
||||
(LPCWSTR)utf8_to_wide(file_path).data,
|
||||
FILE_GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
nullptr, creation, 0, nullptr);
|
||||
}
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE && log_errors) {
|
||||
OS_Error_Code error_code = GetLastError();
|
||||
log_error("Could not open file `%s`, code: %d, %s", file_path, error_code, get_error_string(error_code).data);
|
||||
}
|
||||
|
||||
File file;
|
||||
file.handle = handle;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
internal void file_close (File* file) {
|
||||
CloseHandle(file->handle);
|
||||
}
|
||||
|
||||
internal bool file_read (File file, u8* data, s64 bytes_to_read_count, s64* bytes_read_count) {
|
||||
// ignore bytes_read_count if null.
|
||||
if (data == nullptr) {
|
||||
log_error("file_read called with null destination pointer.\n");
|
||||
if (bytes_read_count) (*bytes_read_count) = 0;
|
||||
return false;
|
||||
}
|
||||
if (bytes_to_read_count <= 0) {
|
||||
if (bytes_read_count) (*bytes_read_count) = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool read_success = false;
|
||||
s64 total_read = 0;
|
||||
|
||||
// loop to read more data than can be specified by the DWORD param ReadFile takes:
|
||||
while (total_read < bytes_to_read_count) {
|
||||
s64 remaining = bytes_to_read_count - total_read;
|
||||
DWORD to_read;
|
||||
if (remaining <= 0x7FFFFFFF) {
|
||||
to_read = (DWORD)remaining;
|
||||
} else {
|
||||
to_read = 0x7FFFFFFF; // 2147483647 bytes ~2GB
|
||||
}
|
||||
|
||||
DWORD single_read_length = 0;
|
||||
read_success = (bool)ReadFile(file.handle, data + total_read, to_read, &single_read_length, nullptr);
|
||||
|
||||
total_read += single_read_length;
|
||||
if (!read_success || single_read_length == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes_read_count) (*bytes_read_count) = total_read;
|
||||
return read_success;
|
||||
}
|
||||
|
||||
internal bool file_length (File file, s64* length) {
|
||||
if (length == nullptr) {
|
||||
log_error("Calling file_length with null `length` param!");
|
||||
return false;
|
||||
}
|
||||
if (!file_is_valid(file)) { return false; }
|
||||
s64 size;
|
||||
bool success = (bool)GetFileSizeEx(file.handle, (PLARGE_INTEGER)&size);
|
||||
|
||||
(*length) = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool file_length (string file_path, s64* length) {
|
||||
if (length == nullptr) {
|
||||
log_error("Calling file_length with null `length` param!");
|
||||
return false;
|
||||
}
|
||||
File f = file_open(file_path);
|
||||
|
||||
if (!file_is_valid(f)) { return false; }
|
||||
bool success = file_length(f, length);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
internal s64 file_current_position (File file) {
|
||||
constexpr s64 invalid_file_position = -1;
|
||||
if (!file_is_valid(file)) { return invalid_file_position; }
|
||||
s64 offset = 0;
|
||||
LARGE_INTEGER liDistanceToMove;
|
||||
bool result = (bool)SetFilePointerEx(file.handle, liDistanceToMove, (PLARGE_INTEGER)&offset, FILE_CURRENT);
|
||||
if (!result) { return invalid_file_position; }
|
||||
return (s64)offset;
|
||||
}
|
||||
|
||||
internal bool file_set_position (File file, s64 position) {
|
||||
if (!file_is_valid(file)) { return false; }
|
||||
if (position < 0) { Assert(false); return false; }
|
||||
|
||||
LARGE_INTEGER position_li; position_li.QuadPart = position;
|
||||
return (bool)SetFilePointerEx(file.handle, position_li, nullptr, FILE_BEGIN);
|
||||
}
|
||||
|
||||
internal ArrayView<u8> read_entire_file (File file) {
|
||||
ArrayView<u8> file_data;
|
||||
|
||||
bool result = file_length(file, &file_data.count);
|
||||
if (!result) return {};
|
||||
result = file_set_position(file, 0);
|
||||
if (!result) return {};
|
||||
|
||||
file_data.data = NewArray<u8>(file_data.count, false);
|
||||
if (file_data.data == nullptr) return {};
|
||||
|
||||
s64 bytes_read = 0;
|
||||
result = file_read(file, file_data.data, file_data.count, &bytes_read);
|
||||
if (!result) {
|
||||
array_free(file_data);
|
||||
return {};
|
||||
}
|
||||
|
||||
Assert(bytes_read == file_data.count);
|
||||
file_data.count = bytes_read;
|
||||
|
||||
return file_data;
|
||||
}
|
||||
|
||||
internal ArrayView<u8> read_entire_file (string file_path, bool log_errors) {
|
||||
File f = file_open(file_path, log_errors=log_errors);
|
||||
if (!file_is_valid(f)) return {};
|
||||
|
||||
ArrayView<u8> file_data = read_entire_file(f);
|
||||
|
||||
file_close(&f);
|
||||
|
||||
return file_data;
|
||||
}
|
||||
|
||||
internal bool file_write (File* file, void* data, s64 length) {
|
||||
// @incomplete - deal with inputs > 32 bits (>2GB)
|
||||
u32 length_u32 = (u32)length;
|
||||
Assert(length == length_u32);
|
||||
|
||||
u32 bytes_written;
|
||||
bool result = (bool)WriteFile(file->handle, data, length_u32, (LPDWORD)&bytes_written, nullptr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal bool write_entire_file (string file_path, void* file_data, s64 count) {
|
||||
File f = file_open(file_path, true, false);
|
||||
if (!file_is_valid(f)) return false;
|
||||
|
||||
bool result = file_write(&f, file_data, count);
|
||||
|
||||
file_close(&f);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal bool write_entire_file (string file_path, ArrayView<u8> file_data) {
|
||||
return write_entire_file(file_path, file_data.data, file_data.count);
|
||||
}
|
||||
|
||||
// #window_creation
|
||||
Window_Type create_window (string new_window_name) {
|
||||
return 0;
|
||||
|
||||
@ -5,6 +5,15 @@ struct Condition_Variable;
|
||||
struct Semaphore;
|
||||
struct Mutex;
|
||||
struct OS_Thread;
|
||||
struct File {
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
// struct File_Contents {
|
||||
// File file = {};
|
||||
// ArrayView<u8> file_data = {};
|
||||
// bool read_success = false;
|
||||
// };
|
||||
|
||||
enum class Wait_For_Result : s32 {
|
||||
SUCCESS = 0,
|
||||
@ -28,5 +37,30 @@ internal void wait (Condition_Variable* cv, Mutex* mutex, s32 wait_time_ms = -1)
|
||||
internal void wake (Condition_Variable* cv);
|
||||
internal void wake_all (Condition_Variable* cv);
|
||||
|
||||
typedef u32 OS_Error_Code;
|
||||
internal string get_error_string (OS_Error_Code error_code);
|
||||
|
||||
internal bool file_is_valid (File file);
|
||||
internal File file_open (string file_path, bool for_writing=false, bool keep_existing_content=false, bool log_errors=false);
|
||||
internal void file_close (File* file);
|
||||
internal bool file_read (File file, void* data, s64 bytes_to_read_count, s64* bytes_read_count=nullptr);
|
||||
internal bool file_length (File file, s64* length);
|
||||
internal bool file_length (string file_path, s64* length);
|
||||
internal s64 file_current_position (File file);
|
||||
internal bool file_set_position (File file, s64 position);
|
||||
internal ArrayView<u8> read_entire_file (File file);
|
||||
internal ArrayView<u8> read_entire_file (string file_path, bool log_errors=false);
|
||||
|
||||
// use to_byte_view to convert ArrayView<non-u8> to ArrayView<u8>
|
||||
internal bool file_write (File* file, void* data, s64 length);
|
||||
internal bool write_entire_file (string file_path, void* file_data, s64 count);
|
||||
internal bool write_entire_file (string file_path, ArrayView<u8> file_data);
|
||||
|
||||
// file_write
|
||||
// write_entire_file...
|
||||
|
||||
// #TODO #fs File System Operations
|
||||
// file_move, file_delete
|
||||
|
||||
// #window_creation
|
||||
typedef HWND Window_Type;
|
||||
|
||||
@ -12,13 +12,13 @@
|
||||
#include "lib/Base/Array.h"
|
||||
#include "lib/Base/General_Purpose_Allocator.h"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "lib/OS/OS_Win32.h"
|
||||
#endif
|
||||
|
||||
#include "lib/Base/Arena.h"
|
||||
#include "lib/Base/Arena_Array.h"
|
||||
#include "lib/Base/String.h"
|
||||
#if OS_WINDOWS
|
||||
# include "lib/OS/OS_Win32.h"
|
||||
#endif
|
||||
#include "lib/Base/Logger.h"
|
||||
#include "lib/Base/String.cpp"
|
||||
|
||||
@ -27,9 +27,9 @@
|
||||
|
||||
#include "lib/Base/ErrorType.cpp"
|
||||
#include "lib/Base/Base_Thread_Context.h"
|
||||
#include "lib/Base/Expandable_Arena.h"
|
||||
#include "lib/Base/Timing.h"
|
||||
#include "lib/Base/Arena_Table.cpp"
|
||||
#include "lib/Base/Expandable_Arena.h"
|
||||
|
||||
#include "lib/Base/Arena.cpp"
|
||||
|
||||
|
||||
@ -197,8 +197,8 @@ internal void Main_Entry_Point (int argc, WCHAR **argv) {
|
||||
// See: main_thread_base_entry_point
|
||||
{ Timed_Block_Print("string_builder_testing");
|
||||
temp_reset();
|
||||
push_allocator(get_temp_allocator());
|
||||
// tip: use auto_reset or auto_release with `get_thread_context()->arena`
|
||||
push_allocator(temp());
|
||||
// tip: use auto_reset or auto_release with `thread_context()->arena`
|
||||
|
||||
// String builder example:
|
||||
// OK. I can work with this.
|
||||
@ -223,11 +223,11 @@ internal void Main_Entry_Point (int argc, WCHAR **argv) {
|
||||
|
||||
print("Hello, I am just a printed message to stdout\n\n");
|
||||
}
|
||||
{ string s = "hello I am cool";
|
||||
wstring sw = utf8_to_wide(s);
|
||||
printf("testing operator overload: %d\n", !s);
|
||||
printf("testing utf8_to_wide: %ls\n", sw.data);
|
||||
}
|
||||
// { string s = "hello I am cool";
|
||||
// wstring sw = utf8_to_wide(s);
|
||||
// printf("testing operator overload: %d\n", !s);
|
||||
// printf("testing utf8_to_wide: %ls\n", (wchar_t*)sw.data);
|
||||
// }
|
||||
// debug_break();
|
||||
|
||||
// ImGui_Application();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user