From: Dougall Johnson Date: Sun, 25 Jan 2026 18:34:14 +0000 (-0800) Subject: Combine Huffman code and extra bits into single shift operation X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dc030d289c550f2f32aac0cce2663cf677aa335c;p=thirdparty%2Fzlib-ng.git Combine Huffman code and extra bits into single shift operation This changes the "code" structure so that "bits" contains the total number of bits, and "op & 15" contains the non-extra bit count. Based on https://github.com/dougallj/zlib-dougallj/commit/34b9fc457b5247d7d2d732e6f28c9a80ff16abd7 Co-authored-by: Nathan Moinvaziri --- diff --git a/infback.c b/infback.c index c4ace46c1..2dc15458d 100644 --- a/infback.c +++ b/infback.c @@ -374,21 +374,23 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; - if (here.bits <= bits) + if (CODE_BITS(here) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { + unsigned last_bits; last = here; + last_bits = CODE_BITS(last); for (;;) { - here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)last.bits + (unsigned)here.bits <= bits) + here = state->lencode[last.val + (BITS(last_bits + (last.op & 15)) >> last_bits)]; + if (last_bits + CODE_BITS(here) <= bits) break; PULLBYTE(); } - DROPBITS(last.bits); + DROPBITS(last_bits); } - DROPBITS(here.bits); + DROPBITS(CODE_BITS(here)); state->length = here.val; /* process literal */ @@ -415,7 +417,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in } /* length code -- get extra bits, if any */ - state->extra = (here.op & MAX_BITS); + state->extra = CODE_EXTRA(here); if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); @@ -426,27 +428,29 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in /* get distance code */ for (;;) { here = state->distcode[BITS(state->distbits)]; - if (here.bits <= bits) + if (CODE_BITS(here) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { + unsigned last_bits; last = here; + last_bits = CODE_BITS(last); for (;;) { - here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)last.bits + (unsigned)here.bits <= bits) + here = state->distcode[last.val + (BITS(last_bits + (last.op & 15)) >> last_bits)]; + if (last_bits + CODE_BITS(here) <= bits) break; PULLBYTE(); } - DROPBITS(last.bits); + DROPBITS(last_bits); } - DROPBITS(here.bits); + DROPBITS(CODE_BITS(here)); if (here.op & 64) { SET_BAD("invalid distance code"); break; } state->offset = here.val; - state->extra = (here.op & MAX_BITS); + state->extra = CODE_EXTRA(here); /* get distance extra bits, if any */ if (state->extra) { diff --git a/inffast_tpl.h b/inffast_tpl.h index aba9ca4bb..8247b833d 100644 --- a/inffast_tpl.h +++ b/inffast_tpl.h @@ -113,6 +113,7 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { unsigned char *from; /* where to copy match from */ unsigned dist; /* match distance */ unsigned extra_safe; /* copy chunks safely in all cases */ + uint64_t old; /* look-behind buffer for extra bits */ /* copy state to local variables */ state = (struct inflate_state *)strm->state; @@ -138,24 +139,20 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { window is overwritten then future matches with far distances will fail to copy correctly. */ extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + state->wbufsize); -#define REFILL() do { \ - hold |= load_64_bits(in, bits); \ - in += (63 ^ bits) >> 3; \ - bits |= 56; \ - } while (0) - /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { REFILL(); here = lcode[hold & lmask]; Z_TOUCH(here); + old = hold; DROPBITS(here.bits); if (here.op == 0) { TRACE_LITERAL(here.val); *out++ = (unsigned char)(here.val); here = lcode[hold & lmask]; Z_TOUCH(here); + old = hold; DROPBITS(here.bits); if (here.op == 0) { TRACE_LITERAL(here.val); @@ -163,6 +160,7 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { here = lcode[hold & lmask]; Z_TOUCH(here); dolen: + old = hold; DROPBITS(here.bits); if (here.op == 0) { TRACE_LITERAL(here.val); @@ -173,10 +171,7 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { } op = here.op; if (op & 16) { /* length base */ - len = here.val; - op &= MAX_BITS; /* number of extra bits */ - len += BITS(op); - DROPBITS(op); + len = here.val + EXTRA_BITS(old, here, op); TRACE_LENGTH(len); here = dcode[hold & dmask]; Z_TOUCH(here); @@ -184,19 +179,17 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { REFILL(); } dodist: + old = hold; DROPBITS(here.bits); op = here.op; if (op & 16) { /* distance base */ - dist = here.val; - op &= MAX_BITS; /* number of extra bits */ - dist += BITS(op); + dist = here.val + EXTRA_BITS(old, here, op); #ifdef INFLATE_STRICT if (dist > state->dmax) { SET_BAD("invalid distance too far back"); break; } #endif - DROPBITS(op); TRACE_DISTANCE(dist); op = (unsigned)(out - beg); /* max distance in output */ if (dist > op) { /* see if copy from window */ diff --git a/inffixed_tbl.h b/inffixed_tbl.h index 02b4ee687..5f8647bf5 100644 --- a/inffixed_tbl.h +++ b/inffixed_tbl.h @@ -8,87 +8,87 @@ */ static const code lenfix[512] = { - {7,96,0},{8,0,80},{8,0,16},{8,20,115},{7,18,31},{8,0,112},{8,0,48}, - {9,0,192},{7,16,10},{8,0,96},{8,0,32},{9,0,160},{8,0,0},{8,0,128}, - {8,0,64},{9,0,224},{7,16,6},{8,0,88},{8,0,24},{9,0,144},{7,19,59}, - {8,0,120},{8,0,56},{9,0,208},{7,17,17},{8,0,104},{8,0,40},{9,0,176}, - {8,0,8},{8,0,136},{8,0,72},{9,0,240},{7,16,4},{8,0,84},{8,0,20}, - {8,21,227},{7,19,43},{8,0,116},{8,0,52},{9,0,200},{7,17,13},{8,0,100}, - {8,0,36},{9,0,168},{8,0,4},{8,0,132},{8,0,68},{9,0,232},{7,16,8}, - {8,0,92},{8,0,28},{9,0,152},{7,20,83},{8,0,124},{8,0,60},{9,0,216}, - {7,18,23},{8,0,108},{8,0,44},{9,0,184},{8,0,12},{8,0,140},{8,0,76}, - {9,0,248},{7,16,3},{8,0,82},{8,0,18},{8,21,163},{7,19,35},{8,0,114}, - {8,0,50},{9,0,196},{7,17,11},{8,0,98},{8,0,34},{9,0,164},{8,0,2}, - {8,0,130},{8,0,66},{9,0,228},{7,16,7},{8,0,90},{8,0,26},{9,0,148}, - {7,20,67},{8,0,122},{8,0,58},{9,0,212},{7,18,19},{8,0,106},{8,0,42}, - {9,0,180},{8,0,10},{8,0,138},{8,0,74},{9,0,244},{7,16,5},{8,0,86}, - {8,0,22},{8,64,0},{7,19,51},{8,0,118},{8,0,54},{9,0,204},{7,17,15}, + {7,96,0},{8,0,80},{8,0,16},{12,24,115},{9,23,31},{8,0,112},{8,0,48}, + {9,0,192},{7,23,10},{8,0,96},{8,0,32},{9,0,160},{8,0,0},{8,0,128}, + {8,0,64},{9,0,224},{7,23,6},{8,0,88},{8,0,24},{9,0,144},{10,23,59}, + {8,0,120},{8,0,56},{9,0,208},{8,23,17},{8,0,104},{8,0,40},{9,0,176}, + {8,0,8},{8,0,136},{8,0,72},{9,0,240},{7,23,4},{8,0,84},{8,0,20}, + {13,24,227},{10,23,43},{8,0,116},{8,0,52},{9,0,200},{8,23,13},{8,0,100}, + {8,0,36},{9,0,168},{8,0,4},{8,0,132},{8,0,68},{9,0,232},{7,23,8}, + {8,0,92},{8,0,28},{9,0,152},{11,23,83},{8,0,124},{8,0,60},{9,0,216}, + {9,23,23},{8,0,108},{8,0,44},{9,0,184},{8,0,12},{8,0,140},{8,0,76}, + {9,0,248},{7,23,3},{8,0,82},{8,0,18},{13,24,163},{10,23,35},{8,0,114}, + {8,0,50},{9,0,196},{8,23,11},{8,0,98},{8,0,34},{9,0,164},{8,0,2}, + {8,0,130},{8,0,66},{9,0,228},{7,23,7},{8,0,90},{8,0,26},{9,0,148}, + {11,23,67},{8,0,122},{8,0,58},{9,0,212},{9,23,19},{8,0,106},{8,0,42}, + {9,0,180},{8,0,10},{8,0,138},{8,0,74},{9,0,244},{7,23,5},{8,0,86}, + {8,0,22},{19,64,0},{10,23,51},{8,0,118},{8,0,54},{9,0,204},{8,23,15}, {8,0,102},{8,0,38},{9,0,172},{8,0,6},{8,0,134},{8,0,70},{9,0,236}, - {7,16,9},{8,0,94},{8,0,30},{9,0,156},{7,20,99},{8,0,126},{8,0,62}, - {9,0,220},{7,18,27},{8,0,110},{8,0,46},{9,0,188},{8,0,14},{8,0,142}, - {8,0,78},{9,0,252},{7,96,0},{8,0,81},{8,0,17},{8,21,131},{7,18,31}, - {8,0,113},{8,0,49},{9,0,194},{7,16,10},{8,0,97},{8,0,33},{9,0,162}, - {8,0,1},{8,0,129},{8,0,65},{9,0,226},{7,16,6},{8,0,89},{8,0,25}, - {9,0,146},{7,19,59},{8,0,121},{8,0,57},{9,0,210},{7,17,17},{8,0,105}, - {8,0,41},{9,0,178},{8,0,9},{8,0,137},{8,0,73},{9,0,242},{7,16,4}, - {8,0,85},{8,0,21},{8,16,258},{7,19,43},{8,0,117},{8,0,53},{9,0,202}, - {7,17,13},{8,0,101},{8,0,37},{9,0,170},{8,0,5},{8,0,133},{8,0,69}, - {9,0,234},{7,16,8},{8,0,93},{8,0,29},{9,0,154},{7,20,83},{8,0,125}, - {8,0,61},{9,0,218},{7,18,23},{8,0,109},{8,0,45},{9,0,186},{8,0,13}, - {8,0,141},{8,0,77},{9,0,250},{7,16,3},{8,0,83},{8,0,19},{8,21,195}, - {7,19,35},{8,0,115},{8,0,51},{9,0,198},{7,17,11},{8,0,99},{8,0,35}, - {9,0,166},{8,0,3},{8,0,131},{8,0,67},{9,0,230},{7,16,7},{8,0,91}, - {8,0,27},{9,0,150},{7,20,67},{8,0,123},{8,0,59},{9,0,214},{7,18,19}, + {7,23,9},{8,0,94},{8,0,30},{9,0,156},{11,23,99},{8,0,126},{8,0,62}, + {9,0,220},{9,23,27},{8,0,110},{8,0,46},{9,0,188},{8,0,14},{8,0,142}, + {8,0,78},{9,0,252},{7,96,0},{8,0,81},{8,0,17},{13,24,131},{9,23,31}, + {8,0,113},{8,0,49},{9,0,194},{7,23,10},{8,0,97},{8,0,33},{9,0,162}, + {8,0,1},{8,0,129},{8,0,65},{9,0,226},{7,23,6},{8,0,89},{8,0,25}, + {9,0,146},{10,23,59},{8,0,121},{8,0,57},{9,0,210},{8,23,17},{8,0,105}, + {8,0,41},{9,0,178},{8,0,9},{8,0,137},{8,0,73},{9,0,242},{7,23,4}, + {8,0,85},{8,0,21},{8,24,258},{10,23,43},{8,0,117},{8,0,53},{9,0,202}, + {8,23,13},{8,0,101},{8,0,37},{9,0,170},{8,0,5},{8,0,133},{8,0,69}, + {9,0,234},{7,23,8},{8,0,93},{8,0,29},{9,0,154},{11,23,83},{8,0,125}, + {8,0,61},{9,0,218},{9,23,23},{8,0,109},{8,0,45},{9,0,186},{8,0,13}, + {8,0,141},{8,0,77},{9,0,250},{7,23,3},{8,0,83},{8,0,19},{13,24,195}, + {10,23,35},{8,0,115},{8,0,51},{9,0,198},{8,23,11},{8,0,99},{8,0,35}, + {9,0,166},{8,0,3},{8,0,131},{8,0,67},{9,0,230},{7,23,7},{8,0,91}, + {8,0,27},{9,0,150},{11,23,67},{8,0,123},{8,0,59},{9,0,214},{9,23,19}, {8,0,107},{8,0,43},{9,0,182},{8,0,11},{8,0,139},{8,0,75},{9,0,246}, - {7,16,5},{8,0,87},{8,0,23},{8,64,0},{7,19,51},{8,0,119},{8,0,55}, - {9,0,206},{7,17,15},{8,0,103},{8,0,39},{9,0,174},{8,0,7},{8,0,135}, - {8,0,71},{9,0,238},{7,16,9},{8,0,95},{8,0,31},{9,0,158},{7,20,99}, - {8,0,127},{8,0,63},{9,0,222},{7,18,27},{8,0,111},{8,0,47},{9,0,190}, + {7,23,5},{8,0,87},{8,0,23},{21,64,0},{10,23,51},{8,0,119},{8,0,55}, + {9,0,206},{8,23,15},{8,0,103},{8,0,39},{9,0,174},{8,0,7},{8,0,135}, + {8,0,71},{9,0,238},{7,23,9},{8,0,95},{8,0,31},{9,0,158},{11,23,99}, + {8,0,127},{8,0,63},{9,0,222},{9,23,27},{8,0,111},{8,0,47},{9,0,190}, {8,0,15},{8,0,143},{8,0,79},{9,0,254},{7,96,0},{8,0,80},{8,0,16}, - {8,20,115},{7,18,31},{8,0,112},{8,0,48},{9,0,193},{7,16,10},{8,0,96}, - {8,0,32},{9,0,161},{8,0,0},{8,0,128},{8,0,64},{9,0,225},{7,16,6}, - {8,0,88},{8,0,24},{9,0,145},{7,19,59},{8,0,120},{8,0,56},{9,0,209}, - {7,17,17},{8,0,104},{8,0,40},{9,0,177},{8,0,8},{8,0,136},{8,0,72}, - {9,0,241},{7,16,4},{8,0,84},{8,0,20},{8,21,227},{7,19,43},{8,0,116}, - {8,0,52},{9,0,201},{7,17,13},{8,0,100},{8,0,36},{9,0,169},{8,0,4}, - {8,0,132},{8,0,68},{9,0,233},{7,16,8},{8,0,92},{8,0,28},{9,0,153}, - {7,20,83},{8,0,124},{8,0,60},{9,0,217},{7,18,23},{8,0,108},{8,0,44}, - {9,0,185},{8,0,12},{8,0,140},{8,0,76},{9,0,249},{7,16,3},{8,0,82}, - {8,0,18},{8,21,163},{7,19,35},{8,0,114},{8,0,50},{9,0,197},{7,17,11}, + {12,24,115},{9,23,31},{8,0,112},{8,0,48},{9,0,193},{7,23,10},{8,0,96}, + {8,0,32},{9,0,161},{8,0,0},{8,0,128},{8,0,64},{9,0,225},{7,23,6}, + {8,0,88},{8,0,24},{9,0,145},{10,23,59},{8,0,120},{8,0,56},{9,0,209}, + {8,23,17},{8,0,104},{8,0,40},{9,0,177},{8,0,8},{8,0,136},{8,0,72}, + {9,0,241},{7,23,4},{8,0,84},{8,0,20},{13,24,227},{10,23,43},{8,0,116}, + {8,0,52},{9,0,201},{8,23,13},{8,0,100},{8,0,36},{9,0,169},{8,0,4}, + {8,0,132},{8,0,68},{9,0,233},{7,23,8},{8,0,92},{8,0,28},{9,0,153}, + {11,23,83},{8,0,124},{8,0,60},{9,0,217},{9,23,23},{8,0,108},{8,0,44}, + {9,0,185},{8,0,12},{8,0,140},{8,0,76},{9,0,249},{7,23,3},{8,0,82}, + {8,0,18},{13,24,163},{10,23,35},{8,0,114},{8,0,50},{9,0,197},{8,23,11}, {8,0,98},{8,0,34},{9,0,165},{8,0,2},{8,0,130},{8,0,66},{9,0,229}, - {7,16,7},{8,0,90},{8,0,26},{9,0,149},{7,20,67},{8,0,122},{8,0,58}, - {9,0,213},{7,18,19},{8,0,106},{8,0,42},{9,0,181},{8,0,10},{8,0,138}, - {8,0,74},{9,0,245},{7,16,5},{8,0,86},{8,0,22},{8,64,0},{7,19,51}, - {8,0,118},{8,0,54},{9,0,205},{7,17,15},{8,0,102},{8,0,38},{9,0,173}, - {8,0,6},{8,0,134},{8,0,70},{9,0,237},{7,16,9},{8,0,94},{8,0,30}, - {9,0,157},{7,20,99},{8,0,126},{8,0,62},{9,0,221},{7,18,27},{8,0,110}, + {7,23,7},{8,0,90},{8,0,26},{9,0,149},{11,23,67},{8,0,122},{8,0,58}, + {9,0,213},{9,23,19},{8,0,106},{8,0,42},{9,0,181},{8,0,10},{8,0,138}, + {8,0,74},{9,0,245},{7,23,5},{8,0,86},{8,0,22},{19,64,0},{10,23,51}, + {8,0,118},{8,0,54},{9,0,205},{8,23,15},{8,0,102},{8,0,38},{9,0,173}, + {8,0,6},{8,0,134},{8,0,70},{9,0,237},{7,23,9},{8,0,94},{8,0,30}, + {9,0,157},{11,23,99},{8,0,126},{8,0,62},{9,0,221},{9,23,27},{8,0,110}, {8,0,46},{9,0,189},{8,0,14},{8,0,142},{8,0,78},{9,0,253},{7,96,0}, - {8,0,81},{8,0,17},{8,21,131},{7,18,31},{8,0,113},{8,0,49},{9,0,195}, - {7,16,10},{8,0,97},{8,0,33},{9,0,163},{8,0,1},{8,0,129},{8,0,65}, - {9,0,227},{7,16,6},{8,0,89},{8,0,25},{9,0,147},{7,19,59},{8,0,121}, - {8,0,57},{9,0,211},{7,17,17},{8,0,105},{8,0,41},{9,0,179},{8,0,9}, - {8,0,137},{8,0,73},{9,0,243},{7,16,4},{8,0,85},{8,0,21},{8,16,258}, - {7,19,43},{8,0,117},{8,0,53},{9,0,203},{7,17,13},{8,0,101},{8,0,37}, - {9,0,171},{8,0,5},{8,0,133},{8,0,69},{9,0,235},{7,16,8},{8,0,93}, - {8,0,29},{9,0,155},{7,20,83},{8,0,125},{8,0,61},{9,0,219},{7,18,23}, + {8,0,81},{8,0,17},{13,24,131},{9,23,31},{8,0,113},{8,0,49},{9,0,195}, + {7,23,10},{8,0,97},{8,0,33},{9,0,163},{8,0,1},{8,0,129},{8,0,65}, + {9,0,227},{7,23,6},{8,0,89},{8,0,25},{9,0,147},{10,23,59},{8,0,121}, + {8,0,57},{9,0,211},{8,23,17},{8,0,105},{8,0,41},{9,0,179},{8,0,9}, + {8,0,137},{8,0,73},{9,0,243},{7,23,4},{8,0,85},{8,0,21},{8,24,258}, + {10,23,43},{8,0,117},{8,0,53},{9,0,203},{8,23,13},{8,0,101},{8,0,37}, + {9,0,171},{8,0,5},{8,0,133},{8,0,69},{9,0,235},{7,23,8},{8,0,93}, + {8,0,29},{9,0,155},{11,23,83},{8,0,125},{8,0,61},{9,0,219},{9,23,23}, {8,0,109},{8,0,45},{9,0,187},{8,0,13},{8,0,141},{8,0,77},{9,0,251}, - {7,16,3},{8,0,83},{8,0,19},{8,21,195},{7,19,35},{8,0,115},{8,0,51}, - {9,0,199},{7,17,11},{8,0,99},{8,0,35},{9,0,167},{8,0,3},{8,0,131}, - {8,0,67},{9,0,231},{7,16,7},{8,0,91},{8,0,27},{9,0,151},{7,20,67}, - {8,0,123},{8,0,59},{9,0,215},{7,18,19},{8,0,107},{8,0,43},{9,0,183}, - {8,0,11},{8,0,139},{8,0,75},{9,0,247},{7,16,5},{8,0,87},{8,0,23}, - {8,64,0},{7,19,51},{8,0,119},{8,0,55},{9,0,207},{7,17,15},{8,0,103}, - {8,0,39},{9,0,175},{8,0,7},{8,0,135},{8,0,71},{9,0,239},{7,16,9}, - {8,0,95},{8,0,31},{9,0,159},{7,20,99},{8,0,127},{8,0,63},{9,0,223}, - {7,18,27},{8,0,111},{8,0,47},{9,0,191},{8,0,15},{8,0,143},{8,0,79}, + {7,23,3},{8,0,83},{8,0,19},{13,24,195},{10,23,35},{8,0,115},{8,0,51}, + {9,0,199},{8,23,11},{8,0,99},{8,0,35},{9,0,167},{8,0,3},{8,0,131}, + {8,0,67},{9,0,231},{7,23,7},{8,0,91},{8,0,27},{9,0,151},{11,23,67}, + {8,0,123},{8,0,59},{9,0,215},{9,23,19},{8,0,107},{8,0,43},{9,0,183}, + {8,0,11},{8,0,139},{8,0,75},{9,0,247},{7,23,5},{8,0,87},{8,0,23}, + {21,64,0},{10,23,51},{8,0,119},{8,0,55},{9,0,207},{8,23,15},{8,0,103}, + {8,0,39},{9,0,175},{8,0,7},{8,0,135},{8,0,71},{9,0,239},{7,23,9}, + {8,0,95},{8,0,31},{9,0,159},{11,23,99},{8,0,127},{8,0,63},{9,0,223}, + {9,23,27},{8,0,111},{8,0,47},{9,0,191},{8,0,15},{8,0,143},{8,0,79}, {9,0,255} }; static const code distfix[32] = { - {5,16,1},{5,23,257},{5,19,17},{5,27,4097},{5,17,5},{5,25,1025}, - {5,21,65},{5,29,16385},{5,16,3},{5,24,513},{5,20,33},{5,28,8193}, - {5,18,9},{5,26,2049},{5,22,129},{5,64,0},{5,16,2},{5,23,385}, - {5,19,25},{5,27,6145},{5,17,7},{5,25,1537},{5,21,97},{5,29,24577}, - {5,16,4},{5,24,769},{5,20,49},{5,28,12289},{5,18,13},{5,26,3073}, - {5,22,193},{5,64,0} + {5,21,1},{12,21,257},{8,21,17},{16,21,4097},{6,21,5},{14,21,1025}, + {10,21,65},{18,21,16385},{5,21,3},{13,21,513},{9,21,33},{17,21,8193}, + {7,21,9},{15,21,2049},{11,21,129},{5,64,0},{5,21,2},{12,21,385}, + {8,21,25},{16,21,6145},{6,21,7},{14,21,1537},{10,21,97},{18,21,24577}, + {5,21,4},{13,21,769},{9,21,49},{17,21,12289},{7,21,13},{15,21,3073}, + {11,21,193},{5,64,0} }; diff --git a/inflate.c b/inflate.c index 3de5c7fd3..426386ba2 100644 --- a/inflate.c +++ b/inflate.c @@ -485,6 +485,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ + unsigned code_bits; /* bits in current/parent code */ int32_t ret; /* return code */ static const uint16_t order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; @@ -936,23 +937,26 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; - if (here.bits <= bits) + if (CODE_BITS(here) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { + unsigned last_bits; last = here; + last_bits = CODE_BITS(last); for (;;) { - here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)last.bits + (unsigned)here.bits <= bits) + here = state->lencode[last.val + (BITS(last_bits + (last.op & 15)) >> last_bits)]; + if (last_bits + CODE_BITS(here) <= bits) break; PULLBYTE(); } - DROPBITS(last.bits); - state->back += last.bits; + DROPBITS(last_bits); + state->back += last_bits; } - DROPBITS(here.bits); - state->back += here.bits; + code_bits = CODE_BITS(here); + DROPBITS(code_bits); + state->back += code_bits; state->length = here.val; /* process literal */ @@ -977,7 +981,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } /* length code */ - state->extra = (here.op & MAX_BITS); + state->extra = CODE_EXTRA(here); state->mode = LENEXT; Z_FALLTHROUGH; @@ -998,29 +1002,32 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* get distance code */ for (;;) { here = state->distcode[BITS(state->distbits)]; - if (here.bits <= bits) + if (CODE_BITS(here) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { + unsigned last_bits; last = here; + last_bits = CODE_BITS(last); for (;;) { - here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)last.bits + (unsigned)here.bits <= bits) + here = state->distcode[last.val + (BITS(last_bits + (last.op & 15)) >> last_bits)]; + if (last_bits + CODE_BITS(here) <= bits) break; PULLBYTE(); } - DROPBITS(last.bits); - state->back += last.bits; + DROPBITS(last_bits); + state->back += last_bits; } - DROPBITS(here.bits); - state->back += here.bits; + code_bits = CODE_BITS(here); + DROPBITS(code_bits); + state->back += code_bits; if (here.op & 64) { SET_BAD("invalid distance code"); break; } state->offset = here.val; - state->extra = (here.op & MAX_BITS); + state->extra = CODE_EXTRA(here); state->mode = DISTEXT; Z_FALLTHROUGH; diff --git a/inflate_p.h b/inflate_p.h index 6bccc6e42..5ec72ce9d 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -99,6 +99,13 @@ typedef unsigned bits_t; state->bits = bits; \ } while (0) +/* Refill to have at least 56 bits in the bit accumulator */ +#define REFILL() do { \ + hold |= load_64_bits(in, bits); \ + in += (63 ^ bits) >> 3; \ + bits |= 56; \ + } while (0) + /* Clear the input bit accumulator */ #define INITBITS() \ do { \ @@ -110,7 +117,8 @@ typedef unsigned bits_t; not enough available input to do that, then return from inflate()/inflateBack(). */ #define NEEDBITS(n) \ do { \ - while (bits < (bits_t)(n)) \ + unsigned u = (unsigned)(n); \ + while (bits < (bits_t)u) \ PULLBYTE(); \ } while (0) @@ -121,8 +129,9 @@ typedef unsigned bits_t; /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ - hold >>= (n); \ - bits -= (bits_t)(n); \ + unsigned u = (unsigned)(n); \ + hold >>= u; \ + bits -= (bits_t)u; \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ @@ -139,6 +148,34 @@ typedef unsigned bits_t; strm->msg = (char *)errmsg; \ } while (0) +/* Huffman code table entry format for length/distance codes (op & 16 set): + * bits = code_bits + extra_bits (combined for single-shift decode) + * op = 16 | code_bits + * val = base value + * + * For literals (op == 0): bits = code_bits, val = literal byte + */ + +/* Extract code size from a Huffman table entry */ +#define CODE_BITS(here) \ + ((unsigned)((here.op & 16) ? (here.op & 15) : here.bits)) + +/* Extract extra bits count from a length/distance code entry */ +#define CODE_EXTRA(here) \ + ((unsigned)((here.op & 16) ? (here.bits - (here.op & 15)) : 0)) + +/* Extract extra bits value from saved bit accumulator */ +#define EXTRA_BITS(old, here, op) \ + ((old & (((uint64_t)1 << here.bits) - 1)) >> (op & MAX_BITS)) + +/* Build combined op field: preserves extra if not len/dist, else combines with code_bits */ +#define COMBINE_OP(extra, code_bits) \ + ((unsigned char)((extra) & 16 ? (code_bits) | 16 : (extra))) + +/* Build combined bits field: code_bits + extra_bits from extra's low nibble */ +#define COMBINE_BITS(code_bits, extra) \ + ((unsigned char)((code_bits) + ((extra) & 15))) + /* Trace macros for debugging */ #define TRACE_LITERAL(val) \ Tracevv((stderr, val >= 0x20 && val < 0x7f ? \ diff --git a/inftrees.c b/inftrees.c index 63c9b75f1..5151ff459 100644 --- a/inftrees.c +++ b/inftrees.c @@ -6,6 +6,7 @@ #include "zbuild.h" #include "zutil.h" #include "inftrees.h" +#include "inflate_p.h" #include "fallback_builtins.h" #if defined(__SSE2__) @@ -291,7 +292,9 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, /* create table entry */ here.bits = (unsigned char)(len - drop); if (LIKELY(work[sym] >= match)) { - here.op = (unsigned char)(extra[work[sym] - match]); + unsigned op = extra[work[sym] - match]; + here.op = COMBINE_OP(op, here.bits); + here.bits = COMBINE_BITS(here.bits, op); here.val = base[work[sym] - match]; } else if (work[sym] + 1U < match) { here.op = (unsigned char)0; diff --git a/inftrees.h b/inftrees.h index a3d6421fe..6e38c45b2 100644 --- a/inftrees.h +++ b/inftrees.h @@ -33,7 +33,7 @@ typedef struct { /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits + 0001eeee - length or distance, eeee is the number of non-extra bits 01100000 - end of block 01000000 - invalid code */