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
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.nio.ByteBuffer;
25 import java.nio.channels.ClosedChannelException;
26 import java.nio.channels.GatheringByteChannel;
27 import java.nio.channels.ScatteringByteChannel;
28
29 final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
30
31 private static final Recycler<PooledDirectByteBuf> RECYCLER = new Recycler<PooledDirectByteBuf>() {
32 @Override
33 protected PooledDirectByteBuf newObject(Handle 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(Recycler.Handle 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 int _getUnsignedMedium(int index) {
70 index = idx(index);
71 return (memory.get(index) & 0xff) << 16 | (memory.get(index + 1) & 0xff) << 8 | memory.get(index + 2) & 0xff;
72 }
73
74 @Override
75 protected int _getInt(int index) {
76 return memory.getInt(idx(index));
77 }
78
79 @Override
80 protected long _getLong(int index) {
81 return memory.getLong(idx(index));
82 }
83
84 @Override
85 public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
86 checkDstIndex(index, length, dstIndex, dst.capacity());
87 if (dst.hasArray()) {
88 getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
89 } else if (dst.nioBufferCount() > 0) {
90 for (ByteBuffer bb: dst.nioBuffers(dstIndex, length)) {
91 int bbLen = bb.remaining();
92 getBytes(index, bb);
93 index += bbLen;
94 }
95 } else {
96 dst.setBytes(dstIndex, this, index, length);
97 }
98 return this;
99 }
100
101 @Override
102 public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
103 getBytes(index, dst, dstIndex, length, false);
104 return this;
105 }
106
107 private void getBytes(int index, byte[] dst, int dstIndex, int length, boolean internal) {
108 checkDstIndex(index, length, dstIndex, dst.length);
109 ByteBuffer tmpBuf;
110 if (internal) {
111 tmpBuf = internalNioBuffer();
112 } else {
113 tmpBuf = memory.duplicate();
114 }
115 index = idx(index);
116 tmpBuf.clear().position(index).limit(index + length);
117 tmpBuf.get(dst, dstIndex, length);
118 }
119
120 @Override
121 public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
122 checkReadableBytes(length);
123 getBytes(readerIndex, dst, dstIndex, length, true);
124 readerIndex += length;
125 return this;
126 }
127
128 @Override
129 public ByteBuf getBytes(int index, ByteBuffer dst) {
130 getBytes(index, dst, false);
131 return this;
132 }
133
134 private void getBytes(int index, ByteBuffer dst, boolean internal) {
135 checkIndex(index, dst.remaining());
136 ByteBuffer tmpBuf;
137 if (internal) {
138 tmpBuf = internalNioBuffer();
139 } else {
140 tmpBuf = memory.duplicate();
141 }
142 index = idx(index);
143 tmpBuf.clear().position(index).limit(index + dst.remaining());
144 dst.put(tmpBuf);
145 }
146
147 @Override
148 public ByteBuf readBytes(ByteBuffer dst) {
149 int length = dst.remaining();
150 checkReadableBytes(length);
151 getBytes(readerIndex, dst, true);
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
168 byte[] tmp = new byte[length];
169 ByteBuffer tmpBuf;
170 if (internal) {
171 tmpBuf = internalNioBuffer();
172 } else {
173 tmpBuf = memory.duplicate();
174 }
175 tmpBuf.clear().position(idx(index));
176 tmpBuf.get(tmp);
177 out.write(tmp);
178 }
179
180 @Override
181 public ByteBuf readBytes(OutputStream out, int length) throws IOException {
182 checkReadableBytes(length);
183 getBytes(readerIndex, out, length, true);
184 readerIndex += length;
185 return this;
186 }
187
188 @Override
189 public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
190 return getBytes(index, out, length, false);
191 }
192
193 private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
194 checkIndex(index, length);
195 if (length == 0) {
196 return 0;
197 }
198
199 ByteBuffer tmpBuf;
200 if (internal) {
201 tmpBuf = internalNioBuffer();
202 } else {
203 tmpBuf = memory.duplicate();
204 }
205 index = idx(index);
206 tmpBuf.clear().position(index).limit(index + length);
207 return out.write(tmpBuf);
208 }
209
210 @Override
211 public int readBytes(GatheringByteChannel out, int length) throws IOException {
212 checkReadableBytes(length);
213 int readBytes = getBytes(readerIndex, out, length, true);
214 readerIndex += readBytes;
215 return readBytes;
216 }
217
218 @Override
219 protected void _setByte(int index, int value) {
220 memory.put(idx(index), (byte) value);
221 }
222
223 @Override
224 protected void _setShort(int index, int value) {
225 memory.putShort(idx(index), (short) value);
226 }
227
228 @Override
229 protected void _setMedium(int index, int value) {
230 index = idx(index);
231 memory.put(index, (byte) (value >>> 16));
232 memory.put(index + 1, (byte) (value >>> 8));
233 memory.put(index + 2, (byte) value);
234 }
235
236 @Override
237 protected void _setInt(int index, int value) {
238 memory.putInt(idx(index), value);
239 }
240
241 @Override
242 protected void _setLong(int index, long value) {
243 memory.putLong(idx(index), value);
244 }
245
246 @Override
247 public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
248 checkSrcIndex(index, length, srcIndex, src.capacity());
249 if (src.hasArray()) {
250 setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);
251 } else if (src.nioBufferCount() > 0) {
252 for (ByteBuffer bb: src.nioBuffers(srcIndex, length)) {
253 int bbLen = bb.remaining();
254 setBytes(index, bb);
255 index += bbLen;
256 }
257 } else {
258 src.getBytes(srcIndex, this, index, length);
259 }
260 return this;
261 }
262
263 @Override
264 public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
265 checkSrcIndex(index, length, srcIndex, src.length);
266 ByteBuffer tmpBuf = internalNioBuffer();
267 index = idx(index);
268 tmpBuf.clear().position(index).limit(index + length);
269 tmpBuf.put(src, srcIndex, length);
270 return this;
271 }
272
273 @Override
274 public ByteBuf setBytes(int index, ByteBuffer src) {
275 checkIndex(index, src.remaining());
276 ByteBuffer tmpBuf = internalNioBuffer();
277 if (src == tmpBuf) {
278 src = src.duplicate();
279 }
280
281 index = idx(index);
282 tmpBuf.clear().position(index).limit(index + src.remaining());
283 tmpBuf.put(src);
284 return this;
285 }
286
287 @Override
288 public int setBytes(int index, InputStream in, int length) throws IOException {
289 checkIndex(index, length);
290 byte[] tmp = new byte[length];
291 int readBytes = in.read(tmp);
292 if (readBytes <= 0) {
293 return readBytes;
294 }
295 ByteBuffer tmpBuf = internalNioBuffer();
296 tmpBuf.clear().position(idx(index));
297 tmpBuf.put(tmp, 0, readBytes);
298 return readBytes;
299 }
300
301 @Override
302 public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
303 checkIndex(index, length);
304 ByteBuffer tmpBuf = internalNioBuffer();
305 index = idx(index);
306 tmpBuf.clear().position(index).limit(index + length);
307 try {
308 return in.read(tmpBuf);
309 } catch (ClosedChannelException ignored) {
310 return -1;
311 }
312 }
313
314 @Override
315 public ByteBuf copy(int index, int length) {
316 checkIndex(index, length);
317 ByteBuf copy = alloc().directBuffer(length, maxCapacity());
318 copy.writeBytes(this, index, length);
319 return copy;
320 }
321
322 @Override
323 public int nioBufferCount() {
324 return 1;
325 }
326
327 @Override
328 public ByteBuffer nioBuffer(int index, int length) {
329 checkIndex(index, length);
330 index = idx(index);
331 return ((ByteBuffer) memory.duplicate().position(index).limit(index + length)).slice();
332 }
333
334 @Override
335 public ByteBuffer[] nioBuffers(int index, int length) {
336 return new ByteBuffer[] { nioBuffer(index, length) };
337 }
338
339 @Override
340 public ByteBuffer internalNioBuffer(int index, int length) {
341 checkIndex(index, length);
342 index = idx(index);
343 return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
344 }
345
346 @Override
347 public boolean hasArray() {
348 return false;
349 }
350
351 @Override
352 public byte[] array() {
353 throw new UnsupportedOperationException("direct buffer");
354 }
355
356 @Override
357 public int arrayOffset() {
358 throw new UnsupportedOperationException("direct buffer");
359 }
360
361 @Override
362 public boolean hasMemoryAddress() {
363 return false;
364 }
365
366 @Override
367 public long memoryAddress() {
368 throw new UnsupportedOperationException();
369 }
370
371 @Override
372 protected Recycler<?> recycler() {
373 return RECYCLER;
374 }
375 }