mirror of
https://github.com/ziglang/zig.git
synced 2024-12-01 01:22:50 +00:00
91 lines
2.9 KiB
Zig
91 lines
2.9 KiB
Zig
const std = @import("../std.zig");
|
|
const math = std.math;
|
|
const mem = std.mem;
|
|
const Allocator = std.mem.Allocator;
|
|
|
|
pub const decode = @import("lzma/decode.zig");
|
|
|
|
pub fn decompress(
|
|
allocator: Allocator,
|
|
reader: anytype,
|
|
) !Decompress(@TypeOf(reader)) {
|
|
return decompressWithOptions(allocator, reader, .{});
|
|
}
|
|
|
|
pub fn decompressWithOptions(
|
|
allocator: Allocator,
|
|
reader: anytype,
|
|
options: decode.Options,
|
|
) !Decompress(@TypeOf(reader)) {
|
|
const params = try decode.Params.readHeader(reader, options);
|
|
return Decompress(@TypeOf(reader)).init(allocator, reader, params, options.memlimit);
|
|
}
|
|
|
|
pub fn Decompress(comptime ReaderType: type) type {
|
|
return struct {
|
|
const Self = @This();
|
|
|
|
pub const Error =
|
|
ReaderType.Error ||
|
|
Allocator.Error ||
|
|
error{ CorruptInput, EndOfStream, Overflow };
|
|
|
|
pub const Reader = std.io.Reader(*Self, Error, read);
|
|
|
|
allocator: Allocator,
|
|
in_reader: ReaderType,
|
|
to_read: std.ArrayListUnmanaged(u8),
|
|
|
|
buffer: decode.lzbuffer.LzCircularBuffer,
|
|
decoder: decode.rangecoder.RangeDecoder,
|
|
state: decode.DecoderState,
|
|
|
|
pub fn init(allocator: Allocator, source: ReaderType, params: decode.Params, memlimit: ?usize) !Self {
|
|
return Self{
|
|
.allocator = allocator,
|
|
.in_reader = source,
|
|
.to_read = .{},
|
|
|
|
.buffer = decode.lzbuffer.LzCircularBuffer.init(params.dict_size, memlimit orelse math.maxInt(usize)),
|
|
.decoder = try decode.rangecoder.RangeDecoder.init(source),
|
|
.state = try decode.DecoderState.init(allocator, params.properties, params.unpacked_size),
|
|
};
|
|
}
|
|
|
|
pub fn reader(self: *Self) Reader {
|
|
return .{ .context = self };
|
|
}
|
|
|
|
pub fn deinit(self: *Self) void {
|
|
self.to_read.deinit(self.allocator);
|
|
self.buffer.deinit(self.allocator);
|
|
self.state.deinit(self.allocator);
|
|
self.* = undefined;
|
|
}
|
|
|
|
pub fn read(self: *Self, output: []u8) Error!usize {
|
|
const writer = self.to_read.writer(self.allocator);
|
|
while (self.to_read.items.len < output.len) {
|
|
switch (try self.state.process(self.allocator, self.in_reader, writer, &self.buffer, &self.decoder)) {
|
|
.continue_ => {},
|
|
.finished => {
|
|
try self.buffer.finish(writer);
|
|
break;
|
|
},
|
|
}
|
|
}
|
|
const input = self.to_read.items;
|
|
const n = @min(input.len, output.len);
|
|
@memcpy(output[0..n], input[0..n]);
|
|
@memcpy(input[0 .. input.len - n], input[n..]);
|
|
self.to_read.shrinkRetainingCapacity(input.len - n);
|
|
return n;
|
|
}
|
|
};
|
|
}
|
|
|
|
test {
|
|
_ = @import("lzma/test.zig");
|
|
_ = @import("lzma/vec2d.zig");
|
|
}
|