Commit | Line | Data |
---|---|---|
2e7584da NR |
1 | package be.nikiroo.utils; |
2 | ||
3 | import java.io.IOException; | |
4 | import java.io.InputStream; | |
4098af70 N |
5 | import java.util.ArrayList; |
6 | import java.util.List; | |
2e7584da NR |
7 | |
8 | public class NextableInputStream extends InputStream { | |
4098af70 N |
9 | private List<NextableInputStreamStep> steps = new ArrayList<NextableInputStreamStep>(); |
10 | private NextableInputStreamStep step = null; | |
11 | ||
2e7584da NR |
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 | ||
4098af70 N |
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 | ||
2e7584da NR |
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; | |
4098af70 | 67 | while (hasMoreData() && done < blen) { |
2e7584da | 68 | preRead(); |
4098af70 N |
69 | if (hasMoreData()) { |
70 | for (int i = pos; i < blen && i < len; i++) { | |
71 | b[boff + done] = buffer[i]; | |
72 | pos++; | |
73 | done++; | |
74 | } | |
2e7584da NR |
75 | } |
76 | } | |
77 | ||
78 | return done > 0 ? done : -1; | |
79 | } | |
80 | ||
4098af70 N |
81 | @Override |
82 | public int available() throws IOException { | |
83 | return Math.max(0, len - pos); | |
84 | } | |
85 | ||
2e7584da | 86 | private void preRead() throws IOException { |
4098af70 | 87 | if (!eof && in != null && pos >= len && step == null) { |
2e7584da NR |
88 | pos = 0; |
89 | len = in.read(buffer); | |
4098af70 | 90 | checkNexts(true); |
2e7584da NR |
91 | } |
92 | ||
93 | if (pos >= len) { | |
94 | eof = true; | |
95 | } | |
96 | } | |
4098af70 N |
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 | } | |
2e7584da | 119 | } |