• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * UncompressedLZMA2OutputStream
3  *
4  * Author: Lasse Collin <lasse.collin@tukaani.org>
5  *
6  * This file has been put into the public domain.
7  * You can do whatever you want with this file.
8  */
9 
10 package org.tukaani.xz;
11 
12 import java.io.DataOutputStream;
13 import java.io.IOException;
14 
15 class UncompressedLZMA2OutputStream extends FinishableOutputStream {
16     private FinishableOutputStream out;
17     private final DataOutputStream outData;
18 
19     private final byte[] uncompBuf
20             = new byte[LZMA2OutputStream.COMPRESSED_SIZE_MAX];
21     private int uncompPos = 0;
22     private boolean dictResetNeeded = true;
23 
24     private boolean finished = false;
25     private IOException exception = null;
26 
27     private final byte[] tempBuf = new byte[1];
28 
getMemoryUsage()29     static int getMemoryUsage() {
30         // uncompBuf + a little extra
31         return 70;
32     }
33 
UncompressedLZMA2OutputStream(FinishableOutputStream out)34     UncompressedLZMA2OutputStream(FinishableOutputStream out) {
35         if (out == null)
36             throw new NullPointerException();
37 
38         this.out = out;
39         outData = new DataOutputStream(out);
40     }
41 
write(int b)42     public void write(int b) throws IOException {
43         tempBuf[0] = (byte)b;
44         write(tempBuf, 0, 1);
45     }
46 
write(byte[] buf, int off, int len)47     public void write(byte[] buf, int off, int len) throws IOException {
48         if (off < 0 || len < 0 || off + len < 0 || off + len > buf.length)
49             throw new IndexOutOfBoundsException();
50 
51         if (exception != null)
52             throw exception;
53 
54         if (finished)
55             throw new XZIOException("Stream finished or closed");
56 
57         try {
58             while (len > 0) {
59                 int copySize = Math.min(uncompBuf.length - uncompPos, len);
60                 System.arraycopy(buf, off, uncompBuf, uncompPos, copySize);
61                 len -= copySize;
62                 uncompPos += copySize;
63 
64                 if (uncompPos == uncompBuf.length)
65                     writeChunk();
66             }
67         } catch (IOException e) {
68             exception = e;
69             throw e;
70         }
71     }
72 
writeChunk()73     private void writeChunk() throws IOException {
74         outData.writeByte(dictResetNeeded ? 0x01 : 0x02);
75         outData.writeShort(uncompPos - 1);
76         outData.write(uncompBuf, 0, uncompPos);
77         uncompPos = 0;
78         dictResetNeeded = false;
79     }
80 
writeEndMarker()81     private void writeEndMarker() throws IOException {
82         if (exception != null)
83             throw exception;
84 
85         if (finished)
86             throw new XZIOException("Stream finished or closed");
87 
88         try {
89             if (uncompPos > 0)
90                 writeChunk();
91 
92             out.write(0x00);
93         } catch (IOException e) {
94             exception = e;
95             throw e;
96         }
97     }
98 
flush()99     public void flush() throws IOException {
100         if (exception != null)
101             throw exception;
102 
103         if (finished)
104             throw new XZIOException("Stream finished or closed");
105 
106         try {
107             if (uncompPos > 0)
108                 writeChunk();
109 
110             out.flush();
111         } catch (IOException e) {
112             exception = e;
113             throw e;
114         }
115     }
116 
finish()117     public void finish() throws IOException {
118         if (!finished) {
119             writeEndMarker();
120 
121             try {
122                 out.finish();
123             } catch (IOException e) {
124                 exception = e;
125                 throw e;
126             }
127 
128             finished = true;
129         }
130     }
131 
close()132     public void close() throws IOException {
133         if (out != null) {
134             if (!finished) {
135                 try {
136                     writeEndMarker();
137                 } catch (IOException e) {}
138             }
139 
140             try {
141                 out.close();
142             } catch (IOException e) {
143                 if (exception == null)
144                     exception = e;
145             }
146 
147             out = null;
148         }
149 
150         if (exception != null)
151             throw exception;
152     }
153 }
154