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.GatheringByteChannel;
27 import java.nio.channels.ScatteringByteChannel;
28
29
30
31
32
33 class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf {
34
35 protected final ByteBuffer buffer;
36 private final ByteBufAllocator allocator;
37 private ByteBuffer tmpNioBuf;
38
39 ReadOnlyByteBufferBuf(ByteBufAllocator allocator, ByteBuffer buffer) {
40 super(buffer.remaining());
41 if (!buffer.isReadOnly()) {
42 throw new IllegalArgumentException("must be a readonly buffer: " + StringUtil.simpleClassName(buffer));
43 }
44
45 this.allocator = allocator;
46 this.buffer = buffer.slice().order(ByteOrder.BIG_ENDIAN);
47 writerIndex(this.buffer.limit());
48 }
49
50 @Override
51 protected void deallocate() { }
52
53 @Override
54 public byte getByte(int index) {
55 ensureAccessible();
56 return _getByte(index);
57 }
58
59 @Override
60 protected byte _getByte(int index) {
61 return buffer.get(index);
62 }
63
64 @Override
65 public short getShort(int index) {
66 ensureAccessible();
67 return _getShort(index);
68 }
69
70 @Override
71 protected short _getShort(int index) {
72 return buffer.getShort(index);
73 }
74
75 @Override
76 public int getUnsignedMedium(int index) {
77 ensureAccessible();
78 return _getUnsignedMedium(index);
79 }
80
81 @Override
82 protected int _getUnsignedMedium(int index) {
83 return (getByte(index) & 0xff) << 16 |
84 (getByte(index + 1) & 0xff) << 8 |
85 getByte(index + 2) & 0xff;
86 }
87
88 @Override
89 public int getInt(int index) {
90 ensureAccessible();
91 return _getInt(index);
92 }
93
94 @Override
95 protected int _getInt(int index) {
96 return buffer.getInt(index);
97 }
98
99 @Override
100 public long getLong(int index) {
101 ensureAccessible();
102 return _getLong(index);
103 }
104
105 @Override
106 protected long _getLong(int index) {
107 return buffer.getLong(index);
108 }
109
110 @Override
111 public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
112 checkDstIndex(index, length, dstIndex, dst.capacity());
113 if (dst.hasArray()) {
114 getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
115 } else if (dst.nioBufferCount() > 0) {
116 for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
117 int bbLen = bb.remaining();
118 getBytes(index, bb);
119 index += bbLen;
120 }
121 } else {
122 dst.setBytes(dstIndex, this, index, length);
123 }
124 return this;
125 }
126
127 @Override
128 public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
129 checkDstIndex(index, length, dstIndex, dst.length);
130
131 if (dstIndex < 0 || dstIndex > dst.length - length) {
132 throw new IndexOutOfBoundsException(String.format(
133 "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length));
134 }
135
136 ByteBuffer tmpBuf = internalNioBuffer();
137 tmpBuf.clear().position(index).limit(index + length);
138 tmpBuf.get(dst, dstIndex, length);
139 return this;
140 }
141
142 @Override
143 public ByteBuf getBytes(int index, ByteBuffer dst) {
144 checkIndex(index);
145 if (dst == null) {
146 throw new NullPointerException("dst");
147 }
148
149 int bytesToCopy = Math.min(capacity() - index, dst.remaining());
150 ByteBuffer tmpBuf = internalNioBuffer();
151 tmpBuf.clear().position(index).limit(index + bytesToCopy);
152 dst.put(tmpBuf);
153 return this;
154 }
155
156 @Override
157 public ByteBuf setByte(int index, int value) {
158 throw new ReadOnlyBufferException();
159 }
160
161 @Override
162 protected void _setByte(int index, int value) {
163 throw new ReadOnlyBufferException();
164 }
165
166 @Override
167 public ByteBuf setShort(int index, int value) {
168 throw new ReadOnlyBufferException();
169 }
170
171 @Override
172 protected void _setShort(int index, int value) {
173 throw new ReadOnlyBufferException();
174 }
175
176 @Override
177 public ByteBuf setMedium(int index, int value) {
178 throw new ReadOnlyBufferException();
179 }
180
181 @Override
182 protected void _setMedium(int index, int value) {
183 throw new ReadOnlyBufferException();
184 }
185
186 @Override
187 public ByteBuf setInt(int index, int value) {
188 throw new ReadOnlyBufferException();
189 }
190
191 @Override
192 protected void _setInt(int index, int value) {
193 throw new ReadOnlyBufferException();
194 }
195
196 @Override
197 public ByteBuf setLong(int index, long value) {
198 throw new ReadOnlyBufferException();
199 }
200
201 @Override
202 protected void _setLong(int index, long value) {
203 throw new ReadOnlyBufferException();
204 }
205
206 @Override
207 public int capacity() {
208 return maxCapacity();
209 }
210
211 @Override
212 public ByteBuf capacity(int newCapacity) {
213 throw new ReadOnlyBufferException();
214 }
215
216 @Override
217 public ByteBufAllocator alloc() {
218 return allocator;
219 }
220
221 @Override
222 public ByteOrder order() {
223 return ByteOrder.BIG_ENDIAN;
224 }
225
226 @Override
227 public ByteBuf unwrap() {
228 return null;
229 }
230
231 @Override
232 public boolean isDirect() {
233 return buffer.isDirect();
234 }
235
236 @Override
237 public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
238 ensureAccessible();
239 if (length == 0) {
240 return this;
241 }
242
243 if (buffer.hasArray()) {
244 out.write(buffer.array(), index + buffer.arrayOffset(), length);
245 } else {
246 byte[] tmp = new byte[length];
247 ByteBuffer tmpBuf = internalNioBuffer();
248 tmpBuf.clear().position(index);
249 tmpBuf.get(tmp);
250 out.write(tmp);
251 }
252 return this;
253 }
254
255 @Override
256 public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
257 ensureAccessible();
258 if (length == 0) {
259 return 0;
260 }
261
262 ByteBuffer tmpBuf = internalNioBuffer();
263 tmpBuf.clear().position(index).limit(index + length);
264 return out.write(tmpBuf);
265 }
266
267 @Override
268 public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
269 throw new ReadOnlyBufferException();
270 }
271
272 @Override
273 public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
274 throw new ReadOnlyBufferException();
275 }
276
277 @Override
278 public ByteBuf setBytes(int index, ByteBuffer src) {
279 throw new ReadOnlyBufferException();
280 }
281
282 @Override
283 public int setBytes(int index, InputStream in, int length) throws IOException {
284 throw new ReadOnlyBufferException();
285 }
286
287 @Override
288 public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
289 throw new ReadOnlyBufferException();
290 }
291
292 protected final ByteBuffer internalNioBuffer() {
293 ByteBuffer tmpNioBuf = this.tmpNioBuf;
294 if (tmpNioBuf == null) {
295 this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
296 }
297 return tmpNioBuf;
298 }
299
300 @Override
301 public ByteBuf copy(int index, int length) {
302 ensureAccessible();
303 ByteBuffer src;
304 try {
305 src = (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
306 } catch (IllegalArgumentException ignored) {
307 throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
308 }
309
310 ByteBuf dst = src.isDirect() ? alloc().directBuffer(length) : alloc().heapBuffer(length);
311 dst.writeBytes(src);
312 return dst;
313 }
314
315 @Override
316 public int nioBufferCount() {
317 return 1;
318 }
319
320 @Override
321 public ByteBuffer[] nioBuffers(int index, int length) {
322 return new ByteBuffer[] { nioBuffer(index, length) };
323 }
324
325 @Override
326 public ByteBuffer nioBuffer(int index, int length) {
327 return (ByteBuffer) buffer.duplicate().position(index).limit(index + length);
328 }
329
330 @Override
331 public ByteBuffer internalNioBuffer(int index, int length) {
332 ensureAccessible();
333 return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
334 }
335
336 @Override
337 public boolean hasArray() {
338 return buffer.hasArray();
339 }
340
341 @Override
342 public byte[] array() {
343 return buffer.array();
344 }
345
346 @Override
347 public int arrayOffset() {
348 return buffer.arrayOffset();
349 }
350
351 @Override
352 public boolean hasMemoryAddress() {
353 return false;
354 }
355
356 @Override
357 public long memoryAddress() {
358 throw new UnsupportedOperationException();
359 }
360 }