1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 20:47:46 +00:00

Get rid of unsafe indexing

Unsafe indexing is replaced by ImmutableEqVector::position_elem() and a
few branches have been eliminated.

The performance is about the same as for unsafe indexing.
This commit is contained in:
polyphemus 2014-07-31 14:36:42 +02:00
parent 7d7b9dde43
commit 2a238e3c0f

View file

@ -65,24 +65,23 @@ impl<R: Reader> BufReader<R> {
loop { loop {
match self.maybe_fill_buf() { match self.maybe_fill_buf() {
Err(IoError { kind: std::io::EndOfFile, .. }) => (), Ok(0) | Err(IoError { kind: std::io::EndOfFile, .. })
if self.start == self.end => return bytes_consumed,
Err(err) => fail!("read error: {}", err.desc), Err(err) => fail!("read error: {}", err.desc),
_ => () _ => ()
} }
let buffer_used = self.end - self.start; let filled_buf = self.buffer.slice(self.start, self.end);
if buffer_used == 0 { return bytes_consumed; } match filled_buf.position_elem(&b'\n') {
Some(idx) => {
for idx in range(self.start, self.end) { self.start += idx + 1;
// the indices are always correct, use unsafe for speed
if unsafe { *self.buffer.unsafe_ref(idx) } == b'\n' {
self.start = idx + 1;
return bytes_consumed + idx + 1; return bytes_consumed + idx + 1;
} }
_ => ()
} }
bytes_consumed += buffer_used; bytes_consumed += filled_buf.len();
self.start = 0; self.start = 0;
self.end = 0; self.end = 0;
@ -98,41 +97,47 @@ impl<R: Reader> Bytes::Select for BufReader<R> {
_ => () _ => ()
} }
let buffer_used = self.end - self.start; let newline_idx = match self.end - self.start {
0 => return Bytes::EndOfFile,
buf_used if bytes < buf_used => {
// because the output delimiter should only be placed between
// segments check if the byte after bytes is a newline
let buf_slice = self.buffer.slice(self.start,
self.start + bytes + 1);
if buffer_used == 0 { return Bytes::EndOfFile; } match buf_slice.position_elem(&b'\n') {
Some(idx) => idx,
None => {
let segment = self.buffer.slice(self.start,
self.start + bytes);
let (complete, max_segment_len) = { self.start += bytes;
if bytes < buffer_used {
(true, bytes + 1) return Bytes::Complete(segment);
} else { }
(false, buffer_used) }
}
_ => {
let buf_filled = self.buffer.slice(self.start, self.end);
match buf_filled.position_elem(&b'\n') {
Some(idx) => idx,
None => {
let segment = self.buffer.slice(self.start, self.end);
self.start = 0;
self.end = 0;
return Bytes::Partial(segment);
}
}
} }
}; };
for idx in range(self.start, self.start + max_segment_len) { let new_start = self.start + newline_idx + 1;
// the indices are always correct, use unsafe for speed let segment = self.buffer.slice(self.start, new_start);
if unsafe { *self.buffer.unsafe_ref(idx) } == b'\n' {
let segment = self.buffer.slice(self.start, idx + 1);
self.start = idx + 1; self.start = new_start;
Bytes::NewlineFound(segment)
return Bytes::NewlineFound(segment);
}
}
if complete {
let segment = self.buffer.slice(self.start,
self.start + bytes);
self.start += bytes;
Bytes::Complete(segment)
} else {
let segment = self.buffer.slice(self.start, self.end);
self.start = 0;
self.end = 0;
Bytes::Partial(segment)
}
} }
} }