/// <summary> /// Copy from input manipulator to internal window /// </summary> /// <param name="input">source of data</param> /// <param name="length">length of data to copy</param> /// <returns>the number of bytes copied</returns> public int CopyStored( StreamManipulator input, int length ) { length = Math.Min( Math.Min( length, WindowSize - windowFilled ), input.AvailableBytes ); int copied; int tailLen = WindowSize - windowEnd; if( length > tailLen ) { copied = input.CopyBytes( window, windowEnd, tailLen ); if( copied == tailLen ) { copied += input.CopyBytes( window, 0, length - tailLen ); } } else { copied = input.CopyBytes( window, windowEnd, length ); } windowEnd = ( windowEnd + copied ) & WindowMask; windowFilled += copied; return copied; }
/// <summary> /// Creates a new inflater. /// </summary> /// <param name="noHeader"> /// True if no RFC1950/Zlib header and footer fields are expected in the input data /// /// This is used for GZIPed/Blubbped input. /// /// For compatibility with /// Sun JDK you should provide one byte of input more than needed in /// this case. /// </param> public Inflater( bool noHeader ) { this.noHeader = noHeader; this.adler = new Adler32(); input = new StreamManipulator(); outputWindow = new OutputWindow(); mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; }
public bool Decode( StreamManipulator input ) { decode_loop: for( ; ; ) { switch( mode ) { case LNUM: lnum = input.PeekBits( 5 ); if( lnum < 0 ) { return false; } lnum += 257; input.DropBits( 5 ); // System.err.println("LNUM: "+lnum); mode = DNUM; goto case DNUM; // fall through case DNUM: dnum = input.PeekBits( 5 ); if( dnum < 0 ) { return false; } dnum++; input.DropBits( 5 ); // System.err.println("DNUM: "+dnum); num = lnum + dnum; litdistLens = new byte[ num ]; mode = BLNUM; goto case BLNUM; // fall through case BLNUM: blnum = input.PeekBits( 4 ); if( blnum < 0 ) { return false; } blnum += 4; input.DropBits( 4 ); blLens = new byte[ 19 ]; ptr = 0; // System.err.println("BLNUM: "+blnum); mode = BLLENS; goto case BLLENS; // fall through case BLLENS: while( ptr < blnum ) { int len = input.PeekBits( 3 ); if( len < 0 ) { return false; } input.DropBits( 3 ); // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); blLens[ BL_ORDER[ ptr ] ] = (byte)len; ptr++; } blTree = new InflaterHuffmanTree( blLens ); blLens = null; ptr = 0; mode = LENS; goto case LENS; // fall through case LENS: { int symbol; while( ( ( symbol = blTree.GetSymbol( input ) ) & ~15 ) == 0 ) { /* Normal case: symbol in [0..15] */ // System.err.println("litdistLens["+ptr+"]: "+symbol); litdistLens[ ptr++ ] = lastLen = (byte)symbol; if( ptr == num ) { /* Finished */ return true; } } /* need more input ? */ if( symbol < 0 ) { return false; } /* otherwise repeat code */ if( symbol >= 17 ) { /* repeat zero */ // System.err.println("repeating zero"); lastLen = 0; } else { if( ptr == 0 ) { throw new BlubbZipBaseException(); } } repSymbol = symbol - 16; } mode = REPS; goto case REPS; // fall through case REPS: { int bits = repBits[ repSymbol ]; int count = input.PeekBits( bits ); if( count < 0 ) { return false; } input.DropBits( bits ); count += repMin[ repSymbol ]; // System.err.println("litdistLens repeated: "+count); if( ptr + count > num ) { throw new BlubbZipBaseException(); } while( count-- > 0 ) { litdistLens[ ptr++ ] = lastLen; } if( ptr == num ) { /* Finished */ return true; } } mode = LENS; goto decode_loop; } } }
/// <summary> /// Reads the next symbol from input. The symbol is encoded using the /// huffman tree. /// </summary> /// <param name="input"> /// input the input source. /// </param> /// <returns> /// the next symbol, or -1 if not enough input is available. /// </returns> public int GetSymbol( StreamManipulator input ) { int lookahead, symbol; if( ( lookahead = input.PeekBits( 9 ) ) >= 0 ) { if( ( symbol = tree[ lookahead ] ) >= 0 ) { input.DropBits( symbol & 15 ); return symbol >> 4; } int subtree = -( symbol >> 4 ); int bitlen = symbol & 15; if( ( lookahead = input.PeekBits( bitlen ) ) >= 0 ) { symbol = tree[ subtree | ( lookahead >> 9 ) ]; input.DropBits( symbol & 15 ); return symbol >> 4; } else { int bits = input.AvailableBits; lookahead = input.PeekBits( bits ); symbol = tree[ subtree | ( lookahead >> 9 ) ]; if( ( symbol & 15 ) <= bits ) { input.DropBits( symbol & 15 ); return symbol >> 4; } else { return -1; } } } else { int bits = input.AvailableBits; lookahead = input.PeekBits( bits ); symbol = tree[ lookahead ]; if( symbol >= 0 && ( symbol & 15 ) <= bits ) { input.DropBits( symbol & 15 ); return symbol >> 4; } else { return -1; } } }