Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/context_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@ impl BufferedLine {
/// provide a more optimized `ContextBuffer` when `mmap()` is available.
pub struct ContextBuffer {
slots: Vec<BufferedLine>,
/// Number of lines to retain. `slots` is rounded up to a power of two so
/// `push` can mask instead of divide, so it may be larger than this.
capacity: usize,
head: usize,
len: usize,
}

impl ContextBuffer {
pub fn new(capacity: usize) -> Self {
let len = if capacity == 0 {
let slots = if capacity == 0 {
0
} else {
capacity.next_power_of_two()
Expand All @@ -60,8 +63,9 @@ impl ContextBuffer {
line_number: 0,
byte_offset: 0,
};
len
slots
],
capacity,
head: 0,
len: 0,
}
Expand Down Expand Up @@ -90,7 +94,7 @@ impl ContextBuffer {
slot.byte_offset = byte_offset;

self.head = self.head.wrapping_add(1);
self.len = (self.len + 1).min(self.slots.len());
self.len = (self.len + 1).min(self.capacity);
}

pub fn drain_iter(&mut self) -> impl Iterator<Item = &BufferedLine> {
Expand Down
20 changes: 20 additions & 0 deletions tests/test_grep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,26 @@ fn after_before_combined_context() {
.stdout_only("b\nMATCH\nc\n");
}

#[test]
fn before_context_is_not_rounded_to_power_of_two() {
// The context ring buffer rounds its slot count up to a power of two, but
// must still retain only the requested number of lines.
let input = "01\n02\n03\n04\n05\n06\n07\n08\n09\n10\nMM\n";

for (n, expected) in [
("3", "08\n09\n10\nMM\n"),
("5", "06\n07\n08\n09\n10\nMM\n"),
("6", "05\n06\n07\n08\n09\n10\nMM\n"),
("7", "04\n05\n06\n07\n08\n09\n10\nMM\n"),
] {
let (_s, mut c) = ucmd();
c.args(&["-e", "MM", "-B", n])
.pipe_in(input)
.succeeds()
.stdout_only(expected);
}
}

#[test]
fn num_shorthand_is_context() {
// `-2` is shorthand for `-C 2`.
Expand Down
Loading