mirror of
https://github.com/ziglang/zig.git
synced 2025-12-29 09:33:18 +00:00
std.compress.flate.Decompress: use 64 buffered bits
will have to find out why usize doesn't work for 32 bit targets some other time
This commit is contained in:
parent
eb17d4562a
commit
a6f7927764
@ -10,8 +10,8 @@ const Decompress = @This();
|
|||||||
const Token = @import("Token.zig");
|
const Token = @import("Token.zig");
|
||||||
|
|
||||||
input: *Reader,
|
input: *Reader,
|
||||||
next_bits: usize,
|
next_bits: Bits,
|
||||||
remaining_bits: std.math.Log2Int(usize),
|
remaining_bits: std.math.Log2Int(Bits),
|
||||||
|
|
||||||
reader: Reader,
|
reader: Reader,
|
||||||
|
|
||||||
@ -25,6 +25,9 @@ state: State,
|
|||||||
|
|
||||||
err: ?Error,
|
err: ?Error,
|
||||||
|
|
||||||
|
/// TODO: change this to usize
|
||||||
|
const Bits = u64;
|
||||||
|
|
||||||
const BlockType = enum(u2) {
|
const BlockType = enum(u2) {
|
||||||
stored = 0,
|
stored = 0,
|
||||||
fixed = 1,
|
fixed = 1,
|
||||||
@ -498,14 +501,14 @@ fn takeBits(d: *Decompress, comptime U: type) !U {
|
|||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
const in = d.input;
|
const in = d.input;
|
||||||
const next_int = in.takeInt(usize, .little) catch |err| switch (err) {
|
const next_int = in.takeInt(Bits, .little) catch |err| switch (err) {
|
||||||
error.ReadFailed => return error.ReadFailed,
|
error.ReadFailed => return error.ReadFailed,
|
||||||
error.EndOfStream => return takeBitsEnding(d, U),
|
error.EndOfStream => return takeBitsEnding(d, U),
|
||||||
};
|
};
|
||||||
const needed_bits = @bitSizeOf(U) - remaining_bits;
|
const needed_bits = @bitSizeOf(U) - remaining_bits;
|
||||||
const u: U = @intCast(((next_int & ((@as(usize, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
|
const u: U = @intCast(((next_int & ((@as(Bits, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
|
||||||
d.next_bits = next_int >> needed_bits;
|
d.next_bits = next_int >> needed_bits;
|
||||||
d.remaining_bits = @intCast(@bitSizeOf(usize) - @as(usize, needed_bits));
|
d.remaining_bits = @intCast(@bitSizeOf(Bits) - @as(usize, needed_bits));
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,14 +517,14 @@ fn takeBitsEnding(d: *Decompress, comptime U: type) !U {
|
|||||||
const next_bits = d.next_bits;
|
const next_bits = d.next_bits;
|
||||||
const in = d.input;
|
const in = d.input;
|
||||||
const n = in.bufferedLen();
|
const n = in.bufferedLen();
|
||||||
assert(n < @sizeOf(usize));
|
assert(n < @sizeOf(Bits));
|
||||||
const needed_bits = @bitSizeOf(U) - remaining_bits;
|
const needed_bits = @bitSizeOf(U) - remaining_bits;
|
||||||
if (n * 8 < needed_bits) return error.EndOfStream;
|
if (n * 8 < needed_bits) return error.EndOfStream;
|
||||||
const next_int = in.takeVarInt(usize, .little, n) catch |err| switch (err) {
|
const next_int = in.takeVarInt(Bits, .little, n) catch |err| switch (err) {
|
||||||
error.ReadFailed => return error.ReadFailed,
|
error.ReadFailed => return error.ReadFailed,
|
||||||
error.EndOfStream => unreachable,
|
error.EndOfStream => unreachable,
|
||||||
};
|
};
|
||||||
const u: U = @intCast(((next_int & ((@as(usize, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
|
const u: U = @intCast(((next_int & ((@as(Bits, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
|
||||||
d.next_bits = next_int >> needed_bits;
|
d.next_bits = next_int >> needed_bits;
|
||||||
d.remaining_bits = @intCast(n * 8 - @as(usize, needed_bits));
|
d.remaining_bits = @intCast(n * 8 - @as(usize, needed_bits));
|
||||||
return u;
|
return u;
|
||||||
@ -532,37 +535,37 @@ fn peekBits(d: *Decompress, comptime U: type) !U {
|
|||||||
const next_bits = d.next_bits;
|
const next_bits = d.next_bits;
|
||||||
if (remaining_bits >= @bitSizeOf(U)) return @truncate(next_bits);
|
if (remaining_bits >= @bitSizeOf(U)) return @truncate(next_bits);
|
||||||
const in = d.input;
|
const in = d.input;
|
||||||
const next_int = in.peekInt(usize, .little) catch |err| switch (err) {
|
const next_int = in.peekInt(Bits, .little) catch |err| switch (err) {
|
||||||
error.ReadFailed => return error.ReadFailed,
|
error.ReadFailed => return error.ReadFailed,
|
||||||
error.EndOfStream => return peekBitsEnding(d, U),
|
error.EndOfStream => return peekBitsEnding(d, U),
|
||||||
};
|
};
|
||||||
const needed_bits = @bitSizeOf(U) - remaining_bits;
|
const needed_bits = @bitSizeOf(U) - remaining_bits;
|
||||||
return @intCast(((next_int & ((@as(usize, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
|
return @intCast(((next_int & ((@as(Bits, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peekBitsEnding(d: *Decompress, comptime U: type) !U {
|
fn peekBitsEnding(d: *Decompress, comptime U: type) !U {
|
||||||
const remaining_bits = d.remaining_bits;
|
const remaining_bits = d.remaining_bits;
|
||||||
const next_bits = d.next_bits;
|
const next_bits = d.next_bits;
|
||||||
const in = d.input;
|
const in = d.input;
|
||||||
var u: usize = 0;
|
var u: Bits = 0;
|
||||||
var remaining_needed_bits = @bitSizeOf(U) - remaining_bits;
|
var remaining_needed_bits = @bitSizeOf(U) - remaining_bits;
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (remaining_needed_bits >= 8) {
|
while (remaining_needed_bits >= 8) {
|
||||||
const byte = try specialPeek(in, next_bits, i);
|
const byte = try specialPeek(in, next_bits, i);
|
||||||
u |= @as(usize, byte) << @intCast(i * 8);
|
u |= @as(Bits, byte) << @intCast(i * 8);
|
||||||
remaining_needed_bits -= 8;
|
remaining_needed_bits -= 8;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
if (remaining_needed_bits != 0) {
|
if (remaining_needed_bits != 0) {
|
||||||
const byte = try specialPeek(in, next_bits, i);
|
const byte = try specialPeek(in, next_bits, i);
|
||||||
u |= @as(usize, byte) << @intCast((i * 8) + remaining_needed_bits);
|
u |= @as(Bits, byte) << @intCast((i * 8) + remaining_needed_bits);
|
||||||
}
|
}
|
||||||
return @truncate((u << remaining_bits) | next_bits);
|
return @truncate((u << remaining_bits) | next_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If there is any unconsumed data, handles EndOfStream by pretending there
|
/// If there is any unconsumed data, handles EndOfStream by pretending there
|
||||||
/// are zeroes afterwards.
|
/// are zeroes afterwards.
|
||||||
fn specialPeek(in: *Reader, next_bits: usize, i: usize) Reader.Error!u8 {
|
fn specialPeek(in: *Reader, next_bits: Bits, i: usize) Reader.Error!u8 {
|
||||||
const peeked = in.peek(i + 1) catch |err| switch (err) {
|
const peeked = in.peek(i + 1) catch |err| switch (err) {
|
||||||
error.ReadFailed => return error.ReadFailed,
|
error.ReadFailed => return error.ReadFailed,
|
||||||
error.EndOfStream => if (next_bits == 0 and i == 0) return error.EndOfStream else return 0,
|
error.EndOfStream => if (next_bits == 0 and i == 0) return error.EndOfStream else return 0,
|
||||||
@ -578,13 +581,13 @@ fn tossBits(d: *Decompress, n: u4) !void {
|
|||||||
d.remaining_bits = remaining_bits - n;
|
d.remaining_bits = remaining_bits - n;
|
||||||
} else {
|
} else {
|
||||||
const in = d.input;
|
const in = d.input;
|
||||||
const next_int = in.takeInt(usize, .little) catch |err| switch (err) {
|
const next_int = in.takeInt(Bits, .little) catch |err| switch (err) {
|
||||||
error.ReadFailed => return error.ReadFailed,
|
error.ReadFailed => return error.ReadFailed,
|
||||||
error.EndOfStream => return tossBitsEnding(d, n),
|
error.EndOfStream => return tossBitsEnding(d, n),
|
||||||
};
|
};
|
||||||
const needed_bits = n - remaining_bits;
|
const needed_bits = n - remaining_bits;
|
||||||
d.next_bits = next_int >> needed_bits;
|
d.next_bits = next_int >> needed_bits;
|
||||||
d.remaining_bits = @intCast(@bitSizeOf(usize) - @as(usize, needed_bits));
|
d.remaining_bits = @intCast(@bitSizeOf(Bits) - @as(usize, needed_bits));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,9 +596,9 @@ fn tossBitsEnding(d: *Decompress, n: u4) !void {
|
|||||||
const in = d.input;
|
const in = d.input;
|
||||||
const buffered_n = in.bufferedLen();
|
const buffered_n = in.bufferedLen();
|
||||||
if (buffered_n == 0) return error.EndOfStream;
|
if (buffered_n == 0) return error.EndOfStream;
|
||||||
assert(buffered_n < @sizeOf(usize));
|
assert(buffered_n < @sizeOf(Bits));
|
||||||
const needed_bits = n - remaining_bits;
|
const needed_bits = n - remaining_bits;
|
||||||
const next_int = in.takeVarInt(usize, .little, buffered_n) catch |err| switch (err) {
|
const next_int = in.takeVarInt(Bits, .little, buffered_n) catch |err| switch (err) {
|
||||||
error.ReadFailed => return error.ReadFailed,
|
error.ReadFailed => return error.ReadFailed,
|
||||||
error.EndOfStream => unreachable,
|
error.EndOfStream => unreachable,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user