Files
honey/std/io/file.hon
T

125 lines
3.0 KiB
Plaintext

import "@ffi/c"
File :: struct {
io Io
handle Handle
}
FileMode :: enum {
read_only
write_only
read_write
}
OpenError :: enum {
open_failed
}
CloseError :: enum {
close_failed
}
open proc(io Io, path [;0]u8, mode FileMode) File ! OpenError {
handle Handle :: try io.vtable.open(io.context, path, mode)
return File{ io = io, handle = handle }
}
close proc(file File) void ! CloseError {
try file.io.vtable.close(file.io.context, file.handle)
}
reader proc(file File) Reader {
return Reader {
context = file.io.context,
handle = file.handle,
read = file.io.vtable.read,
}
}
writer proc(file File) Writer {
return Writer {
context = file.io.context,
handle = file.handle,
write = file.io.vtable.write,
}
}
hide system_read proc(_ ?@mut anyopaque, handle Handle, buffer []mut u8) usize ! ReadError {
request := buffer.len
maximum usize :: usize(maxval!(c_long))
if (request > maximum) request = maximum
while true {
count c_long :: c.read(handle.file_desc, buffer.ptr, c_ulong(request))
if (count >= 0) return usize(count)
errno c_int :: c.__error()?^
if (errno == c.EINTR) continue
if (errno == c.EBADF) return .not_open_for_reading
return .read_failed
}
}
hide system_write proc(_ ?@mut anyopaque, handle Handle, bytes []u8) usize ! WriteError {
request := bytes.len
maximum usize :: usize(maxval!(c_long))
if (request > maximum) request = maximum
while true {
count c_long :: c.write(handle.file_desc, bytes.ptr, c_ulong(request))
if (count >= 0) return usize(count)
errno c_int :: c.__error()?^
if (errno == c.EINTR) continue
if (errno == c.EBADF) return .not_open_for_writing
return .write_failed
}
}
hide system_open proc(_ ?@mut anyopaque, path [;0]u8, mode FileMode) Handle ! OpenError {
flags := c.O_RDONLY
match mode {
.read_only: flags = c.O_RDONLY
.write_only: flags = c.O_WRONLY
.read_write: flags = c.O_RDWR
}
while true {
fd c_int :: c.open(ptrcast!(c_char, path.ptr), flags)
if (fd >= 0) return Handle{ file_desc = fd }
if (c.__error()?^ != c.EINTR) return .open_failed
}
}
hide system_close proc(_ ?@mut anyopaque, handle Handle) void ! CloseError {
if (c.close(handle.file_desc) != 0) return .close_failed
}
hide system_stdin proc(_ ?@mut anyopaque) Handle {
return Handle{ file_desc = c_int(Stream.stdin) }
}
hide system_stdout proc(_ ?@mut anyopaque) Handle {
return Handle{ file_desc = c_int(Stream.stdout) }
}
hide system_stderr proc(_ ?@mut anyopaque) Handle {
return Handle{ file_desc = c_int(Stream.stderr) }
}
hide system_vtable IoVTable :: IoVTable {
read = system_read,
write = system_write,
open = system_open,
close = system_close,
stdin = system_stdin,
stdout = system_stdout,
stderr = system_stderr,
}
hide system proc() Io {
return Io {
context = null,
vtable = &system_vtable,
}
}