Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.ning.compress.gzip;
  
  import java.io.*;
  import java.util.zip.*;
  
Optimized variant of java.util.zip.GZIPInputStream that reuses underlying java.util.zip.Deflater instance}.
 
     extends InputStream
 {
    
What kinds of chunks do we feed underlying java.util.zip.Inflater?
 
     private final static int INPUT_BUFFER_SIZE = 4096;

    
Enumeration used for keeping track of decoding state within stream
 
     enum State {
         GZIP_HEADER, GZIP_CONTENT, GZIP_TRAILER, GZIP_COMPLETE;
     };
 
     /*
     ///////////////////////////////////////////////////////////////////////
     // Helper objects
     ///////////////////////////////////////////////////////////////////////
      */
 
     protected Inflater _inflater;
 
     protected final CRC32 _crc;

    
Object that handles details of buffer recycling
 
     protected final BufferRecycler _bufferRecycler;
 
     protected final GZIPRecycler _gzipRecycler;
 
     /*
     ///////////////////////////////////////////////////////////////////////
     // State
     ///////////////////////////////////////////////////////////////////////
      */
     
     protected byte[] _buffer;
 
     protected int _bufferPtr;
 
     protected int _bufferEnd;

    
Temporary buffer used for single-byte reads, skipping.
 
     protected byte[] _tmpBuffer;
    
    
Underlying input stream from which compressed data is to be read from.
 
     protected InputStream _rawInput;

    
Flag set to true during handling of header processing
 
     protected OptimizedGZIPInputStream.State _state;
 
     /*
     ///////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////
      */
     
     public OptimizedGZIPInputStream(InputStream inthrows IOException
     {
         super();
          = BufferRecycler.instance();
          = GZIPRecycler.instance();
          = in;
 
          =  = 0;
          = .allocInflater();
          = new CRC32();
 
         // And then need to process header...
         _readHeader();
          = .;
         .reset();
         // and if all is good, kick start inflater etc
         if ( >= ) { // need more data
             _loadMore();
         }
    }
    /*
    ///////////////////////////////////////////////////////////////////////
    // InputStream implementation
    ///////////////////////////////////////////////////////////////////////
     */
    @Override
    public int available()
    {
        if ( == .) {
            return 0;
        }
        // not sure if this makes sense but...
        return .finished() ? 0 : 1;
    }
    @Override
    public void close() throws IOException
    {
         = .;
        if ( != null) {
            .close();
             = null;
        }
        byte[] b = ;
        if (b != null) {
             = null;
            .releaseInputBuffer(b);
        }
        b = ;
        if (b != null) {
             = null;
            .releaseDecodeBuffer(b);
        }
        Inflater i = ;
        if (i != null) {
             = null;
            .releaseInflater(i);
        }
    }
    @Override
    public void mark(int limit) {
        // not supported... but not lethal to call
    }
    @Override
    public boolean markSupported() {
        return false;
    }
    @Override
    public final int read() throws IOException
    {
        byte[] tmp = _getTmpBuffer();
        int count = read(tmp, 0, 1);
        if (count < 0) {
            return -1;
        }
        return tmp[0] & 0xFF;
    }
    @Override
    public final int read(byte[] bufthrows IOException {
        return read(buf, 0, buf.length);
    }
    @Override
    public final int read(byte[] bufint offsetint lenthrows IOException
    {
        if (buf == null) {
            throw new NullPointerException();
        }
        if (offset < 0 || len < 0 || len > buf.length - offset) {
            throw new IndexOutOfBoundsException();
        }
        if ( == .) { // closed or EOF
            return -1;
        }
        if (len == 0) {
            return 0;
        }
        try {
            int count;
            while ((count = .inflate(bufoffsetlen)) == 0) {
                if (.finished() || .needsDictionary()) {
                    _readTrailer();
                     = .;
                    return -1;
                }
                if (.needsInput()) {
                    _loadMore();
                    .setInput(-);
                     = ;
                }
            }
            .update(bufoffsetcount);
            return count;
        } catch (DataFormatException e) {
            String s = e.getMessage();
            throw new GZIPException(s != null ? s : "Invalid ZLIB data format");
        }
    }
    @Override
    public void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }
    @Override
    public long skip(long nthrows IOException
    {
        if (n < 0) {
            throw new IllegalArgumentException("negative skip length");
        }
        byte[] tmp = _getTmpBuffer();
        long total = 0;
        while (true) {
            int max = (int) (n - total);
            if (max == 0) {
                break;
            }
            int count = read(tmp, 0, Math.min(maxtmp.length));
            total += count;
        }
        return total;
    }
    /*
    ///////////////////////////////////////////////////////////////////////
    // Internal methods
    ///////////////////////////////////////////////////////////////////////
     */
    protected byte[] _getTmpBuffer()
    {
        if ( == null) {
        }
        return ;
    }
    protected final void _readHeader() throws IOException
    {
         = .;
        // Check header magic
        int sig = _readShort();
        if (sig != .) {
            throw new GZIPException("Not in GZIP format (got 0x"+Integer.toHexString(sig)
                    +", should be 0x"+Integer.toHexString(.)+")");
        }
        // Check compression method
        if (_readByte() != .) {
            throw new GZIPException("Unsupported compression method (only support Deflate, "+.+")");
        }
        // Read flags
        int flg = _readByte();
        // Skip MTIME, XFL, and OS fields
        _skipBytes(6);
        // Skip optional extra field
        if ((flg & .) != 0) {
            _skipBytes(_readShort());
        }
        // Skip optional file name
        if ((flg & .) != 0) {
            while (_readByte() != 0) ;
        }
        // Skip optional file comment
        if ((flg & .) != 0) {
            while (_readByte() != 0) ;
        }
        // Check optional header CRC
        if ((flg & .) != 0) {
            int act = (int).getValue() & 0xffff;
            int exp = _readShort();
            if (act != exp) {
                throw new GZIPException("Corrupt GZIP header (header CRC 0x"
                                      +Integer.toHexString(act)+", expected 0x "
                                      +Integer.toHexString(exp));
            }
        }        
    }
    protected final void _readTrailer() throws IOException
    {
        int actCrc = (int.getValue();
        // does Inflater have leftovers?
        int remains = .getRemaining();
        if (remains > 0) {
            // ok, let's update ptr to indicate where we are at...
             =  - remains;
        } else { // if not, just load more
            _loadMore(8);
        }
        int expCrc = _readInt();
        int expCount = _readInt();
        int actCount32 = (int.getBytesWritten();
        if (actCount32 != expCount) {
            throw new GZIPException("Corrupt trailer: expected byte count "+expCount+", read "+actCount32);
        }
        if (expCrc != actCrc) {
            throw new GZIPException("Corrupt trailer: expected CRC "+Integer.toHexString(expCrc)+", computed "+Integer.toHexString(actCrc));
        }
    }
    private final void _skipBytes(int countthrows IOException
    {
        while (--count >= 0) {
            _readByte();
        }
    }
    private final int _readByte() throws IOException
    {
        if ( >= ) {
            _loadMore();
        }
        byte b = [++];
        if ( == .) {
            .update(b);
        }
        return b & 0xFF;
    }
    private final int _readShort() throws IOException
    {
        // LSB... blech
        return _readByte() | (_readByte() << 8);
    }
    private final int _readInt() throws IOException
    {
        // LSB... yuck
        return _readByte() | (_readByte() << 8)
            | (_readByte() << 16) | (_readByte() << 24);
    }
    private final void _loadMore() throws IOException
    {
        // let's read at most 8k; deflater has to buffer some of data
        _loadMore(Math.min(.));
    }
    private final void _loadMore(int maxthrows IOException
    {
        int count = .read(, 0, max);
        if (count < 1) {
            String prob = (count < 0) ?
                "Unexpected end of input" : "Strange underlying stream (returned 0 bytes for read)";
            throw new GZIPException(prob+" when reading "+);
        }
         = 0;
         = count;
    }
New to GrepCode? Check out our FAQ X