Lumenarium/src_v2/platform/win32/lumenarium_win32_file.cpp

291 lines
7.7 KiB
C++

#define win32_open_files_cap 32
char win32_open_file_paths[win32_open_files_cap][MAX_PATH];
u64 win32_open_files_len = 1; // zero is invalid
HANDLE win32_open_files[win32_open_files_cap];
void
win32_files_init()
{
for (u32 i = 0; i < win32_open_files_cap; i++)
{
win32_open_files[i] = INVALID_HANDLE_VALUE;
}
}
HANDLE
win32_get_open_file_handle(Platform_File_Handle file)
{
return win32_open_files[file.value];
}
internal u64
win32_high_low_to_u64(u32 low_part, u32 high_part)
{
ULARGE_INTEGER Time = {};
Time.LowPart = low_part;
Time.HighPart = high_part;
u64 result = Time.QuadPart;
return result;
}
internal u64
win32_file_time_to_u64(FILETIME file_time)
{
return win32_high_low_to_u64(file_time.dwLowDateTime, file_time.dwHighDateTime);
}
Platform_File_Handle
platform_file_open(String path, Platform_File_Access_Flags flags_access, Platform_File_Create_Flags flags_create)
{
Platform_File_Handle result = {};
DWORD flags_create_ = OPEN_EXISTING;
HANDLE file_handle = CreateFileA(
(char*)path.str,
(DWORD)flags_access,
0, // share mode
NULL, // security attributes
(DWORD)flags_create,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (file_handle != INVALID_HANDLE_VALUE)
{
if (win32_open_files_len < win32_open_files_cap)
{
result.value = win32_open_files_len++;
}
else
{
// search for emtpy index
for (u32 i = 1; i < win32_open_files_cap; i++)
{
if (win32_open_files[i] == INVALID_HANDLE_VALUE)
{
result.value = i;
}
}
}
assert(result.value != 0);
win32_open_files[result.value] = file_handle;
memory_copy(path.str, (u8*)win32_open_file_paths[result.value], path.len);
win32_open_file_paths[result.value][path.len] = 0; // null term
}
else
{
win32_get_last_error();
}
return result;
}
void
platform_file_close(Platform_File_Handle file_handle)
{
assert(file_handle.value < win32_open_files_len);
CloseHandle(win32_get_open_file_handle(file_handle));
win32_open_files[file_handle.value] = INVALID_HANDLE_VALUE;
}
u64
win32_get_file_size(HANDLE h)
{
DWORD size_low, size_high;
size_low = GetFileSize(h, &size_high);
if (size_low == INVALID_FILE_SIZE)
{
win32_get_last_error();
return 0;
}
LARGE_INTEGER win32_size;
win32_size.LowPart = size_low;
win32_size.HighPart = size_high;
return (u64)win32_size.QuadPart;
}
Platform_File_Info
platform_file_get_info(Platform_File_Handle file_handle, Allocator* allocator)
{
Platform_File_Info result = {};
HANDLE h = win32_get_open_file_handle(file_handle);
if (h == INVALID_HANDLE_VALUE) return result;
// File Size
u64 win32_size = win32_get_file_size(h);
if (win32_size == 0 && win32_last_error != 0) return result;
// File Times
FILETIME time_created, time_last_write;
if (!GetFileTime(h, &time_created, (LPFILETIME)0, &time_last_write))
{
win32_get_last_error();
return result;
}
// File Path
// call GetFullPathName with empty dest just to get the length needed
DWORD file_name_len_needed = GetFullPathName(
win32_open_file_paths[file_handle.value], 0, 0, 0
);
if (!file_name_len_needed)
{
win32_get_last_error();
return result;
}
result.path = allocator_alloc_string(allocator, (u64)file_name_len_needed);
result.path.len = (u64)GetFullPathName(
win32_open_file_paths[file_handle.value],
(DWORD)result.path.cap,
(char*)result.path.str,
0
);
result.path_abs = result.path;
// File Attributes
DWORD file_attrs = GetFileAttributesA((char*)result.path.str);
if (!file_attrs)
{
win32_get_last_error();
return result;
}
result.size = win32_size;
result.time_created = win32_file_time_to_u64(time_created);
result.time_last_write = win32_file_time_to_u64(time_last_write);
if (has_flag(file_attrs, FILE_ATTRIBUTE_DIRECTORY))
{
add_flag(result.flags, FileFlag_IsDir);
}
return result;
}
Data
platform_file_read_all(Platform_File_Handle file_handle, Allocator* allocator)
{
Data result = {};
HANDLE h = win32_get_open_file_handle(file_handle);
if (h == INVALID_HANDLE_VALUE) return result;
u64 file_size = win32_get_file_size(h);
if (file_size == 0 && win32_last_error != 0) return result;
result.base = allocator_alloc(allocator, file_size + 1);
result.size = file_size + 1;
DWORD bytes_read = 0;
if (ReadFile(h, (void*)result.base, (DWORD)result.size, &bytes_read, NULL))
{
result.base[result.size - 1] = 0;
}
else
{
win32_get_last_error();
}
return result;
}
bool
platform_file_write_all(Platform_File_Handle file_handle, Data file_data)
{
bool result = false;
HANDLE h = win32_get_open_file_handle(file_handle);
if (h == INVALID_HANDLE_VALUE) return result;
// Set file pointer to beginning
SetFilePointer(h, 0, 0, FILE_BEGIN);
DWORD bytes_written = 0;
if (WriteFile(h, file_data.base, (DWORD)file_data.size, &bytes_written, NULL))
{
result = (bytes_written == file_data.size);
}
return result;
}
void
platform_dir_enum_(String path, Platform_Enum_Dir_Flags flags, Allocator* allocator, Platform_File_Info_List* list)
{
WIN32_FIND_DATA ffd;
HANDLE search_handle = FindFirstFile((char*)path.str, &ffd);
if (search_handle != INVALID_HANDLE_VALUE)
{
do
{
Platform_File_Info_List_Ele* ele = allocator_alloc_struct(
allocator, Platform_File_Info_List_Ele
);
sll_push(list->first, list->last, ele);
} while (FindNextFile(search_handle, &ffd));
}
}
Platform_File_Info_List
platform_dir_enum(String path, Platform_Enum_Dir_Flags flags, Allocator* allocator)
{
Platform_File_Info_List result = {};
platform_dir_enum_(path, flags, allocator, &result);
return result;
}
String
platform_get_exe_path(Allocator* allocator)
{
String result = allocator_alloc_string(allocator, (u64)MAX_PATH);
result.len = (u64)GetModuleFileName(NULL, (char*)result.str, (DWORD)result.cap);
if (!result.len) return result;
return result;
}
bool
platform_pwd_set(String path)
{
bool result = SetCurrentDirectory((char*)path.str);
if (!result) win32_get_last_error();
return result;
}
void
platform_file_async_work_on_job(Platform_File_Async_Job* job)
{
Platform_File_Handle file = {};
if (has_flag(job->args.flags, PlatformFileAsyncJob_Read))
{
file = platform_file_open(job->args.path, FileAccess_Read, FileCreate_OpenExisting);
Data result = platform_file_read_all(file, platform_file_jobs_arena);
if (result.base != 0)
{
job->args.data = result;
add_flag(job->args.flags, PlatformFileAsyncJob_Success);
}
else
{
add_flag(job->args.flags, PlatformFileAsyncJob_Failed);
}
}
else if (has_flag(job->args.flags, PlatformFileAsyncJob_Write))
{
file = platform_file_open(job->args.path, FileAccess_Write, FileCreate_OpenAlways);
if (platform_file_write_all(file, job->args.data))
{
add_flag(job->args.flags, PlatformFileAsyncJob_Success);
}
else
{
add_flag(job->args.flags, PlatformFileAsyncJob_Failed);
}
}
platform_file_close(file);
}