#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */ #include"puff.h"/* prototype for puff() */
#define local static/* for local function definitions */
/* *Maximumsforallocationsandloops.Itisnotusefultochangethese-- *theyarefixedbythedeflateformat.
*/ #define MAXBITS 15/* maximum bits in a code */ #define MAXLCODES 286/* maximum number of literal/length codes */ #define MAXDCODES 30/* maximum number of distance codes */ #define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ #define FIXLCODES 288/* number of fixed literal/length codes */
/* input and output state */ struct state { /* output state */ unsignedchar *out; /* output buffer */ unsignedlong outlen; /* available space at out */ unsignedlong outcnt; /* bytes written to out so far */
/* input state */ constunsignedchar *in; /* input buffer */ unsignedlong inlen; /* available input at in */ unsignedlong incnt; /* bytes read so far */ int bitbuf; /* bit buffer */ int bitcnt; /* number of bits in bit buffer */
/* input limit error return state for bits() and decode() */
jmp_buf env;
};
/* *Returnneedbitsfromtheinputstream.Thisalwaysleaveslessthan *eightbitsinthebuffer.bits()worksproperlyforneed==0. * *Formatnotes: * *-Bitsarestoredinbytesfromtheleastsignificantbittothemost *significantbit.Thereforebitsaredroppedfromthebottomofthebit *buffer,usingshiftright,andnewbytesareappendedtothetopofthe *bitbuffer,usingshiftleft.
*/
local int bits(struct state *s, int need)
{ long val; /* bit accumulator (can use up to 20 bits) */
/* load at least need bits into val */
val = s->bitbuf; while (s->bitcnt < need) { if (s->incnt == s->inlen)
longjmp(s->env, 1); /* out of input */
val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */
s->bitcnt += 8;
}
/* drop need bits and update buffer, always zero to seven bits left */
s->bitbuf = (int)(val >> need);
s->bitcnt -= need;
/* return need bits, zeroing the bits above that */ return (int)(val & ((1L << need) - 1));
}
/* *Processastoredblock. * *Formatnotes: * *-Afterthetwo-bitstoredblocktype(00),thestoredblocklengthand *storedbytesarebyte-alignedforfastcopying.Thereforeanyleftover *bitsinthebytethathasthelastbitofthetype,asmanyasseven,are *discarded.Thevalueofthediscardedbitsarenotdefinedandshouldnot *becheckedagainstanyexpectation. * *-Thesecondinvertedcopyofthestoredblocklengthdoesnothavetobe *checked,butit'sprobablyagoodideatodosoanyway. * *-Astoredblockcanhavezerolength.Thisissometimesusedtobyte-align *subsetsofthecompresseddataforrandomaccessorpartialrecovery.
*/
local int stored(struct state *s)
{ unsigned len; /* length of stored block */
/* discard leftover bits from current byte (assumes s->bitcnt < 8) */
s->bitbuf = 0;
s->bitcnt = 0;
/* get length and check against its one's complement */ if (s->incnt + 4 > s->inlen) return2; /* not enough input */
len = s->in[s->incnt++];
len |= s->in[s->incnt++] << 8; if (s->in[s->incnt++] != (~len & 0xff) ||
s->in[s->incnt++] != ((~len >> 8) & 0xff)) return -2; /* didn't match complement! */
/* copy len bytes from in to out */ if (s->incnt + len > s->inlen) return2; /* not enough input */ if (s->out != NIL) { if (s->outcnt + len > s->outlen) return1; /* not enough output space */ while (len--)
s->out[s->outcnt++] = s->in[s->incnt++];
} else { /* just scanning */
s->outcnt += len;
s->incnt += len;
}
/* done with a valid stored block */ return0;
}
/* *Huffmancodedecodingtables.count[1..MAXBITS]isthenumberofsymbolsof *eachlength,whichforacanonicalcodearesteppedthroughinorder. *symbol[]arethesymbolvaluesincanonicalorder,wherethenumberof *entriesisthesumofthecountsincount[].Thedecodingprocesscanbe *seeninthefunctiondecode()below.
*/ struct huffman { short *count; /* number of symbols of each length */ short *symbol; /* canonically ordered symbols */
};
/* *Decodeacodefromthestreamsusinghuffmantableh.Returnthesymbolor *anegativevalueifthereisanerror.Ifallofthelengthsarezero,i.e. *anemptycode,orifthecodeisincompleteandaninvalidcodeisreceived, *then-10isreturnedafterreadingMAXBITSbits. * *Formatnotes: * *-Thecodesasstoredinthecompresseddataarebit-reversedrelativeto *asimpleintegerorderingofcodesofthesamelengths.Hencebelowthe *bitsarepulledfromthecompresseddataoneatatimeandusedto *buildthecodevaluereversedfromwhatisinthestreaminorderto *permitsimpleintegercomparisonsfordecoding.Atable-baseddecoding *scheme(asusedinzlib)doesnotneedtodothisreversal. * *-Thefirstcodefortheshortestlengthisallzeros.Subsequentcodesof *thesamelengtharesimplyintegerincrementsofthepreviouscode.When *movingupalength,azerobitisappendedtothecode.Foracomplete *code,thelastcodeofthelongestlengthwillbeallones. * *-Incompletecodesarehandledbythisdecoder,sincetheyarepermitted *inthedeflateformat.Seetheformatnotesforfixed()anddynamic().
*/ #ifdef SLOW
local int decode(struct state *s, conststruct huffman *h)
{ int len; /* current number of bits in code */ int code; /* len bits being decoded */ int first; /* first code of length len */ int count; /* number of codes of length len */ int index; /* index of first code of length len in symbol table */
code = first = index = 0; for (len = 1; len <= MAXBITS; len++) {
code |= bits(s, 1); /* get next bit */
count = h->count[len]; if (code - count < first) /* if length len, return symbol */ return h->symbol[index + (code - first)];
index += count; /* else update for next length */
first += count;
first <<= 1;
code <<= 1;
} return -10; /* ran out of codes */
}
/* *Afasterversionofdecode()forrealapplicationsofthiscode.It'snot *asreadable,butitmakespuff()twiceasfast.Anditonlymakesthecode *afewpercentlarger.
*/ #else/* !SLOW */
local int decode(struct state *s, conststruct huffman *h)
{ int len; /* current number of bits in code */ int code; /* len bits being decoded */ int first; /* first code of length len */ int count; /* number of codes of length len */ int index; /* index of first code of length len in symbol table */ int bitbuf; /* bits from stream */ int left; /* bits left in next or left to process */ short *next; /* next number of codes */
bitbuf = s->bitbuf;
left = s->bitcnt;
code = first = index = 0;
len = 1;
next = h->count + 1; while (1) { while (left--) {
code |= bitbuf & 1;
bitbuf >>= 1;
count = *next++; if (code - count < first) { /* if length len, return symbol */
s->bitbuf = bitbuf;
s->bitcnt = (s->bitcnt - len) & 7; return h->symbol[index + (code - first)];
}
index += count; /* else update for next length */
first += count;
first <<= 1;
code <<= 1;
len++;
}
left = (MAXBITS+1) - len; if (left == 0) break; if (s->incnt == s->inlen)
longjmp(s->env, 1); /* out of input */
bitbuf = s->in[s->incnt++]; if (left > 8)
left = 8;
} return -10; /* ran out of codes */
} #endif/* SLOW */
/* *Giventhelistofcodelengthslength[0..n-1]representingacanonical *Huffmancodefornsymbols,constructthetablesrequiredtodecodethose *codes.Thosetablesarethenumberofcodesofeachlength,andthesymbols *sortedbylength,retainingtheiroriginalorderwithineachlength.The *returnvalueiszeroforacompletecodeset,negativeforanover- *subscribedcodeset,andpositiveforanincompletecodeset.Thetables *canbeusedifthereturnvalueiszeroorpositive,buttheycannotbeused *ifthereturnvalueisnegative.Ifthereturnvalueiszero,itisnot *possiblefordecode()usingthattabletoreturnanerror--anystreamof *enoughbitswillresolvetoasymbol.Ifthereturnvalueispositive,then *itispossiblefordecode()usingthattabletoreturnanerrorforreceived *codespasttheendoftheincompletelengths. * *Notusedbydecode(),butusedforerrorchecking,h->count[0]isthenumber *ofthensymbolsnotinthecode.Son-h->count[0]isthenumberof *codes.Thisisusefulforcheckingforincompletecodesthathavemorethan *onesymbol,whichisanerrorinadynamicblock. * *Assumption:foralliin0..n-1,0<=length[i]<=MAXBITS *Thisisassuredbytheconstructionofthelengtharraysindynamic()and *fixed()andisnotverifiedbyconstruct(). * *Formatnotes: * *-Permittedandexpectedexamplesofincompletecodesareoneofthefixed *codesandanycodewithasinglesymbolwhichindeflateiscodedasone *bitinsteadofzerobits.Seetheformatnotesforfixed()anddynamic(). * *-Withinagivencodelength,thesymbolsarekeptinascendingorderfor *thecodebitsdefinition.
*/
local int construct(struct huffman *h, constshort *length, int n)
{ int symbol; /* current symbol when stepping through length[] */ int len; /* current length when stepping through h->count[] */ int left; /* number of possible codes left of current length */ short offs[MAXBITS+1]; /* offsets in symbol table for each length */
/* count number of codes of each length */ for (len = 0; len <= MAXBITS; len++)
h->count[len] = 0; for (symbol = 0; symbol < n; symbol++)
(h->count[length[symbol]])++; /* assumes lengths are within bounds */ if (h->count[0] == n) /* no codes! */ return0; /* complete, but decode() will fail */
/* check for an over-subscribed or incomplete set of lengths */
left = 1; /* one possible code of zero length */ for (len = 1; len <= MAXBITS; len++) {
left <<= 1; /* one more bit, double codes left */
left -= h->count[len]; /* deduct count from possible codes */ if (left < 0) return left; /* over-subscribed--return negative */
} /* left > 0 means incomplete */
/* generate offsets into symbol table for each length for sorting */
offs[1] = 0; for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + h->count[len];
/* *putsymbolsintablesortedbylength,bysymbolorderwithineach *length
*/ for (symbol = 0; symbol < n; symbol++) if (length[symbol] != 0)
h->symbol[offs[length[symbol]]++] = symbol;
/* return zero for complete set, positive for incomplete set */ return left;
}
/* decode literals and length/distance pairs */ do {
symbol = decode(s, lencode); if (symbol < 0) return symbol; /* invalid symbol */ if (symbol < 256) { /* literal: symbol is the byte */ /* write out the literal */ if (s->out != NIL) { if (s->outcnt == s->outlen) return1;
s->out[s->outcnt] = symbol;
}
s->outcnt++;
} elseif (symbol > 256) { /* length */ /* get and compute length */
symbol -= 257; if (symbol >= 29) return -10; /* invalid fixed code */
len = lens[symbol] + bits(s, lext[symbol]);
/* get and check distance */
symbol = decode(s, distcode); if (symbol < 0) return symbol; /* invalid symbol */
dist = dists[symbol] + bits(s, dext[symbol]); #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (dist > s->outcnt) return -11; /* distance too far back */ #endif
/* copy length bytes from distance bytes back */ if (s->out != NIL) { if (s->outcnt + len > s->outlen) return1; while (len--) {
s->out[s->outcnt] = #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
dist > s->outcnt ? 0 : #endif
s->out[s->outcnt - dist];
s->outcnt++;
}
} else
s->outcnt += len;
}
} while (symbol != 256); /* end of block symbol */
/* done with a valid fixed or dynamic block */ return0;
}
/* get number of lengths in each table, check lengths */
nlen = bits(s, 5) + 257;
ndist = bits(s, 5) + 1;
ncode = bits(s, 4) + 4; if (nlen > MAXLCODES || ndist > MAXDCODES) return -3; /* bad counts */
/* read code length code lengths (really), missing lengths are zero */ for (index = 0; index < ncode; index++)
lengths[order[index]] = bits(s, 3); for (; index < 19; index++)
lengths[order[index]] = 0;
/* build huffman table for code lengths codes (use lencode temporarily) */
err = construct(&lencode, lengths, 19); if (err != 0) /* require complete code set here */ return -4;
/* read length/literal and distance code length tables */
index = 0; while (index < nlen + ndist) { int symbol; /* decoded value */ int len; /* last length to repeat */
symbol = decode(s, &lencode); if (symbol < 0) return symbol; /* invalid symbol */ if (symbol < 16) /* length in 0..15 */
lengths[index++] = symbol; else { /* repeat instruction */
len = 0; /* assume repeating zeros */ if (symbol == 16) { /* repeat last length 3..6 times */ if (index == 0) return -5; /* no last length! */
len = lengths[index - 1]; /* last length */
symbol = 3 + bits(s, 2);
} elseif (symbol == 17) /* repeat zero 3..10 times */
symbol = 3 + bits(s, 3); else/* == 18, repeat zero 11..138 times */
symbol = 11 + bits(s, 7); if (index + symbol > nlen + ndist) return -6; /* too many lengths! */ while (symbol--) /* repeat last or zero symbol times */
lengths[index++] = len;
}
}
/* check for end-of-block code -- there better be one! */ if (lengths[256] == 0) return -9;
/* build huffman table for literal/length codes */
err = construct(&lencode, lengths, nlen); if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1])) return -7; /* incomplete code ok only for single length 1 code */
/* build huffman table for distance codes */
err = construct(&distcode, lengths + nlen, ndist); if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1])) return -8; /* incomplete code ok only for single length 1 code */
/* decode data until end-of-block code */ return codes(s, &lencode, &distcode);
}
/* *Inflatesourcetodest.Onreturn,destlenandsourcelenareupdatedtothe *sizeoftheuncompresseddataandthesizeofthedeflatedatarespectively. *Onsuccess,thereturnvalueofpuff()iszero.Ifthereisanerrorinthe *sourcedata,i.e.itisnotinthedeflateformat,thenanegativevalueis *returned.Ifthereisnotenoughinputavailableorthereisnotenough *outputspace,thenapositiveerrorisreturned.Inthatcase,destlenand *sourcelenarenotupdatedtofacilitateretryingfromthebeginningwiththe *provisionofmoreinputdataormoreoutputspace.Inthecaseofinvalid *inflatedata(anegativeerror),thedestandsourcepointersareupdatedto *facilitatethedebuggingofdeflators. * *puff()alsohasamodetodeterminethesizeoftheuncompressedoutputwith *nooutputwritten.Forthisdestmustbe(unsignedchar*)0.Inthiscase, *theinputvalueof*destlenisignored,andonreturn*destlenissettothe *sizeoftheuncompressedoutput. * *Thereturncodesare: * *2:availableinflatedatadidnotterminate *1:outputspaceexhaustedbeforecompletinginflate *0:successfulinflate *-1:invalidblocktype(type==3) *-2:storedblocklengthdidnotmatchone'scomplement *-3:dynamicblockcodedescription:toomanylengthordistancecodes *-4:dynamicblockcodedescription:codelengthscodesincomplete *-5:dynamicblockcodedescription:repeatlengthswithnofirstlength *-6:dynamicblockcodedescription:repeatmorethanspecifiedlengths *-7:dynamicblockcodedescription:invalidliteral/lengthcodelengths *-8:dynamicblockcodedescription:invaliddistancecodelengths *-9:dynamicblockcodedescription:missingend-of-blockcode *-10:invalidliteral/lengthordistancecodeinfixedordynamicblock *-11:distanceistoofarbackinfixedordynamicblock * *Formatnotes: * *-Threebitsarereadforeachblocktodeterminethekindofblockand *whetherornotitisthelastblock.Thentheblockisdecodedandthe *processrepeatedifitwasnotthelastblock. * *-Theleftoverbitsinthelastbyteofthedeflatedataafterthelast *block(ifitwasafixedordynamicblock)areundefinedandhaveno *expectedvaluestocheck.
*/ int puff(unsignedchar *dest, /* pointer to destination pointer */ unsignedlong *destlen, /* amount of output space */ constunsignedchar *source, /* pointer to source data pointer */ unsignedlong *sourcelen) /* amount of input available */
{ struct state s; /* input/output state */ int last, type; /* block information */ int err; /* return value */
/* initialize output state */
s.out = dest;
s.outlen = *destlen; /* ignored if dest is NIL */
s.outcnt = 0;
/* return if bits() or decode() tries to read past available input */ if (setjmp(s.env) != 0) /* if came back here via longjmp() */
err = 2; /* then skip do-loop, return error */ else { /* process blocks until last block or error */ do {
last = bits(&s, 1); /* one if last block */
type = bits(&s, 2); /* block type 0..3 */
err = type == 0 ?
stored(&s) :
(type == 1 ?
fixed(&s) :
(type == 2 ?
dynamic(&s) :
-1)); /* type == 3, invalid */ if (err != 0) break; /* return with error */
} while (!last);
}
/* update the lengths and return */ if (err <= 0) {
*destlen = s.outcnt;
*sourcelen = s.incnt;
} return err;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.37Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-17)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.