125 lines
3.0 KiB
Plaintext
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,
|
|
}
|
|
}
|