|
const std = @import("../../../std.zig"); const math = std.math; const mem = std.mem; const Allocator = std.mem.Allocator; const ArrayListUnmanaged = std.ArrayListUnmanaged; |
LzAccumBufferBuffer |
/// An accumulating buffer for LZ sequences pub const LzAccumBuffer = struct { /// Buffer buf: ArrayListUnmanaged(u8), |
init()Buffer memory limit |
/// Buffer memory limit memlimit: usize, |
appendByte()Total number of bytes sent through the buffer |
/// Total number of bytes sent through the buffer len: usize, |
reset()Reset the internal dictionary |
const Self = @This(); |
lastOr()Retrieve the last byte or return a default |
pub fn init(memlimit: usize) Self { return Self{ .buf = .{}, .memlimit = memlimit, .len = 0, }; } |
lastN()Retrieve the n-th last byte |
pub fn appendByte(self: *Self, allocator: Allocator, byte: u8) !void { try self.buf.append(allocator, byte); self.len += 1; } |
appendLiteral()Append a literal |
/// Reset the internal dictionary pub fn reset(self: *Self, writer: anytype) !void { try writer.writeAll(self.buf.items); self.buf.clearRetainingCapacity(); self.len = 0; } |
appendLz()Fetch an LZ sequence (length, distance) from inside the buffer |
/// Retrieve the last byte or return a default |
lastOr()A circular buffer for LZ sequences |
pub fn lastOr(self: Self, lit: u8) u8 { const buf_len = self.buf.items.len; return if (buf_len == 0) lit else self.buf.items[buf_len - 1]; } |
deinit()Circular buffer |
/// Retrieve the n-th last byte |
lastN()Length of the buffer |
pub fn lastN(self: Self, dist: usize) !u8 { const buf_len = self.buf.items.len; if (dist > buf_len) { return error.CorruptInput; } |
init()Buffer memory limit |
return self.buf.items[buf_len - dist]; } |
get()Current position |
/// Append a literal |
appendLiteral()Total number of bytes sent through the buffer |
pub fn appendLiteral( self: *Self, allocator: Allocator, lit: u8, writer: anytype, ) !void { _ = writer; if (self.len >= self.memlimit) { return error.CorruptInput; } try self.buf.append(allocator, lit); self.len += 1; } |
lastOr()Retrieve the last byte or return a default |
/// Fetch an LZ sequence (length, distance) from inside the buffer |
appendLz()Retrieve the n-th last byte |
pub fn appendLz( self: *Self, allocator: Allocator, len: usize, dist: usize, writer: anytype, ) !void { _ = writer; |
appendLiteral()Append a literal |
const buf_len = self.buf.items.len; if (dist > buf_len) { return error.CorruptInput; } |
appendLz()Fetch an LZ sequence (length, distance) from inside the buffer |
var offset = buf_len - dist; var i: usize = 0; while (i < len) : (i += 1) { const x = self.buf.items[offset]; try self.buf.append(allocator, x); offset += 1; } self.len += len; } |
finish() |
pub fn finish(self: *Self, writer: anytype) !void { try writer.writeAll(self.buf.items); self.buf.clearRetainingCapacity(); } |
deinit() |
pub fn deinit(self: *Self, allocator: Allocator) void { self.buf.deinit(allocator); self.* = undefined; } }; /// A circular buffer for LZ sequences pub const LzCircularBuffer = struct { /// Circular buffer buf: ArrayListUnmanaged(u8), /// Length of the buffer dict_size: usize, /// Buffer memory limit memlimit: usize, /// Current position cursor: usize, /// Total number of bytes sent through the buffer len: usize, const Self = @This(); pub fn init(dict_size: usize, memlimit: usize) Self { return Self{ .buf = .{}, .dict_size = dict_size, .memlimit = memlimit, .cursor = 0, .len = 0, }; } pub fn get(self: Self, index: usize) u8 { return if (0 <= index and index < self.buf.items.len) self.buf.items[index] else 0; } pub fn set(self: *Self, allocator: Allocator, index: usize, value: u8) !void { if (index >= self.memlimit) { return error.CorruptInput; } try self.buf.ensureTotalCapacity(allocator, 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: Self, 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: Self, 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: *Self, allocator: Allocator, lit: u8, writer: anytype, ) !void { try self.set(allocator, 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: *Self, allocator: Allocator, len: usize, dist: usize, writer: anytype, ) !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(allocator, x, writer); offset += 1; if (offset == self.dict_size) { offset = 0; } } } pub fn finish(self: *Self, writer: anytype) !void { if (self.cursor > 0) { try writer.writeAll(self.buf.items[0..self.cursor]); self.cursor = 0; } } pub fn deinit(self: *Self, allocator: Allocator) void { self.buf.deinit(allocator); self.* = undefined; } }; |
Generated by zstd-live on 2025-08-13 02:35:15 UTC. |