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    *   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  
17  package io.netty.buffer;
18  
19  import io.netty.util.Recycler;
20  import io.netty.util.internal.ObjectPool.Handle;
21  import io.netty.util.internal.PlatformDependent;
22  
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.nio.ByteBuffer;
27  
28  final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
29  
30      private static final Recycler<PooledDirectByteBuf> RECYCLER =
31              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.reuse(maxCapacity);
41          return buf;
42      }
43  
44      private PooledDirectByteBuf(Handle<PooledDirectByteBuf> 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 short _getShortLE(int index) {
70          return ByteBufUtil.swapShort(_getShort(index));
71      }
72  
73      @Override
74      protected int _getUnsignedMedium(int index) {
75          index = idx(index);
76          return (memory.get(index) & 0xff)     << 16 |
77                 (memory.get(index + 1) & 0xff) << 8  |
78                 memory.get(index + 2) & 0xff;
79      }
80  
81      @Override
82      protected int _getUnsignedMediumLE(int index) {
83          index = idx(index);
84          return memory.get(index)      & 0xff        |
85                 (memory.get(index + 1) & 0xff) << 8  |
86                 (memory.get(index + 2) & 0xff) << 16;
87      }
88  
89      @Override
90      protected int _getInt(int index) {
91          return memory.getInt(idx(index));
92      }
93  
94      @Override
95      protected int _getIntLE(int index) {
96          return ByteBufUtil.swapInt(_getInt(index));
97      }
98  
99      @Override
100     protected long _getLong(int index) {
101         return memory.getLong(idx(index));
102     }
103 
104     @Override
105     protected long _getLongLE(int index) {
106         return ByteBufUtil.swapLong(_getLong(index));
107     }
108 
109     @Override
110     public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
111         checkDstIndex(index, length, dstIndex, dst.capacity());
112         if (dst.hasArray()) {
113             getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
114         } else {
115             ByteBuf unwrapped = dst instanceof WrappedByteBuf ? dst.unwrap() : dst;
116             if (unwrapped instanceof AbstractByteBuf) {
117                 ByteBuffer dstBuf = unwrapped.internalNioBuffer(dstIndex, length);
118                 PlatformDependent.absolutePut(dstBuf, dstBuf.position(), memory, idx(index), length);
119             } else if (dst.nioBufferCount() > 0) {
120                 for (ByteBuffer bb : dst.nioBuffers(dstIndex, length)) {
121                     int bbLen = bb.remaining();
122                     getBytes(index, bb);
123                     index += bbLen;
124                 }
125             } else {
126                 dst.setBytes(dstIndex, this, index, length);
127             }
128         }
129         return this;
130     }
131 
132     @Override
133     public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
134         checkDstIndex(index, length, dstIndex, dst.length);
135         _internalNioBuffer(index, length, true).get(dst, dstIndex, length);
136         return this;
137     }
138 
139     @Override
140     public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
141         checkDstIndex(length, dstIndex, dst.length);
142         _internalNioBuffer(readerIndex, length, false).get(dst, dstIndex, length);
143         readerIndex += length;
144         return this;
145     }
146 
147     @Override
148     public ByteBuf getBytes(int index, ByteBuffer dst) {
149         dst.put(duplicateInternalNioBuffer(index, dst.remaining()));
150         return this;
151     }
152 
153     @Override
154     public ByteBuf readBytes(ByteBuffer dst) {
155         int length = dst.remaining();
156         checkReadableBytes(length);
157         dst.put(_internalNioBuffer(readerIndex, length, false));
158         readerIndex += length;
159         return this;
160     }
161 
162     @Override
163     public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
164         getBytes(index, out, length, false);
165         return this;
166     }
167 
168     private void getBytes(int index, OutputStream out, int length, boolean internal) throws IOException {
169         checkIndex(index, length);
170         if (length == 0) {
171             return;
172         }
173         ByteBufUtil.readBytes(alloc(), internal ? internalNioBuffer() : memory.duplicate(), idx(index), length, out);
174     }
175 
176     @Override
177     public ByteBuf readBytes(OutputStream out, int length) throws IOException {
178         checkReadableBytes(length);
179         getBytes(readerIndex, out, length, true);
180         readerIndex += length;
181         return this;
182     }
183 
184     @Override
185     protected void _setByte(int index, int value) {
186         memory.put(idx(index), (byte) value);
187     }
188 
189     @Override
190     protected void _setShort(int index, int value) {
191         memory.putShort(idx(index), (short) value);
192     }
193 
194     @Override
195     protected void _setShortLE(int index, int value) {
196         _setShort(index, ByteBufUtil.swapShort((short) value));
197     }
198 
199     @Override
200     protected void _setMedium(int index, int value) {
201         index = idx(index);
202         memory.put(index, (byte) (value >>> 16));
203         memory.put(index + 1, (byte) (value >>> 8));
204         memory.put(index + 2, (byte) value);
205     }
206 
207     @Override
208     protected void _setMediumLE(int index, int value) {
209         index = idx(index);
210         memory.put(index, (byte) value);
211         memory.put(index + 1, (byte) (value >>> 8));
212         memory.put(index + 2, (byte) (value >>> 16));
213     }
214 
215     @Override
216     protected void _setInt(int index, int value) {
217         memory.putInt(idx(index), value);
218     }
219 
220     @Override
221     protected void _setIntLE(int index, int value) {
222         _setInt(index, ByteBufUtil.swapInt(value));
223     }
224 
225     @Override
226     protected void _setLong(int index, long value) {
227         memory.putLong(idx(index), value);
228     }
229 
230     @Override
231     protected void _setLongLE(int index, long value) {
232         _setLong(index, ByteBufUtil.swapLong(value));
233     }
234 
235     @Override
236     public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
237         checkSrcIndex(index, length, srcIndex, src.capacity());
238         if (src.hasArray()) {
239             setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);
240         } else if (src.nioBufferCount() > 0) {
241             for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) {
242                 int bbLen = bb.remaining();
243                 setBytes(index, bb);
244                 index += bbLen;
245             }
246         } else {
247             src.getBytes(srcIndex, this, index, length);
248         }
249         return this;
250     }
251 
252     @Override
253     public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
254         checkSrcIndex(index, length, srcIndex, src.length);
255         _internalNioBuffer(index, length, false).put(src, srcIndex, length);
256         return this;
257     }
258 
259     @Override
260     public ByteBuf setBytes(int index, ByteBuffer src) {
261         int length = src.remaining();
262         checkIndex(index, length);
263         ByteBuffer tmpBuf = internalNioBuffer();
264         if (src == tmpBuf) {
265             src = src.duplicate();
266         }
267 
268         index = idx(index);
269         tmpBuf.limit(index + length).position(index);
270         tmpBuf.put(src);
271         return this;
272     }
273 
274     @Override
275     public int setBytes(int index, InputStream in, int length) throws IOException {
276         checkIndex(index, length);
277         byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
278         int readBytes = in.read(tmp, 0, length);
279         if (readBytes <= 0) {
280             return readBytes;
281         }
282         ByteBuffer tmpBuf = internalNioBuffer();
283         tmpBuf.position(idx(index));
284         tmpBuf.put(tmp, 0, readBytes);
285         return readBytes;
286     }
287 
288     @Override
289     public ByteBuf copy(int index, int length) {
290         checkIndex(index, length);
291         ByteBuf copy = alloc().directBuffer(length, maxCapacity());
292         return copy.writeBytes(this, index, length);
293     }
294 
295     @Override
296     public boolean hasArray() {
297         return false;
298     }
299 
300     @Override
301     public byte[] array() {
302         throw new UnsupportedOperationException("direct buffer");
303     }
304 
305     @Override
306     public int arrayOffset() {
307         throw new UnsupportedOperationException("direct buffer");
308     }
309 
310     @Override
311     public boolean hasMemoryAddress() {
312         PoolChunk<ByteBuffer> chunk = this.chunk;
313         return chunk != null && chunk.cleanable.hasMemoryAddress();
314     }
315 
316     @Override
317     public long memoryAddress() {
318         ensureAccessible();
319         if (!hasMemoryAddress()) {
320             throw new UnsupportedOperationException();
321         }
322         return chunk.cleanable.memoryAddress() + offset;
323     }
324 
325     @Override
326     long _memoryAddress() {
327         return hasMemoryAddress() ? chunk.cleanable.memoryAddress() + offset : 0L;
328     }
329 }