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