1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
19
20 import io.netty.util.ReferenceCounted;
21 import io.netty.util.internal.ObjectUtil;
22 import io.netty.util.internal.StringUtil;
23
24 import java.io.DataInput;
25 import java.io.DataInputStream;
26 import java.io.EOFException;
27 import java.io.IOException;
28 import java.io.InputStream;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public class ByteBufInputStream extends InputStream implements DataInput {
47 private final ByteBuf buffer;
48 private final int startIndex;
49 private final int endIndex;
50 private boolean closed;
51
52
53
54
55
56
57 private final boolean releaseOnClose;
58
59
60
61
62
63
64
65 public ByteBufInputStream(ByteBuf buffer) {
66 this(buffer, buffer.readableBytes());
67 }
68
69
70
71
72
73
74
75
76
77
78
79 public ByteBufInputStream(ByteBuf buffer, int length) {
80 this(buffer, length, false);
81 }
82
83
84
85
86
87
88
89
90
91 public ByteBufInputStream(ByteBuf buffer, boolean releaseOnClose) {
92 this(buffer, buffer.readableBytes(), releaseOnClose);
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public ByteBufInputStream(ByteBuf buffer, int length, boolean releaseOnClose) {
108 ObjectUtil.checkNotNull(buffer, "buffer");
109 if (length < 0) {
110 if (releaseOnClose) {
111 buffer.release();
112 }
113 checkPositiveOrZero(length, "length");
114 }
115 if (length > buffer.readableBytes()) {
116 if (releaseOnClose) {
117 buffer.release();
118 }
119 throw new IndexOutOfBoundsException("Too many bytes to be read - Needs "
120 + length + ", maximum is " + buffer.readableBytes());
121 }
122
123 this.releaseOnClose = releaseOnClose;
124 this.buffer = buffer;
125 startIndex = buffer.readerIndex();
126 endIndex = startIndex + length;
127 buffer.markReaderIndex();
128 }
129
130
131
132
133 public int readBytes() {
134 return buffer.readerIndex() - startIndex;
135 }
136
137 @Override
138 public void close() throws IOException {
139 try {
140 super.close();
141 } finally {
142
143 if (releaseOnClose && !closed) {
144 closed = true;
145 buffer.release();
146 }
147 }
148 }
149
150 @Override
151 public int available() throws IOException {
152 return endIndex - buffer.readerIndex();
153 }
154
155
156 @Override
157 public void mark(int readlimit) {
158 buffer.markReaderIndex();
159 }
160
161 @Override
162 public boolean markSupported() {
163 return true;
164 }
165
166 @Override
167 public int read() throws IOException {
168 int available = available();
169 if (available == 0) {
170 return -1;
171 }
172 return buffer.readByte() & 0xff;
173 }
174
175 @Override
176 public int read(byte[] b, int off, int len) throws IOException {
177 int available = available();
178 if (available == 0) {
179 return -1;
180 }
181
182 len = Math.min(available, len);
183 buffer.readBytes(b, off, len);
184 return len;
185 }
186
187
188 @Override
189 public void reset() throws IOException {
190 buffer.resetReaderIndex();
191 }
192
193 @Override
194 public long skip(long n) throws IOException {
195 if (n > Integer.MAX_VALUE) {
196 return skipBytes(Integer.MAX_VALUE);
197 } else {
198 return skipBytes((int) n);
199 }
200 }
201
202 @Override
203 public boolean readBoolean() throws IOException {
204 checkAvailable(1);
205 return read() != 0;
206 }
207
208 @Override
209 public byte readByte() throws IOException {
210 int available = available();
211 if (available == 0) {
212 throw new EOFException();
213 }
214 return buffer.readByte();
215 }
216
217 @Override
218 public char readChar() throws IOException {
219 return (char) readShort();
220 }
221
222 @Override
223 public double readDouble() throws IOException {
224 return Double.longBitsToDouble(readLong());
225 }
226
227 @Override
228 public float readFloat() throws IOException {
229 return Float.intBitsToFloat(readInt());
230 }
231
232 @Override
233 public void readFully(byte[] b) throws IOException {
234 readFully(b, 0, b.length);
235 }
236
237 @Override
238 public void readFully(byte[] b, int off, int len) throws IOException {
239 checkAvailable(len);
240 buffer.readBytes(b, off, len);
241 }
242
243 @Override
244 public int readInt() throws IOException {
245 checkAvailable(4);
246 return buffer.readInt();
247 }
248
249 private StringBuilder lineBuf;
250
251 @Override
252 public String readLine() throws IOException {
253 int available = available();
254 if (available == 0) {
255 return null;
256 }
257
258 if (lineBuf != null) {
259 lineBuf.setLength(0);
260 }
261
262 loop: do {
263 int c = buffer.readUnsignedByte();
264 --available;
265 switch (c) {
266 case '\n':
267 break loop;
268
269 case '\r':
270 if (available > 0 && (char) buffer.getUnsignedByte(buffer.readerIndex()) == '\n') {
271 buffer.skipBytes(1);
272 --available;
273 }
274 break loop;
275
276 default:
277 if (lineBuf == null) {
278 lineBuf = new StringBuilder();
279 }
280 lineBuf.append((char) c);
281 }
282 } while (available > 0);
283
284 return lineBuf != null && lineBuf.length() > 0 ? lineBuf.toString() : StringUtil.EMPTY_STRING;
285 }
286
287 @Override
288 public long readLong() throws IOException {
289 checkAvailable(8);
290 return buffer.readLong();
291 }
292
293 @Override
294 public short readShort() throws IOException {
295 checkAvailable(2);
296 return buffer.readShort();
297 }
298
299 @Override
300 public String readUTF() throws IOException {
301 return DataInputStream.readUTF(this);
302 }
303
304 @Override
305 public int readUnsignedByte() throws IOException {
306 return readByte() & 0xff;
307 }
308
309 @Override
310 public int readUnsignedShort() throws IOException {
311 return readShort() & 0xffff;
312 }
313
314 @Override
315 public int skipBytes(int n) throws IOException {
316 int nBytes = Math.min(available(), n);
317 buffer.skipBytes(nBytes);
318 return nBytes;
319 }
320
321 private void checkAvailable(int fieldSize) throws IOException {
322 if (fieldSize < 0) {
323 throw new IndexOutOfBoundsException("fieldSize cannot be a negative number");
324 }
325 if (fieldSize > available()) {
326 throw new EOFException("fieldSize is too long! Length is " + fieldSize
327 + ", but maximum is " + available());
328 }
329 }
330 }