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
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 }