implement a max read/write at a time for non-windows (windows already has this)

This commit is contained in:
Laytan Laats
2023-12-02 21:11:11 +01:00
parent 7eabeda870
commit 9a1c4dc56d
4 changed files with 69 additions and 13 deletions
+21 -5
View File
@@ -568,15 +568,24 @@ close :: proc(fd: Handle) -> bool {
return _unix_close(fd) == 0
}
// If you read or write more than `SSIZE_MAX` bytes, most darwin implementations will return `EINVAL`
// but it is really implementation defined. `SSIZE_MAX` is also implementation defined but usually
// the max of an i32 on Darwin.
// In practice a read/write call would probably never read/write these big buffers all at once,
// which is why the number of bytes is returned and why there are procs that will call this in a
// loop for you.
// We set a max of 1GB to keep alignment and to be safe.
@(private)
MAX_RW :: 0x7fffffff // The limit on Darwin is max(i32), trying to read/write more than that fails.
MAX_RW :: 1 << 30
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_written := _unix_write(fd, raw_data(data), c.size_t(len(data)))
to_write := min(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_write(fd, raw_data(data), to_write)
if bytes_written < 0 {
return -1, Errno(get_last_error())
}
@@ -588,18 +597,23 @@ read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
return 0, ERROR_NONE
}
bytes_read := _unix_read(fd, raw_data(data), c.size_t(len(data)))
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_read(fd, raw_data(data), to_read)
if bytes_read < 0 {
return -1, Errno(get_last_error())
}
return bytes_read, ERROR_NONE
}
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_read := _unix_pread(fd, raw_data(data), c.size_t(len(data)), offset)
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_pread(fd, raw_data(data), to_read, offset)
if bytes_read < 0 {
return -1, Errno(get_last_error())
}
@@ -611,7 +625,9 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
return 0, ERROR_NONE
}
bytes_written := _unix_pwrite(fd, raw_data(data), c.size_t(len(data)), offset)
to_write := min(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_pwrite(fd, raw_data(data), to_write, offset)
if bytes_written < 0 {
return -1, Errno(get_last_error())
}
+13 -2
View File
@@ -326,8 +326,17 @@ close :: proc(fd: Handle) -> Errno {
return ERROR_NONE
}
// If you read or write more than `INT_MAX` bytes, FreeBSD returns `EINVAL`.
// In practice a read/write call would probably never read/write these big buffers all at once,
// which is why the number of bytes is returned and why there are procs that will call this in a
// loop for you.
// We set a max of 1GB to keep alignment and to be safe.
@(private)
MAX_RW :: 1 << 30
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)))
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_read(fd, &data[0], to_read)
if bytes_read == -1 {
return -1, Errno(get_last_error())
}
@@ -338,7 +347,9 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_written := _unix_write(fd, &data[0], c.size_t(len(data)))
to_write := min(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_write(fd, &data[0], to_write)
if bytes_written == -1 {
return -1, Errno(get_last_error())
}
+22 -4
View File
@@ -547,12 +547,23 @@ close :: proc(fd: Handle) -> Errno {
return _get_errno(unix.sys_close(int(fd)))
}
// If you read or write more than `SSIZE_MAX` bytes, result is implementation defined (probably an error).
// `SSIZE_MAX` is also implementation defined but usually the max of a `ssize_t` which is `max(int)` in Odin.
// In practice a read/write call would probably never read/write these big buffers all at once,
// which is why the number of bytes is returned and why there are procs that will call this in a
// loop for you.
// We set a max of 1GB to keep alignment and to be safe.
@(private)
MAX_RW :: 1 << 30
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_read := unix.sys_read(int(fd), raw_data(data), len(data))
to_read := min(uint(len(data)), MAX_RW)
bytes_read := unix.sys_read(int(fd), raw_data(data), to_read)
if bytes_read < 0 {
return -1, _get_errno(bytes_read)
}
@@ -564,18 +575,23 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
return 0, ERROR_NONE
}
bytes_written := unix.sys_write(int(fd), raw_data(data), len(data))
to_write := min(uint(len(data)), MAX_RW)
bytes_written := unix.sys_write(int(fd), raw_data(data), to_write)
if bytes_written < 0 {
return -1, _get_errno(bytes_written)
}
return bytes_written, ERROR_NONE
}
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_read := unix.sys_pread(int(fd), raw_data(data), len(data), offset)
to_read := min(uint(len(data)), MAX_RW)
bytes_read := unix.sys_pread(int(fd), raw_data(data), to_read, offset)
if bytes_read < 0 {
return -1, _get_errno(bytes_read)
}
@@ -587,7 +603,9 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
return 0, ERROR_NONE
}
bytes_written := unix.sys_pwrite(int(fd), raw_data(data), uint(len(data)), offset)
to_write := min(uint(len(data)), MAX_RW)
bytes_written := unix.sys_pwrite(int(fd), raw_data(data), to_write, offset)
if bytes_written < 0 {
return -1, _get_errno(bytes_written)
}
+13 -2
View File
@@ -325,8 +325,17 @@ close :: proc(fd: Handle) -> Errno {
return ERROR_NONE
}
// If you read or write more than `SSIZE_MAX` bytes, OpenBSD returns `EINVAL`.
// In practice a read/write call would probably never read/write these big buffers all at once,
// which is why the number of bytes is returned and why there are procs that will call this in a
// loop for you.
// We set a max of 1GB to keep alignment and to be safe.
@(private)
MAX_RW :: 1 << 30
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)))
to_read := min(c.size_t(len(data)), MAX_RW)
bytes_read := _unix_read(fd, &data[0], to_read)
if bytes_read == -1 {
return -1, Errno(get_last_error())
}
@@ -337,7 +346,9 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_written := _unix_write(fd, &data[0], c.size_t(len(data)))
to_write := min(c.size_t(len(data)), MAX_RW)
bytes_written := _unix_write(fd, &data[0], to_write)
if bytes_written == -1 {
return -1, Errno(get_last_error())
}