Update flakes
This commit is contained in:
parent
54f6673a03
commit
7f67221222
216
flake.lock
216
flake.lock
@ -1,5 +1,29 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"binned_allocator": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-FhnSM7KbQSOg9jMiJxEpXJbPX4uvkLzFbG5DaGlgYrc=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://gist.github.com/silversquirl/c1e4840048fdf48e669b6eac76d80634/archive/8bbe137e65f26854ff936046d884a45d4fa156de.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://gist.github.com/silversquirl/c1e4840048fdf48e669b6eac76d80634/archive/8bbe137e65f26854ff936046d884a45d4fa156de.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"diffz": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-CHRuEEeYGEpotuPo4vRe1qKz0EmkZwVvNjZagFj07ok=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/diffz/archive/2fd03fc72760a700e41f30f2b180f26e11c3365b.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/diffz/archive/2fd03fc72760a700e41f30f2b180f26e11c3365b.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-compat": {
|
"flake-compat": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
@ -16,6 +40,22 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flake-compat_2": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1673956053,
|
||||||
|
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1659877975,
|
"lastModified": 1659877975,
|
||||||
@ -31,46 +71,194 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"flake-utils_2": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1661151577,
|
"lastModified": 1685518550,
|
||||||
"narHash": "sha256-++S0TuJtuz9IpqP8rKktWyHZKpgdyrzDFUXVY07MTRI=",
|
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
||||||
"owner": "NixOS",
|
"owner": "numtide",
|
||||||
"repo": "nixpkgs",
|
"repo": "flake-utils",
|
||||||
"rev": "54060e816971276da05970a983487a25810c38a7",
|
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "numtide",
|
||||||
"ref": "nixpkgs-unstable",
|
"repo": "flake-utils",
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flake-utils_3": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1659877975,
|
||||||
|
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"zls",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1660459072,
|
||||||
|
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"known_folders": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-hgzm6HrtusbhmWEq6moKYGf5sWc52UwyHTjAIjr6EEQ=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/known-folders/archive/d13ba6137084e55f873f6afb67447fe8906cc951.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/known-folders/archive/d13ba6137084e55f873f6afb67447fe8906cc951.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1687502512,
|
||||||
|
"narHash": "sha256-dBL/01TayOSZYxtY4cMXuNCBk8UMLoqRZA+94xiFpJA=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "3ae20aa58a6c0d1ca95c9b11f59a2d12eebc511f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"zig": "zig"
|
"nixpkgs": "nixpkgs",
|
||||||
|
"zig": "zig",
|
||||||
|
"zls": "zls"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tres": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"narHash": "sha256-yhAH7npmBmlOkoHAitbDEv9CUx3zOc2GyErR8WPQCYQ=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/tres/archive/220d01f3931595e3a2e2a6a0693363c0bfaf47e9.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/ziglibs/tres/archive/220d01f3931595e3a2e2a6a0693363c0bfaf47e9.tar.gz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zig": {
|
"zig": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1684670828,
|
"lastModified": 1687653075,
|
||||||
"narHash": "sha256-e3HSmT9ufQ0WZYh6hOPx87dg/4jjLoJLl6zAEzev07E=",
|
"narHash": "sha256-2PH/eKQ78Oe8yspR11iIhB1mAUqDZ+xlvC5Z5lRvKyY=",
|
||||||
"owner": "mitchellh",
|
"owner": "mitchellh",
|
||||||
"repo": "zig-overlay",
|
"repo": "zig-overlay",
|
||||||
"rev": "22a39bd5ce8f8b0fdec3049ca5bfb54c748380bd",
|
"rev": "2adb751d4e9d6ab472c44e5fe8bde98e51fec0a1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "mitchellh",
|
"owner": "mitchellh",
|
||||||
|
"ref": "main",
|
||||||
"repo": "zig-overlay",
|
"repo": "zig-overlay",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"zig-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat_2",
|
||||||
|
"flake-utils": "flake-utils_3",
|
||||||
|
"nixpkgs": [
|
||||||
|
"zls",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1687653075,
|
||||||
|
"narHash": "sha256-2PH/eKQ78Oe8yspR11iIhB1mAUqDZ+xlvC5Z5lRvKyY=",
|
||||||
|
"owner": "mitchellh",
|
||||||
|
"repo": "zig-overlay",
|
||||||
|
"rev": "2adb751d4e9d6ab472c44e5fe8bde98e51fec0a1",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "mitchellh",
|
||||||
|
"ref": "main",
|
||||||
|
"repo": "zig-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zls": {
|
||||||
|
"inputs": {
|
||||||
|
"binned_allocator": "binned_allocator",
|
||||||
|
"diffz": "diffz",
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"known_folders": "known_folders",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"tres": "tres",
|
||||||
|
"zig-overlay": "zig-overlay"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1687692338,
|
||||||
|
"narHash": "sha256-RCf3DFTcldHwwtlcwzTVUU9Ej8alAGqhPvMXwrjYvjg=",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"rev": "c32e04ad38305af716f35c2687811707c0626854",
|
||||||
|
"revCount": 1722,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.andr3h3nriqu3s.com/andr3/zls"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.andr3h3nriqu3s.com/andr3/zls"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
13
flake.nix
13
flake.nix
@ -1,9 +1,18 @@
|
|||||||
{
|
{
|
||||||
description = "A very basic flake";
|
description = "A very basic flake";
|
||||||
|
|
||||||
inputs.zig.url = "github:mitchellh/zig-overlay";
|
inputs = {
|
||||||
|
nixpkgs.url ="nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
outputs = { self, zig, ... }: {
|
zig.url = "github:mitchellh/zig-overlay/main";
|
||||||
|
zig.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|
||||||
|
zls.url = "git+https://git.andr3h3nriqu3s.com/andr3/zls";
|
||||||
|
zls.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, zig, zls, ... }: {
|
||||||
packages.x86_64-linux.zig = zig.packages.x86_64-linux.master;
|
packages.x86_64-linux.zig = zig.packages.x86_64-linux.master;
|
||||||
|
packages.x86_64-linux.zls = zls.packages.x86_64-linux.default;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
332
src/HuffmanGraph.zig
Normal file
332
src/HuffmanGraph.zig
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const mem = std.mem;
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
const walkers = @import("walker.zig");
|
||||||
|
const BitWalkerUint = walkers.BitWalkerUint;
|
||||||
|
const BitWalker = walkers.BitWalker;
|
||||||
|
|
||||||
|
pub fn HuffmanGraph(comptime valueType: type) type {
|
||||||
|
return struct {
|
||||||
|
const Node = struct {
|
||||||
|
const NodeSelf = @This();
|
||||||
|
|
||||||
|
left: ?*NodeSelf,
|
||||||
|
right: ?*NodeSelf,
|
||||||
|
value: ?valueType,
|
||||||
|
|
||||||
|
allocator: mem.Allocator,
|
||||||
|
|
||||||
|
fn init(allocator: mem.Allocator) !*NodeSelf {
|
||||||
|
var node = try allocator.create(NodeSelf);
|
||||||
|
node.left = null;
|
||||||
|
node.right = null;
|
||||||
|
node.value = null;
|
||||||
|
node.allocator = allocator;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: *NodeSelf) void {
|
||||||
|
if (self.left) |left| {
|
||||||
|
left.deinit();
|
||||||
|
}
|
||||||
|
if (self.right) |right| {
|
||||||
|
right.deinit();
|
||||||
|
}
|
||||||
|
self.allocator.destroy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print(self: *NodeSelf, curDepth: usize, targetDepth: usize) void {
|
||||||
|
if (curDepth != targetDepth) {
|
||||||
|
if (self.left) |l| {
|
||||||
|
l.print(curDepth + 1, targetDepth);
|
||||||
|
} else {
|
||||||
|
utils.printf(" , ", .{});
|
||||||
|
}
|
||||||
|
if (self.right) |r| {
|
||||||
|
r.print(curDepth + 1, targetDepth);
|
||||||
|
} else {
|
||||||
|
utils.printf(" . ", .{});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.value) |v| {
|
||||||
|
utils.printf(" {any} ", .{v});
|
||||||
|
} else {
|
||||||
|
utils.printf(" _ ", .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn depth(self: *NodeSelf) usize {
|
||||||
|
var d: usize = 0;
|
||||||
|
if (self.right) |r| {
|
||||||
|
d = r.depth();
|
||||||
|
}
|
||||||
|
if (self.left) |l| {
|
||||||
|
d = std.math.max(d, l.depth());
|
||||||
|
}
|
||||||
|
return d + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn valid(self: *NodeSelf) bool {
|
||||||
|
var has_child = self.right == null and self.left == null;
|
||||||
|
if (self.value != null)
|
||||||
|
return has_child;
|
||||||
|
|
||||||
|
if (has_child)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (self.right) |r|
|
||||||
|
if (!r.valid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (self.left) |l|
|
||||||
|
if (!l.valid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
root: *Node,
|
||||||
|
allocator: mem.Allocator,
|
||||||
|
stored_depth: ?usize = null,
|
||||||
|
|
||||||
|
iterNode: *Node,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
fn init(allocator: mem.Allocator) !Self {
|
||||||
|
var root = try Node.init(allocator);
|
||||||
|
return Self{
|
||||||
|
.root = root,
|
||||||
|
.iterNode = root,
|
||||||
|
.allocator = allocator,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(self: *Self) void {
|
||||||
|
var d = self.depth() + 1;
|
||||||
|
for (0..d) |i| {
|
||||||
|
self.root.print(0, i);
|
||||||
|
utils.printf("\n", .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addValue(self: *Self, code: u64, size: usize, value: valueType) !void {
|
||||||
|
var walker = try BitWalkerUint(u64).init(code, size, true);
|
||||||
|
|
||||||
|
var curNode: *Node = self.root;
|
||||||
|
|
||||||
|
while (walker.walkBit()) |bit| {
|
||||||
|
if (bit == 1) {
|
||||||
|
if (curNode.left) |nextNode| {
|
||||||
|
curNode = nextNode;
|
||||||
|
} else {
|
||||||
|
curNode.left = try Node.init(self.allocator);
|
||||||
|
curNode = curNode.left.?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (curNode.right) |nextNode| {
|
||||||
|
curNode = nextNode;
|
||||||
|
} else {
|
||||||
|
curNode.right = try Node.init(self.allocator);
|
||||||
|
curNode = curNode.right.?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curNode.value = value;
|
||||||
|
self.stored_depth = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn depth(self: *Self) usize {
|
||||||
|
if (self.stored_depth) |d| {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stored_depth = self.root.depth() - 1;
|
||||||
|
return self.stored_depth.?;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter(self: *Self, bit: u1) anyerror!?valueType {
|
||||||
|
var node = self.iterNode;
|
||||||
|
|
||||||
|
var nextNode: ?*Node = null;
|
||||||
|
|
||||||
|
if (bit == 1) {
|
||||||
|
nextNode = node.left;
|
||||||
|
} else {
|
||||||
|
nextNode = node.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextNode) |new_node| {
|
||||||
|
if (new_node.value) |value| {
|
||||||
|
self.iterNode = self.root;
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
self.iterNode = new_node;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.InvalidBitSequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nextBitW(self: *Self, bitw: *BitWalker) !valueType {
|
||||||
|
while (true) {
|
||||||
|
if (try self.iter(try bitw.bitWalk())) |value|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn valid(self: *Self) bool {
|
||||||
|
return self.root.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.root.deinit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_dynamic_graph(walker: *BitWalker, len_to_read: usize, allocator: mem.Allocator) !HuffmanGraph(u64) {
|
||||||
|
const list: [19]u8 = .{ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
|
||||||
|
|
||||||
|
const lens: []u8 = try allocator.alloc(u8, 19);
|
||||||
|
defer allocator.free(lens);
|
||||||
|
mem.set(u8, lens, 0);
|
||||||
|
|
||||||
|
for (0..len_to_read) |i| {
|
||||||
|
lens[list[i]] = @intCast(u8, try walker.walk(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = try GraphBuilder(u64).init(allocator, 19, 0, 8);
|
||||||
|
defer builder.deinit();
|
||||||
|
|
||||||
|
while (!builder.done()) {
|
||||||
|
builder.addValue(builder.i, lens[builder.i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return try builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn GraphBuilder(comptime T: type) type {
|
||||||
|
return struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
allocator: mem.Allocator,
|
||||||
|
values: []T,
|
||||||
|
lens: []usize,
|
||||||
|
bl_count: []usize,
|
||||||
|
size: usize,
|
||||||
|
max: usize = 0,
|
||||||
|
i: usize = 0,
|
||||||
|
|
||||||
|
pub fn init(allocator: mem.Allocator, size: usize, default: T, maxlen: usize) !Self {
|
||||||
|
var values = try allocator.alloc(T, size);
|
||||||
|
mem.set(T, values, default);
|
||||||
|
|
||||||
|
var lens = try allocator.alloc(usize, size);
|
||||||
|
mem.set(usize, lens, 0);
|
||||||
|
|
||||||
|
var bl_count = try allocator.alloc(usize, maxlen);
|
||||||
|
mem.set(usize, bl_count, 0);
|
||||||
|
|
||||||
|
return Self{
|
||||||
|
.allocator = allocator,
|
||||||
|
.bl_count = bl_count,
|
||||||
|
.size = size,
|
||||||
|
.values = values,
|
||||||
|
.lens = lens,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn skip(self: *Self, len: usize) void {
|
||||||
|
self.i += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn done(self: *Self) bool {
|
||||||
|
return self.i >= self.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addValue(self: *Self, value: T, len: usize) void {
|
||||||
|
if (len > self.max) {
|
||||||
|
self.max = len;
|
||||||
|
}
|
||||||
|
self.values[self.i] = value;
|
||||||
|
self.lens[self.i] = len;
|
||||||
|
self.bl_count[len] += 1;
|
||||||
|
self.i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self: *Self) !HuffmanGraph(T) {
|
||||||
|
self.bl_count[0] = 0;
|
||||||
|
|
||||||
|
var next_code = try self.allocator.alloc(usize, self.max + 1);
|
||||||
|
defer self.allocator.free(next_code);
|
||||||
|
std.mem.set(usize, next_code, 0);
|
||||||
|
|
||||||
|
var code: usize = 0;
|
||||||
|
for (1..(self.max + 1)) |bits| {
|
||||||
|
code = @shlExact(code + self.bl_count[bits - 1], 1);
|
||||||
|
next_code[bits] = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
var codes = try self.allocator.alloc(u64, self.size);
|
||||||
|
defer self.allocator.free(codes);
|
||||||
|
std.mem.set(usize, codes, 0);
|
||||||
|
|
||||||
|
for (0..self.size) |n| {
|
||||||
|
var len = self.lens[n];
|
||||||
|
if (len != 0) {
|
||||||
|
codes[n] = next_code[len];
|
||||||
|
next_code[len] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var graph = try HuffmanGraph(T).init(self.allocator);
|
||||||
|
errdefer graph.deinit();
|
||||||
|
|
||||||
|
for (0..self.size) |i| {
|
||||||
|
if (self.lens[i] == 0)
|
||||||
|
continue;
|
||||||
|
try graph.addValue(codes[i], self.lens[i], self.values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!graph.valid())
|
||||||
|
return error.graph_not_valid;
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buildWithDynamic(self: *Self, bitw: *BitWalker, graph: *HuffmanGraph(u64)) !HuffmanGraph(T) {
|
||||||
|
while (!self.done()) {
|
||||||
|
var v = try graph.nextBitW(bitw);
|
||||||
|
|
||||||
|
if (v == 16) {
|
||||||
|
const len = try bitw.walk(2) + 3;
|
||||||
|
const last = self.lens[self.i - 1];
|
||||||
|
for (0..len) |_| {
|
||||||
|
self.addValue(self.i, last);
|
||||||
|
}
|
||||||
|
} else if (v == 17) {
|
||||||
|
self.skip(try bitw.walk(3) + 3);
|
||||||
|
} else if (v == 18) {
|
||||||
|
self.skip(try bitw.walk(7) + 11);
|
||||||
|
} else {
|
||||||
|
self.addValue(self.i, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try self.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.allocator.free(self.values);
|
||||||
|
self.allocator.free(self.lens);
|
||||||
|
self.allocator.free(self.bl_count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
408
src/zip.zig
Normal file
408
src/zip.zig
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const mem = std.mem;
|
||||||
|
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
const print = utils.print;
|
||||||
|
|
||||||
|
const walkers = @import("walker.zig");
|
||||||
|
const BitWalker = walkers.BitWalker;
|
||||||
|
const BitWalkerUint = walkers.BitWalkerUint;
|
||||||
|
|
||||||
|
const huffmanstuff = @import("HuffmanGraph.zig");
|
||||||
|
const HuffmanGraph = huffmanstuff.HuffmanGraph;
|
||||||
|
const GraphBuilder = huffmanstuff.GraphBuilder;
|
||||||
|
const create_dynamic_graph = huffmanstuff.create_dynamic_graph;
|
||||||
|
|
||||||
|
fn get_len_value(bitw: *BitWalker, len_code: usize) !usize {
|
||||||
|
var extra_bits: usize = switch (len_code) {
|
||||||
|
257...264 => 0,
|
||||||
|
265...268 => 1,
|
||||||
|
269...272 => 2,
|
||||||
|
273...276 => 3,
|
||||||
|
277...280 => 4,
|
||||||
|
281...284 => 5,
|
||||||
|
285 => 0,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
var to_add = try bitw.walk(extra_bits);
|
||||||
|
|
||||||
|
var base_value: usize = switch (len_code) {
|
||||||
|
257 => 3,
|
||||||
|
258 => 4,
|
||||||
|
259 => 5,
|
||||||
|
260 => 6,
|
||||||
|
261 => 7,
|
||||||
|
262 => 8,
|
||||||
|
263 => 9,
|
||||||
|
264 => 10,
|
||||||
|
265 => 11,
|
||||||
|
266 => 13,
|
||||||
|
267 => 15,
|
||||||
|
268 => 17,
|
||||||
|
269 => 19,
|
||||||
|
270 => 23,
|
||||||
|
271 => 27,
|
||||||
|
272 => 31,
|
||||||
|
273 => 35,
|
||||||
|
274 => 43,
|
||||||
|
275 => 51,
|
||||||
|
276 => 59,
|
||||||
|
277 => 67,
|
||||||
|
278 => 83,
|
||||||
|
279 => 99,
|
||||||
|
280 => 115,
|
||||||
|
281 => 131,
|
||||||
|
282 => 163,
|
||||||
|
283 => 195,
|
||||||
|
284 => 227,
|
||||||
|
285 => 258,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
return base_value + to_add;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_dist_value(bitw: *BitWalker, dist_graph: *HuffmanGraph(u64)) !usize {
|
||||||
|
var dist = try dist_graph.nextBitW(bitw);
|
||||||
|
|
||||||
|
var extra_bits: usize = switch (dist) {
|
||||||
|
0...3 => 0,
|
||||||
|
4...29 => (dist / 2) - 1,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
var to_add = try bitw.walk(extra_bits);
|
||||||
|
|
||||||
|
var base_value: usize = switch (dist) {
|
||||||
|
0...3 => dist + 1,
|
||||||
|
// import math
|
||||||
|
// def d(dist):
|
||||||
|
// return 2**math.floor(dist/2) + (2**(math.floor(dist / 2) - 1) * (dist % 2)) + 1
|
||||||
|
4...29 => std.math.pow(usize, 2, dist / 2) + (std.math.pow(usize, 2, (dist / 2) - 1) * (dist % 2)) + 1,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
return base_value + to_add;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BlockData = struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
bitw: *BitWalker,
|
||||||
|
allocator: mem.Allocator,
|
||||||
|
|
||||||
|
last: bool,
|
||||||
|
blockType: u8,
|
||||||
|
|
||||||
|
literal_graph: ?HuffmanGraph(u64) = null,
|
||||||
|
dist_graph: ?HuffmanGraph(u64) = null,
|
||||||
|
output: *[]u8,
|
||||||
|
|
||||||
|
allOutput: *[]u8,
|
||||||
|
|
||||||
|
fn init(allocator: mem.Allocator, bitw: *BitWalker, output: *[]u8, allOutput: *[]u8) !Self {
|
||||||
|
return Self{
|
||||||
|
.bitw = bitw,
|
||||||
|
.allocator = allocator,
|
||||||
|
.last = try bitw.walk(1) == 1,
|
||||||
|
.blockType = @intCast(u8, try bitw.walk(2)),
|
||||||
|
|
||||||
|
.output = output,
|
||||||
|
.allOutput = allOutput,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uncompress(self: *Self, start_place: usize) !usize {
|
||||||
|
return switch (self.blockType) {
|
||||||
|
0 => self.not_compressed(start_place),
|
||||||
|
1 => self.fixed(start_place),
|
||||||
|
2 => self.dynamic_huffman(start_place),
|
||||||
|
3 => error.block_type_error,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn not_compressed(self: *Self, start_value: usize) !usize {
|
||||||
|
var bitw = self.bitw;
|
||||||
|
try bitw.nextByte();
|
||||||
|
|
||||||
|
var size = try bitw.walk(16);
|
||||||
|
var nsize = try bitw.walk(24);
|
||||||
|
_ = nsize;
|
||||||
|
|
||||||
|
var i = start_value;
|
||||||
|
while (i < size) : (i += 1) {
|
||||||
|
self.output.ptr[i] = @intCast(u8, try bitw.walk(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fixed(self: *Self, start_value: usize) !usize {
|
||||||
|
var litBuilder = try GraphBuilder(u64).init(self.allocator, 288, 0, 10);
|
||||||
|
defer litBuilder.deinit();
|
||||||
|
|
||||||
|
for (0..144) |i| {
|
||||||
|
litBuilder.addValue(i, 8);
|
||||||
|
}
|
||||||
|
for (144..256) |i| {
|
||||||
|
litBuilder.addValue(i, 9);
|
||||||
|
}
|
||||||
|
for (256..280) |i| {
|
||||||
|
litBuilder.addValue(i, 7);
|
||||||
|
}
|
||||||
|
for (280..288) |i| {
|
||||||
|
litBuilder.addValue(i, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
var lit = try litBuilder.build();
|
||||||
|
|
||||||
|
self.literal_graph = lit;
|
||||||
|
|
||||||
|
var distBuilder = try GraphBuilder(u64).init(self.allocator, 32, 0, 10);
|
||||||
|
defer distBuilder.deinit();
|
||||||
|
|
||||||
|
for (0..32) |i| {
|
||||||
|
distBuilder.addValue(i, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dist_graph = try distBuilder.build();
|
||||||
|
|
||||||
|
var bitw = self.bitw;
|
||||||
|
|
||||||
|
var lastRead: u64 = 0;
|
||||||
|
var i: usize = start_value;
|
||||||
|
while (true) {
|
||||||
|
lastRead = try lit.nextBitW(bitw);
|
||||||
|
if (lastRead == 256) {
|
||||||
|
break;
|
||||||
|
} else if (lastRead > 256) {
|
||||||
|
var len = try get_len_value(bitw, lastRead);
|
||||||
|
var dist = try get_dist_value(bitw, &self.dist_graph.?);
|
||||||
|
|
||||||
|
print("{} {}", .{ i, dist });
|
||||||
|
|
||||||
|
var pos: isize = @intCast(isize, i) - @intCast(isize, dist);
|
||||||
|
for (0..len) |j| {
|
||||||
|
if ((pos + @intCast(isize, j)) < 0) {
|
||||||
|
self.output.ptr[i] = self.allOutput.ptr[@intCast(usize, @intCast(isize, self.allOutput.len) - pos + @intCast(isize, j))];
|
||||||
|
} else {
|
||||||
|
self.output.ptr[i] = self.output.ptr[@intCast(usize, pos + @intCast(isize, j))];
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
} else if (lastRead < 256) {
|
||||||
|
self.output.ptr[i] = @intCast(u8, lastRead);
|
||||||
|
i += 1;
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dynamic_huffman(self: *Self, start_place: usize) !usize {
|
||||||
|
var bitw = self.bitw;
|
||||||
|
|
||||||
|
var number_of_literal_codes: u32 = @intCast(u32, try bitw.walk(5)) + 257;
|
||||||
|
var number_of_dist_codes = try bitw.walk(5) + 1;
|
||||||
|
var number_of_length_codes = try bitw.walk(4) + 4;
|
||||||
|
|
||||||
|
var dynamic_graph = try create_dynamic_graph(bitw, number_of_length_codes, self.allocator);
|
||||||
|
defer dynamic_graph.deinit();
|
||||||
|
|
||||||
|
var builder = try GraphBuilder(u64).init(self.allocator, number_of_literal_codes, 0, 16);
|
||||||
|
// destory either the 1st or the 2nd graph
|
||||||
|
defer builder.deinit();
|
||||||
|
|
||||||
|
self.literal_graph = try builder.buildWithDynamic(bitw, &dynamic_graph);
|
||||||
|
var graph = self.literal_graph.?;
|
||||||
|
|
||||||
|
// Destory the first builder
|
||||||
|
builder.deinit();
|
||||||
|
|
||||||
|
builder = try GraphBuilder(u64).init(self.allocator, number_of_dist_codes, 0, 16);
|
||||||
|
self.dist_graph = try builder.buildWithDynamic(bitw, &dynamic_graph);
|
||||||
|
|
||||||
|
var lastRead: u64 = 0;
|
||||||
|
|
||||||
|
var i: usize = start_place;
|
||||||
|
while (true) {
|
||||||
|
lastRead = try graph.nextBitW(bitw);
|
||||||
|
if (lastRead == 256) {
|
||||||
|
break;
|
||||||
|
} else if (lastRead > 256) {
|
||||||
|
var len = try get_len_value(bitw, lastRead);
|
||||||
|
var dist = try get_dist_value(bitw, &self.dist_graph.?);
|
||||||
|
|
||||||
|
var pos: isize = @intCast(isize, i) - @intCast(isize, dist);
|
||||||
|
for (0..len) |j| {
|
||||||
|
if ((pos + @intCast(isize, j)) < 0) {
|
||||||
|
self.output.ptr[i] = self.allOutput.ptr[@intCast(usize, @intCast(isize, self.allOutput.len) - pos + @intCast(isize, j))];
|
||||||
|
} else {
|
||||||
|
self.output.ptr[i] = self.output.ptr[@intCast(usize, pos + @intCast(isize, j))];
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
} else if (lastRead < 256) {
|
||||||
|
self.output.ptr[i] = @intCast(u8, lastRead);
|
||||||
|
i += 1;
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: *Self) void {
|
||||||
|
if (self.literal_graph != null) {
|
||||||
|
self.literal_graph.?.deinit();
|
||||||
|
}
|
||||||
|
if (self.dist_graph != null) {
|
||||||
|
self.dist_graph.?.deinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
|
||||||
|
const ZipFileHeader = struct {
|
||||||
|
version: u16,
|
||||||
|
general: u16,
|
||||||
|
compression_method: u16,
|
||||||
|
last_mod_time: u16,
|
||||||
|
last_mod_date: u16,
|
||||||
|
crc_32: u32,
|
||||||
|
compressed_size: u32,
|
||||||
|
uncompressed_size: u32,
|
||||||
|
file_name_length: u16,
|
||||||
|
extra_field_length: u16,
|
||||||
|
|
||||||
|
file_name: []u8,
|
||||||
|
extra_field: []u8,
|
||||||
|
compressed_content: []u8,
|
||||||
|
uncompressed_content: []u8,
|
||||||
|
decompressed: bool,
|
||||||
|
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
allOutput: *[]u8,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
fn init(allocator: std.mem.Allocator, reader: std.fs.File.Reader, allOutput: *[]u8) !Self {
|
||||||
|
if (try reader.readInt(u32, .Big) == LOCAL_FILE_HEADER_SIGNATURE) {
|
||||||
|
return error.InvalidError;
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = Self{
|
||||||
|
.allocator = allocator,
|
||||||
|
.version = try reader.readInt(u16, .Little),
|
||||||
|
.general = try reader.readInt(u16, .Little),
|
||||||
|
.compression_method = try reader.readInt(u16, .Little),
|
||||||
|
.last_mod_time = try reader.readInt(u16, .Little),
|
||||||
|
.last_mod_date = try reader.readInt(u16, .Little),
|
||||||
|
.crc_32 = try reader.readInt(u32, .Little),
|
||||||
|
.compressed_size = try reader.readInt(u32, .Little),
|
||||||
|
.uncompressed_size = try reader.readInt(u32, .Little),
|
||||||
|
.file_name_length = try reader.readInt(u16, .Little),
|
||||||
|
.extra_field_length = try reader.readInt(u16, .Little),
|
||||||
|
.file_name = undefined,
|
||||||
|
.extra_field = undefined,
|
||||||
|
.compressed_content = undefined,
|
||||||
|
.uncompressed_content = undefined,
|
||||||
|
.decompressed = false,
|
||||||
|
.allOutput = allOutput,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.file_name = try allocator.alloc(u8, self.file_name_length);
|
||||||
|
self.extra_field = try allocator.alloc(u8, self.extra_field_length);
|
||||||
|
self.compressed_content = try allocator.alloc(u8, self.compressed_size);
|
||||||
|
|
||||||
|
_ = try reader.read(self.file_name);
|
||||||
|
_ = try reader.read(self.extra_field);
|
||||||
|
_ = try reader.read(self.compressed_content);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract(self: *Self) !void {
|
||||||
|
// already decompressed
|
||||||
|
if (self.decompressed) return;
|
||||||
|
|
||||||
|
// already decompressed
|
||||||
|
if (self.compression_method == 0) {
|
||||||
|
self.uncompressed_content = try self.allocator.alloc(u8, self.uncompressed_size);
|
||||||
|
mem.copy(u8, self.uncompressed_content, self.compressed_content);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.compression_method != 8) {
|
||||||
|
return error.unsuported_compression_method;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.uncompressed_content = try self.allocator.alloc(u8, self.uncompressed_size);
|
||||||
|
errdefer self.allocator.free(self.uncompressed_content);
|
||||||
|
mem.set(u8, self.uncompressed_content, 0);
|
||||||
|
|
||||||
|
var bitw = try BitWalker.init(&self.compressed_content);
|
||||||
|
|
||||||
|
var is_last = false;
|
||||||
|
var output_place: usize = 0;
|
||||||
|
|
||||||
|
while (!is_last) {
|
||||||
|
var block = try BlockData.init(self.allocator, &bitw, &self.uncompressed_content, self.allOutput);
|
||||||
|
defer block.deinit();
|
||||||
|
|
||||||
|
is_last = block.last;
|
||||||
|
|
||||||
|
output_place = try block.uncompress(output_place);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.decompressed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.allocator.free(self.file_name);
|
||||||
|
self.allocator.free(self.extra_field);
|
||||||
|
self.allocator.free(self.compressed_content);
|
||||||
|
if (self.decompressed) {
|
||||||
|
self.allocator.free(self.uncompressed_content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ZipFile = struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
reader: std.fs.File.Reader,
|
||||||
|
|
||||||
|
allOutput: []u8,
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator, reader: std.fs.File.Reader) !Self {
|
||||||
|
return Self{
|
||||||
|
.allocator = allocator,
|
||||||
|
.reader = reader,
|
||||||
|
.allOutput = try allocator.alloc(u8, 0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readFile(self: *Self) !ZipFileHeader {
|
||||||
|
var zip_header = try ZipFileHeader.init(self.allocator, self.reader, &self.allOutput);
|
||||||
|
errdefer zip_header.deinit();
|
||||||
|
try zip_header.extract();
|
||||||
|
|
||||||
|
var new_all = try mem.concat(self.allocator, u8, &.{ self.allOutput, zip_header.uncompressed_content });
|
||||||
|
self.allocator.free(self.allOutput);
|
||||||
|
self.allOutput = new_all;
|
||||||
|
|
||||||
|
return zip_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.allocator.free(self.allOutput);
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user