struct CircularBuffer [src]

A circular buffer for LZ sequences

Fields

buf: ArrayList(u8)Circular buffer
dict_size: usizeLength of the buffer
mem_limit: usizeBuffer memory limit
cursor: usizeCurrent position
len: usizeTotal number of bytes sent through the buffer

Members

Source

pub const CircularBuffer = struct { /// Circular buffer buf: ArrayList(u8), /// Length of the buffer dict_size: usize, /// Buffer memory limit mem_limit: usize, /// Current position cursor: usize, /// Total number of bytes sent through the buffer len: usize, pub fn init(dict_size: usize, mem_limit: usize) CircularBuffer { return .{ .buf = .{}, .dict_size = dict_size, .mem_limit = mem_limit, .cursor = 0, .len = 0, }; } pub fn get(self: CircularBuffer, index: usize) u8 { return if (0 <= index and index < self.buf.items.len) self.buf.items[index] else 0; } pub fn set(self: *CircularBuffer, gpa: Allocator, index: usize, value: u8) !void { if (index >= self.mem_limit) { return error.CorruptInput; } try self.buf.ensureTotalCapacity(gpa, index + 1); while (self.buf.items.len < index) { self.buf.appendAssumeCapacity(0); } self.buf.appendAssumeCapacity(value); } /// Retrieve the last byte or return a default pub fn lastOr(self: CircularBuffer, lit: u8) u8 { return if (self.len == 0) lit else self.get((self.dict_size + self.cursor - 1) % self.dict_size); } /// Retrieve the n-th last byte pub fn lastN(self: CircularBuffer, dist: usize) !u8 { if (dist > self.dict_size or dist > self.len) { return error.CorruptInput; } const offset = (self.dict_size + self.cursor - dist) % self.dict_size; return self.get(offset); } /// Append a literal pub fn appendLiteral( self: *CircularBuffer, gpa: Allocator, lit: u8, writer: *Writer, ) !void { try self.set(gpa, self.cursor, lit); self.cursor += 1; self.len += 1; // Flush the circular buffer to the output if (self.cursor == self.dict_size) { try writer.writeAll(self.buf.items); self.cursor = 0; } } /// Fetch an LZ sequence (length, distance) from inside the buffer pub fn appendLz( self: *CircularBuffer, gpa: Allocator, len: usize, dist: usize, writer: *Writer, ) !void { if (dist > self.dict_size or dist > self.len) { return error.CorruptInput; } var offset = (self.dict_size + self.cursor - dist) % self.dict_size; var i: usize = 0; while (i < len) : (i += 1) { const x = self.get(offset); try self.appendLiteral(gpa, x, writer); offset += 1; if (offset == self.dict_size) { offset = 0; } } } pub fn finish(self: *CircularBuffer, writer: *Writer) !void { if (self.cursor > 0) { try writer.writeAll(self.buf.items[0..self.cursor]); self.cursor = 0; } } pub fn deinit(self: *CircularBuffer, gpa: Allocator) void { self.buf.deinit(gpa); self.* = undefined; } }