/* Other housekeeping constants */ #define BZIP2_IOBUF_SIZE 4096
/* This is what we know about each Huffman coding group */ struct group_data { /* We have an extra slot at the end of limit[] for a sentinel value. */ int limit[MAX_HUFCODE_BITS+1]; int base[MAX_HUFCODE_BITS]; int permute[MAX_SYMBOLS]; int minLen, maxLen;
};
/* Structure holding all the housekeeping data, including IO buffers and
memory that persists between calls to bunzip */ struct bunzip_data { /* State for interrupting output loop */ int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; /* I/O tracking data (file handles, buffers, positions, etc.) */ long (*fill)(void*, unsignedlong); long inbufCount, inbufPos /*, outbufPos*/; unsignedchar *inbuf /*,*outbuf*/; unsignedint inbufBitCount, inbufBits; /* The CRC values stored in the block header and calculated from the
data */ unsignedint crc32Table[256], headerCRC, totalCRC, writeCRC; /* Intermediate buffer and its size (in bytes) */ unsignedint *dbuf, dbufSize; /* These things are a bit too big to go on the stack */ unsignedchar selectors[32768]; /* nSelectors = 15 bits */ struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ int io_error; /* non-zero if we have IO error */ int byteCount[256]; unsignedchar symToByte[256], mtfSymbol[256];
};
/* Return the next nnn bits of input. All reads from the compressed input
are done through this function. All reads are big endian */ staticunsignedint INIT get_bits(struct bunzip_data *bd, char bits_wanted)
{ unsignedint bits = 0;
/* If we need to get more data from the byte buffer, do so. (Loopgettingonebyteatatimetoenforceendiannessandavoid
unaligned access.) */ while (bd->inbufBitCount < bits_wanted) { /* If we need to read more data from file into byte buffer, do
so */ if (bd->inbufPos == bd->inbufCount) { if (bd->io_error) return0;
bd->inbufCount = bd->fill(bd->inbuf, BZIP2_IOBUF_SIZE); if (bd->inbufCount <= 0) {
bd->io_error = RETVAL_UNEXPECTED_INPUT_EOF; return0;
}
bd->inbufPos = 0;
} /* Avoid 32-bit overflow (dump bit buffer to top of output) */ if (bd->inbufBitCount >= 24) {
bits = bd->inbufBits&((1 << bd->inbufBitCount)-1);
bits_wanted -= bd->inbufBitCount;
bits <<= bits_wanted;
bd->inbufBitCount = 0;
} /* Grab next 8 bits of input from buffer. */
bd->inbufBits = (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++];
bd->inbufBitCount += 8;
} /* Calculate result */
bd->inbufBitCount -= bits_wanted;
bits |= (bd->inbufBits >> bd->inbufBitCount)&((1 << bits_wanted)-1);
return bits;
}
/* Unpacks the next block and sets up for the inverse burrows-wheeler step. */
/* Read in header signature and CRC, then validate signature.
(last block signature means CRC is for whole file, return now) */
i = get_bits(bd, 24);
j = get_bits(bd, 24);
bd->headerCRC = get_bits(bd, 32); if ((i == 0x177245) && (j == 0x385090)) return RETVAL_LAST_BLOCK; if ((i != 0x314159) || (j != 0x265359)) return RETVAL_NOT_BZIP_DATA; /* We can add support for blockRandomised if anybody complains. Therewassomecodeforthisinbusybox1.0.0-pre3,butnobodyever
noticed that it didn't actually work. */ if (get_bits(bd, 1)) return RETVAL_OBSOLETE_INPUT;
origPtr = get_bits(bd, 24); if (origPtr >= dbufSize) return RETVAL_DATA_ERROR; /* mapping table: if some byte values are never used (encoding things likeasciitext),thecompressioncoderemovesthegapstohavefewer symbolstodealwith,andwritesasparsebitfieldindicatingwhich valueswerepresent.Wemakeatranslationtabletoconvertthe
symbols back to the corresponding bytes. */
t = get_bits(bd, 16);
symTotal = 0; for (i = 0; i < 16; i++) { if (t&(1 << (15-i))) {
k = get_bits(bd, 16); for (j = 0; j < 16; j++) if (k&(1 << (15-j)))
symToByte[symTotal++] = (16*i)+j;
}
} /* How many different Huffman coding groups does this block use? */
groupCount = get_bits(bd, 3); if (groupCount < 2 || groupCount > MAX_GROUPS) return RETVAL_DATA_ERROR; /* nSelectors: Every GROUP_SIZE many symbols we select a new Huffmancodinggroup.Readinthegroupselectorlist, whichisstoredasMTFencodedbitruns.(MTF=MoveTo Front,aseachvalueisusedit'smovedtothestartofthe
list.) */
nSelectors = get_bits(bd, 15); if (!nSelectors) return RETVAL_DATA_ERROR; for (i = 0; i < groupCount; i++)
mtfSymbol[i] = i; for (i = 0; i < nSelectors; i++) { /* Get next value */ for (j = 0; get_bits(bd, 1); j++) if (j >= groupCount) return RETVAL_DATA_ERROR; /* Decode MTF to get the next selector */
uc = mtfSymbol[j]; for (; j; j--)
mtfSymbol[j] = mtfSymbol[j-1];
mtfSymbol[0] = selectors[i] = uc;
} /* Read the Huffman coding tables for each group, which code forsymTotalliteralsymbols,plustworunsymbols(RUNA,
RUNB) */
symCount = symTotal+2; for (j = 0; j < groupCount; j++) { unsignedchar length[MAX_SYMBOLS]; unsignedshort temp[MAX_HUFCODE_BITS+1]; int minLen, maxLen, pp; /* Read Huffman code lengths for each symbol. They're storedinawaysimilartomtf;recordastarting valueforthefirstsymbol,andanoffsetfromthe previousvalueforeveryssymbolafterthat. (Subtracting1beforetheloopandthenaddingit backattheendisanoptimizationthatmakesthe testinsidetheloopsimpler:symbollength0 becomesnegative,soanunsignedinequalitycatches
it.) */
t = get_bits(bd, 5)-1; for (i = 0; i < symCount; i++) { for (;;) { if (((unsigned)t) > (MAX_HUFCODE_BITS-1)) return RETVAL_DATA_ERROR;
/* If first bit is 0, stop. Else secondbitindicateswhetherto incrementordecrementthevalue. Optimization:grab2bitsandunget
the second if the first was 0. */
k = get_bits(bd, 2); if (k < 2) {
bd->inbufBitCount++; break;
} /* Add one if second bit 1, else
* subtract 1. Avoids if/else */
t += (((k+1)&2)-1);
} /* Correct for the initial -1, to get the
* final symbol length */
length[i] = t+1;
} /* Find largest and smallest lengths in this group */
minLen = maxLen = length[0];
for (i = 1; i < symCount; i++) { if (length[i] > maxLen)
maxLen = length[i]; elseif (length[i] < minLen)
minLen = length[i];
}
/* Calculate permute[], base[], and limit[] tables from *length[]. * *permute[]isthelookuptableforconverting *Huffmancodedsymbolsintodecodedsymbols.base[] *istheamounttosubtractfromthevalueofa *Huffmansymbolofagivenlengthwhenusing *permute[]. * *limit[]indicatesthelargestnumericalvaluea *symbolwithagivennumberofbitscanhave.This *ishowtheHuffmancodescanvaryinlength:each *codewithavalue>limit[length]needsanother *bit.
*/
hufGroup = bd->groups+j;
hufGroup->minLen = minLen;
hufGroup->maxLen = maxLen; /* Note that minLen can't be smaller than 1, so we adjustthebaseandlimitarraypointerssowe're notalwayswastingthefirstentry.Wedothis
again when using them (during symbol decoding).*/
base = hufGroup->base-1;
limit = hufGroup->limit-1; /* Calculate permute[]. Concurrently, initialize
* temp[] and limit[]. */
pp = 0; for (i = minLen; i <= maxLen; i++) {
temp[i] = limit[i] = 0; for (t = 0; t < symCount; t++) if (length[t] == i)
hufGroup->permute[pp++] = t;
} /* Count symbols coded for at each bit length */ for (i = 0; i < symCount; i++)
temp[length[i]]++; /* Calculate limit[] (the largest symbol-coding value *ateachbitlength,whichis(previouslimit<< *1)+symbolsatthislevel),andbase[](numberof *symbolstoignoreateachbitlength,whichislimit *minusthecumulativecountofsymbolscodedfor
*already). */
pp = t = 0; for (i = minLen; i < maxLen; i++) {
pp += temp[i]; /* We read the largest possible symbol size andthenungetbitsafterdetermininghow manyweneed,andthoseextrabitscouldbe settoanything.(They'renoisefrom futuresymbols.)Ateachlevelwe're reallyonlyinterestedinthefirstfew bits,soherewesetallthetrailing to-be-ignoredbitsto1sotheydon't affectthevalue>limit[length]
comparison. */
limit[i] = (pp << (maxLen - i)) - 1;
pp <<= 1;
base[i+1] = pp-(t += temp[i]);
}
limit[maxLen+1] = INT_MAX; /* Sentinel value for
* reading next sym. */
limit[maxLen] = pp+temp[maxLen]-1;
base[minLen] = 0;
} /* We've finished reading and digesting the block header. Now readthisblock'sHuffmancodedsymbolsfromthefileand undotheHuffmancodingandrunlengthencoding,savingthe
result into dbuf[dbufCount++] = uc */
/* Initialize symbol occurrence counters and symbol Move To
* Front table */ for (i = 0; i < 256; i++) {
byteCount[i] = 0;
mtfSymbol[i] = (unsignedchar)i;
} /* Loop through compressed symbols. */
runPos = dbufCount = symCount = selector = 0; for (;;) { /* Determine which Huffman coding group to use. */ if (!(symCount--)) {
symCount = GROUP_SIZE-1; if (selector >= nSelectors) return RETVAL_DATA_ERROR;
hufGroup = bd->groups+selectors[selector++];
base = hufGroup->base-1;
limit = hufGroup->limit-1;
} /* Read next Huffman-coded symbol. */ /* Note: It is far cheaper to read maxLen bits and backupthanitistoreadminLenbitsandthenan additionalbitatatime,testingaswego. Becausethereisatrailinglastblock(withfile CRC),thereisnodangeroftheoverreadcausingan unexpectedEOFforavalidcompressedfile.Asa furtheroptimization,wedothereadinline (fallingbacktoacalltoget_bitsifthebuffer runsdry).Thefollowing(uptogot_huff_bits:)is equivalenttoj=get_bits(bd,hufGroup->maxLen);
*/ while (bd->inbufBitCount < hufGroup->maxLen) { if (bd->inbufPos == bd->inbufCount) {
j = get_bits(bd, hufGroup->maxLen); goto got_huff_bits;
}
bd->inbufBits =
(bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++];
bd->inbufBitCount += 8;
}
bd->inbufBitCount -= hufGroup->maxLen;
j = (bd->inbufBits >> bd->inbufBitCount)&
((1 << hufGroup->maxLen)-1);
got_huff_bits: /* Figure how many bits are in next symbol and
* unget extras */
i = hufGroup->minLen; while (j > limit[i])
++i;
bd->inbufBitCount += (hufGroup->maxLen - i); /* Huffman decode value to get nextSym (with bounds checking) */ if ((i > hufGroup->maxLen)
|| (((unsigned)(j = (j>>(hufGroup->maxLen-i))-base[i]))
>= MAX_SYMBOLS)) return RETVAL_DATA_ERROR;
nextSym = hufGroup->permute[j]; /* We have now decoded the symbol, which indicates eitheranewliteralbyte,orarepeatedrunofthe mostrecentliteralbyte.First,checkifnextSym indicatesarepeatedrun,andifsoloopcollecting
how many times to repeat the last literal. */ if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */ /* If this is the start of a new run, zero out
* counter */ if (!runPos) {
runPos = 1;
t = 0;
} /* Neat trick that saves 1 symbol: instead of or-ing0or1ateachbitposition,add1 or2instead.Forexample,1011is1<<0 +1<<1+2<<2.1010is2<<0+2<<1 +1<<2.Youcanmakeanybitpattern thatwayusing1lesssymbolthanthebasic or0/1method(exceptallbits0,which wouldusenosymbols,butarunoflength0 doesn'tmeananythinginthiscontext).
Thus space is saved. */
t += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */
runPos <<= 1; continue;
} /* When we hit the first non-run symbol after a run, wenowknowhowmanytimestorepeatthelast literal,soappendthatmanycopiestoourbuffer ofdecodedsymbols(dbuf)now.(Thelastliteral usedistheoneattheheadofthemtfSymbol
array.) */ if (runPos) {
runPos = 0; if (dbufCount+t >= dbufSize) return RETVAL_DATA_ERROR;
uc = symToByte[mtfSymbol[0]];
byteCount[uc] += t; while (t--)
dbuf[dbufCount++] = uc;
} /* Is this the terminating symbol? */ if (nextSym > symTotal) break; /* At this point, nextSym indicates a new literal character.Subtractonetogetthepositioninthe MTFarrayatwhichthisliteraliscurrentlytobe found.(Notethattheresultcan'tbe-1or0, because0and1areRUNAandRUNB.Butanother instanceofthefirstsymbolinthemtfarray, position0,wouldhavebeenhandledaspartofa runabove.Therefore1unusedmtfpositionminus2
non-literal nextSym values equals -1.) */ if (dbufCount >= dbufSize) return RETVAL_DATA_ERROR;
i = nextSym - 1;
uc = mtfSymbol[i]; /* Adjust the MTF array. Since we typically expect to *moveonlyasmallnumberofsymbols,andarebound *by256inanycase,usingmemmoveherewould *typicallybebiggerandslowerduetofunctioncall
*overhead and other assorted setup costs. */ do {
mtfSymbol[i] = mtfSymbol[i-1];
} while (--i);
mtfSymbol[0] = uc;
uc = symToByte[uc]; /* We have our literal byte. Save it into dbuf. */
byteCount[uc]++;
dbuf[dbufCount++] = (unsignedint)uc;
} /* At this point, we've read all the Huffman-coded symbols (andrepeatedruns)forthisblockfromtheinputstream, anddecodedthemintotheintermediatebuffer.Thereare dbufCountmanydecodedbytesindbuf[].Nowundothe Burrows-Wheelertransformondbuf.See http://dogma.net/markn/articles/bwt/bwt.htm
*/ /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
j = 0; for (i = 0; i < 256; i++) {
k = j+byteCount[i];
byteCount[i] = j;
j = k;
} /* Figure out what order dbuf would be in if we sorted it. */ for (i = 0; i < dbufCount; i++) {
uc = (unsignedchar)(dbuf[i] & 0xff);
dbuf[byteCount[uc]] |= (i << 8);
byteCount[uc]++;
} /* Decode first byte by hand to initialize "previous" byte. Notethatitdoesn'tgetoutput,andifthefirstthree charactersareidenticalitdoesn'tqualifyasarun(hence
writeRunCountdown = 5). */ if (dbufCount) { if (origPtr >= dbufCount) return RETVAL_DATA_ERROR;
bd->writePos = dbuf[origPtr];
bd->writeCurrent = (unsignedchar)(bd->writePos&0xff);
bd->writePos >>= 8;
bd->writeRunCountdown = 5;
}
bd->writeCount = dbufCount;
return RETVAL_OK;
}
/* Undo burrows-wheeler transform on intermediate buffer to produce output. Ifstart_bunzipwasinitializedwithout_fd=-1,thenuptolenbytesof dataarewrittentooutbuf.Returnvalueisnumberofbyteswrittenor error(allerrorsarenegativenumbers).Ifout_fd!=-1,outbufandlen areignored,dataiswrittentoout_fdandreturnisRETVAL_OKorerror.
*/
staticint INIT read_bunzip(struct bunzip_data *bd, char *outbuf, int len)
{ constunsignedint *dbuf; int pos, xcurrent, previous, gotcount;
/* If last read was short due to end of file, return last block now */ if (bd->writeCount < 0) return bd->writeCount;
/* We will always have pending decoded data to write into the output bufferunlessthisistheveryfirstcall(inwhichcasewehaven't
Huffman-decoded a block into the intermediate buffer yet). */
if (bd->writeCopies) { /* Inside the loop, writeCopies means extra copies (beyond 1) */
--bd->writeCopies; /* Loop outputting bytes */ for (;;) { /* If the output buffer is full, snapshot
* state and return */ if (gotcount >= len) {
bd->writePos = pos;
bd->writeCurrent = xcurrent;
bd->writeCopies++; return len;
} /* Write next byte into output buffer, updating CRC */
outbuf[gotcount++] = xcurrent;
bd->writeCRC = (((bd->writeCRC) << 8)
^bd->crc32Table[((bd->writeCRC) >> 24)
^xcurrent]); /* Loop now if we're outputting multiple
* copies of this byte */ if (bd->writeCopies) {
--bd->writeCopies; continue;
}
decode_next_byte: if (!bd->writeCount--) break; /* Follow sequence vector to undo
* Burrows-Wheeler transform */
previous = xcurrent;
pos = dbuf[pos];
xcurrent = pos&0xff;
pos >>= 8; /* After 3 consecutive copies of the same byte,the4thisarepeatcount.Wecount downfrom4instead*ofcountingupbecause
testing for non-zero is faster */ if (--bd->writeRunCountdown) { if (xcurrent != previous)
bd->writeRunCountdown = 4;
} else { /* We have a repeated run, this byte
* indicates the count */
bd->writeCopies = xcurrent;
xcurrent = previous;
bd->writeRunCountdown = 5; /* Sometimes there are just 3 bytes
* (run length 0) */ if (!bd->writeCopies) goto decode_next_byte; /* Subtract the 1 copy we'd output
* anyway to get extras */
--bd->writeCopies;
}
} /* Decompression of this block completed successfully */
bd->writeCRC = ~bd->writeCRC;
bd->totalCRC = ((bd->totalCRC << 1) |
(bd->totalCRC >> 31)) ^ bd->writeCRC; /* If this block had a CRC error, force file level CRC error. */ if (bd->writeCRC != bd->headerCRC) {
bd->totalCRC = bd->headerCRC+1; return RETVAL_LAST_BLOCK;
}
}
/* Refill the intermediate buffer by Huffman-decoding next
* block of input */ /* (previous is just a convenient unused temp variable here) */
previous = get_next_block(bd); if (previous) {
bd->writeCount = previous; return (previous != RETVAL_LAST_BLOCK) ? previous : gotcount;
}
bd->writeCRC = 0xffffffffUL;
pos = bd->writePos;
xcurrent = bd->writeCurrent; goto decode_next_byte;
}
/* Init the CRC32 table (big endian) */ for (i = 0; i < 256; i++) {
c = i << 24; for (j = 8; j; j--)
c = c&0x80000000 ? (c << 1)^(CRC32_POLY_BE) : (c << 1);
bd->crc32Table[i] = c;
}
/* Ensure that file starts with "BZh['1'-'9']." */
i = get_bits(bd, 32); if (((unsignedint)(i-BZh0-1)) >= 9) return RETVAL_NOT_BZIP_DATA;
/* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
uncompressed data. Allocate intermediate buffer for block. */
bd->dbufSize = 100000*(i-BZh0);
/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip2 data,
not end of file.) */ STATICint INIT bunzip2(unsignedchar *buf, long len, long (*fill)(void*, unsignedlong), long (*flush)(void*, unsignedlong), unsignedchar *outbuf, long *pos, void(*error)(char *x))
{ struct bunzip_data *bd; int i = -1; unsignedchar *inbuf;
if (flush)
outbuf = malloc(BZIP2_IOBUF_SIZE);
if (!outbuf) {
error("Could not allocate output buffer"); return RETVAL_OUT_OF_MEMORY;
} if (buf)
inbuf = buf; else
inbuf = malloc(BZIP2_IOBUF_SIZE); if (!inbuf) {
error("Could not allocate input buffer");
i = RETVAL_OUT_OF_MEMORY; goto exit_0;
}
i = start_bunzip(&bd, inbuf, len, fill); if (!i) { for (;;) {
i = read_bunzip(bd, outbuf, BZIP2_IOBUF_SIZE); if (i <= 0) break; if (!flush)
outbuf += i; else if (i != flush(outbuf, i)) {
i = RETVAL_UNEXPECTED_OUTPUT_EOF; break;
}
}
} /* Check CRC and release memory */ if (i == RETVAL_LAST_BLOCK) { if (bd->headerCRC != bd->totalCRC)
error("Data integrity error when decompressing."); else
i = RETVAL_OK;
} elseif (i == RETVAL_UNEXPECTED_OUTPUT_EOF) {
error("Compressed file ends unexpectedly");
} if (!bd) goto exit_1; if (bd->dbuf)
large_free(bd->dbuf); if (pos)
*pos = bd->inbufPos;
free(bd);
exit_1: if (!buf)
free(inbuf);
exit_0: if (flush)
free(outbuf); return i;
}
#ifdef PREBOOT STATICint INIT __decompress(unsignedchar *buf, long len, long (*fill)(void*, unsignedlong), long (*flush)(void*, unsignedlong), unsignedchar *outbuf, long olen, long *pos, void (*error)(char *x))
{ return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error);
} #endif
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet am 2026-09-28)
¤
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.