mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-29 17:34:34 +00:00
Add bufio.Lookahead_Reader
This commit is contained in:
83
core/bufio/lookahead_reader.odin
Normal file
83
core/bufio/lookahead_reader.odin
Normal file
@@ -0,0 +1,83 @@
|
||||
package bufio
|
||||
|
||||
import "core:io"
|
||||
|
||||
// Loadahead_Reader provides io lookahead.
|
||||
// This is useful for tokenizers/parsers.
|
||||
// Loadahead_Reader is similar to bufio.Reader, but unlike bufio.Reader, Loadahead_Reader's buffer size
|
||||
// will EXACTLY match the specified size, whereas bufio.Reader's buffer size may differ from the specified size.
|
||||
// This makes sure that the buffer will not be accidentally read beyond the expected size.
|
||||
Loadahead_Reader :: struct {
|
||||
r: io.Reader,
|
||||
buf: []byte,
|
||||
n: int,
|
||||
}
|
||||
|
||||
lookahead_reader_init :: proc(lr: ^Loadahead_Reader, r: io.Reader, buf: []byte) -> ^Loadahead_Reader {
|
||||
lr.r = r;
|
||||
lr.buf = buf;
|
||||
lr.n = 0;
|
||||
return lr;
|
||||
}
|
||||
|
||||
lookahead_reader_buffer :: proc(lr: ^Loadahead_Reader) -> []byte {
|
||||
return lr.buf[:lr.n];
|
||||
}
|
||||
|
||||
|
||||
// lookahead_reader_peek returns a slice of the Lookahead_Reader which holds n bytes
|
||||
// If the Lookahead_Reader cannot hold enough bytes, it will read from the underlying reader to populate the rest.
|
||||
// NOTE: The returned buffer is not a copy of the underlying buffer
|
||||
lookahead_reader_peek :: proc(lr: ^Loadahead_Reader, n: int) -> ([]byte, io.Error) {
|
||||
switch {
|
||||
case n < 0:
|
||||
return nil, .Negative_Read;
|
||||
case n > len(lr.buf):
|
||||
return nil, .Buffer_Full;
|
||||
}
|
||||
|
||||
n := n;
|
||||
err: io.Error;
|
||||
read_count: int;
|
||||
|
||||
if lr.n < n {
|
||||
read_count, err = io.read_at_least(lr.r, lr.buf[lr.n:], n-lr.n);
|
||||
if err == .Unexpected_EOF {
|
||||
err = .EOF;
|
||||
}
|
||||
}
|
||||
|
||||
lr.n += read_count;
|
||||
|
||||
if n > lr.n {
|
||||
n = lr.n;
|
||||
}
|
||||
return lr.buf[:n], err;
|
||||
}
|
||||
|
||||
// lookahead_reader_peek_all returns a slice of the Lookahead_Reader populating the full buffer
|
||||
// If the Lookahead_Reader cannot hold enough bytes, it will read from the underlying reader to populate the rest.
|
||||
// NOTE: The returned buffer is not a copy of the underlying buffer
|
||||
lookahead_reader_peek_all :: proc(lr: ^Loadahead_Reader) -> ([]byte, io.Error) {
|
||||
return lookahead_reader_peek(lr, len(lr.buf));
|
||||
}
|
||||
|
||||
|
||||
// lookahead_reader_consume drops the first n populated bytes from the Lookahead_Reader.
|
||||
lookahead_reader_consume :: proc(lr: ^Loadahead_Reader, n: int) -> io.Error {
|
||||
switch {
|
||||
case n == 0:
|
||||
return nil;
|
||||
case n < 0:
|
||||
return .Negative_Read;
|
||||
case lr.n < n:
|
||||
return .Short_Buffer;
|
||||
}
|
||||
copy(lr.buf, lr.buf[n:lr.n]);
|
||||
lr.n -= n;
|
||||
return nil;
|
||||
}
|
||||
|
||||
lookahead_reader_consume_all :: proc(lr: ^Loadahead_Reader) -> io.Error {
|
||||
return lookahead_reader_consume(lr, lr.n);
|
||||
}
|
||||
Reference in New Issue
Block a user