struct AccumBuffer [src]
An accumulating buffer for LZ sequences
Fields
buf: ArrayList(u8)Buffer
memlimit: usizeBuffer memory limit
len: usizeTotal number of bytes sent through the buffer
Members
- appendByte (Function)
- appendLiteral (Function)
- appendLz (Function)
- deinit (Function)
- finish (Function)
- init (Function)
- lastN (Function)
- lastOr (Function)
- reset (Function)
Source
pub const AccumBuffer = struct {
/// Buffer
buf: ArrayList(u8),
/// Buffer memory limit
memlimit: usize,
/// Total number of bytes sent through the buffer
len: usize,
pub fn init(memlimit: usize) AccumBuffer {
return .{
.buf = .{},
.memlimit = memlimit,
.len = 0,
};
}
pub fn appendByte(self: *AccumBuffer, allocator: Allocator, byte: u8) !void {
try self.buf.append(allocator, byte);
self.len += 1;
}
/// Reset the internal dictionary
pub fn reset(self: *AccumBuffer, writer: *Writer) !void {
try writer.writeAll(self.buf.items);
self.buf.clearRetainingCapacity();
self.len = 0;
}
/// Retrieve the last byte or return a default
pub fn lastOr(self: AccumBuffer, lit: u8) u8 {
const buf_len = self.buf.items.len;
return if (buf_len == 0)
lit
else
self.buf.items[buf_len - 1];
}
/// Retrieve the n-th last byte
pub fn lastN(self: AccumBuffer, dist: usize) !u8 {
const buf_len = self.buf.items.len;
if (dist > buf_len) {
return error.CorruptInput;
}
return self.buf.items[buf_len - dist];
}
/// Append a literal
pub fn appendLiteral(
self: *AccumBuffer,
allocator: Allocator,
lit: u8,
writer: *Writer,
) !void {
_ = writer;
if (self.len >= self.memlimit) {
return error.CorruptInput;
}
try self.buf.append(allocator, lit);
self.len += 1;
}
/// Fetch an LZ sequence (length, distance) from inside the buffer
pub fn appendLz(
self: *AccumBuffer,
allocator: Allocator,
len: usize,
dist: usize,
writer: *Writer,
) !void {
_ = writer;
const buf_len = self.buf.items.len;
if (dist > buf_len) return error.CorruptInput;
try self.buf.ensureUnusedCapacity(allocator, len);
const buffer = self.buf.allocatedSlice();
const src = buffer[buf_len - dist ..][0..len];
const dst = buffer[buf_len..][0..len];
// This is not a @memmove; it intentionally repeats patterns caused by
// iterating one byte at a time.
for (dst, src) |*d, s| d.* = s;
self.buf.items.len = buf_len + len;
self.len += len;
}
pub fn finish(self: *AccumBuffer, writer: *Writer) !void {
try writer.writeAll(self.buf.items);
self.buf.clearRetainingCapacity();
}
pub fn deinit(self: *AccumBuffer, allocator: Allocator) void {
self.buf.deinit(allocator);
self.* = undefined;
}
}