Commit e03d6c42ea
Changed files (9)
lib
std
compress
lib/std/compress/lzma/decode/lzma.zig
@@ -1,398 +0,0 @@
-const std = @import("../../../std.zig");
-const assert = std.debug.assert;
-const math = std.math;
-const Allocator = std.mem.Allocator;
-const ArrayListUnmanaged = std.ArrayListUnmanaged;
-const FixedBufferStream = std.io.FixedBufferStream;
-
-const LzCircularBuffer = @import("lzbuffer.zig").LzCircularBuffer;
-const Options = @import("../decode.zig").Options;
-const Vec2D = @import("../vec2d.zig").Vec2D;
-const rangecoder = @import("rangecoder.zig");
-const BitTree = rangecoder.BitTree;
-const LenDecoder = rangecoder.LenDecoder;
-const RangeDecoder = rangecoder.RangeDecoder;
-
-const ProcessingStatus = enum {
- continue_,
- finished,
-};
-
-pub const LzmaProperties = struct {
- lc: u4,
- lp: u3,
- pb: u3,
-
- fn validate(self: LzmaProperties) void {
- assert(self.lc <= 8);
- assert(self.lp <= 4);
- assert(self.pb <= 4);
- }
-};
-
-pub const LzmaParams = struct {
- properties: LzmaProperties,
- dict_size: u32,
- unpacked_size: ?u64,
-
- pub fn readHeader(reader: anytype, options: Options) !LzmaParams {
- var props = try reader.readByte();
- if (props >= 225) {
- return error.CorruptInput;
- }
-
- const lc = @intCast(u4, props % 9);
- props /= 9;
- const lp = @intCast(u3, props % 5);
- props /= 5;
- const pb = @intCast(u3, props);
-
- const dict_size_provided = try reader.readIntLittle(u32);
- const dict_size = math.max(0x1000, dict_size_provided);
-
- const unpacked_size = switch (options.unpacked_size) {
- .read_from_header => blk: {
- const unpacked_size_provided = try reader.readIntLittle(u64);
- const marker_mandatory = unpacked_size_provided == 0xFFFF_FFFF_FFFF_FFFF;
- break :blk if (marker_mandatory)
- null
- else
- unpacked_size_provided;
- },
- .read_header_but_use_provided => |x| blk: {
- _ = try reader.readIntLittle(u64);
- break :blk x;
- },
- .use_provided => |x| x,
- };
-
- return LzmaParams{
- .properties = LzmaProperties{ .lc = lc, .lp = lp, .pb = pb },
- .dict_size = dict_size,
- .unpacked_size = unpacked_size,
- };
- }
-};
-
-pub const DecoderState = struct {
- lzma_props: LzmaProperties,
- unpacked_size: ?u64,
- literal_probs: Vec2D(u16),
- pos_slot_decoder: [4]BitTree(6),
- align_decoder: BitTree(4),
- pos_decoders: [115]u16,
- is_match: [192]u16,
- is_rep: [12]u16,
- is_rep_g0: [12]u16,
- is_rep_g1: [12]u16,
- is_rep_g2: [12]u16,
- is_rep_0long: [192]u16,
- state: usize,
- rep: [4]usize,
- len_decoder: LenDecoder,
- rep_len_decoder: LenDecoder,
-
- pub fn init(
- allocator: Allocator,
- lzma_props: LzmaProperties,
- unpacked_size: ?u64,
- ) !DecoderState {
- return .{
- .lzma_props = lzma_props,
- .unpacked_size = unpacked_size,
- .literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (lzma_props.lc + lzma_props.lp), 0x300 }),
- .pos_slot_decoder = .{.{}} ** 4,
- .align_decoder = .{},
- .pos_decoders = .{0x400} ** 115,
- .is_match = .{0x400} ** 192,
- .is_rep = .{0x400} ** 12,
- .is_rep_g0 = .{0x400} ** 12,
- .is_rep_g1 = .{0x400} ** 12,
- .is_rep_g2 = .{0x400} ** 12,
- .is_rep_0long = .{0x400} ** 192,
- .state = 0,
- .rep = .{0} ** 4,
- .len_decoder = .{},
- .rep_len_decoder = .{},
- };
- }
-
- pub fn deinit(self: *DecoderState, allocator: Allocator) void {
- self.literal_probs.deinit(allocator);
- self.* = undefined;
- }
-
- pub fn resetState(self: *DecoderState, allocator: Allocator, new_props: LzmaProperties) !void {
- new_props.validate();
- if (self.lzma_props.lc + self.lzma_props.lp == new_props.lc + new_props.lp) {
- self.literal_probs.fill(0x400);
- } else {
- self.literal_probs.deinit(allocator);
- self.literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (new_props.lc + new_props.lp), 0x300 });
- }
-
- self.lzma_props = new_props;
- for (self.pos_slot_decoder) |*t| t.reset();
- self.align_decoder.reset();
- self.pos_decoders = .{0x400} ** 115;
- self.is_match = .{0x400} ** 192;
- self.is_rep = .{0x400} ** 12;
- self.is_rep_g0 = .{0x400} ** 12;
- self.is_rep_g1 = .{0x400} ** 12;
- self.is_rep_g2 = .{0x400} ** 12;
- self.is_rep_0long = .{0x400} ** 192;
- self.state = 0;
- self.rep = .{0} ** 4;
- self.len_decoder.reset();
- self.rep_len_decoder.reset();
- }
-
- fn processNextInner(
- self: *DecoderState,
- allocator: Allocator,
- reader: anytype,
- writer: anytype,
- buffer: anytype,
- decoder: *RangeDecoder,
- update: bool,
- ) !ProcessingStatus {
- const pos_state = buffer.len & ((@as(usize, 1) << self.lzma_props.pb) - 1);
-
- if (!try decoder.decodeBit(
- reader,
- &self.is_match[(self.state << 4) + pos_state],
- update,
- )) {
- const byte: u8 = try self.decodeLiteral(reader, buffer, decoder, update);
-
- if (update) {
- try buffer.appendLiteral(allocator, byte, writer);
-
- self.state = if (self.state < 4)
- 0
- else if (self.state < 10)
- self.state - 3
- else
- self.state - 6;
- }
- return .continue_;
- }
-
- var len: usize = undefined;
- if (try decoder.decodeBit(reader, &self.is_rep[self.state], update)) {
- if (!try decoder.decodeBit(reader, &self.is_rep_g0[self.state], update)) {
- if (!try decoder.decodeBit(
- reader,
- &self.is_rep_0long[(self.state << 4) + pos_state],
- update,
- )) {
- if (update) {
- self.state = if (self.state < 7) 9 else 11;
- const dist = self.rep[0] + 1;
- try buffer.appendLz(allocator, 1, dist, writer);
- }
- return .continue_;
- }
- } else {
- const idx: usize = if (!try decoder.decodeBit(reader, &self.is_rep_g1[self.state], update))
- 1
- else if (!try decoder.decodeBit(reader, &self.is_rep_g2[self.state], update))
- 2
- else
- 3;
- if (update) {
- const dist = self.rep[idx];
- var i = idx;
- while (i > 0) : (i -= 1) {
- self.rep[i] = self.rep[i - 1];
- }
- self.rep[0] = dist;
- }
- }
-
- len = try self.rep_len_decoder.decode(reader, decoder, pos_state, update);
-
- if (update) {
- self.state = if (self.state < 7) 8 else 11;
- }
- } else {
- if (update) {
- self.rep[3] = self.rep[2];
- self.rep[2] = self.rep[1];
- self.rep[1] = self.rep[0];
- }
-
- len = try self.len_decoder.decode(reader, decoder, pos_state, update);
-
- if (update) {
- self.state = if (self.state < 7) 7 else 10;
- }
-
- const rep_0 = try self.decodeDistance(reader, decoder, len, update);
-
- if (update) {
- self.rep[0] = rep_0;
- if (self.rep[0] == 0xFFFF_FFFF) {
- if (decoder.isFinished()) {
- return .finished;
- }
- return error.CorruptInput;
- }
- }
- }
-
- if (update) {
- len += 2;
-
- const dist = self.rep[0] + 1;
- try buffer.appendLz(allocator, len, dist, writer);
- }
-
- return .continue_;
- }
-
- fn processNext(
- self: *DecoderState,
- allocator: Allocator,
- reader: anytype,
- writer: anytype,
- buffer: anytype,
- decoder: *RangeDecoder,
- ) !ProcessingStatus {
- return self.processNextInner(allocator, reader, writer, buffer, decoder, true);
- }
-
- pub fn process(
- self: *DecoderState,
- allocator: Allocator,
- reader: anytype,
- writer: anytype,
- buffer: anytype,
- decoder: *RangeDecoder,
- ) !void {
- while (true) {
- if (self.unpacked_size) |unpacked_size| {
- if (buffer.len >= unpacked_size) {
- break;
- }
- } else if (decoder.isFinished()) {
- break;
- }
-
- if (try self.processNext(allocator, reader, writer, buffer, decoder) == .finished) {
- break;
- }
- }
-
- if (self.unpacked_size) |len| {
- if (len != buffer.len) {
- return error.CorruptInput;
- }
- }
- }
-
- fn decodeLiteral(
- self: *DecoderState,
- reader: anytype,
- buffer: anytype,
- decoder: *RangeDecoder,
- update: bool,
- ) !u8 {
- const def_prev_byte = 0;
- const prev_byte = @as(usize, buffer.lastOr(def_prev_byte));
-
- var result: usize = 1;
- const lit_state = ((buffer.len & ((@as(usize, 1) << self.lzma_props.lp) - 1)) << self.lzma_props.lc) +
- (prev_byte >> (8 - self.lzma_props.lc));
- const probs = try self.literal_probs.getMut(lit_state);
-
- if (self.state >= 7) {
- var match_byte = @as(usize, try buffer.lastN(self.rep[0] + 1));
-
- while (result < 0x100) {
- const match_bit = (match_byte >> 7) & 1;
- match_byte <<= 1;
- const bit = @boolToInt(try decoder.decodeBit(
- reader,
- &probs[((@as(usize, 1) + match_bit) << 8) + result],
- update,
- ));
- result = (result << 1) ^ bit;
- if (match_bit != bit) {
- break;
- }
- }
- }
-
- while (result < 0x100) {
- result = (result << 1) ^ @boolToInt(try decoder.decodeBit(reader, &probs[result], update));
- }
-
- return @truncate(u8, result - 0x100);
- }
-
- fn decodeDistance(
- self: *DecoderState,
- reader: anytype,
- decoder: *RangeDecoder,
- length: usize,
- update: bool,
- ) !usize {
- const len_state = if (length > 3) 3 else length;
-
- const pos_slot = @as(usize, try self.pos_slot_decoder[len_state].parse(reader, decoder, update));
- if (pos_slot < 4)
- return pos_slot;
-
- const num_direct_bits = @intCast(u5, (pos_slot >> 1) - 1);
- var result = (2 ^ (pos_slot & 1)) << num_direct_bits;
-
- if (pos_slot < 14) {
- result += try decoder.parseReverseBitTree(
- reader,
- num_direct_bits,
- &self.pos_decoders,
- result - pos_slot,
- update,
- );
- } else {
- result += @as(usize, try decoder.get(reader, num_direct_bits - 4)) << 4;
- result += try self.align_decoder.parseReverse(reader, decoder, update);
- }
-
- return result;
- }
-};
-
-pub const LzmaDecoder = struct {
- params: LzmaParams,
- memlimit: usize,
- state: DecoderState,
-
- pub fn init(allocator: Allocator, params: LzmaParams, memlimit: ?usize) !LzmaDecoder {
- return LzmaDecoder{
- .params = params,
- .memlimit = memlimit orelse math.maxInt(usize),
- .state = try DecoderState.init(allocator, params.properties, params.unpacked_size),
- };
- }
-
- pub fn deinit(self: *LzmaDecoder, allocator: Allocator) void {
- self.state.deinit(allocator);
- self.* = undefined;
- }
-
- pub fn decompress(
- self: *LzmaDecoder,
- allocator: Allocator,
- reader: anytype,
- writer: anytype,
- ) !void {
- var buffer = LzCircularBuffer.init(self.params.dict_size, self.memlimit);
- defer buffer.deinit(allocator);
-
- var decoder = try RangeDecoder.init(reader);
- try self.state.process(allocator, reader, writer, &buffer, &decoder);
- try buffer.finish(writer);
- }
-};
lib/std/compress/lzma/decode/rangecoder.zig
@@ -1,8 +1,5 @@
const std = @import("../../../std.zig");
const mem = std.mem;
-const Allocator = std.mem.Allocator;
-const ArrayListUnmanaged = std.ArrayListUnmanaged;
-const FixedBufferStream = std.io.FixedBufferStream;
pub const RangeDecoder = struct {
range: u32,
lib/std/compress/lzma/decode.zig
@@ -1,8 +1,17 @@
+const std = @import("../../std.zig");
+const assert = std.debug.assert;
+const math = std.math;
+const Allocator = std.mem.Allocator;
+
pub const lzbuffer = @import("decode/lzbuffer.zig");
-pub const lzma = @import("decode/lzma.zig");
-pub const lzma2 = @import("decode/lzma2.zig");
pub const rangecoder = @import("decode/rangecoder.zig");
+const LzCircularBuffer = lzbuffer.LzCircularBuffer;
+const BitTree = rangecoder.BitTree;
+const LenDecoder = rangecoder.LenDecoder;
+const RangeDecoder = rangecoder.RangeDecoder;
+const Vec2D = @import("vec2d.zig").Vec2D;
+
pub const Options = struct {
unpacked_size: UnpackedSize = .read_from_header,
memlimit: ?usize = null,
@@ -14,3 +23,387 @@ pub const UnpackedSize = union(enum) {
read_header_but_use_provided: ?u64,
use_provided: ?u64,
};
+
+const ProcessingStatus = enum {
+ continue_,
+ finished,
+};
+
+pub const Properties = struct {
+ lc: u4,
+ lp: u3,
+ pb: u3,
+
+ fn validate(self: Properties) void {
+ assert(self.lc <= 8);
+ assert(self.lp <= 4);
+ assert(self.pb <= 4);
+ }
+};
+
+pub const Params = struct {
+ properties: Properties,
+ dict_size: u32,
+ unpacked_size: ?u64,
+
+ pub fn readHeader(reader: anytype, options: Options) !Params {
+ var props = try reader.readByte();
+ if (props >= 225) {
+ return error.CorruptInput;
+ }
+
+ const lc = @intCast(u4, props % 9);
+ props /= 9;
+ const lp = @intCast(u3, props % 5);
+ props /= 5;
+ const pb = @intCast(u3, props);
+
+ const dict_size_provided = try reader.readIntLittle(u32);
+ const dict_size = math.max(0x1000, dict_size_provided);
+
+ const unpacked_size = switch (options.unpacked_size) {
+ .read_from_header => blk: {
+ const unpacked_size_provided = try reader.readIntLittle(u64);
+ const marker_mandatory = unpacked_size_provided == 0xFFFF_FFFF_FFFF_FFFF;
+ break :blk if (marker_mandatory)
+ null
+ else
+ unpacked_size_provided;
+ },
+ .read_header_but_use_provided => |x| blk: {
+ _ = try reader.readIntLittle(u64);
+ break :blk x;
+ },
+ .use_provided => |x| x,
+ };
+
+ return Params{
+ .properties = Properties{ .lc = lc, .lp = lp, .pb = pb },
+ .dict_size = dict_size,
+ .unpacked_size = unpacked_size,
+ };
+ }
+};
+
+pub const DecoderState = struct {
+ lzma_props: Properties,
+ unpacked_size: ?u64,
+ literal_probs: Vec2D(u16),
+ pos_slot_decoder: [4]BitTree(6),
+ align_decoder: BitTree(4),
+ pos_decoders: [115]u16,
+ is_match: [192]u16,
+ is_rep: [12]u16,
+ is_rep_g0: [12]u16,
+ is_rep_g1: [12]u16,
+ is_rep_g2: [12]u16,
+ is_rep_0long: [192]u16,
+ state: usize,
+ rep: [4]usize,
+ len_decoder: LenDecoder,
+ rep_len_decoder: LenDecoder,
+
+ pub fn init(
+ allocator: Allocator,
+ lzma_props: Properties,
+ unpacked_size: ?u64,
+ ) !DecoderState {
+ return .{
+ .lzma_props = lzma_props,
+ .unpacked_size = unpacked_size,
+ .literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (lzma_props.lc + lzma_props.lp), 0x300 }),
+ .pos_slot_decoder = .{.{}} ** 4,
+ .align_decoder = .{},
+ .pos_decoders = .{0x400} ** 115,
+ .is_match = .{0x400} ** 192,
+ .is_rep = .{0x400} ** 12,
+ .is_rep_g0 = .{0x400} ** 12,
+ .is_rep_g1 = .{0x400} ** 12,
+ .is_rep_g2 = .{0x400} ** 12,
+ .is_rep_0long = .{0x400} ** 192,
+ .state = 0,
+ .rep = .{0} ** 4,
+ .len_decoder = .{},
+ .rep_len_decoder = .{},
+ };
+ }
+
+ pub fn deinit(self: *DecoderState, allocator: Allocator) void {
+ self.literal_probs.deinit(allocator);
+ self.* = undefined;
+ }
+
+ pub fn resetState(self: *DecoderState, allocator: Allocator, new_props: Properties) !void {
+ new_props.validate();
+ if (self.lzma_props.lc + self.lzma_props.lp == new_props.lc + new_props.lp) {
+ self.literal_probs.fill(0x400);
+ } else {
+ self.literal_probs.deinit(allocator);
+ self.literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (new_props.lc + new_props.lp), 0x300 });
+ }
+
+ self.lzma_props = new_props;
+ for (self.pos_slot_decoder) |*t| t.reset();
+ self.align_decoder.reset();
+ self.pos_decoders = .{0x400} ** 115;
+ self.is_match = .{0x400} ** 192;
+ self.is_rep = .{0x400} ** 12;
+ self.is_rep_g0 = .{0x400} ** 12;
+ self.is_rep_g1 = .{0x400} ** 12;
+ self.is_rep_g2 = .{0x400} ** 12;
+ self.is_rep_0long = .{0x400} ** 192;
+ self.state = 0;
+ self.rep = .{0} ** 4;
+ self.len_decoder.reset();
+ self.rep_len_decoder.reset();
+ }
+
+ fn processNextInner(
+ self: *DecoderState,
+ allocator: Allocator,
+ reader: anytype,
+ writer: anytype,
+ buffer: anytype,
+ decoder: *RangeDecoder,
+ update: bool,
+ ) !ProcessingStatus {
+ const pos_state = buffer.len & ((@as(usize, 1) << self.lzma_props.pb) - 1);
+
+ if (!try decoder.decodeBit(
+ reader,
+ &self.is_match[(self.state << 4) + pos_state],
+ update,
+ )) {
+ const byte: u8 = try self.decodeLiteral(reader, buffer, decoder, update);
+
+ if (update) {
+ try buffer.appendLiteral(allocator, byte, writer);
+
+ self.state = if (self.state < 4)
+ 0
+ else if (self.state < 10)
+ self.state - 3
+ else
+ self.state - 6;
+ }
+ return .continue_;
+ }
+
+ var len: usize = undefined;
+ if (try decoder.decodeBit(reader, &self.is_rep[self.state], update)) {
+ if (!try decoder.decodeBit(reader, &self.is_rep_g0[self.state], update)) {
+ if (!try decoder.decodeBit(
+ reader,
+ &self.is_rep_0long[(self.state << 4) + pos_state],
+ update,
+ )) {
+ if (update) {
+ self.state = if (self.state < 7) 9 else 11;
+ const dist = self.rep[0] + 1;
+ try buffer.appendLz(allocator, 1, dist, writer);
+ }
+ return .continue_;
+ }
+ } else {
+ const idx: usize = if (!try decoder.decodeBit(reader, &self.is_rep_g1[self.state], update))
+ 1
+ else if (!try decoder.decodeBit(reader, &self.is_rep_g2[self.state], update))
+ 2
+ else
+ 3;
+ if (update) {
+ const dist = self.rep[idx];
+ var i = idx;
+ while (i > 0) : (i -= 1) {
+ self.rep[i] = self.rep[i - 1];
+ }
+ self.rep[0] = dist;
+ }
+ }
+
+ len = try self.rep_len_decoder.decode(reader, decoder, pos_state, update);
+
+ if (update) {
+ self.state = if (self.state < 7) 8 else 11;
+ }
+ } else {
+ if (update) {
+ self.rep[3] = self.rep[2];
+ self.rep[2] = self.rep[1];
+ self.rep[1] = self.rep[0];
+ }
+
+ len = try self.len_decoder.decode(reader, decoder, pos_state, update);
+
+ if (update) {
+ self.state = if (self.state < 7) 7 else 10;
+ }
+
+ const rep_0 = try self.decodeDistance(reader, decoder, len, update);
+
+ if (update) {
+ self.rep[0] = rep_0;
+ if (self.rep[0] == 0xFFFF_FFFF) {
+ if (decoder.isFinished()) {
+ return .finished;
+ }
+ return error.CorruptInput;
+ }
+ }
+ }
+
+ if (update) {
+ len += 2;
+
+ const dist = self.rep[0] + 1;
+ try buffer.appendLz(allocator, len, dist, writer);
+ }
+
+ return .continue_;
+ }
+
+ fn processNext(
+ self: *DecoderState,
+ allocator: Allocator,
+ reader: anytype,
+ writer: anytype,
+ buffer: anytype,
+ decoder: *RangeDecoder,
+ ) !ProcessingStatus {
+ return self.processNextInner(allocator, reader, writer, buffer, decoder, true);
+ }
+
+ pub fn process(
+ self: *DecoderState,
+ allocator: Allocator,
+ reader: anytype,
+ writer: anytype,
+ buffer: anytype,
+ decoder: *RangeDecoder,
+ ) !void {
+ while (true) {
+ if (self.unpacked_size) |unpacked_size| {
+ if (buffer.len >= unpacked_size) {
+ break;
+ }
+ } else if (decoder.isFinished()) {
+ break;
+ }
+
+ if (try self.processNext(allocator, reader, writer, buffer, decoder) == .finished) {
+ break;
+ }
+ }
+
+ if (self.unpacked_size) |len| {
+ if (len != buffer.len) {
+ return error.CorruptInput;
+ }
+ }
+ }
+
+ fn decodeLiteral(
+ self: *DecoderState,
+ reader: anytype,
+ buffer: anytype,
+ decoder: *RangeDecoder,
+ update: bool,
+ ) !u8 {
+ const def_prev_byte = 0;
+ const prev_byte = @as(usize, buffer.lastOr(def_prev_byte));
+
+ var result: usize = 1;
+ const lit_state = ((buffer.len & ((@as(usize, 1) << self.lzma_props.lp) - 1)) << self.lzma_props.lc) +
+ (prev_byte >> (8 - self.lzma_props.lc));
+ const probs = try self.literal_probs.getMut(lit_state);
+
+ if (self.state >= 7) {
+ var match_byte = @as(usize, try buffer.lastN(self.rep[0] + 1));
+
+ while (result < 0x100) {
+ const match_bit = (match_byte >> 7) & 1;
+ match_byte <<= 1;
+ const bit = @boolToInt(try decoder.decodeBit(
+ reader,
+ &probs[((@as(usize, 1) + match_bit) << 8) + result],
+ update,
+ ));
+ result = (result << 1) ^ bit;
+ if (match_bit != bit) {
+ break;
+ }
+ }
+ }
+
+ while (result < 0x100) {
+ result = (result << 1) ^ @boolToInt(try decoder.decodeBit(reader, &probs[result], update));
+ }
+
+ return @truncate(u8, result - 0x100);
+ }
+
+ fn decodeDistance(
+ self: *DecoderState,
+ reader: anytype,
+ decoder: *RangeDecoder,
+ length: usize,
+ update: bool,
+ ) !usize {
+ const len_state = if (length > 3) 3 else length;
+
+ const pos_slot = @as(usize, try self.pos_slot_decoder[len_state].parse(reader, decoder, update));
+ if (pos_slot < 4)
+ return pos_slot;
+
+ const num_direct_bits = @intCast(u5, (pos_slot >> 1) - 1);
+ var result = (2 ^ (pos_slot & 1)) << num_direct_bits;
+
+ if (pos_slot < 14) {
+ result += try decoder.parseReverseBitTree(
+ reader,
+ num_direct_bits,
+ &self.pos_decoders,
+ result - pos_slot,
+ update,
+ );
+ } else {
+ result += @as(usize, try decoder.get(reader, num_direct_bits - 4)) << 4;
+ result += try self.align_decoder.parseReverse(reader, decoder, update);
+ }
+
+ return result;
+ }
+};
+
+pub const Decoder = struct {
+ params: Params,
+ memlimit: usize,
+ state: DecoderState,
+
+ pub fn init(allocator: Allocator, params: Params, memlimit: ?usize) !Decoder {
+ return Decoder{
+ .params = params,
+ .memlimit = memlimit orelse math.maxInt(usize),
+ .state = try DecoderState.init(allocator, params.properties, params.unpacked_size),
+ };
+ }
+
+ pub fn deinit(self: *Decoder, allocator: Allocator) void {
+ self.state.deinit(allocator);
+ self.* = undefined;
+ }
+
+ pub fn decompress(
+ self: *Decoder,
+ allocator: Allocator,
+ reader: anytype,
+ writer: anytype,
+ ) !void {
+ var buffer = LzCircularBuffer.init(self.params.dict_size, self.memlimit);
+ defer buffer.deinit(allocator);
+
+ var decoder = try RangeDecoder.init(reader);
+ try self.state.process(allocator, reader, writer, &buffer, &decoder);
+ try buffer.finish(writer);
+ }
+};
lib/std/compress/lzma/lzma2_test.zig
@@ -1,27 +0,0 @@
-const std = @import("../../std.zig");
-const lzma = @import("../lzma.zig");
-
-fn testDecompress(compressed: []const u8, writer: anytype) !void {
- const allocator = std.testing.allocator;
- var stream = std.io.fixedBufferStream(compressed);
- try lzma.lzma2Decompress(allocator, stream.reader(), writer);
-}
-
-fn testDecompressEqual(expected: []const u8, compressed: []const u8) !void {
- const allocator = std.testing.allocator;
- var decomp = std.ArrayList(u8).init(allocator);
- defer decomp.deinit();
- try testDecompress(compressed, decomp.writer());
- try std.testing.expectEqualSlices(u8, expected, decomp.items);
-}
-
-fn testDecompressError(expected: anyerror, compressed: []const u8) !void {
- return std.testing.expectError(expected, testDecompress(compressed, std.io.null_writer));
-}
-
-test {
- try testDecompressEqual(
- "Hello\nWorld!\n",
- &[_]u8{ 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02, 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00 },
- );
-}
lib/std/compress/lzma/lzma_test.zig → lib/std/compress/lzma/test.zig
@@ -4,7 +4,7 @@ const lzma = @import("../lzma.zig");
fn testDecompress(compressed: []const u8, writer: anytype) !void {
const allocator = std.testing.allocator;
var stream = std.io.fixedBufferStream(compressed);
- try lzma.lzmaDecompress(allocator, stream.reader(), writer, .{});
+ try lzma.decompress(allocator, stream.reader(), writer, .{});
}
fn testDecompressEqual(expected: []const u8, compressed: []const u8) !void {
@@ -19,7 +19,7 @@ fn testDecompressError(expected: anyerror, compressed: []const u8) !void {
return std.testing.expectError(expected, testDecompress(compressed, std.io.null_writer));
}
-test "decompress empty world" {
+test "LZMA: decompress empty world" {
try testDecompressEqual(
"",
&[_]u8{
@@ -29,7 +29,7 @@ test "decompress empty world" {
);
}
-test "decompress hello world" {
+test "LZMA: decompress hello world" {
try testDecompressEqual(
"Hello world\n",
&[_]u8{
@@ -40,7 +40,7 @@ test "decompress hello world" {
);
}
-test "decompress huge dict" {
+test "LZMA: decompress huge dict" {
try testDecompressEqual(
"Hello world\n",
&[_]u8{
@@ -51,35 +51,35 @@ test "decompress huge dict" {
);
}
-test "unknown size with end of payload marker" {
+test "LZMA: unknown size with end of payload marker" {
try testDecompressEqual(
"Hello\nWorld!\n",
@embedFile("testdata/good-unknown_size-with_eopm.lzma"),
);
}
-test "known size without end of payload marker" {
+test "LZMA: known size without end of payload marker" {
try testDecompressEqual(
"Hello\nWorld!\n",
@embedFile("testdata/good-known_size-without_eopm.lzma"),
);
}
-test "known size with end of payload marker" {
+test "LZMA: known size with end of payload marker" {
try testDecompressEqual(
"Hello\nWorld!\n",
@embedFile("testdata/good-known_size-with_eopm.lzma"),
);
}
-test "too big uncompressed size in header" {
+test "LZMA: too big uncompressed size in header" {
try testDecompressError(
error.CorruptInput,
@embedFile("testdata/bad-too_big_size-with_eopm.lzma"),
);
}
-test "too small uncompressed size in header" {
+test "LZMA: too small uncompressed size in header" {
try testDecompressError(
error.CorruptInput,
@embedFile("testdata/bad-too_small_size-without_eopm-3.lzma"),
lib/std/compress/lzma/decode/lzma2.zig → lib/std/compress/lzma2/decode.zig
@@ -1,20 +1,20 @@
-const std = @import("../../../std.zig");
+const std = @import("../../std.zig");
const Allocator = std.mem.Allocator;
-const lzma = @import("lzma.zig");
-const DecoderState = lzma.DecoderState;
-const LzmaProperties = lzma.LzmaProperties;
-const LzAccumBuffer = @import("lzbuffer.zig").LzAccumBuffer;
-const RangeDecoder = @import("rangecoder.zig").RangeDecoder;
+const lzma = @import("../lzma.zig");
+const DecoderState = lzma.decode.DecoderState;
+const LzAccumBuffer = lzma.decode.lzbuffer.LzAccumBuffer;
+const Properties = lzma.decode.Properties;
+const RangeDecoder = lzma.decode.rangecoder.RangeDecoder;
-pub const Lzma2Decoder = struct {
+pub const Decoder = struct {
lzma_state: DecoderState,
- pub fn init(allocator: Allocator) !Lzma2Decoder {
- return Lzma2Decoder{
+ pub fn init(allocator: Allocator) !Decoder {
+ return Decoder{
.lzma_state = try DecoderState.init(
allocator,
- LzmaProperties{
+ Properties{
.lc = 0,
.lp = 0,
.pb = 0,
@@ -24,13 +24,13 @@ pub const Lzma2Decoder = struct {
};
}
- pub fn deinit(self: *Lzma2Decoder, allocator: Allocator) void {
+ pub fn deinit(self: *Decoder, allocator: Allocator) void {
self.lzma_state.deinit(allocator);
self.* = undefined;
}
pub fn decompress(
- self: *Lzma2Decoder,
+ self: *Decoder,
allocator: Allocator,
reader: anytype,
writer: anytype,
@@ -53,7 +53,7 @@ pub const Lzma2Decoder = struct {
}
fn parseLzma(
- self: *Lzma2Decoder,
+ self: *Decoder,
allocator: Allocator,
reader: anytype,
writer: anytype,
@@ -129,7 +129,7 @@ pub const Lzma2Decoder = struct {
return error.CorruptInput;
}
- new_props = LzmaProperties{ .lc = lc, .lp = lp, .pb = pb };
+ new_props = Properties{ .lc = lc, .lp = lp, .pb = pb };
}
try self.lzma_state.resetState(allocator, new_props);
lib/std/compress/lzma.zig
@@ -1,36 +1,21 @@
const std = @import("../std.zig");
const Allocator = std.mem.Allocator;
-const FixedBufferStream = std.io.FixedBufferStream;
pub const decode = @import("lzma/decode.zig");
-pub const LzmaParams = decode.lzma.LzmaParams;
-pub const LzmaDecoder = decode.lzma.LzmaDecoder;
-pub const Lzma2Decoder = decode.lzma2.Lzma2Decoder;
-pub fn lzmaDecompress(
+pub fn decompress(
allocator: Allocator,
reader: anytype,
writer: anytype,
options: decode.Options,
) !void {
- const params = try LzmaParams.readHeader(reader, options);
- var decoder = try LzmaDecoder.init(allocator, params, options.memlimit);
- defer decoder.deinit(allocator);
- return decoder.decompress(allocator, reader, writer);
-}
-
-pub fn lzma2Decompress(
- allocator: Allocator,
- reader: anytype,
- writer: anytype,
-) !void {
- var decoder = try Lzma2Decoder.init(allocator);
+ const params = try decode.Params.readHeader(reader, options);
+ var decoder = try decode.Decoder.init(allocator, params, options.memlimit);
defer decoder.deinit(allocator);
return decoder.decompress(allocator, reader, writer);
}
test {
- _ = @import("lzma/lzma_test.zig");
- _ = @import("lzma/lzma2_test.zig");
+ _ = @import("lzma/test.zig");
_ = @import("lzma/vec2d.zig");
}
lib/std/compress/lzma2.zig
@@ -0,0 +1,26 @@
+const std = @import("../std.zig");
+const Allocator = std.mem.Allocator;
+
+pub const decode = @import("lzma2/decode.zig");
+
+pub fn decompress(
+ allocator: Allocator,
+ reader: anytype,
+ writer: anytype,
+) !void {
+ var decoder = try decode.Decoder.init(allocator);
+ defer decoder.deinit(allocator);
+ return decoder.decompress(allocator, reader, writer);
+}
+
+test {
+ const expected = "Hello\nWorld!\n";
+ const compressed = &[_]u8{ 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x02, 0x00, 0x06, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x0A, 0x00 };
+
+ const allocator = std.testing.allocator;
+ var decomp = std.ArrayList(u8).init(allocator);
+ defer decomp.deinit();
+ var stream = std.io.fixedBufferStream(compressed);
+ try decompress(allocator, stream.reader(), decomp.writer());
+ try std.testing.expectEqualSlices(u8, expected, decomp.items);
+}
lib/std/compress.zig
@@ -3,6 +3,7 @@ const std = @import("std.zig");
pub const deflate = @import("compress/deflate.zig");
pub const gzip = @import("compress/gzip.zig");
pub const lzma = @import("compress/lzma.zig");
+pub const lzma2 = @import("compress/lzma2.zig");
pub const xz = @import("compress/xz.zig");
pub const zlib = @import("compress/zlib.zig");
@@ -40,6 +41,7 @@ test {
_ = deflate;
_ = gzip;
_ = lzma;
+ _ = lzma2;
_ = xz;
_ = zlib;
}