6f3afc2b261fe439f65c79dbce20602be3bfdd53
[nikiroo-utils.git] / src / be / nikiroo / utils / NextableInputStream.java
1 package be.nikiroo.utils;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.ArrayList;
6 import java.util.List;
7
8 public class NextableInputStream extends InputStream {
9 private List<NextableInputStreamStep> steps = new ArrayList<NextableInputStreamStep>();
10 private NextableInputStreamStep step = null;
11
12 private InputStream in;
13 private boolean eof;
14 private int pos = 0;
15 private int len = 0;
16 private byte[] buffer = new byte[4096];
17
18 public NextableInputStream(InputStream in) {
19 this.in = in;
20 }
21
22 public void addStep(NextableInputStreamStep step) {
23 steps.add(step);
24 }
25
26 public boolean next() {
27 if (!hasMoreData() && step != null) {
28 len = step.getResumeLen();
29 pos += step.getSkip();
30 eof = false;
31 step = null;
32
33 checkNexts(false);
34
35 return true;
36 }
37
38 return false;
39 }
40
41 @Override
42 public int read() throws IOException {
43 preRead();
44 if (eof) {
45 return -1;
46 }
47
48 return buffer[pos++];
49 }
50
51 @Override
52 public int read(byte[] b) throws IOException {
53 return read(b, 0, b.length);
54 }
55
56 @Override
57 public int read(byte[] b, int boff, int blen) throws IOException {
58 if (b == null) {
59 throw new NullPointerException();
60 } else if (boff < 0 || blen < 0 || blen > b.length - boff) {
61 throw new IndexOutOfBoundsException();
62 } else if (blen == 0) {
63 return 0;
64 }
65
66 int done = 0;
67 while (hasMoreData() && done < blen) {
68 preRead();
69 if (hasMoreData()) {
70 for (int i = pos; i < blen && i < len; i++) {
71 b[boff + done] = buffer[i];
72 pos++;
73 done++;
74 }
75 }
76 }
77
78 return done > 0 ? done : -1;
79 }
80
81 @Override
82 public int available() throws IOException {
83 return Math.max(0, len - pos);
84 }
85
86 private void preRead() throws IOException {
87 if (!eof && in != null && pos >= len && step == null) {
88 pos = 0;
89 len = in.read(buffer);
90 checkNexts(true);
91 }
92
93 if (pos >= len) {
94 eof = true;
95 }
96 }
97
98 private boolean hasMoreData() {
99 return !(eof && pos >= len);
100 }
101
102 private void checkNexts(boolean newBuffer) {
103 if (!eof) {
104 for (NextableInputStreamStep step : steps) {
105 if (newBuffer) {
106 step.clearBuffer();
107 }
108
109 int stopAt = step.stop(buffer, pos, len);
110 if (stopAt >= 0) {
111 this.step = step;
112 len = stopAt;
113 eof = true;
114 break;
115 }
116 }
117 }
118 }
119 }