Home | History | Annotate | Download | only in dec
      1 /* Copyright 2017 Google Inc. All Rights Reserved.
      2 
      3    Distributed under MIT license.
      4    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
      5 */
      6 
      7 package org.brotli.wrapper.dec;
      8 
      9 import java.io.IOException;
     10 import java.io.InputStream;
     11 import java.nio.channels.Channels;
     12 
     13 /**
     14  * InputStream that wraps native brotli decoder.
     15  */
     16 public class BrotliInputStream extends InputStream {
     17   /** The default internal buffer size used by the decoder. */
     18   private static final int DEFAULT_BUFFER_SIZE = 16384;
     19 
     20   private final Decoder decoder;
     21 
     22   /**
     23    * Creates a BrotliInputStream.
     24    *
     25    * @param source underlying source
     26    * @param bufferSize intermediate buffer size
     27    */
     28   public BrotliInputStream(InputStream source, int bufferSize)
     29       throws IOException {
     30     this.decoder = new Decoder(Channels.newChannel(source), bufferSize);
     31   }
     32 
     33   public BrotliInputStream(InputStream source) throws IOException {
     34     this(source, DEFAULT_BUFFER_SIZE);
     35   }
     36 
     37   @Override
     38   public void close() throws IOException {
     39     decoder.close();
     40   }
     41 
     42   @Override
     43   public int available() {
     44     return (decoder.buffer != null) ? decoder.buffer.remaining() : 0;
     45   }
     46 
     47   @Override
     48   public int read() throws IOException {
     49     if (decoder.closed) {
     50       throw new IOException("read after close");
     51     }
     52     if (decoder.decode() == -1) {
     53       return -1;
     54     }
     55     return decoder.buffer.get() & 0xFF;
     56   }
     57 
     58   @Override
     59   public int read(byte[] b) throws IOException {
     60     return read(b, 0, b.length);
     61   }
     62 
     63   @Override
     64   public int read(byte[] b, int off, int len) throws IOException {
     65     if (decoder.closed) {
     66       throw new IOException("read after close");
     67     }
     68     if (decoder.decode() == -1) {
     69       return -1;
     70     }
     71     int result = 0;
     72     while (len > 0) {
     73       int limit = Math.min(len, decoder.buffer.remaining());
     74       decoder.buffer.get(b, off, limit);
     75       off += limit;
     76       len -= limit;
     77       result += limit;
     78       if (decoder.decode() == -1) {
     79         break;
     80       }
     81     }
     82     return result;
     83   }
     84 
     85   @Override
     86   public long skip(long n) throws IOException {
     87     if (decoder.closed) {
     88       throw new IOException("read after close");
     89     }
     90     long result = 0;
     91     while (n > 0) {
     92       if (decoder.decode() == -1) {
     93         break;
     94       }
     95       int limit = (int) Math.min(n, (long) decoder.buffer.remaining());
     96       decoder.discard(limit);
     97       result += limit;
     98       n -= limit;
     99     }
    100     return result;
    101   }
    102 }
    103