1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import io.netty.util.internal.StringUtil;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 import java.nio.ReadOnlyBufferException;
26 import java.nio.channels.FileChannel;
27 import java.nio.channels.GatheringByteChannel;
28 import java.nio.channels.ScatteringByteChannel;
29
30
31
32
33
34 class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf {
35
36 protected final ByteBuffer buffer;
37 private final ByteBufAllocator allocator;
38 private ByteBuffer tmpNioBuf;
39
40 ReadOnlyByteBufferBuf(ByteBufAllocator allocator, ByteBuffer buffer) {
41 super(buffer.remaining());
42 if (!buffer.isReadOnly()) {
43 throw new IllegalArgumentException("must be a readonly buffer: " + StringUtil.simpleClassName(buffer));
44 }
45
46 this.allocator = allocator;
47 this.buffer = buffer.slice().order(ByteOrder.BIG_ENDIAN);
48 writerIndex(this.buffer.limit());
49 }
50
51 @Override
52 protected void deallocate() { }
53
54 @Override
55 public boolean isWritable() {
56 return false;
57 }
58
59 @Override
60 public boolean isWritable(int numBytes) {
61 return false;
62 }
63
64 @Override
65 public ByteBuf ensureWritable(int minWritableBytes) {
66 throw new ReadOnlyBufferException();
67 }
68
69 @Override
70 public int ensureWritable(int minWritableBytes, boolean force) {
71 return 1;
72 }
73
74 @Override
75 public byte getByte(int index) {
76 ensureAccessible();
77 return _getByte(index);
78 }
79
80 @Override
81 protected byte _getByte(int index) {
82 return buffer.get(index);
83 }
84
85 @Override
86 public short getShort(int index) {
87 ensureAccessible();
88 return _getShort(index);
89 }
90
91 @Override
92 protected short _getShort(int index) {
93 return buffer.getShort(index);
94 }
95
96 @Override
97 public short getShortLE(int index) {
98 ensureAccessible();
99 return _getShortLE(index);
100 }
101
102 @Override
103 protected short _getShortLE(int index) {
104 return ByteBufUtil.swapShort(buffer.getShort(index));
105 }
106
107 @Override
108 public int getUnsignedMedium(int index) {
109 ensureAccessible();
110 return _getUnsignedMedium(index);
111 }
112
113 @Override
114 protected int _getUnsignedMedium(int index) {
115 return (getByte(index) & 0xff) << 16 |
116 (getByte(index + 1) & 0xff) << 8 |
117 getByte(index + 2) & 0xff;
118 }
119
120 @Override
121 public int getUnsignedMediumLE(int index) {
122 ensureAccessible();
123 return _getUnsignedMediumLE(index);
124 }
125
126 @Override
127 protected int _getUnsignedMediumLE(int index) {
128 return getByte(index) & 0xff |
129 (getByte(index + 1) & 0xff) << 8 |
130 (getByte(index + 2) & 0xff) << 16;
131 }
132
133 @Override
134 public int getInt(int index) {
135 ensureAccessible();
136 return _getInt(index);
137 }
138
139 @Override
140 protected int _getInt(int index) {
141 return buffer.getInt(index);
142 }
143
144 @Override
145 public int getIntLE(int index) {
146 ensureAccessible();
147 return _getIntLE(index);
148 }
149
150 @Override
151 protected int _getIntLE(int index) {
152 return ByteBufUtil.swapInt(buffer.getInt(index));
153 }
154
155 @Override
156 public long getLong(int index) {
157 ensureAccessible();
158 return _getLong(index);
159 }
160
161 @Override
162 protected long _getLong(int index) {
163 return buffer.getLong(index);
164 }
165
166 @Override
167 public long getLongLE(int index) {
168 ensureAccessible();
169 return _getLongLE(index);
170 }
171
172 @Override
173 protected long _getLongLE(int index) {
174 return ByteBufUtil.swapLong(buffer.getLong(index));
175 }
176
177 @Override
178 public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
179 checkDstIndex(index, length, dstIndex, dst.capacity());
180 if (dst.hasArray()) {
181 getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
182 } else if (dst.nioBufferCount() > 0) {
183 for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
184 int bbLen = bb.remaining();
185 getBytes(index, bb);
186 index += bbLen;
187 }
188 } else {
189 dst.setBytes(dstIndex, this, index, length);
190 }
191 return this;
192 }
193
194 @Override
195 public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
196 checkDstIndex(index, length, dstIndex, dst.length);
197
198 ByteBuffer tmpBuf = internalNioBuffer();
199 tmpBuf.clear().position(index).limit(index + length);
200 tmpBuf.get(dst, dstIndex, length);
201 return this;
202 }
203
204 @Override
205 public ByteBuf getBytes(int index, ByteBuffer dst) {
206 checkIndex(index, dst.remaining());
207
208 ByteBuffer tmpBuf = internalNioBuffer();
209 tmpBuf.clear().position(index).limit(index + dst.remaining());
210 dst.put(tmpBuf);
211 return this;
212 }
213
214 @Override
215 public ByteBuf setByte(int index, int value) {
216 throw new ReadOnlyBufferException();
217 }
218
219 @Override
220 protected void _setByte(int index, int value) {
221 throw new ReadOnlyBufferException();
222 }
223
224 @Override
225 public ByteBuf setShort(int index, int value) {
226 throw new ReadOnlyBufferException();
227 }
228
229 @Override
230 protected void _setShort(int index, int value) {
231 throw new ReadOnlyBufferException();
232 }
233
234 @Override
235 public ByteBuf setShortLE(int index, int value) {
236 throw new ReadOnlyBufferException();
237 }
238
239 @Override
240 protected void _setShortLE(int index, int value) {
241 throw new ReadOnlyBufferException();
242 }
243
244 @Override
245 public ByteBuf setMedium(int index, int value) {
246 throw new ReadOnlyBufferException();
247 }
248
249 @Override
250 protected void _setMedium(int index, int value) {
251 throw new ReadOnlyBufferException();
252 }
253
254 @Override
255 public ByteBuf setMediumLE(int index, int value) {
256 throw new ReadOnlyBufferException();
257 }
258
259 @Override
260 protected void _setMediumLE(int index, int value) {
261 throw new ReadOnlyBufferException();
262 }
263
264 @Override
265 public ByteBuf setInt(int index, int value) {
266 throw new ReadOnlyBufferException();
267 }
268
269 @Override
270 protected void _setInt(int index, int value) {
271 throw new ReadOnlyBufferException();
272 }
273
274 @Override
275 public ByteBuf setIntLE(int index, int value) {
276 throw new ReadOnlyBufferException();
277 }
278
279 @Override
280 protected void _setIntLE(int index, int value) {
281 throw new ReadOnlyBufferException();
282 }
283
284 @Override
285 public ByteBuf setLong(int index, long value) {
286 throw new ReadOnlyBufferException();
287 }
288
289 @Override
290 protected void _setLong(int index, long value) {
291 throw new ReadOnlyBufferException();
292 }
293
294 @Override
295 public ByteBuf setLongLE(int index, long value) {
296 throw new ReadOnlyBufferException();
297 }
298
299 @Override
300 protected void _setLongLE(int index, long value) {
301 throw new ReadOnlyBufferException();
302 }
303
304 @Override
305 public int capacity() {
306 return maxCapacity();
307 }
308
309 @Override
310 public ByteBuf capacity(int newCapacity) {
311 throw new ReadOnlyBufferException();
312 }
313
314 @Override
315 public ByteBufAllocator alloc() {
316 return allocator;
317 }
318
319 @Override
320 public ByteOrder order() {
321 return ByteOrder.BIG_ENDIAN;
322 }
323
324 @Override
325 public ByteBuf unwrap() {
326 return null;
327 }
328
329 @Override
330 public boolean isReadOnly() {
331 return buffer.isReadOnly();
332 }
333
334 @Override
335 public boolean isDirect() {
336 return buffer.isDirect();
337 }
338
339 @Override
340 public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
341 ensureAccessible();
342 if (length == 0) {
343 return this;
344 }
345
346 if (buffer.hasArray()) {
347 out.write(buffer.array(), index + buffer.arrayOffset(), length);
348 } else {
349 byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
350 ByteBuffer tmpBuf = internalNioBuffer();
351 tmpBuf.clear().position(index);
352 tmpBuf.get(tmp, 0, length);
353 out.write(tmp, 0, length);
354 }
355 return this;
356 }
357
358 @Override
359 public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
360 ensureAccessible();
361 if (length == 0) {
362 return 0;
363 }
364
365 ByteBuffer tmpBuf = internalNioBuffer();
366 tmpBuf.clear().position(index).limit(index + length);
367 return out.write(tmpBuf);
368 }
369
370 @Override
371 public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
372 ensureAccessible();
373 if (length == 0) {
374 return 0;
375 }
376
377 ByteBuffer tmpBuf = internalNioBuffer();
378 tmpBuf.clear().position(index).limit(index + length);
379 return out.write(tmpBuf, position);
380 }
381
382 @Override
383 public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
384 throw new ReadOnlyBufferException();
385 }
386
387 @Override
388 public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
389 throw new ReadOnlyBufferException();
390 }
391
392 @Override
393 public ByteBuf setBytes(int index, ByteBuffer src) {
394 throw new ReadOnlyBufferException();
395 }
396
397 @Override
398 public int setBytes(int index, InputStream in, int length) throws IOException {
399 throw new ReadOnlyBufferException();
400 }
401
402 @Override
403 public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
404 throw new ReadOnlyBufferException();
405 }
406
407 @Override
408 public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
409 throw new ReadOnlyBufferException();
410 }
411
412 protected final ByteBuffer internalNioBuffer() {
413 ByteBuffer tmpNioBuf = this.tmpNioBuf;
414 if (tmpNioBuf == null) {
415 this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
416 }
417 return tmpNioBuf;
418 }
419
420 @Override
421 public ByteBuf copy(int index, int length) {
422 ensureAccessible();
423 ByteBuffer src;
424 try {
425 src = (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
426 } catch (IllegalArgumentException ignored) {
427 throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
428 }
429
430 ByteBuf dst = src.isDirect() ? alloc().directBuffer(length) : alloc().heapBuffer(length);
431 dst.writeBytes(src);
432 return dst;
433 }
434
435 @Override
436 public int nioBufferCount() {
437 return 1;
438 }
439
440 @Override
441 public ByteBuffer[] nioBuffers(int index, int length) {
442 return new ByteBuffer[] { nioBuffer(index, length) };
443 }
444
445 @Override
446 public ByteBuffer nioBuffer(int index, int length) {
447 checkIndex(index, length);
448 return (ByteBuffer) buffer.duplicate().position(index).limit(index + length);
449 }
450
451 @Override
452 public ByteBuffer internalNioBuffer(int index, int length) {
453 ensureAccessible();
454 return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
455 }
456
457 @Override
458 public final boolean isContiguous() {
459 return true;
460 }
461
462 @Override
463 public boolean hasArray() {
464 return buffer.hasArray();
465 }
466
467 @Override
468 public byte[] array() {
469 return buffer.array();
470 }
471
472 @Override
473 public int arrayOffset() {
474 return buffer.arrayOffset();
475 }
476
477 @Override
478 public boolean hasMemoryAddress() {
479 return false;
480 }
481
482 @Override
483 public long memoryAddress() {
484 throw new UnsupportedOperationException();
485 }
486 }