1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io.input.buffer;
18
19 import static org.apache.commons.io.IOUtils.EOF;
20
21 import java.io.BufferedInputStream;
22 import java.io.FilterInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.util.Objects;
26
27 import org.apache.commons.io.IOUtils;
28
29
30
31
32
33
34
35 public class CircularBufferInputStream extends FilterInputStream {
36
37
38 protected final CircularByteBuffer buffer;
39
40
41 protected final int bufferSize;
42
43
44 private boolean eof;
45
46
47
48
49
50
51
52 public CircularBufferInputStream(final InputStream inputStream) {
53 this(inputStream, IOUtils.DEFAULT_BUFFER_SIZE);
54 }
55
56
57
58
59
60
61
62 @SuppressWarnings("resource")
63 public CircularBufferInputStream(final InputStream inputStream, final int bufferSize) {
64 super(Objects.requireNonNull(inputStream, "inputStream"));
65 if (bufferSize <= 0) {
66 throw new IllegalArgumentException("Illegal bufferSize: " + bufferSize);
67 }
68 this.buffer = new CircularByteBuffer(bufferSize);
69 this.bufferSize = bufferSize;
70 this.eof = false;
71 }
72
73 @Override
74 public void close() throws IOException {
75 super.close();
76 eof = true;
77 buffer.clear();
78 }
79
80
81
82
83
84
85 protected void fillBuffer() throws IOException {
86 if (eof) {
87 return;
88 }
89 int space = buffer.getSpace();
90 final byte[] buf = IOUtils.byteArray(space);
91 while (space > 0) {
92 final int res = in.read(buf, 0, space);
93 if (res == EOF) {
94 eof = true;
95 return;
96 }
97 if (res > 0) {
98 buffer.add(buf, 0, res);
99 space -= res;
100 }
101 }
102 }
103
104
105
106
107
108
109
110
111 protected boolean haveBytes(final int count) throws IOException {
112 if (buffer.getCurrentNumberOfBytes() < count) {
113 fillBuffer();
114 }
115 return buffer.hasBytes();
116 }
117
118 @Override
119 public int read() throws IOException {
120 if (!haveBytes(1)) {
121 return EOF;
122 }
123 return buffer.read() & 0xFF;
124 }
125
126 @Override
127 public int read(final byte[] targetBuffer, final int offset, final int length) throws IOException {
128 Objects.requireNonNull(targetBuffer, "targetBuffer");
129 if (offset < 0) {
130 throw new IllegalArgumentException("Offset must not be negative");
131 }
132 if (length < 0) {
133 throw new IllegalArgumentException("Length must not be negative");
134 }
135 if (!haveBytes(length)) {
136 return EOF;
137 }
138 final int result = Math.min(length, buffer.getCurrentNumberOfBytes());
139 for (int i = 0; i < result; i++) {
140 targetBuffer[offset + i] = buffer.read();
141 }
142 return result;
143 }
144 }