io: allow BufferedReader.read_line() to accept custom line delimiters (#20655)

This commit is contained in:
syrmel 2024-01-26 10:37:30 +01:00 committed by GitHub
parent 2c6a8c536c
commit 754c83a8ac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 6 deletions

View file

@ -21,6 +21,12 @@ pub struct BufferedReaderConfig {
retries int = 2 // how many times to retry before assuming the stream ended retries int = 2 // how many times to retry before assuming the stream ended
} }
// BufferedReadLineConfig are options that can be given to the read_line() function.
@[params]
pub struct BufferedReadLineConfig {
delim u8 = `\n` // line delimiter
}
// new_buffered_reader creates a new BufferedReader. // new_buffered_reader creates a new BufferedReader.
pub fn new_buffered_reader(o BufferedReaderConfig) &BufferedReader { pub fn new_buffered_reader(o BufferedReaderConfig) &BufferedReader {
if o.cap <= 0 { if o.cap <= 0 {
@ -107,10 +113,10 @@ pub fn (r BufferedReader) end_of_stream() bool {
return r.end_of_stream return r.end_of_stream
} }
// read_line attempts to read a line from the buffered reader // read_line attempts to read a line from the buffered reader.
// it will read until it finds a new line character (\n) or // It will read until it finds the specified line delimiter
// the end of stream. // such as (\n, the default or \0) or the end of stream.
pub fn (mut r BufferedReader) read_line() !string { pub fn (mut r BufferedReader) read_line(config BufferedReadLineConfig) !string {
if r.end_of_stream { if r.end_of_stream {
return Eof{} return Eof{}
} }
@ -132,10 +138,10 @@ pub fn (mut r BufferedReader) read_line() !string {
for ; i < r.len; i++ { for ; i < r.len; i++ {
r.total_read++ r.total_read++
c := r.buf[i] c := r.buf[i]
if c == `\n` { if c == config.delim {
// great, we hit something // great, we hit something
// do some checking for whether we hit \r\n or just \n // do some checking for whether we hit \r\n or just \n
if i != 0 && r.buf[i - 1] == `\r` { if i != 0 && config.delim == `\n` && r.buf[i - 1] == `\r` {
x := i - 1 x := i - 1
line << r.buf[r.offset..x] line << r.buf[r.offset..x]
} else { } else {

View file

@ -161,3 +161,26 @@ fn test_totalread_readline() {
assert r.total_read == text.len assert r.total_read == text.len
} }
fn test_read_line_until_zero_terminated() {
text := 'This is a test\0Nice try!\0'
mut s := StringReader{
text: text
}
mut r := new_buffered_reader(reader: s)
line1 := r.read_line(delim: `\0`) or {
assert false
panic('bad')
}
assert line1 == 'This is a test'
line2 := r.read_line(delim: `\0`) or {
assert false
panic('bad')
}
assert line2 == 'Nice try!'
if _ := r.read_line(delim: `\0`) {
assert false
panic('bad')
}
assert r.end_of_stream()
}