Files
sindri/src/file/header.odin
T
2026-08-03 09:13:34 +02:00

90 lines
2.1 KiB
Odin

package file
import "core:fmt"
import "core:mem"
import "core:os"
MAGIC_STRING :: 0x514D21 // SINDRI
VERSION :: 1
COMPRESSION :: 0
SIZE_PER_CHUNK :: 2 * (1 << 30) // 2GiB
PATH_SIZE :: 512
// -----------------------------------------
Header :: struct #packed #all_or_none {
magic_string: u32,
version: u16,
compression: u16,
size_per_chunk: u64,
total_size: u64,
number_of_assets: u32,
// asset_index: []AssetIndex,
}
AssetIndex :: struct #packed #all_or_none {
relpath: [PATH_SIZE]u8,
size: u64,
offset: u64,
}
// -----------------------------------------
// remove :: proc(name: string) -> Error {…}
// create :: proc(name: string) -> (^File, Error) {…}
// write_at :: proc(f: ^File, p: []u8, offset: i64) -> (n: int, err: Error) {…}
// Returning `[]u8` is owned by the caller.
compute_header :: proc(
entries: [dynamic]FileEntry,
compression: u16 = COMPRESSION,
size_per_chunk: u64 = SIZE_PER_CHUNK,
allocator := context.allocator,
) -> (
header: Header,
asset_index: []AssetIndex,
) {
number_of_assets := cast(u32)len(entries)
index_size: u64 = size_of(AssetIndex) * cast(u64)number_of_assets
data_offset: u64 = size_of(Header) + index_size
total_size: u64 = data_offset
bytes := make([]u8, index_size, allocator)
for f, i in entries {
path_length := len(f.relpath)
if path_length > 512 {
fmt.eprintln("error: path exeeds maximum of 512:", f.relpath)
os.exit(1)
}
offset_in_bytes := size_of(AssetIndex) * cast(u64)i
offset_pointer := mem.ptr_offset(
&bytes[0],
offset_in_bytes,
)
ai := cast(^AssetIndex)offset_pointer
copy(ai.relpath[:PATH_SIZE], f.relpath)
ai.size = cast(u64)f.size
ai.offset = data_offset
data_offset += ai.size
total_size += ai.size
}
header = Header {
magic_string = MAGIC_STRING,
version = VERSION,
compression = compression,
size_per_chunk = size_per_chunk,
total_size = total_size,
number_of_assets = number_of_assets,
}
assert(len(bytes) % size_of(AssetIndex) == 0) // clean multiple
return header, mem.slice_data_cast([]AssetIndex, bytes) // transmute slice with proper size
}