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