reading the start of the huffman tree

This commit is contained in:
Andre Henriques 2023-06-24 11:14:16 +01:00
parent a80e954aa3
commit 6264dd9e87
3 changed files with 175 additions and 3 deletions

View File

@ -261,12 +261,11 @@ const BlockData = struct {
if (self.blockType != 2) {
return error.unsuported_block_type;
}
try self.dynamic_huffman;
try self.dynamic_huffman();
}
fn dynamic_huffman() !void {
fn dynamic_huffman(self: *Self) !void {
var bitw = self.bitw;
var number_of_literal_codes: u32 = @as(u32, try bitw.walk(5)) + 257;

20
src/utils.zig Normal file
View File

@ -0,0 +1,20 @@
const std = @import("std");
const stdout = std.io.getStdOut().writer();
const stderr = std.io.getStdErr().writer();
pub fn print(comptime str: []const u8, params: anytype) void {
stdout.print(str ++ "\n", params) catch {};
}
pub fn printf(comptime str: []const u8, params: anytype) void {
stdout.print(str, params) catch {};
}
pub fn pErr(comptime str: []const u8, params: anytype) void {
stderr.print(str ++ "\n", params) catch {};
}
pub fn exit(comptime str: []const u8, params: anytype, exitCode: u8) void {
pErr(str, params);
std.os.exit(exitCode);
}

153
src/walker.zig Normal file
View File

@ -0,0 +1,153 @@
const std = @import("std");
const utils = @import("utils.zig");
pub fn BitWalkerUint(comptime T: anytype, comptime reverse: bool) type {
const typeInfo = @typeInfo(T);
if (typeInfo != .Int) {
@compileError("This needs to be a int");
}
if (typeInfo.Int.signedness == .signed) {
@compileError("The integer needs to be unsigned");
}
return struct {
value: T,
mask: T,
// TODO this is probably wrong
in_byte_position: i16,
size: u8,
const Self = @This();
pub fn init(value: T, size: u8) !Self {
if (typeInfo.Int.bits < size)
return error.invlaid_size;
var start_value: u8 = 0;
if (reverse) {
start_value = size - 1;
}
var mask: T = 1;
var i: u8 = 0;
while (i < start_value) : (i += 1) {
mask = @shlExact(mask, 1);
}
return Self{
.value = value,
.in_byte_position = start_value,
.size = size,
.mask = mask,
};
}
pub fn walkBit(self: *Self) ?u1 {
if (self.mask == 0)
return null;
var result = (self.value & self.mask) == self.mask;
if (reverse) {
self.in_byte_position -= 1;
if (self.mask == 1) {
self.mask = 0;
} else {
self.mask = @shrExact(self.mask, 1);
}
} else {
self.in_byte_position += 1;
self.mask = @shlExact(self.mask, 1);
if (self.in_byte_position > self.size) {
self.mask = 0;
} else {
self.mask = @shrExact(self.mask, 1);
}
}
return @boolToInt(result);
}
};
}
pub const BitWalker = struct {
const Self = @This();
data: *[]u8,
position: usize = 0,
in_byte_position: u3 = 0,
direction: bool = false,
pub fn init(data: *[]u8, direction: bool) Self {
return Self{
.data = data,
.direction = direction,
};
}
pub fn bitWalk(self: *Self) !u1 {
return @intCast(u1, try self.walk(1));
}
// TODO direction
pub fn walk(self: *Self, bits: u3) !u8 {
if (bits > 8 or bits == 0) return error.invalid_bit_number;
var byte = self.data.ptr[self.position];
// jumps over bytes
if (self.in_byte_position + @as(u4, bits) > 8) {
// Generate a mast that covers the last part of the old byte
var old_mask: u8 = 0;
var i: usize = 0;
while (i < 8 - @as(u4, self.in_byte_position)) : (i += 1) {
old_mask = @shlExact(old_mask, 1) + 1;
}
old_mask = @shlExact(old_mask, self.in_byte_position);
var next_byte = self.data.ptr[self.position + 1];
var new_byte_pos: u3 = @intCast(u3, @as(u4, bits) - (8 - @as(u4, self.in_byte_position)));
var new_mask: u8 = 0;
var j: usize = 0;
while (j < new_byte_pos) : (j += 1) {
new_mask = @shlExact(new_mask, 1) + 1;
}
var result = @shrExact(byte & old_mask, self.in_byte_position) + @shlExact(next_byte & new_mask, @intCast(u3, 8 - @as(u4, self.in_byte_position)));
//print("mask: {b}, new_mask: {b}", .{ old_mask, new_mask });
//print("here {b} {b}", .{ byte, old_mask });
//print("here_new {b} {b}", .{ next_byte, new_mask });
//print("result {}", .{result});
self.position += 1;
self.in_byte_position = new_byte_pos;
return result;
}
// Generate a mast that covers the last part of the old byte
var old_mask: u8 = 0;
var i: usize = 0;
while (i < bits) : (i += 1) {
old_mask = @shlExact(old_mask, 1) + 1;
}
old_mask = @shlExact(old_mask, self.in_byte_position);
const result = @shrExact(byte & old_mask, self.in_byte_position);
const sum = @intCast(u4, self.in_byte_position) + @intCast(u4, bits);
if (sum == 8) {
self.position += 1;
self.in_byte_position = 0;
} else {
self.in_byte_position += bits;
}
return result;
}
};