mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
terminal: test for match in second slice of circ buf
This commit is contained in:
@ -118,12 +118,16 @@ const SlidingWindow = struct {
|
|||||||
/// the invariant that the window is always big enough to contain
|
/// the invariant that the window is always big enough to contain
|
||||||
/// the needle.
|
/// the needle.
|
||||||
pub fn next(self: *SlidingWindow, needle: []const u8) ?Selection {
|
pub fn next(self: *SlidingWindow, needle: []const u8) ?Selection {
|
||||||
|
const slices = slices: {
|
||||||
|
// If we have less data then the needle then we can't possibly match
|
||||||
const data_len = self.data.len();
|
const data_len = self.data.len();
|
||||||
if (data_len == 0) return null;
|
if (data_len < needle.len) return null;
|
||||||
const slices = self.data.getPtrSlice(
|
|
||||||
|
break :slices self.data.getPtrSlice(
|
||||||
self.data_offset,
|
self.data_offset,
|
||||||
data_len - self.data_offset,
|
data_len - self.data_offset,
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// Search the first slice for the needle.
|
// Search the first slice for the needle.
|
||||||
if (std.mem.indexOf(u8, slices[0], needle)) |idx| {
|
if (std.mem.indexOf(u8, slices[0], needle)) |idx| {
|
||||||
@ -134,7 +138,6 @@ const SlidingWindow = struct {
|
|||||||
|
|
||||||
// Search the last slice for the needle.
|
// Search the last slice for the needle.
|
||||||
if (std.mem.indexOf(u8, slices[1], needle)) |idx| {
|
if (std.mem.indexOf(u8, slices[1], needle)) |idx| {
|
||||||
if (true) @panic("TODO: test");
|
|
||||||
return self.selection(slices[0].len + idx, needle.len);
|
return self.selection(slices[0].len + idx, needle.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +185,10 @@ const SlidingWindow = struct {
|
|||||||
self.data.deleteOldest(prune_data_len);
|
self.data.deleteOldest(prune_data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Our data offset now moves to needle.len - 1 from the end so
|
||||||
|
// that we can handle the overlap case.
|
||||||
|
self.data_offset = self.data.len() - needle.len + 1;
|
||||||
|
|
||||||
self.assertIntegrity();
|
self.assertIntegrity();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -615,3 +622,55 @@ test "SlidingWindow two pages no match keeps both pages" {
|
|||||||
// No pruning because both pages are needed to fit needle.
|
// No pruning because both pages are needed to fit needle.
|
||||||
try testing.expectEqual(2, w.meta.len());
|
try testing.expectEqual(2, w.meta.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "SlidingWindow single append across circular buffer boundary" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
var w = try SlidingWindow.initEmpty(alloc);
|
||||||
|
defer w.deinit(alloc);
|
||||||
|
|
||||||
|
var s = try Screen.init(alloc, 80, 24, 0);
|
||||||
|
defer s.deinit();
|
||||||
|
try s.testWriteString("XXXXXXXXXXXXXXXXXXXboo!XXXXX");
|
||||||
|
|
||||||
|
// We are trying to break a circular buffer boundary so the way we
|
||||||
|
// do this is to duplicate the data then do a failing search. This
|
||||||
|
// will cause the first page to be pruned. The next time we append we'll
|
||||||
|
// put it in the middle of the circ buffer. We assert this so that if
|
||||||
|
// our implementation changes our test will fail.
|
||||||
|
try testing.expect(s.pages.pages.first == s.pages.pages.last);
|
||||||
|
const node: *PageList.List.Node = s.pages.pages.first.?;
|
||||||
|
try w.append(alloc, node);
|
||||||
|
try w.append(alloc, node);
|
||||||
|
{
|
||||||
|
// No wrap around yet
|
||||||
|
const slices = w.data.getPtrSlice(0, w.data.len());
|
||||||
|
try testing.expect(slices[0].len > 0);
|
||||||
|
try testing.expect(slices[1].len == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search non-match, prunes page
|
||||||
|
try testing.expect(w.next("abc") == null);
|
||||||
|
try testing.expectEqual(1, w.meta.len());
|
||||||
|
|
||||||
|
// Add new page, now wraps
|
||||||
|
try w.append(alloc, node);
|
||||||
|
{
|
||||||
|
const slices = w.data.getPtrSlice(0, w.data.len());
|
||||||
|
try testing.expect(slices[0].len > 0);
|
||||||
|
try testing.expect(slices[1].len > 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const sel = w.next("boo!").?;
|
||||||
|
try testing.expectEqual(point.Point{ .active = .{
|
||||||
|
.x = 19,
|
||||||
|
.y = 0,
|
||||||
|
} }, s.pages.pointFromPin(.active, sel.start()).?);
|
||||||
|
try testing.expectEqual(point.Point{ .active = .{
|
||||||
|
.x = 22,
|
||||||
|
.y = 0,
|
||||||
|
} }, s.pages.pointFromPin(.active, sel.end()).?);
|
||||||
|
}
|
||||||
|
try testing.expect(w.next("boo!") == null);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user