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    *   http://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         if (dstIndex < 0 || dstIndex > dst.length - length) {
199             throw new IndexOutOfBoundsException(String.format(
200                     "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dst.length));
201         }
202 
203         ByteBuffer tmpBuf = internalNioBuffer();
204         tmpBuf.clear().position(index).limit(index + length);
205         tmpBuf.get(dst, dstIndex, length);
206         return this;
207     }
208 
209     @Override
210     public ByteBuf getBytes(int index, ByteBuffer dst) {
211         checkIndex(index);
212         if (dst == null) {
213             throw new NullPointerException("dst");
214         }
215 
216         int bytesToCopy = Math.min(capacity() - index, dst.remaining());
217         ByteBuffer tmpBuf = internalNioBuffer();
218         tmpBuf.clear().position(index).limit(index + bytesToCopy);
219         dst.put(tmpBuf);
220         return this;
221     }
222 
223     @Override
224     public ByteBuf setByte(int index, int value) {
225         throw new ReadOnlyBufferException();
226     }
227 
228     @Override
229     protected void _setByte(int index, int value) {
230         throw new ReadOnlyBufferException();
231     }
232 
233     @Override
234     public ByteBuf setShort(int index, int value) {
235         throw new ReadOnlyBufferException();
236     }
237 
238     @Override
239     protected void _setShort(int index, int value) {
240         throw new ReadOnlyBufferException();
241     }
242 
243     @Override
244     public ByteBuf setShortLE(int index, int value) {
245         throw new ReadOnlyBufferException();
246     }
247 
248     @Override
249     protected void _setShortLE(int index, int value) {
250         throw new ReadOnlyBufferException();
251     }
252 
253     @Override
254     public ByteBuf setMedium(int index, int value) {
255         throw new ReadOnlyBufferException();
256     }
257 
258     @Override
259     protected void _setMedium(int index, int value) {
260         throw new ReadOnlyBufferException();
261     }
262 
263     @Override
264     public ByteBuf setMediumLE(int index, int value) {
265         throw new ReadOnlyBufferException();
266     }
267 
268     @Override
269     protected void _setMediumLE(int index, int value) {
270         throw new ReadOnlyBufferException();
271     }
272 
273     @Override
274     public ByteBuf setInt(int index, int value) {
275         throw new ReadOnlyBufferException();
276     }
277 
278     @Override
279     protected void _setInt(int index, int value) {
280         throw new ReadOnlyBufferException();
281     }
282 
283     @Override
284     public ByteBuf setIntLE(int index, int value) {
285         throw new ReadOnlyBufferException();
286     }
287 
288     @Override
289     protected void _setIntLE(int index, int value) {
290         throw new ReadOnlyBufferException();
291     }
292 
293     @Override
294     public ByteBuf setLong(int index, long value) {
295         throw new ReadOnlyBufferException();
296     }
297 
298     @Override
299     protected void _setLong(int index, long value) {
300         throw new ReadOnlyBufferException();
301     }
302 
303     @Override
304     public ByteBuf setLongLE(int index, long value) {
305         throw new ReadOnlyBufferException();
306     }
307 
308     @Override
309     protected void _setLongLE(int index, long value) {
310         throw new ReadOnlyBufferException();
311     }
312 
313     @Override
314     public int capacity() {
315         return maxCapacity();
316     }
317 
318     @Override
319     public ByteBuf capacity(int newCapacity) {
320         throw new ReadOnlyBufferException();
321     }
322 
323     @Override
324     public ByteBufAllocator alloc() {
325         return allocator;
326     }
327 
328     @Override
329     public ByteOrder order() {
330         return ByteOrder.BIG_ENDIAN;
331     }
332 
333     @Override
334     public ByteBuf unwrap() {
335         return null;
336     }
337 
338     @Override
339     public boolean isReadOnly() {
340         return buffer.isReadOnly();
341     }
342 
343     @Override
344     public boolean isDirect() {
345         return buffer.isDirect();
346     }
347 
348     @Override
349     public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
350         ensureAccessible();
351         if (length == 0) {
352             return this;
353         }
354 
355         if (buffer.hasArray()) {
356             out.write(buffer.array(), index + buffer.arrayOffset(), length);
357         } else {
358             byte[] tmp = new byte[length];
359             ByteBuffer tmpBuf = internalNioBuffer();
360             tmpBuf.clear().position(index);
361             tmpBuf.get(tmp);
362             out.write(tmp);
363         }
364         return this;
365     }
366 
367     @Override
368     public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
369         ensureAccessible();
370         if (length == 0) {
371             return 0;
372         }
373 
374         ByteBuffer tmpBuf = internalNioBuffer();
375         tmpBuf.clear().position(index).limit(index + length);
376         return out.write(tmpBuf);
377     }
378 
379     @Override
380     public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
381         ensureAccessible();
382         if (length == 0) {
383             return 0;
384         }
385 
386         ByteBuffer tmpBuf = internalNioBuffer();
387         tmpBuf.clear().position(index).limit(index + length);
388         return out.write(tmpBuf, position);
389     }
390 
391     @Override
392     public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
393         throw new ReadOnlyBufferException();
394     }
395 
396     @Override
397     public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
398         throw new ReadOnlyBufferException();
399     }
400 
401     @Override
402     public ByteBuf setBytes(int index, ByteBuffer src) {
403         throw new ReadOnlyBufferException();
404     }
405 
406     @Override
407     public int setBytes(int index, InputStream in, int length) throws IOException {
408         throw new ReadOnlyBufferException();
409     }
410 
411     @Override
412     public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
413         throw new ReadOnlyBufferException();
414     }
415 
416     @Override
417     public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
418         throw new ReadOnlyBufferException();
419     }
420 
421     protected final ByteBuffer internalNioBuffer() {
422         ByteBuffer tmpNioBuf = this.tmpNioBuf;
423         if (tmpNioBuf == null) {
424             this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
425         }
426         return tmpNioBuf;
427     }
428 
429     @Override
430     public ByteBuf copy(int index, int length) {
431         ensureAccessible();
432         ByteBuffer src;
433         try {
434             src = (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
435         } catch (IllegalArgumentException ignored) {
436             throw new IndexOutOfBoundsException("Too many bytes to read - Need " + (index + length));
437         }
438 
439         ByteBuf dst = src.isDirect() ? alloc().directBuffer(length) : alloc().heapBuffer(length);
440         dst.writeBytes(src);
441         return dst;
442     }
443 
444     @Override
445     public int nioBufferCount() {
446         return 1;
447     }
448 
449     @Override
450     public ByteBuffer[] nioBuffers(int index, int length) {
451         return new ByteBuffer[] { nioBuffer(index, length) };
452     }
453 
454     @Override
455     public ByteBuffer nioBuffer(int index, int length) {
456         return (ByteBuffer) buffer.duplicate().position(index).limit(index + length);
457     }
458 
459     @Override
460     public ByteBuffer internalNioBuffer(int index, int length) {
461         ensureAccessible();
462         return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
463     }
464 
465     @Override
466     public boolean hasArray() {
467         return buffer.hasArray();
468     }
469 
470     @Override
471     public byte[] array() {
472         return buffer.array();
473     }
474 
475     @Override
476     public int arrayOffset() {
477         return buffer.arrayOffset();
478     }
479 
480     @Override
481     public boolean hasMemoryAddress() {
482         return false;
483     }
484 
485     @Override
486     public long memoryAddress() {
487         throw new UnsupportedOperationException();
488     }
489 }