240 lines
7.4 KiB
C++
240 lines
7.4 KiB
C++
#include <stdio.h>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Memory
|
|
//-----------------------------------------------------------------------------
|
|
const size_t os_page_size = 4096;
|
|
|
|
CORE_Static OS_Memory
|
|
os_reserve(size_t size) {
|
|
OS_Memory result = {};
|
|
size_t adjusted_size = align_up(size, os_page_size);
|
|
result.data = (U8 *)VirtualAlloc(0, adjusted_size, MEM_RESERVE, PAGE_READWRITE);
|
|
assert_message(result.data, "Failed to reserve virtual memory");
|
|
result.reserve = adjusted_size;
|
|
return result;
|
|
}
|
|
|
|
CORE_Static B32
|
|
os_commit(OS_Memory *m, size_t size) {
|
|
size_t commit = align_up(size, os_page_size);
|
|
size_t total_commit = m->commit + commit;
|
|
total_commit = clamp_top(total_commit, m->reserve);
|
|
size_t adjusted_commit = total_commit - m->commit;
|
|
if (adjusted_commit != 0) {
|
|
void *result = VirtualAlloc((U8 *)m->data + m->commit, adjusted_commit, MEM_COMMIT, PAGE_READWRITE);
|
|
assert_message(result, "Failed to commit more memory");
|
|
m->commit += adjusted_commit;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
CORE_Static void
|
|
os_release(OS_Memory *m) {
|
|
BOOL result = VirtualFree(m->data, 0, MEM_RELEASE);
|
|
assert_message(result != 0, "Failed to release OS_Memory");
|
|
if (result) {
|
|
m->data = 0;
|
|
m->commit = 0;
|
|
m->reserve = 0;
|
|
}
|
|
}
|
|
|
|
CORE_Static B32
|
|
os_decommit_pos(OS_Memory *m, size_t pos) {
|
|
size_t aligned = align_down(pos, os_page_size);
|
|
size_t adjusted_pos = clamp_top(aligned, m->commit);
|
|
size_t size_to_decommit = m->commit - adjusted_pos;
|
|
if (size_to_decommit) {
|
|
U8 *base_address = m->data + adjusted_pos;
|
|
BOOL result = VirtualFree(base_address, size_to_decommit, MEM_DECOMMIT);
|
|
if (result) {
|
|
m->commit -= size_to_decommit;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Time
|
|
//-----------------------------------------------------------------------------
|
|
global S64 Global_counts_per_second;
|
|
api F64 os_time() {
|
|
if (Global_counts_per_second == 0) {
|
|
LARGE_INTEGER freq;
|
|
QueryPerformanceFrequency(&freq);
|
|
Global_counts_per_second = freq.QuadPart;
|
|
}
|
|
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
F64 result = (F64)time.QuadPart / (F64)Global_counts_per_second;
|
|
return result;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Filesystem
|
|
//-----------------------------------------------------------------------------
|
|
CORE_Static B32
|
|
os_write_file(String filename, String filecontent) {
|
|
FILE *f = fopen((const char *)filename.str, "w");
|
|
if (f) {
|
|
fwrite(filecontent.str, 1, filecontent.len, f);
|
|
fclose(f);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
CORE_Static String
|
|
os_read_file(Allocator *a, String name) {
|
|
String result = {0};
|
|
FILE *f = fopen((char *)name.str, "rb");
|
|
if (f) {
|
|
fseek(f, 0, SEEK_END);
|
|
result.len = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
result.str = (U8 *)allocate_size(a, result.len + 1, false);
|
|
fread(result.str, result.len, 1, f);
|
|
fclose(f);
|
|
result.str[result.len] = 0;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
CORE_Static String
|
|
os_get_working_dir(Allocator *a) {
|
|
wchar_t buffer[2048];
|
|
DWORD written = GetCurrentDirectoryW(2048, buffer);
|
|
assert(written != 0);
|
|
String16 string16 = string16_from_widechar(buffer);
|
|
String result = string16_to_string8(a, string16);
|
|
string_path_normalize(result);
|
|
return result;
|
|
}
|
|
|
|
CORE_Static String
|
|
os_get_exe_dir(Allocator *a) {
|
|
wchar_t buffer[2048];
|
|
DWORD written = GetModuleFileNameW(0, buffer, 2048);
|
|
assert(written != 0);
|
|
String16 string16 = string16_from_widechar(buffer);
|
|
String result = string16_to_string8(a, string16);
|
|
string_path_normalize(result);
|
|
result = string_chop_last_slash(result);
|
|
|
|
if (string16.len > result.len) result.str[result.len] = 0;
|
|
string_path_normalize(result);
|
|
return result;
|
|
}
|
|
|
|
CORE_Static String
|
|
os_get_absolute_path(Allocator *a, String path) {
|
|
char buff[2048];
|
|
Arena scratch = arena_from_buffer(buff, 2048);
|
|
String16 path16 = string8_to_string16(&scratch, path);
|
|
|
|
wchar_t *buffer = allocate_array(&scratch, wchar_t, 512);
|
|
DWORD written = GetFullPathNameW((wchar_t *)path16.str, 512, buffer, 0);
|
|
if (written == 0) return {};
|
|
|
|
String16 absolute16 = string16_from_widechar(buffer);
|
|
String absolute = string16_to_string8(a, absolute16);
|
|
string_path_normalize(absolute);
|
|
return absolute;
|
|
}
|
|
|
|
CORE_Static B32
|
|
os_does_file_exist(String path) {
|
|
char buff[2048];
|
|
Arena scratch = arena_from_buffer(buff, buff_cap(buff));
|
|
String16 path16 = string8_to_string16(&scratch, path);
|
|
DWORD attribs = GetFileAttributesW((wchar_t *)path16.str);
|
|
B32 result = attribs == INVALID_FILE_ATTRIBUTES ? false : true;
|
|
return result;
|
|
}
|
|
|
|
CORE_Static Array<OS_File_Info>
|
|
os_list_dir(Arena *scratch, Allocator *a, String dir, U32 flags = LIST_NO_FLAGS) {
|
|
Scratch_Scope _scope(scratch);
|
|
Array<String> dirs_to_read = {scratch};
|
|
dirs_to_read.add(dir);
|
|
|
|
Array<OS_File_Info> result = {a};
|
|
for (auto it = dirs_to_read.begin(); it != dirs_to_read.end(); it++) {
|
|
String modified_path = string_fmt(scratch, "%Q\\*", it);
|
|
String16 path16 = string8_to_string16(scratch, modified_path);
|
|
|
|
WIN32_FIND_DATAW ffd;
|
|
HANDLE handle = FindFirstFileW((wchar_t *)path16.str, &ffd);
|
|
if (handle == INVALID_HANDLE_VALUE) continue;
|
|
|
|
do {
|
|
|
|
//
|
|
// Skip '.' and '..'
|
|
//
|
|
if (ffd.cFileName[0] == '.') {
|
|
if (ffd.cFileName[1] == '.') {
|
|
if (ffd.cFileName[2] == 0)
|
|
continue;
|
|
}
|
|
|
|
if (ffd.cFileName[1] == 0)
|
|
continue;
|
|
}
|
|
|
|
String16 filename16 = string16_from_widechar(ffd.cFileName);
|
|
String filename = string16_to_string8(scratch, filename16);
|
|
|
|
String full_file_path = string_fmt(a, "%Q/%Q", dir, filename);
|
|
OS_File_Info listing = {full_file_path, os_get_absolute_path(a, full_file_path)};
|
|
|
|
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
listing.is_directory = true;
|
|
|
|
if (flags & LIST_RECURSE_INTO_DIRS) {
|
|
dirs_to_read.add(full_file_path);
|
|
}
|
|
}
|
|
|
|
result.add(listing);
|
|
|
|
} while (FindNextFileW(handle, &ffd) != 0);
|
|
|
|
DWORD error = GetLastError();
|
|
if (error != ERROR_NO_MORE_FILES) {
|
|
// Not sure what to do here hmmm
|
|
}
|
|
FindClose(handle);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool os_enable_console_colors() {
|
|
// Set output mode to handle virtual terminal sequences
|
|
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
if (hOut != INVALID_HANDLE_VALUE) {
|
|
DWORD dwMode = 0;
|
|
if (GetConsoleMode(hOut, &dwMode)) {
|
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
|
if (SetConsoleMode(hOut, dwMode)) {
|
|
return true;
|
|
}
|
|
else {
|
|
printf("Failed to enable colored terminal output C\n");
|
|
}
|
|
}
|
|
else {
|
|
printf("Failed to enable colored terminal output B\n");
|
|
}
|
|
}
|
|
else {
|
|
printf("Failed to enable colored terminal output A\n");
|
|
}
|
|
return false;
|
|
} |