1 /*******************************************************************************
2 * Copyright (c) 2007, 2012 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.compressions.impl;
15 import java.io.FileInputStream;
16 import java.io.FileNotFoundException;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.nio.ByteBuffer;
20 import java.nio.ByteOrder;
21 import java.nio.IntBuffer;
22 import java.nio.channels.ReadableByteChannel;
25 * @author Hannu Niemistö
26 * @author Tuukka Lehtonen
28 public abstract class DecompressingInputStream extends InputStream {
30 protected InputStream stream;
31 protected ReadableByteChannel channel;
32 protected ByteBuffer header;
33 protected IntBuffer intHeader;
34 protected ByteBuffer compressed;
35 protected ByteBuffer uncompressed;
36 protected byte[] compressedArray;
38 public DecompressingInputStream(File file) throws FileNotFoundException {
39 this(new FileInputStream(file));
42 public DecompressingInputStream(FileInputStream stream) {
43 this(stream, stream.getChannel());
46 public DecompressingInputStream(InputStream stream) {
50 public DecompressingInputStream(InputStream stream, ReadableByteChannel channel) {
52 this.channel = channel;
53 header = ByteBuffer.allocate(8);
54 header.order(ByteOrder.LITTLE_ENDIAN);
55 intHeader = header.asIntBuffer();
59 public int read() throws IOException {
60 if(uncompressed == null || uncompressed.remaining() == 0)
63 return uncompressed.get();
67 public int read(byte[] b, int off, int len) throws IOException {
70 if(uncompressed == null || uncompressed.remaining() == 0) {
72 return bytes == 0 ? -1 : bytes;
75 int s = Math.min(len, uncompressed.remaining());
76 uncompressed.get(b, off, s);
85 public void close() throws IOException {
86 if (channel != null) {
96 private boolean fillBuffer() throws IOException {
98 if (channel != null) {
99 if (Channels.read(channel, header) < 8)
102 if (Channels.readStream(stream, header.array(), 8) < 8)
106 intHeader.position(0);
107 int compressedSize = intHeader.get();
108 int uncompressedSize = intHeader.get();
110 if(uncompressedSize == 0)
113 uncompressed = ensureBufferSize(uncompressed, uncompressedSize);
114 compressed = ensureBufferSize(compressed, compressedSize);
116 compressed.position(0);
117 compressed.limit(compressedSize);
118 if (channel != null) {
119 if (Channels.read(channel, compressed) < compressedSize)
122 if (compressedArray == null || compressedArray.length < compressedSize)
123 compressedArray = new byte[compressedSize];
124 if (Channels.readStream(stream, compressedArray, compressedSize) < 8)
126 compressed.put(compressedArray, 0, compressedSize);
129 decompress(compressed, 0, compressedSize, uncompressed, 0, uncompressedSize);
131 uncompressed.position(0);
132 uncompressed.limit(uncompressedSize);
137 private ByteBuffer ensureBufferSize(ByteBuffer buffer, int minCapacity) {
138 int oldCapacity = buffer != null ? buffer.capacity() : 0;
139 if (buffer == null || oldCapacity < minCapacity) {
140 int newCapacity = grow(oldCapacity, minCapacity);
141 //System.out.println("ensureBufferSize(" + oldCapacity + ", " + minCapacity + "), new capacity " + newCapacity);
142 buffer = allocateBuffer(newCapacity);
147 protected ByteBuffer allocateBuffer(int capacity) {
148 return ByteBuffer.allocateDirect(capacity);
152 * @param oldCapacity current capacity of a buffer
154 * @return new capacity
156 private static int grow(int oldCapacity, int minCapacity) {
157 // overflow-conscious code
158 int newCapacity = oldCapacity + (oldCapacity >> 1);
159 if (newCapacity - minCapacity < 0)
160 newCapacity = minCapacity;
161 if (newCapacity < 0) // overflow
162 throw new OutOfMemoryError();
166 public abstract void decompress(ByteBuffer compressed, int compressedOffset, int compressedSize,
167 ByteBuffer uncompressed, int uncompressedOffset, int uncompressedSize) throws IOException;