diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-10-06 15:39:42 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-10-10 03:38:51 -0700 |
| commit | ee1e6529bddc4ea262e6453589a8042e0128594e (patch) | |
| tree | ef21691dab3dade61813b2cc579534f73cc519d6 /src/libstd/rt/io | |
| parent | facefa7c8d1adf6c851dca88fcf4f5d26f72caa9 (diff) | |
| download | rust-ee1e6529bddc4ea262e6453589a8042e0128594e.tar.gz rust-ee1e6529bddc4ea262e6453589a8042e0128594e.zip | |
Implement BufferedReader.{read_until, read_line}
These two functions will be useful when replacing various other counterparts used by std::io consumers.
Diffstat (limited to 'src/libstd/rt/io')
| -rw-r--r-- | src/libstd/rt/io/buffered.rs | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/src/libstd/rt/io/buffered.rs b/src/libstd/rt/io/buffered.rs index 2269469ee23..725477bec41 100644 --- a/src/libstd/rt/io/buffered.rs +++ b/src/libstd/rt/io/buffered.rs @@ -55,6 +55,7 @@ use prelude::*; use num; use vec; +use str; use super::{Reader, Writer, Stream, Decorator}; // libuv recommends 64k buffers to maximize throughput @@ -84,23 +85,69 @@ impl<R: Reader> BufferedReader<R> { pub fn new(inner: R) -> BufferedReader<R> { BufferedReader::with_capacity(DEFAULT_CAPACITY, inner) } -} -impl<R: Reader> Reader for BufferedReader<R> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + /// Reads the next line of input, interpreted as a sequence of utf-8 + /// encoded unicode codepoints. If a newline is encountered, then the + /// newline is contained in the returned string. + pub fn read_line(&mut self) -> ~str { + str::from_utf8_owned(self.read_until('\n' as u8)) + } + + /// Reads a sequence of bytes leading up to a specified delimeter. Once the + /// specified byte is encountered, reading ceases and the bytes up to and + /// including the delimiter are returned. + pub fn read_until(&mut self, byte: u8) -> ~[u8] { + let mut res = ~[]; + let mut used; + loop { + { + let available = self.fill_buffer(); + match available.iter().position(|&b| b == byte) { + Some(i) => { + res.push_all(available.slice_to(i + 1)); + used = i + 1; + break + } + None => { + res.push_all(available); + used = available.len(); + } + } + } + if used == 0 { + break + } + self.pos += used; + } + self.pos += used; + return res; + } + + fn fill_buffer<'a>(&'a mut self) -> &'a [u8] { if self.pos == self.cap { match self.inner.read(self.buf) { Some(cap) => { self.pos = 0; self.cap = cap; } - None => return None + None => {} } } + return self.buf.slice(self.pos, self.cap); + } +} - let src = self.buf.slice(self.pos, self.cap); - let nread = num::min(src.len(), buf.len()); - vec::bytes::copy_memory(buf, src, nread); +impl<R: Reader> Reader for BufferedReader<R> { + fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + let nread = { + let available = self.fill_buffer(); + if available.len() == 0 { + return None; + } + let nread = num::min(available.len(), buf.len()); + vec::bytes::copy_memory(buf, available, nread); + nread + }; self.pos += nread; Some(nread) } @@ -355,4 +402,15 @@ mod test { stream.write(buf); stream.flush(); } + + #[test] + fn test_read_until() { + let inner = MemReader::new(~[0, 1, 2, 1, 0]); + let mut reader = BufferedReader::with_capacity(2, inner); + assert_eq!(reader.read_until(0), Some(~[0])); + assert_eq!(reader.read_until(2), Some(~[1, 2])); + assert_eq!(reader.read_until(1), Some(~[1])); + assert_eq!(reader.read_until(8), Some(~[0])); + assert_eq!(reader.read_until(9), None); + } } |
