| /* Copyright 2017 Google Inc. All Rights Reserved. |
| |
| Distributed under MIT license. |
| See file LICENSE for detail or copy at https://opensource.org/licenses/MIT |
| */ |
| |
| package org.brotli.wrapper.enc; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.nio.channels.Channels; |
| |
| /** |
| * Output stream that wraps native brotli encoder. |
| */ |
| public class BrotliOutputStream extends OutputStream { |
| /** The default internal buffer size used by the encoder. */ |
| private static final int DEFAULT_BUFFER_SIZE = 16384; |
| |
| private final Encoder encoder; |
| |
| /** |
| * Creates a BrotliOutputStream. |
| * |
| * @param destination underlying destination |
| * @param params encoding settings |
| * @param bufferSize intermediate buffer size |
| */ |
| public BrotliOutputStream(OutputStream destination, Encoder.Parameters params, int bufferSize) |
| throws IOException { |
| this.encoder = new Encoder(Channels.newChannel(destination), params, bufferSize); |
| } |
| |
| public BrotliOutputStream(OutputStream destination, Encoder.Parameters params) |
| throws IOException { |
| this(destination, params, DEFAULT_BUFFER_SIZE); |
| } |
| |
| public BrotliOutputStream(OutputStream destination) throws IOException { |
| this(destination, new Encoder.Parameters()); |
| } |
| |
| @Override |
| public void close() throws IOException { |
| encoder.close(); |
| } |
| |
| @Override |
| public void flush() throws IOException { |
| if (encoder.closed) { |
| throw new IOException("write after close"); |
| } |
| encoder.flush(); |
| } |
| |
| @Override |
| public void write(int b) throws IOException { |
| if (encoder.closed) { |
| throw new IOException("write after close"); |
| } |
| while (!encoder.encode(EncoderJNI.Operation.PROCESS)) { |
| // Busy-wait loop. |
| } |
| encoder.inputBuffer.put((byte) b); |
| } |
| |
| @Override |
| public void write(byte[] b) throws IOException { |
| this.write(b, 0, b.length); |
| } |
| |
| @Override |
| public void write(byte[] b, int off, int len) throws IOException { |
| if (encoder.closed) { |
| throw new IOException("write after close"); |
| } |
| while (len > 0) { |
| if (!encoder.encode(EncoderJNI.Operation.PROCESS)) { |
| continue; |
| } |
| int limit = Math.min(len, encoder.inputBuffer.remaining()); |
| encoder.inputBuffer.put(b, off, limit); |
| off += limit; |
| len -= limit; |
| } |
| } |
| } |