commit 21854035d2bdb0b391532ae8beab5c6183aeafdc
parent b76a7ab5a224fa229ac845e686738e086a973315
Author: Bor Grošelj Simić <bgs@turminal.net>
Date: Sat, 23 Apr 2022 00:45:29 +0200
bufio::buffered: use rbuffer as unread buffer
Implements: https://todo.sr.ht/~sircmpwn/hare/631
Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>
Diffstat:
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/bufio/buffered.ha b/bufio/buffered.ha
@@ -36,7 +36,6 @@ export type bufstream = struct {
ravail: size,
wavail: size,
flush: []u8,
- unread: []u8,
};
// Creates a stream which buffers reads and writes for the underlying stream.
@@ -99,16 +98,17 @@ export fn setflush(s: *bufstream, b: []u8) void = {
// Unreads a slice of bytes. The next read calls on this buffer will consume the
// un-read data before consuming further data from the underlying source, or any
-// buffered data.
+// buffered data. The amount of data that can be un-read is guaranteed to be at
+// least as much as the size of the previous read from the stream.
export fn unread(s: *bufstream, buf: []u8) void = {
- append(s.unread, buf...);
+ assert(len(buf) + s.ravail > len(s.rbuffer));
+ s.rbuffer[len(buf)..len(buf) + s.ravail] = s.rbuffer[..s.ravail];
+ s.rbuffer[..len(buf)] = buf;
};
// Unreads a rune; see [[unread]].
-export fn unreadrune(s: *bufstream, rn: rune) void = {
- const buf = utf8::encoderune(rn);
- insert(s.unread[0], buf...);
-};
+export fn unreadrune(s: *bufstream, rn: rune) void =
+ unread(s, utf8::encoderune(rn));
// Returns true if an [[io::handle]] is a [[buffered]] stream.
export fn isbuffered(in: io::handle) bool = {
@@ -130,13 +130,6 @@ fn buffered_close_static(s: *io::stream) void = {
fn buffered_read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = {
assert(s.reader == &buffered_read);
let s = s: *bufstream;
- if (len(s.unread) != 0) {
- let n = if (len(buf) < len(s.unread)) len(buf) else len(s.unread);
- buf[..n] = s.unread[..n];
- delete(s.unread[..n]);
- return n;
- };
-
let n = if (len(buf) < len(s.rbuffer)) len(buf) else len(s.rbuffer);
if (n > s.ravail) {
let z = match (io::read(s.source, s.rbuffer[s.ravail..])) {