01: /*
02: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
03: * (http://h2database.com/html/license.html).
04: * Initial Developer: H2 Group
05: */
06: package org.h2.compress;
07:
08: import java.io.IOException;
09: import java.io.OutputStream;
10:
11: import org.h2.engine.Constants;
12:
13: /**
14: * An output stream to write an LZF stream.
15: * The data is automatically compressed.
16: */
17: public class LZFOutputStream extends OutputStream {
18:
19: static final int MAGIC = ('H' << 24) | ('2' << 16) | ('I' << 8)
20: | 'S';
21:
22: private final OutputStream out;
23: private final CompressLZF compress = new CompressLZF();
24: private final byte[] buffer;
25: private int pos;
26: private byte[] outBuffer;
27:
28: public LZFOutputStream(OutputStream out) throws IOException {
29: this .out = out;
30: int len = Constants.IO_BUFFER_SIZE_COMPRESS;
31: buffer = new byte[len];
32: ensureOutput(len);
33: writeInt(MAGIC);
34: }
35:
36: private void ensureOutput(int len) {
37: // TODO calculate the maximum overhead (worst case) for the output
38: // buffer
39: int outputLen = (len < 100 ? len + 100 : len) * 2;
40: if (outBuffer == null || outBuffer.length < outputLen) {
41: outBuffer = new byte[outputLen];
42: }
43: }
44:
45: public void write(int b) throws IOException {
46: if (pos >= buffer.length) {
47: flush();
48: }
49: buffer[pos++] = (byte) b;
50: }
51:
52: private void compressAndWrite(byte[] buff, int len)
53: throws IOException {
54: if (len > 0) {
55: ensureOutput(len);
56: int compressed = compress.compress(buff, len, outBuffer, 0);
57: if (compressed > len) {
58: writeInt(-len);
59: out.write(buff, 0, len);
60: } else {
61: writeInt(compressed);
62: writeInt(len);
63: out.write(outBuffer, 0, compressed);
64: }
65: }
66: }
67:
68: private void writeInt(int x) throws IOException {
69: out.write((byte) (x >> 24));
70: out.write((byte) (x >> 16));
71: out.write((byte) (x >> 8));
72: out.write((byte) x);
73: }
74:
75: public void write(byte[] buff, int off, int len) throws IOException {
76: while (len > 0) {
77: int copy = Math.min(buffer.length - pos, len);
78: System.arraycopy(buff, off, buffer, pos, copy);
79: pos += copy;
80: if (pos >= buffer.length) {
81: flush();
82: }
83: off += copy;
84: len -= copy;
85: }
86: }
87:
88: public void flush() throws IOException {
89: compressAndWrite(buffer, pos);
90: pos = 0;
91: }
92:
93: public void close() throws IOException {
94: flush();
95: out.close();
96: }
97:
98: }
|