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