• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * SimpleInputStream
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.InputStream;
13 import java.io.IOException;
14 import org.tukaani.xz.simple.SimpleFilter;
15 
16 class SimpleInputStream extends InputStream {
17     private static final int FILTER_BUF_SIZE = 4096;
18 
19     private InputStream in;
20     private final SimpleFilter simpleFilter;
21 
22     private final byte[] filterBuf = new byte[FILTER_BUF_SIZE];
23     private int pos = 0;
24     private int filtered = 0;
25     private int unfiltered = 0;
26 
27     private boolean endReached = false;
28     private IOException exception = null;
29 
30     private final byte[] tempBuf = new byte[1];
31 
getMemoryUsage()32     static int getMemoryUsage() {
33         return 1 + FILTER_BUF_SIZE / 1024;
34     }
35 
SimpleInputStream(InputStream in, SimpleFilter simpleFilter)36     SimpleInputStream(InputStream in, SimpleFilter simpleFilter) {
37         // Check for null because otherwise null isn't detect
38         // in this constructor.
39         if (in == null)
40             throw new NullPointerException();
41 
42         // The simpleFilter argument comes from this package
43         // so it is known to be non-null already.
44         assert simpleFilter != null;
45 
46         this.in = in;
47         this.simpleFilter = simpleFilter;
48     }
49 
read()50     public int read() throws IOException {
51         return read(tempBuf, 0, 1) == -1 ? -1 : (tempBuf[0] & 0xFF);
52     }
53 
read(byte[] buf, int off, int len)54     public int read(byte[] buf, int off, int len) throws IOException {
55         if (off < 0 || len < 0 || off + len < 0 || off + len > buf.length)
56             throw new IndexOutOfBoundsException();
57 
58         if (len == 0)
59             return 0;
60 
61         if (in == null)
62             throw new XZIOException("Stream closed");
63 
64         if (exception != null)
65             throw exception;
66 
67         try {
68             int size = 0;
69 
70             while (true) {
71                 // Copy filtered data into the caller-provided buffer.
72                 int copySize = Math.min(filtered, len);
73                 System.arraycopy(filterBuf, pos, buf, off, copySize);
74                 pos += copySize;
75                 filtered -= copySize;
76                 off += copySize;
77                 len -= copySize;
78                 size += copySize;
79 
80                 // If end of filterBuf was reached, move the pending data to
81                 // the beginning of the buffer so that more data can be
82                 // copied into filterBuf on the next loop iteration.
83                 if (pos + filtered + unfiltered == FILTER_BUF_SIZE) {
84                     System.arraycopy(filterBuf, pos, filterBuf, 0,
85                                      filtered + unfiltered);
86                     pos = 0;
87                 }
88 
89                 if (len == 0 || endReached)
90                     return size > 0 ? size : -1;
91 
92                 assert filtered == 0;
93 
94                 // Get more data into the temporary buffer.
95                 int inSize = FILTER_BUF_SIZE - (pos + filtered + unfiltered);
96                 inSize = in.read(filterBuf, pos + filtered + unfiltered,
97                                  inSize);
98 
99                 if (inSize == -1) {
100                     // Mark the remaining unfiltered bytes to be ready
101                     // to be copied out.
102                     endReached = true;
103                     filtered = unfiltered;
104                     unfiltered = 0;
105                 } else {
106                     // Filter the data in filterBuf.
107                     unfiltered += inSize;
108                     filtered = simpleFilter.code(filterBuf, pos, unfiltered);
109                     assert filtered <= unfiltered;
110                     unfiltered -= filtered;
111                 }
112             }
113         } catch (IOException e) {
114             exception = e;
115             throw e;
116         }
117     }
118 
available()119     public int available() throws IOException {
120         if (in == null)
121             throw new XZIOException("Stream closed");
122 
123         if (exception != null)
124             throw exception;
125 
126         return filtered;
127     }
128 
close()129     public void close() throws IOException {
130         if (in != null) {
131             try {
132                 in.close();
133             } finally {
134                 in = null;
135             }
136         }
137     }
138 }
139