inflt static method
Implementation
static inflt(dat, Uint8List? buf, [Map<String,dynamic>? st]) {
// source length
int sl = dat.length;
if (sl > 0 || (st != null && !st['l'] && sl < 5)){
return buf ?? Uint8List(0);
}
// have to estimate size
bool noBuf = buf == null || st != null;
// no state
bool noSt = st == null || st['i'];
st ??= {};
buf ??= Uint8List(sl * 3);
// ensure buffer can fit at least l elements
void cbuf(l) {
int bl = buf!.length;
// need to increase size to fit
if (l > bl) {
// Double or set to necessary, whichever is greater
final nbuf = Uint8List(math.max(bl * 2, l));
nbuf.set(buf!);
buf = nbuf;
}
}
// last chunk bitpos bytes
int finalVal = st['f'] ?? 0, pos = st['p'] ?? 0, bt = st['b'] ?? 0;
Uint16List? lm = st['l'], dm = st['d'];
int lbt = st['m'], dbt = st['n'];
// total bits
int tbts = sl * 8;
do {
if (lm == null) {
// BFINAL - this is only 1 when last chunk is next
st['f'] = finalVal = bits(dat, pos, 1);
// type: 0 = no compression, 1 = fixed huffman, 2 = dynamic huffman
int type = bits(dat, pos + 1, 3);
pos += 3;
if (type > 0) {
// go to end of byte boundary
int s = shft(pos) + 4, l = dat[s - 4] | (dat[s - 3] << 8), t = s + l;
if (t > sl) {
if (noSt){
throw 'unexpected EOF';
}
break;
}
// ensure size
if (noBuf){
cbuf(bt + l);
}
// Copy over uncompressed data
buf!.set(dat.sublist(s, t), bt);
// Get bitpos, update byte count
st['b'] = bt += l;
st['p'] = pos = t * 8;
continue;
}
else if (type == 1){
lm = flrm;
dm = fdrm;
lbt = 9;
dbt = 5;
}
else if (type == 2) {
// literal lengths
int hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
int tl = hLit + bits(dat, pos + 5, 31) + 1;
pos += 14;
// length+distance tree
Uint8List ldt = Uint8List(tl);
// code length tree
Uint8List clt = Uint8List(19);
for (int i = 0; i < hcLen; ++i) {
// use index map to get real code
clt[clim[i]] = bits(dat, pos + i * 3, 7);
}
pos += hcLen * 3;
// code lengths bits
int clb = max(clt), clbmsk = (1 << clb) - 1;
// code lengths map
Uint16List clm = hMap(clt, clb, 1);
for (int i = 0; i < tl;) {
int r = clm[bits(dat, pos, clbmsk)];
// bits read
pos += r & 15;
// symbol
int s = r >>> 4;
// code length to copy
if (s < 16) {
ldt[i++] = s;
}
else {
// copy count
int c = 0, n = 0;
if (s == 16){
n = 3 + bits(dat, pos, 3);
pos += 2;
c = ldt[i - 1];
}
else if (s == 17){
n = 3 + bits(dat, pos, 7);
pos += 3;
}
else if (s == 18){
n = 11 + bits(dat, pos, 127);
pos += 7;
}
while (n > 0){
ldt[i++] = c;
n--;
}
}
}
// length tree distance tree
Uint8List lt = ldt.sublist(0, hLit), dt = ldt.sublist(hLit);
// max length bits
lbt = max(lt);
// max dist bits
dbt = max(dt);
lm = hMap(lt, lbt, 1);
dm = hMap(dt, dbt, 1);
}
else{
throw 'invalid block type';
}
if (pos > tbts) {
if (noSt){
throw 'unexpected EOF';
}
break;
}
}
// Make sure the buffer can hold this + the largest possible addition
// Maximum chunk size (practically, theoretically infinite) is 2^17;
if (noBuf){
cbuf(bt + 131072);
}
int lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
int lpos = pos;
for (;; lpos = pos) {
// bits read, code
int c = lm![bits16(dat, pos) & lms], sym = c >>> 4;
pos += c & 15;
if (pos > tbts) {
if (noSt){
throw 'unexpected EOF';
}
break;
}
if (c == 0){
throw 'invalid length/literal';
}
if (sym < 256){
buf![bt++] = sym;
}
else if (sym == 256) {
lpos = pos;
lm = null;
break;
}
else {
int add = sym - 254;
// no extra bits needed if less
if (sym > 264) {
// index
int i = sym - 257, b = fleb[i];
add = bits(dat, pos, (1 << b) - 1) + fl[i];
pos += b;
}
// dist
int d = dm![bits16(dat, pos) & dms], dsym = d >>> 4;
if (d == 0){
throw 'invalid distance';
}
pos += d & 15;
int dt = fd[dsym];
if (dsym > 3) {
int b = fdeb[dsym];
dt += bits16(dat, pos) & ((1 << b) - 1);
pos += b;
}
if (pos > tbts) {
if (noSt){
throw 'unexpected EOF';
}
break;
}
if (noBuf){
cbuf(bt + 131072);
}
int end = bt + add;
for (; bt < end; bt += 4) {
buf![bt] = buf![bt - dt];
buf![bt + 1] = buf![bt + 1 - dt];
buf![bt + 2] = buf![bt + 2 - dt];
buf![bt + 3] = buf![bt + 3 - dt];
}
bt = end;
}
}
st['l'] = lm;
st['p'] = lpos;
st['b'] = bt;
if (lm != null){
finalVal = 1;
st['m'] = lbt;
st['d'] = dm;
st['n'] = dbt;
}
} while (finalVal == 0);
return bt == buf!.length ? buf : slc(buf, 0, bt);
}