filesystem.rin
includes/learn/filesystem.rin · 61 lines
// Paths under the repository root, wherever the executable was run from:
// LearnOpenGL's FileSystem::getPath. The root is found by walking up from
// the executable until a directory holds `resources`.
//
// filesystem_path("resources/textures/container.jpg")
import "../win32.rin"
import "std/memops.rin"
import "std/cstr.rin"
import "std/print.rin"
filesystem_root: [260]char = {};
filesystem_arena: memops_arena = {};
filesystem_find_root: proc() -> void = {
memops_arena_initialize(filesystem_arena&);
GetModuleFileNameA(null, filesystem_root[0]&, 260);
for (depth: i32 = 0; depth < 8; depth += 1) {
cut: i64 = -1;
for (i: u64 = 0; filesystem_root[i] != 0; i += 1) {
if (filesystem_root[i] == '\\' || filesystem_root[i] == '/') { cut = cast(i, i64); }
}
if (cut < 0) { break; }
filesystem_root[cut] = 0;
probe: [260]char = {};
cstr_copy(probe, filesystem_root[0]&);
cstr_append(probe, "/resources");
attributes: DWORD = GetFileAttributesA(probe[0]&);
if (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { return; }
}
printf("filesystem: no resources directory above the executable\n");
exit(1);
}
filesystem_path: proc(relative: [*]const char) -> [*]const char = {
if (filesystem_root[0] == 0) { filesystem_find_root(); }
size: u64 = cstr_length(filesystem_root[0]&) + cstr_length(relative) + 2;
out: [*]char = cast(memops_arena_push(filesystem_arena&, size, 1), [*]char);
buffer: []char = out[0..size];
cstr_copy(buffer, filesystem_root[0]&);
cstr_append(buffer, "/");
cstr_append(buffer, relative);
return out;
}
// The whole file, followed by a zero byte so text can be read in place.
// Null if it cannot be opened.
filesystem_read: proc(path: [*]const char, out_size: *u64) -> [*]u8 = {
if (filesystem_root[0] == 0) { filesystem_find_root(); }
file: *FILE = fopen(path, "rb");
if (file == null) { return null; }
fseek(file, 0, 2);
size: u64 = cast(ftell(file), u64);
fseek(file, 0, 0);
data: [*]u8 = cast(memops_arena_push(filesystem_arena&, size + 1, 16), [*]u8);
fread(data, 1, size, file);
fclose(file);
data[size] = 0;
if (out_size != null) { out_size[0] = size; }
return data;
}