hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 235bdab44ca526567e112b23cd1aaff6dce042e4
parent df4284d616b4107ac680852d82812da74c56da6e
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon,  5 Apr 2021 15:30:36 -0400

bufio: add unread functions

Diffstat:
Mbufio/buffered.ha | 24++++++++++++++++++++++++
Mbufio/scanner.ha | 4++--
2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/bufio/buffered.ha b/bufio/buffered.ha @@ -1,4 +1,5 @@ use bytes; +use encoding::utf8; use errors; use io; use strings; @@ -11,6 +12,7 @@ export type bufstream = struct { ravail: size, wavail: size, flush: []u8, + unread: []u8, }; export fn static_buffered( @@ -102,6 +104,22 @@ export fn any_isbuffered(s: *io::stream) bool = { return true; }; +// 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. +export fn unread(s: *io::stream, buf: []u8) void = { + assert(isbuffered(s), "bufio: unread used on non-buffered stream"); + let s = s: *bufstream; + append(s.unread, ...buf); +}; + +// Unreads a rune; see [unread]. +export fn unreadrune(s: *io::stream, rn: rune) void = { + assert(isbuffered(s), "bufio: unread used on non-buffered stream"); + let s = s: *bufstream; + append(s.unread, ...utf8::encoderune(rn)); +}; + fn buffered_close(s: *io::stream) void = { assert(s.closer == &buffered_close); if (s.writer != null) { @@ -127,6 +145,12 @@ fn buffered_unwrap(s: *io::stream) *io::stream = { 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) { diff --git a/bufio/scanner.ha b/bufio/scanner.ha @@ -14,8 +14,8 @@ export fn scanbyte(stream: *io::stream) (u8 | io::EOF | io::error) = { }; }; -// Reads a slice of bytes until the delimiter. Delimiter is not -// included. The return value must be freed by the caller. +// Reads a slice of bytes until the delimiter. Delimiter is not included. The +// return value must be freed by the caller. export fn scantok(stream: *io::stream, delim: u8) ([]u8 | io::EOF | io::error) = { let buf: []u8 = [];