View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
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   * Read-only ByteBuf which wraps a read-only ByteBuffer.
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 }