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