Deflate64CompressorInputStream.java
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.commons.compress.compressors.deflate64;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.compress.compressors.CompressorInputStream;
import org.apache.commons.compress.utils.InputStreamStatistics;
import org.apache.commons.io.IOUtils;
/**
* Deflate64 decompressor.
*
* @since 1.16
* @NotThreadSafe
*/
public class Deflate64CompressorInputStream extends CompressorInputStream implements InputStreamStatistics {
private InputStream originalStream;
private HuffmanDecoder decoder;
private long compressedBytesRead;
private final byte[] oneByte = new byte[1];
Deflate64CompressorInputStream(final HuffmanDecoder decoder) {
this.decoder = decoder;
}
/**
* Constructs a Deflate64CompressorInputStream.
*
* @param in the stream to read from
*/
public Deflate64CompressorInputStream(final InputStream in) {
this(new HuffmanDecoder(in));
originalStream = in;
}
@Override
public int available() throws IOException {
return decoder != null ? decoder.available() : 0;
}
@Override
public void close() throws IOException {
try {
closeDecoder();
} finally {
IOUtils.close(originalStream);
originalStream = null;
}
}
private void closeDecoder() {
final Closeable c = decoder;
IOUtils.closeQuietly(c);
decoder = null;
}
/**
* @since 1.17
*/
@Override
public long getCompressedCount() {
return compressedBytesRead;
}
/**
* @throws java.io.EOFException if the underlying stream is exhausted before the end of deflated data was reached.
*/
@Override
public int read() throws IOException {
while (true) {
final int r = read(oneByte);
switch (r) {
case 1:
return oneByte[0] & 0xFF;
case -1:
return -1;
case 0:
continue;
default:
throw new IllegalStateException("Invalid return value from read: " + r);
}
}
}
/**
* @throws java.io.EOFException if the underlying stream is exhausted before the end of deflated data was reached.
*/
@Override
public int read(final byte[] b, final int off, final int len) throws IOException {
if (len == 0) {
return 0;
}
int read = -1;
if (decoder != null) {
try {
read = decoder.decode(b, off, len);
} catch (final RuntimeException ex) {
throw new IOException("Invalid Deflate64 input", ex);
}
compressedBytesRead = decoder.getBytesRead();
count(read);
if (read == -1) {
closeDecoder();
}
}
return read;
}
}