Skip to content

Commit ee1e652

Browse files
committed
Implement BufferedReader.{read_until, read_line}
These two functions will be useful when replacing various other counterparts used by std::io consumers.
1 parent facefa7 commit ee1e652

File tree

1 file changed

+65
-7
lines changed

1 file changed

+65
-7
lines changed

src/libstd/rt/io/buffered.rs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ use prelude::*;
5555

5656
use num;
5757
use vec;
58+
use str;
5859
use super::{Reader, Writer, Stream, Decorator};
5960

6061
// libuv recommends 64k buffers to maximize throughput
@@ -84,23 +85,69 @@ impl<R: Reader> BufferedReader<R> {
8485
pub fn new(inner: R) -> BufferedReader<R> {
8586
BufferedReader::with_capacity(DEFAULT_CAPACITY, inner)
8687
}
87-
}
8888

89-
impl<R: Reader> Reader for BufferedReader<R> {
90-
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
89+
/// Reads the next line of input, interpreted as a sequence of utf-8
90+
/// encoded unicode codepoints. If a newline is encountered, then the
91+
/// newline is contained in the returned string.
92+
pub fn read_line(&mut self) -> ~str {
93+
str::from_utf8_owned(self.read_until('\n' as u8))
94+
}
95+
96+
/// Reads a sequence of bytes leading up to a specified delimeter. Once the
97+
/// specified byte is encountered, reading ceases and the bytes up to and
98+
/// including the delimiter are returned.
99+
pub fn read_until(&mut self, byte: u8) -> ~[u8] {
100+
let mut res = ~[];
101+
let mut used;
102+
loop {
103+
{
104+
let available = self.fill_buffer();
105+
match available.iter().position(|&b| b == byte) {
106+
Some(i) => {
107+
res.push_all(available.slice_to(i + 1));
108+
used = i + 1;
109+
break
110+
}
111+
None => {
112+
res.push_all(available);
113+
used = available.len();
114+
}
115+
}
116+
}
117+
if used == 0 {
118+
break
119+
}
120+
self.pos += used;
121+
}
122+
self.pos += used;
123+
return res;
124+
}
125+
126+
fn fill_buffer<'a>(&'a mut self) -> &'a [u8] {
91127
if self.pos == self.cap {
92128
match self.inner.read(self.buf) {
93129
Some(cap) => {
94130
self.pos = 0;
95131
self.cap = cap;
96132
}
97-
None => return None
133+
None => {}
98134
}
99135
}
136+
return self.buf.slice(self.pos, self.cap);
137+
}
138+
}
100139

101-
let src = self.buf.slice(self.pos, self.cap);
102-
let nread = num::min(src.len(), buf.len());
103-
vec::bytes::copy_memory(buf, src, nread);
140+
impl<R: Reader> Reader for BufferedReader<R> {
141+
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
142+
let nread = {
143+
let available = self.fill_buffer();
144+
if available.len() == 0 {
145+
return None;
146+
}
147+
let nread = num::min(available.len(), buf.len());
148+
vec::bytes::copy_memory(buf, available, nread);
149+
nread
150+
};
104151
self.pos += nread;
105152
Some(nread)
106153
}
@@ -355,4 +402,15 @@ mod test {
355402
stream.write(buf);
356403
stream.flush();
357404
}
405+
406+
#[test]
407+
fn test_read_until() {
408+
let inner = MemReader::new(~[0, 1, 2, 1, 0]);
409+
let mut reader = BufferedReader::with_capacity(2, inner);
410+
assert_eq!(reader.read_until(0), Some(~[0]));
411+
assert_eq!(reader.read_until(2), Some(~[1, 2]));
412+
assert_eq!(reader.read_until(1), Some(~[1]));
413+
assert_eq!(reader.read_until(8), Some(~[0]));
414+
assert_eq!(reader.read_until(9), None);
415+
}
358416
}

0 commit comments

Comments
 (0)