1 package be
.nikiroo
.utils
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
7 * This {@link InputStream} can be separated into sub-streams (you can process
8 * it as a normal {@link InputStream} but, when it is spent, you can call
9 * {@link NextableInputStream#next()} on it to unlock new data).
11 * The separation in sub-streams is done via {@link NextableInputStreamStep}.
15 public class NextableInputStream
extends InputStream
{
16 private NextableInputStreamStep step
;
17 private boolean stopped
;
19 private InputStream in
;
23 private byte[] buffer
= new byte[4096];
26 * Create a new {@link NextableInputStream} that wraps the given
27 * {@link InputStream}.
30 * the {@link InputStream} to wrap
32 * how to separate it into sub-streams (can be NULL, but in that
33 * case it will behave as a normal {@link InputStream})
35 public NextableInputStream(InputStream in
, NextableInputStreamStep step
) {
41 * Unblock the processing of the next sub-stream.
43 * It can only be called when the "current" stream is spent (i.e., you must
44 * first process the stream until it is spent).
46 * We consider that when the under-laying {@link InputStream} is also spent,
47 * we cannot have a next sub-stream (it will thus return FALSE).
49 * {@link IOException}s can happen when we have no data available in the
50 * buffer; in that case, we fetch more data to know if we can have a next
53 * @return TRUE if we unblocked the next sub-stream, FALSE if not
56 * in case of I/O error
58 public boolean next() throws IOException
{
59 if (!hasMoreData() && stopped
) {
60 len
= step
.getResumeLen();
61 pos
+= step
.getResumeSkip();
68 // consider that if EOF, there is no next
76 public int read() throws IOException
{
86 public int read(byte[] b
) throws IOException
{
87 return read(b
, 0, b
.length
);
91 public int read(byte[] b
, int boff
, int blen
) throws IOException
{
93 throw new NullPointerException();
94 } else if (boff
< 0 || blen
< 0 || blen
> b
.length
- boff
) {
95 throw new IndexOutOfBoundsException();
96 } else if (blen
== 0) {
101 while (hasMoreData() && done
< blen
) {
104 for (int i
= pos
; i
< blen
&& i
< len
; i
++) {
105 b
[boff
+ done
] = buffer
[i
];
112 return done
> 0 ? done
: -1;
116 public int available() throws IOException
{
117 return Math
.max(0, len
- pos
);
121 * Check if we still have some data in the buffer and, if not, fetch some.
123 * @return TRUE if we fetched some data, FALSE if there are still some in
126 * @throws IOException
127 * in case of I/O error
129 private boolean preRead() throws IOException
{
130 boolean hasRead
= false;
131 if (!eof
&& in
!= null && pos
>= len
&& !stopped
) {
133 len
= in
.read(buffer
);
146 * We have more data available in the buffer or we can fetch more.
148 * @return TRUE if it is the case, FALSE if not
150 private boolean hasMoreData() {
151 return !(eof
&& pos
>= len
);
155 * Check that the buffer didn't overshot to the next item, and fix
156 * {@link NextableInputStream#len} if needed.
158 * If {@link NextableInputStream#len} is fixed,
159 * {@link NextableInputStream#eof} and {@link NextableInputStream#stopped}
163 * we changed the buffer, we need to clear some information in
164 * the {@link NextableInputStreamStep}
166 private void checkBuffer(boolean newBuffer
) {
172 int stopAt
= step
.stop(buffer
, pos
, len
);