/// <summary> /// Initializes a new instance of the BZip2DecoderStream class. /// </summary> /// <param name="stream">The compressed input stream.</param> /// <param name="ownsStream">Whether ownership of stream passes to the new instance.</param> public BZip2DecoderStream(Stream stream, Ownership ownsStream) { _compressedStream = stream; _ownsCompressed = ownsStream; _bitstream = new BigEndianBitStream(new BufferedStream(stream)); // The Magic BZh byte[] magic = new byte[3]; magic[0] = (byte)_bitstream.Read(8); magic[1] = (byte)_bitstream.Read(8); magic[2] = (byte)_bitstream.Read(8); if (magic[0] != 0x42 || magic[1] != 0x5A || magic[2] != 0x68) { throw new InvalidDataException("Bad magic at start of stream"); } // The size of the decompression blocks in multiples of 100,000 int blockSize = (int)_bitstream.Read(8) - 0x30; if (blockSize < 1 || blockSize > 9) { throw new InvalidDataException("Unexpected block size in header: " + blockSize); } blockSize *= 100000; _rleStream = new BZip2RleStream(); _blockDecoder = new BZip2BlockDecoder(blockSize); _blockBuffer = new byte[blockSize]; if (ReadBlock() == 0) { _eof = true; } }
public int Process(BitStream bitstream, byte[] outputBuffer, int outputBufferOffset) { _crc = 0; for (int i = 0; i < 4; ++i) { _crc = (_crc << 8) | bitstream.Read(8); } bool rand = bitstream.Read(1) != 0; int origPtr = (int)bitstream.Read(24); int thisBlockSize = ReadBuffer(bitstream, outputBuffer, outputBufferOffset); _inverseBurrowsWheeler.OriginalIndex = origPtr; _inverseBurrowsWheeler.Process(outputBuffer, outputBufferOffset, thisBlockSize, outputBuffer, outputBufferOffset); if (rand) { BZip2Randomizer randomizer = new BZip2Randomizer(); randomizer.Process(outputBuffer, outputBufferOffset, thisBlockSize, outputBuffer, outputBufferOffset); } return thisBlockSize; }
public BZip2CombinedHuffmanTrees(BitStream bitstream, int maxSymbols) { _bitstream = bitstream; Initialize(maxSymbols); }
private static int ReadBuffer(BitStream bitstream, byte[] buffer, int offset) { // The MTF state int numInUse = 0; MoveToFront moveFrontTransform = new MoveToFront(); bool[] inUseGroups = new bool[16]; for (int i = 0; i < 16; ++i) { inUseGroups[i] = bitstream.Read(1) != 0; } for (int i = 0; i < 256; ++i) { if (inUseGroups[i / 16]) { if (bitstream.Read(1) != 0) { moveFrontTransform.Set(numInUse, (byte)i); numInUse++; } } } // Initialize 'virtual' Huffman tree from bitstream BZip2CombinedHuffmanTrees huffmanTree = new BZip2CombinedHuffmanTrees(bitstream, numInUse + 2); // Main loop reading data int readBytes = 0; while (true) { uint symbol = huffmanTree.NextSymbol(); if (symbol < 2) { // RLE, with length stored in a binary-style format uint runLength = 0; int bitShift = 0; while (symbol < 2) { runLength += (symbol + 1) << bitShift; bitShift++; symbol = huffmanTree.NextSymbol(); } byte b = moveFrontTransform.Head; while (runLength > 0) { buffer[offset + readBytes] = b; ++readBytes; --runLength; } } if (symbol <= numInUse) { // Single byte byte b = moveFrontTransform.GetAndMove((int)symbol - 1); buffer[offset + readBytes] = b; ++readBytes; } else if (symbol == numInUse + 1) { // End of block marker return readBytes; } else { throw new InvalidDataException("Invalid symbol from Huffman table"); } } }