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;
}
Part of rin-dx11, LearnOpenGL's lessons rewritten for Direct3D 11 and rin. Licensed CC BY-NC 4.0, after LearnOpenGL by Joey de Vries.