001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.compress;
007:
008: import java.io.IOException;
009: import java.io.InputStream;
010:
011: /**
012: * An input stream to read from an LZF stream.
013: * The data is automatically expanded.
014: */
015: public class LZFInputStream extends InputStream {
016:
017: private final InputStream in;
018: private CompressLZF decompress = new CompressLZF();
019: private int pos;
020: private int bufferLength;
021: private byte[] inBuffer;
022: private byte[] buffer;
023:
024: public LZFInputStream(InputStream in) throws IOException {
025: this .in = in;
026: if (readInt() != LZFOutputStream.MAGIC) {
027: throw new IOException("Not an LZFInputStream");
028: }
029: }
030:
031: private byte[] ensureSize(byte[] buff, int len) {
032: return buff == null || buff.length < len ? new byte[len] : buff;
033: }
034:
035: private void fillBuffer() throws IOException {
036: if (buffer != null && pos < bufferLength) {
037: return;
038: }
039: int len = readInt();
040: if (decompress == null) {
041: // EOF
042: this .bufferLength = 0;
043: } else if (len < 0) {
044: len = -len;
045: buffer = ensureSize(buffer, len);
046: readFully(buffer, len);
047: this .bufferLength = len;
048: } else {
049: inBuffer = ensureSize(inBuffer, len);
050: int size = readInt();
051: readFully(inBuffer, len);
052: buffer = ensureSize(buffer, size);
053: decompress.expand(inBuffer, 0, len, buffer, 0, size);
054: this .bufferLength = size;
055: }
056: pos = 0;
057: }
058:
059: private void readFully(byte[] buff, int len) throws IOException {
060: int off = 0;
061: while (len > 0) {
062: int l = in.read(buff, off, len);
063: len -= l;
064: off += l;
065: }
066: }
067:
068: private int readInt() throws IOException {
069: int x = in.read();
070: if (x < 0) {
071: close();
072: decompress = null;
073: return 0;
074: }
075: x = (x << 24) + (in.read() << 16) + (in.read() << 8)
076: + in.read();
077: return x;
078: }
079:
080: public int read() throws IOException {
081: fillBuffer();
082: if (pos >= bufferLength) {
083: return -1;
084: }
085: return buffer[pos++] & 255;
086: }
087:
088: public int read(byte[] b) throws IOException {
089: return read(b, 0, b.length);
090: }
091:
092: public int read(byte[] b, int off, int len) throws IOException {
093: if (len == 0) {
094: return 0;
095: }
096: int read = 0;
097: while (len > 0) {
098: int r = readBlock(b, off, len);
099: if (r < 0) {
100: break;
101: }
102: read += r;
103: off += r;
104: len -= r;
105: }
106: return read == 0 ? -1 : read;
107: }
108:
109: private int readBlock(byte[] b, int off, int len)
110: throws IOException {
111: fillBuffer();
112: if (pos >= bufferLength) {
113: return -1;
114: }
115: int max = Math.min(len, bufferLength - pos);
116: max = Math.min(max, b.length - off);
117: System.arraycopy(buffer, pos, b, off, max);
118: pos += max;
119: return max;
120: }
121:
122: public void close() throws IOException {
123: in.close();
124: }
125:
126: }
|