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.internal.ObjectPool;
20  import io.netty.util.internal.ObjectPool.Handle;
21  import io.netty.util.internal.ObjectPool.ObjectCreator;
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 ObjectPool<PooledDirectByteBuf> RECYCLER = ObjectPool.newPool(
31              new ObjectCreator<PooledDirectByteBuf>() {
32          @Override
33          public 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 if (dst.nioBufferCount() > 0) {
115             for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
116                 int bbLen = bb.remaining();
117                 getBytes(index, bb);
118                 index += bbLen;
119             }
120         } else {
121             dst.setBytes(dstIndex, this, index, length);
122         }
123         return this;
124     }
125 
126     @Override
127     public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
128         checkDstIndex(index, length, dstIndex, dst.length);
129         _internalNioBuffer(index, length, true).get(dst, dstIndex, length);
130         return this;
131     }
132 
133     @Override
134     public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
135         checkDstIndex(length, dstIndex, dst.length);
136         _internalNioBuffer(readerIndex, length, false).get(dst, dstIndex, length);
137         readerIndex += length;
138         return this;
139     }
140 
141     @Override
142     public ByteBuf getBytes(int index, ByteBuffer dst) {
143         dst.put(duplicateInternalNioBuffer(index, dst.remaining()));
144         return this;
145     }
146 
147     @Override
148     public ByteBuf readBytes(ByteBuffer dst) {
149         int length = dst.remaining();
150         checkReadableBytes(length);
151         dst.put(_internalNioBuffer(readerIndex, length, false));
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         ByteBufUtil.readBytes(alloc(), internal ? internalNioBuffer() : memory.duplicate(), idx(index), length, out);
168     }
169 
170     @Override
171     public ByteBuf readBytes(OutputStream out, int length) throws IOException {
172         checkReadableBytes(length);
173         getBytes(readerIndex, out, length, true);
174         readerIndex += length;
175         return this;
176     }
177 
178     @Override
179     protected void _setByte(int index, int value) {
180         memory.put(idx(index), (byte) value);
181     }
182 
183     @Override
184     protected void _setShort(int index, int value) {
185         memory.putShort(idx(index), (short) value);
186     }
187 
188     @Override
189     protected void _setShortLE(int index, int value) {
190         _setShort(index, ByteBufUtil.swapShort((short) value));
191     }
192 
193     @Override
194     protected void _setMedium(int index, int value) {
195         index = idx(index);
196         memory.put(index, (byte) (value >>> 16));
197         memory.put(index + 1, (byte) (value >>> 8));
198         memory.put(index + 2, (byte) value);
199     }
200 
201     @Override
202     protected void _setMediumLE(int index, int value) {
203         index = idx(index);
204         memory.put(index, (byte) value);
205         memory.put(index + 1, (byte) (value >>> 8));
206         memory.put(index + 2, (byte) (value >>> 16));
207     }
208 
209     @Override
210     protected void _setInt(int index, int value) {
211         memory.putInt(idx(index), value);
212     }
213 
214     @Override
215     protected void _setIntLE(int index, int value) {
216         _setInt(index, ByteBufUtil.swapInt(value));
217     }
218 
219     @Override
220     protected void _setLong(int index, long value) {
221         memory.putLong(idx(index), value);
222     }
223 
224     @Override
225     protected void _setLongLE(int index, long value) {
226         _setLong(index, ByteBufUtil.swapLong(value));
227     }
228 
229     @Override
230     public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
231         checkSrcIndex(index, length, srcIndex, src.capacity());
232         if (src.hasArray()) {
233             setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);
234         } else if (src.nioBufferCount() > 0) {
235             for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) {
236                 int bbLen = bb.remaining();
237                 setBytes(index, bb);
238                 index += bbLen;
239             }
240         } else {
241             src.getBytes(srcIndex, this, index, length);
242         }
243         return this;
244     }
245 
246     @Override
247     public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
248         checkSrcIndex(index, length, srcIndex, src.length);
249         _internalNioBuffer(index, length, false).put(src, srcIndex, length);
250         return this;
251     }
252 
253     @Override
254     public ByteBuf setBytes(int index, ByteBuffer src) {
255         int length = src.remaining();
256         checkIndex(index, length);
257         ByteBuffer tmpBuf = internalNioBuffer();
258         if (src == tmpBuf) {
259             src = src.duplicate();
260         }
261 
262         index = idx(index);
263         tmpBuf.limit(index + length).position(index);
264         tmpBuf.put(src);
265         return this;
266     }
267 
268     @Override
269     public int setBytes(int index, InputStream in, int length) throws IOException {
270         checkIndex(index, length);
271         byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
272         int readBytes = in.read(tmp, 0, length);
273         if (readBytes <= 0) {
274             return readBytes;
275         }
276         ByteBuffer tmpBuf = internalNioBuffer();
277         tmpBuf.position(idx(index));
278         tmpBuf.put(tmp, 0, readBytes);
279         return readBytes;
280     }
281 
282     @Override
283     public ByteBuf copy(int index, int length) {
284         checkIndex(index, length);
285         ByteBuf copy = alloc().directBuffer(length, maxCapacity());
286         return copy.writeBytes(this, index, length);
287     }
288 
289     @Override
290     public boolean hasArray() {
291         return false;
292     }
293 
294     @Override
295     public byte[] array() {
296         throw new UnsupportedOperationException("direct buffer");
297     }
298 
299     @Override
300     public int arrayOffset() {
301         throw new UnsupportedOperationException("direct buffer");
302     }
303 
304     @Override
305     public boolean hasMemoryAddress() {
306         return false;
307     }
308 
309     @Override
310     public long memoryAddress() {
311         throw new UnsupportedOperationException();
312     }
313 }