mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
CircBuf: add ensureUnusedCapacity, appendSlice
This commit is contained in:
@ -75,6 +75,19 @@ pub fn CircBuf(comptime T: type, comptime default: T) type {
|
|||||||
self.full = self.head == self.tail;
|
self.full = self.head == self.tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Append a slice to the buffer. If the buffer cannot fit the
|
||||||
|
/// entire slice then an error will be returned. It is up to the
|
||||||
|
/// caller to rotate the circular buffer if they want to overwrite
|
||||||
|
/// the oldest data.
|
||||||
|
pub fn appendSlice(
|
||||||
|
self: *Self,
|
||||||
|
slice: []const T,
|
||||||
|
) Allocator.Error!void {
|
||||||
|
const storage = self.getPtrSlice(self.len(), slice.len);
|
||||||
|
fastmem.copy(T, storage[0], slice[0..storage[0].len]);
|
||||||
|
fastmem.copy(T, storage[1], slice[storage[0].len..]);
|
||||||
|
}
|
||||||
|
|
||||||
/// Clear the buffer.
|
/// Clear the buffer.
|
||||||
pub fn clear(self: *Self) void {
|
pub fn clear(self: *Self) void {
|
||||||
self.head = 0;
|
self.head = 0;
|
||||||
@ -91,6 +104,34 @@ pub fn CircBuf(comptime T: type, comptime default: T) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the first (oldest) value in the buffer.
|
||||||
|
pub fn first(self: Self) ?*T {
|
||||||
|
// Note: this can be more efficient by not using the
|
||||||
|
// iterator, but this was an easy way to implement it.
|
||||||
|
var it = self.iterator(.forward);
|
||||||
|
return it.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the last (newest) value in the buffer.
|
||||||
|
pub fn last(self: Self) ?*T {
|
||||||
|
// Note: this can be more efficient by not using the
|
||||||
|
// iterator, but this was an easy way to implement it.
|
||||||
|
var it = self.iterator(.reverse);
|
||||||
|
return it.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensures that there is enough capacity to store amount more
|
||||||
|
/// items via append.
|
||||||
|
pub fn ensureUnusedCapacity(
|
||||||
|
self: *Self,
|
||||||
|
alloc: Allocator,
|
||||||
|
amount: usize,
|
||||||
|
) Allocator.Error!void {
|
||||||
|
const new_cap = self.len() + amount;
|
||||||
|
if (new_cap <= self.capacity()) return;
|
||||||
|
try self.resize(alloc, new_cap);
|
||||||
|
}
|
||||||
|
|
||||||
/// Resize the buffer to the given size (larger or smaller).
|
/// Resize the buffer to the given size (larger or smaller).
|
||||||
/// If larger, new values will be set to the default value.
|
/// If larger, new values will be set to the default value.
|
||||||
pub fn resize(self: *Self, alloc: Allocator, size: usize) Allocator.Error!void {
|
pub fn resize(self: *Self, alloc: Allocator, size: usize) Allocator.Error!void {
|
||||||
@ -365,6 +406,94 @@ test "CircBuf reverse iterator" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "CircBuf first/last" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
const Buf = CircBuf(u8, 0);
|
||||||
|
var buf = try Buf.init(alloc, 3);
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try buf.append(1);
|
||||||
|
try buf.append(2);
|
||||||
|
try buf.append(3);
|
||||||
|
try testing.expectEqual(3, buf.last().?.*);
|
||||||
|
try testing.expectEqual(1, buf.first().?.*);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "CircBuf first/last empty" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
const Buf = CircBuf(u8, 0);
|
||||||
|
var buf = try Buf.init(alloc, 0);
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try testing.expect(buf.first() == null);
|
||||||
|
try testing.expect(buf.last() == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "CircBuf first/last empty with cap" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
const Buf = CircBuf(u8, 0);
|
||||||
|
var buf = try Buf.init(alloc, 3);
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try testing.expect(buf.first() == null);
|
||||||
|
try testing.expect(buf.last() == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "CircBuf append slice" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
const Buf = CircBuf(u8, 0);
|
||||||
|
var buf = try Buf.init(alloc, 5);
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
try buf.appendSlice("hello");
|
||||||
|
{
|
||||||
|
var it = buf.iterator(.forward);
|
||||||
|
try testing.expect(it.next().?.* == 'h');
|
||||||
|
try testing.expect(it.next().?.* == 'e');
|
||||||
|
try testing.expect(it.next().?.* == 'l');
|
||||||
|
try testing.expect(it.next().?.* == 'l');
|
||||||
|
try testing.expect(it.next().?.* == 'o');
|
||||||
|
try testing.expect(it.next() == null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "CircBuf append slice with wrap" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
const Buf = CircBuf(u8, 0);
|
||||||
|
var buf = try Buf.init(alloc, 4);
|
||||||
|
defer buf.deinit(alloc);
|
||||||
|
|
||||||
|
// Fill the buffer
|
||||||
|
_ = buf.getPtrSlice(0, buf.capacity());
|
||||||
|
try testing.expect(buf.full);
|
||||||
|
try testing.expectEqual(@as(usize, 4), buf.len());
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
buf.deleteOldest(2);
|
||||||
|
try testing.expect(!buf.full);
|
||||||
|
try testing.expectEqual(@as(usize, 2), buf.len());
|
||||||
|
|
||||||
|
try buf.appendSlice("AB");
|
||||||
|
{
|
||||||
|
var it = buf.iterator(.forward);
|
||||||
|
try testing.expect(it.next().?.* == 0);
|
||||||
|
try testing.expect(it.next().?.* == 0);
|
||||||
|
try testing.expect(it.next().?.* == 'A');
|
||||||
|
try testing.expect(it.next().?.* == 'B');
|
||||||
|
try testing.expect(it.next() == null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "CircBuf getPtrSlice fits" {
|
test "CircBuf getPtrSlice fits" {
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
Reference in New Issue
Block a user