diff --git a/src/main.zig b/src/main.zig index 6e0a8e9..786c491 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const mem = std.mem; const stdout = std.io.getStdOut().writer(); const stderr = std.io.getStdErr().writer(); @@ -20,6 +21,36 @@ fn usage() void { exit("", .{}, 1); } +fn BitWalkerUint(T: anytype) type { + + var typeInfo = @typeInfo(T); + + if (typeInfo == std.builtin.Type.Int) { + @compileError("This needs to be a int"); + } + + if (typeInfo.Int.is_signed) { + @compileError("The integer needs to be unsigned"); + } + + var size = typeInfo.Int.bits; + + return struct { + t: T, + // TODO this is probably wrong + in_byte_position: u8, + + const Self = @This(); + + fn init(value: T) Self { + return Self { + .t = value, + .in_byte_position = 0, + }; + } + }; +} + const BitWalker = struct { const Self = @This(); @@ -62,10 +93,10 @@ const BitWalker = struct { 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}); + //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; @@ -100,11 +131,46 @@ fn HuffmanGraph(valueType: type) type { const Node = struct { left: ?Node, right: ?Node, - value: valueType, - fn init() Node {} + value: ?valueType, + + allocator: mem.Allocator, + + fn init(allocator: mem.Allocator) !*Node { + + var node = try allocator.create(Node); + node.left = null; + node.right = null; + node.value = null; + node.allocator = allocator; + + return node; + } + + fn deinit(self: *Node) void { + if (self.left) |left| { + left.deinit(); + } + if (self.right) |right| { + right.deinit(); + } + self.allocator.destory(self); + } }; - head: Node, + root: Node, + + const Self = @This(); + + fn init(allocator: mem.Allocator) !Self { + var root = try Node.init(allocator); + return Self { + root, + }; + } + + fn deinit(self: *Self) void { + self.root.deinit(); + } }; } @@ -114,25 +180,49 @@ const DynamicDecoder = struct { len_to_read: usize, codes: [19]u3, walker: *BitWalker, + allocator: mem.Allocator, - fn init(walker: *BitWalker, len_to_read: usize) !Self { + fn init(walker: *BitWalker, len_to_read: usize, allocator: mem.Allocator) !Self { const list: [19]u8 = .{ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - var codes: [19]u3 = .{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + var lenList: [19]u3 = .{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + var bl_count: [7]u8 = .{0, 0, 0, 0, 0, 0, 0}; for (0..(len_to_read + 4)) |i| { - print("{} {}", .{ walker.position, walker.in_byte_position }); var data: u3 = @intCast(u3, try walker.walk(3)); + lenList[i] = data; if (data == 0) { continue; } - print("{} - {}", .{ list[i], data }); - codes[i] = data; + bl_count[data - 1] += 1; + } + + var bl_count: []u8 = allocator.allocator(u8, max - 1); + + var next_codes: [19]u3 = .{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + var code = 0; + bl_count[0] = 0; + for (1..max) |bits| { + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = code; + } + + var codes: [19]u3 = .{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + for (0..19) |n| { + var len = lenList[n]; + if (len != 0) { + codes = next_code[len]; + next_code[len] += 1; + } } return .{ .len_to_read = len_to_read, .codes = codes, .walker = walker, + .allocator = allocator, }; } }; @@ -230,7 +320,7 @@ const ZipFileHeader = struct { var number_of_literal_codes = try bitw.walk(5); var number_of_dist_codes = try bitw.walk(5); - var number_of_length_codes = try bitw.walk(5); + var number_of_length_codes = try bitw.walk(4); print("number of literal codes: {}", .{number_of_literal_codes}); print("number of dist codes: {}", .{number_of_dist_codes});