1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 }