1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.buffer;
17
18 import io.netty.util.internal.PlatformDependent;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 import java.nio.ReadOnlyBufferException;
26
27 import static io.netty.util.internal.MathUtil.isOutOfBounds;
28 import static io.netty.util.internal.ObjectUtil.checkNotNull;
29 import static io.netty.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER;
30
31
32
33
34 final class UnsafeByteBufUtil {
35 private static final boolean UNALIGNED = PlatformDependent.isUnaligned();
36 private static final byte ZERO = 0;
37 private static final int MAX_HAND_ROLLED_SET_ZERO_BYTES = 64;
38
39 static byte getByte(long address) {
40 return PlatformDependent.getByte(address);
41 }
42
43 static short getShort(long address) {
44 if (UNALIGNED) {
45 short v = PlatformDependent.getShort(address);
46 return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
47 }
48 return (short) (PlatformDependent.getByte(address) << 8 | PlatformDependent.getByte(address + 1) & 0xff);
49 }
50
51 static short getShortLE(long address) {
52 if (UNALIGNED) {
53 short v = PlatformDependent.getShort(address);
54 return BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(v) : v;
55 }
56 return (short) (PlatformDependent.getByte(address) & 0xff | PlatformDependent.getByte(address + 1) << 8);
57 }
58
59 static int getUnsignedMedium(long address) {
60 if (UNALIGNED) {
61 return (PlatformDependent.getByte(address) & 0xff) << 16 |
62 (BIG_ENDIAN_NATIVE_ORDER ? PlatformDependent.getShort(address + 1)
63 : Short.reverseBytes(PlatformDependent.getShort(address + 1))) & 0xffff;
64 }
65 return (PlatformDependent.getByte(address) & 0xff) << 16 |
66 (PlatformDependent.getByte(address + 1) & 0xff) << 8 |
67 PlatformDependent.getByte(address + 2) & 0xff;
68 }
69
70 static int getUnsignedMediumLE(long address) {
71 if (UNALIGNED) {
72 return (PlatformDependent.getByte(address) & 0xff) |
73 ((BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(PlatformDependent.getShort(address + 1))
74 : PlatformDependent.getShort(address + 1)) & 0xffff) << 8;
75 }
76 return PlatformDependent.getByte(address) & 0xff |
77 (PlatformDependent.getByte(address + 1) & 0xff) << 8 |
78 (PlatformDependent.getByte(address + 2) & 0xff) << 16;
79 }
80
81 static int getInt(long address) {
82 if (UNALIGNED) {
83 int v = PlatformDependent.getInt(address);
84 return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
85 }
86 return PlatformDependent.getByte(address) << 24 |
87 (PlatformDependent.getByte(address + 1) & 0xff) << 16 |
88 (PlatformDependent.getByte(address + 2) & 0xff) << 8 |
89 PlatformDependent.getByte(address + 3) & 0xff;
90 }
91
92 static int getIntLE(long address) {
93 if (UNALIGNED) {
94 int v = PlatformDependent.getInt(address);
95 return BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(v) : v;
96 }
97 return PlatformDependent.getByte(address) & 0xff |
98 (PlatformDependent.getByte(address + 1) & 0xff) << 8 |
99 (PlatformDependent.getByte(address + 2) & 0xff) << 16 |
100 PlatformDependent.getByte(address + 3) << 24;
101 }
102
103 static long getLong(long address) {
104 if (UNALIGNED) {
105 long v = PlatformDependent.getLong(address);
106 return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
107 }
108 return ((long) PlatformDependent.getByte(address)) << 56 |
109 (PlatformDependent.getByte(address + 1) & 0xffL) << 48 |
110 (PlatformDependent.getByte(address + 2) & 0xffL) << 40 |
111 (PlatformDependent.getByte(address + 3) & 0xffL) << 32 |
112 (PlatformDependent.getByte(address + 4) & 0xffL) << 24 |
113 (PlatformDependent.getByte(address + 5) & 0xffL) << 16 |
114 (PlatformDependent.getByte(address + 6) & 0xffL) << 8 |
115 (PlatformDependent.getByte(address + 7)) & 0xffL;
116 }
117
118 static long getLongLE(long address) {
119 if (UNALIGNED) {
120 long v = PlatformDependent.getLong(address);
121 return BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(v) : v;
122 }
123 return (PlatformDependent.getByte(address)) & 0xffL |
124 (PlatformDependent.getByte(address + 1) & 0xffL) << 8 |
125 (PlatformDependent.getByte(address + 2) & 0xffL) << 16 |
126 (PlatformDependent.getByte(address + 3) & 0xffL) << 24 |
127 (PlatformDependent.getByte(address + 4) & 0xffL) << 32 |
128 (PlatformDependent.getByte(address + 5) & 0xffL) << 40 |
129 (PlatformDependent.getByte(address + 6) & 0xffL) << 48 |
130 ((long) PlatformDependent.getByte(address + 7)) << 56;
131 }
132
133 static void setByte(long address, int value) {
134 PlatformDependent.putByte(address, (byte) value);
135 }
136
137 static void setShort(long address, int value) {
138 if (UNALIGNED) {
139 PlatformDependent.putShort(
140 address, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
141 } else {
142 PlatformDependent.putByte(address, (byte) (value >>> 8));
143 PlatformDependent.putByte(address + 1, (byte) value);
144 }
145 }
146
147 static void setShortLE(long address, int value) {
148 if (UNALIGNED) {
149 PlatformDependent.putShort(
150 address, BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) value) : (short) value);
151 } else {
152 PlatformDependent.putByte(address, (byte) value);
153 PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
154 }
155 }
156
157 static void setMedium(long address, int value) {
158 PlatformDependent.putByte(address, (byte) (value >>> 16));
159 if (UNALIGNED) {
160 PlatformDependent.putShort(address + 1, BIG_ENDIAN_NATIVE_ORDER ? (short) value
161 : Short.reverseBytes((short) value));
162 } else {
163 PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
164 PlatformDependent.putByte(address + 2, (byte) value);
165 }
166 }
167
168 static void setMediumLE(long address, int value) {
169 PlatformDependent.putByte(address, (byte) value);
170 if (UNALIGNED) {
171 PlatformDependent.putShort(address + 1, BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) (value >>> 8))
172 : (short) (value >>> 8));
173 } else {
174 PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
175 PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
176 }
177 }
178
179 static void setInt(long address, int value) {
180 if (UNALIGNED) {
181 PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
182 } else {
183 PlatformDependent.putByte(address, (byte) (value >>> 24));
184 PlatformDependent.putByte(address + 1, (byte) (value >>> 16));
185 PlatformDependent.putByte(address + 2, (byte) (value >>> 8));
186 PlatformDependent.putByte(address + 3, (byte) value);
187 }
188 }
189
190 static void setIntLE(long address, int value) {
191 if (UNALIGNED) {
192 PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(value) : value);
193 } else {
194 PlatformDependent.putByte(address, (byte) value);
195 PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
196 PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
197 PlatformDependent.putByte(address + 3, (byte) (value >>> 24));
198 }
199 }
200
201 static void setLong(long address, long value) {
202 if (UNALIGNED) {
203 PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
204 } else {
205 PlatformDependent.putByte(address, (byte) (value >>> 56));
206 PlatformDependent.putByte(address + 1, (byte) (value >>> 48));
207 PlatformDependent.putByte(address + 2, (byte) (value >>> 40));
208 PlatformDependent.putByte(address + 3, (byte) (value >>> 32));
209 PlatformDependent.putByte(address + 4, (byte) (value >>> 24));
210 PlatformDependent.putByte(address + 5, (byte) (value >>> 16));
211 PlatformDependent.putByte(address + 6, (byte) (value >>> 8));
212 PlatformDependent.putByte(address + 7, (byte) value);
213 }
214 }
215
216 static void setLongLE(long address, long value) {
217 if (UNALIGNED) {
218 PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(value) : value);
219 } else {
220 PlatformDependent.putByte(address, (byte) value);
221 PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
222 PlatformDependent.putByte(address + 2, (byte) (value >>> 16));
223 PlatformDependent.putByte(address + 3, (byte) (value >>> 24));
224 PlatformDependent.putByte(address + 4, (byte) (value >>> 32));
225 PlatformDependent.putByte(address + 5, (byte) (value >>> 40));
226 PlatformDependent.putByte(address + 6, (byte) (value >>> 48));
227 PlatformDependent.putByte(address + 7, (byte) (value >>> 56));
228 }
229 }
230
231 static byte getByte(byte[] array, int index) {
232 return PlatformDependent.getByte(array, index);
233 }
234
235 static short getShort(byte[] array, int index) {
236 if (UNALIGNED) {
237 short v = PlatformDependent.getShort(array, index);
238 return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
239 }
240 return (short) (PlatformDependent.getByte(array, index) << 8 |
241 PlatformDependent.getByte(array, index + 1) & 0xff);
242 }
243
244 static short getShortLE(byte[] array, int index) {
245 if (UNALIGNED) {
246 short v = PlatformDependent.getShort(array, index);
247 return BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(v) : v;
248 }
249 return (short) (PlatformDependent.getByte(array, index) & 0xff |
250 PlatformDependent.getByte(array, index + 1) << 8);
251 }
252
253 static int getUnsignedMedium(byte[] array, int index) {
254 if (UNALIGNED) {
255 return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
256 (BIG_ENDIAN_NATIVE_ORDER ? PlatformDependent.getShort(array, index + 1)
257 : Short.reverseBytes(PlatformDependent.getShort(array, index + 1)))
258 & 0xffff;
259 }
260 return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
261 (PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
262 PlatformDependent.getByte(array, index + 2) & 0xff;
263 }
264
265 static int getUnsignedMediumLE(byte[] array, int index) {
266 if (UNALIGNED) {
267 return (PlatformDependent.getByte(array, index) & 0xff) |
268 ((BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes(PlatformDependent.getShort(array, index + 1))
269 : PlatformDependent.getShort(array, index + 1)) & 0xffff) << 8;
270 }
271 return PlatformDependent.getByte(array, index) & 0xff |
272 (PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
273 (PlatformDependent.getByte(array, index + 2) & 0xff) << 16;
274 }
275
276 static int getInt(byte[] array, int index) {
277 if (UNALIGNED) {
278 int v = PlatformDependent.getInt(array, index);
279 return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
280 }
281 return PlatformDependent.getByte(array, index) << 24 |
282 (PlatformDependent.getByte(array, index + 1) & 0xff) << 16 |
283 (PlatformDependent.getByte(array, index + 2) & 0xff) << 8 |
284 PlatformDependent.getByte(array, index + 3) & 0xff;
285 }
286
287 static int getIntLE(byte[] array, int index) {
288 if (UNALIGNED) {
289 int v = PlatformDependent.getInt(array, index);
290 return BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(v) : v;
291 }
292 return PlatformDependent.getByte(array, index) & 0xff |
293 (PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
294 (PlatformDependent.getByte(array, index + 2) & 0xff) << 16 |
295 PlatformDependent.getByte(array, index + 3) << 24;
296 }
297
298 static long getLong(byte[] array, int index) {
299 if (UNALIGNED) {
300 long v = PlatformDependent.getLong(array, index);
301 return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
302 }
303 return ((long) PlatformDependent.getByte(array, index)) << 56 |
304 (PlatformDependent.getByte(array, index + 1) & 0xffL) << 48 |
305 (PlatformDependent.getByte(array, index + 2) & 0xffL) << 40 |
306 (PlatformDependent.getByte(array, index + 3) & 0xffL) << 32 |
307 (PlatformDependent.getByte(array, index + 4) & 0xffL) << 24 |
308 (PlatformDependent.getByte(array, index + 5) & 0xffL) << 16 |
309 (PlatformDependent.getByte(array, index + 6) & 0xffL) << 8 |
310 (PlatformDependent.getByte(array, index + 7)) & 0xffL;
311 }
312
313 static long getLongLE(byte[] array, int index) {
314 if (UNALIGNED) {
315 long v = PlatformDependent.getLong(array, index);
316 return BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(v) : v;
317 }
318 return PlatformDependent.getByte(array, index) & 0xffL |
319 (PlatformDependent.getByte(array, index + 1) & 0xffL) << 8 |
320 (PlatformDependent.getByte(array, index + 2) & 0xffL) << 16 |
321 (PlatformDependent.getByte(array, index + 3) & 0xffL) << 24 |
322 (PlatformDependent.getByte(array, index + 4) & 0xffL) << 32 |
323 (PlatformDependent.getByte(array, index + 5) & 0xffL) << 40 |
324 (PlatformDependent.getByte(array, index + 6) & 0xffL) << 48 |
325 ((long) PlatformDependent.getByte(array, index + 7)) << 56;
326 }
327
328 static void setByte(byte[] array, int index, int value) {
329 PlatformDependent.putByte(array, index, (byte) value);
330 }
331
332 static void setShort(byte[] array, int index, int value) {
333 if (UNALIGNED) {
334 PlatformDependent.putShort(array, index,
335 BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
336 } else {
337 PlatformDependent.putByte(array, index, (byte) (value >>> 8));
338 PlatformDependent.putByte(array, index + 1, (byte) value);
339 }
340 }
341
342 static void setShortLE(byte[] array, int index, int value) {
343 if (UNALIGNED) {
344 PlatformDependent.putShort(array, index,
345 BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) value) : (short) value);
346 } else {
347 PlatformDependent.putByte(array, index, (byte) value);
348 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
349 }
350 }
351
352 static void setMedium(byte[] array, int index, int value) {
353 PlatformDependent.putByte(array, index, (byte) (value >>> 16));
354 if (UNALIGNED) {
355 PlatformDependent.putShort(array, index + 1,
356 BIG_ENDIAN_NATIVE_ORDER ? (short) value
357 : Short.reverseBytes((short) value));
358 } else {
359 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
360 PlatformDependent.putByte(array, index + 2, (byte) value);
361 }
362 }
363
364 static void setMediumLE(byte[] array, int index, int value) {
365 PlatformDependent.putByte(array, index, (byte) value);
366 if (UNALIGNED) {
367 PlatformDependent.putShort(array, index + 1,
368 BIG_ENDIAN_NATIVE_ORDER ? Short.reverseBytes((short) (value >>> 8))
369 : (short) (value >>> 8));
370 } else {
371 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
372 PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
373 }
374 }
375
376 static void setInt(byte[] array, int index, int value) {
377 if (UNALIGNED) {
378 PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
379 } else {
380 PlatformDependent.putByte(array, index, (byte) (value >>> 24));
381 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 16));
382 PlatformDependent.putByte(array, index + 2, (byte) (value >>> 8));
383 PlatformDependent.putByte(array, index + 3, (byte) value);
384 }
385 }
386
387 static void setIntLE(byte[] array, int index, int value) {
388 if (UNALIGNED) {
389 PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? Integer.reverseBytes(value) : value);
390 } else {
391 PlatformDependent.putByte(array, index, (byte) value);
392 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
393 PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
394 PlatformDependent.putByte(array, index + 3, (byte) (value >>> 24));
395 }
396 }
397
398 static void setLong(byte[] array, int index, long value) {
399 if (UNALIGNED) {
400 PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
401 } else {
402 PlatformDependent.putByte(array, index, (byte) (value >>> 56));
403 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 48));
404 PlatformDependent.putByte(array, index + 2, (byte) (value >>> 40));
405 PlatformDependent.putByte(array, index + 3, (byte) (value >>> 32));
406 PlatformDependent.putByte(array, index + 4, (byte) (value >>> 24));
407 PlatformDependent.putByte(array, index + 5, (byte) (value >>> 16));
408 PlatformDependent.putByte(array, index + 6, (byte) (value >>> 8));
409 PlatformDependent.putByte(array, index + 7, (byte) value);
410 }
411 }
412
413 static void setLongLE(byte[] array, int index, long value) {
414 if (UNALIGNED) {
415 PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? Long.reverseBytes(value) : value);
416 } else {
417 PlatformDependent.putByte(array, index, (byte) value);
418 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
419 PlatformDependent.putByte(array, index + 2, (byte) (value >>> 16));
420 PlatformDependent.putByte(array, index + 3, (byte) (value >>> 24));
421 PlatformDependent.putByte(array, index + 4, (byte) (value >>> 32));
422 PlatformDependent.putByte(array, index + 5, (byte) (value >>> 40));
423 PlatformDependent.putByte(array, index + 6, (byte) (value >>> 48));
424 PlatformDependent.putByte(array, index + 7, (byte) (value >>> 56));
425 }
426 }
427
428 private static void batchSetZero(byte[] data, int index, int length) {
429 int longBatches = length / 8;
430 for (int i = 0; i < longBatches; i++) {
431 PlatformDependent.putLong(data, index, ZERO);
432 index += 8;
433 }
434 final int remaining = length % 8;
435 for (int i = 0; i < remaining; i++) {
436 PlatformDependent.putByte(data, index + i, ZERO);
437 }
438 }
439
440 static void setZero(byte[] array, int index, int length) {
441 if (length == 0) {
442 return;
443 }
444
445 if (UNALIGNED && length <= MAX_HAND_ROLLED_SET_ZERO_BYTES) {
446 batchSetZero(array, index, length);
447 } else {
448 PlatformDependent.setMemory(array, index, length, ZERO);
449 }
450 }
451
452 static ByteBuf copy(AbstractByteBuf buf, long addr, int index, int length) {
453 buf.checkIndex(index, length);
454 ByteBuf copy = buf.alloc().directBuffer(length, buf.maxCapacity());
455 if (length != 0) {
456 if (copy.hasMemoryAddress()) {
457 PlatformDependent.copyMemory(addr, copy.memoryAddress(), length);
458 copy.setIndex(0, length);
459 } else {
460 copy.writeBytes(buf, index, length);
461 }
462 }
463 return copy;
464 }
465
466 static int setBytes(AbstractByteBuf buf, long addr, int index, InputStream in, int length) throws IOException {
467 buf.checkIndex(index, length);
468 ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
469 try {
470 byte[] tmp = tmpBuf.array();
471 int offset = tmpBuf.arrayOffset();
472 int readBytes = in.read(tmp, offset, length);
473 if (readBytes > 0) {
474 PlatformDependent.copyMemory(tmp, offset, addr, readBytes);
475 }
476 return readBytes;
477 } finally {
478 tmpBuf.release();
479 }
480 }
481
482 static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuf dst, int dstIndex, int length) {
483 buf.checkIndex(index, length);
484 checkNotNull(dst, "dst");
485 if (isOutOfBounds(dstIndex, length, dst.capacity())) {
486 throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
487 }
488
489 if (dst.hasMemoryAddress()) {
490 PlatformDependent.copyMemory(addr, dst.memoryAddress() + dstIndex, length);
491 } else if (dst.hasArray()) {
492 PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dstIndex, length);
493 } else {
494 dst.setBytes(dstIndex, buf, index, length);
495 }
496 }
497
498 static void getBytes(AbstractByteBuf buf, long addr, int index, byte[] dst, int dstIndex, int length) {
499 buf.checkIndex(index, length);
500 checkNotNull(dst, "dst");
501 if (isOutOfBounds(dstIndex, length, dst.length)) {
502 throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
503 }
504 if (length != 0) {
505 PlatformDependent.copyMemory(addr, dst, dstIndex, length);
506 }
507 }
508
509 static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer dst) {
510 buf.checkIndex(index, dst.remaining());
511 if (dst.remaining() == 0) {
512 return;
513 }
514
515 if (dst.isDirect()) {
516 if (dst.isReadOnly()) {
517
518 throw new ReadOnlyBufferException();
519 }
520
521 long dstAddress = PlatformDependent.directBufferAddress(dst);
522 PlatformDependent.copyMemory(addr, dstAddress + dst.position(), dst.remaining());
523 dst.position(dst.position() + dst.remaining());
524 } else if (dst.hasArray()) {
525
526 PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dst.position(), dst.remaining());
527 dst.position(dst.position() + dst.remaining());
528 } else {
529 dst.put(buf.nioBuffer());
530 }
531 }
532
533 static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuf src, int srcIndex, int length) {
534 buf.checkIndex(index, length);
535 checkNotNull(src, "src");
536 if (isOutOfBounds(srcIndex, length, src.capacity())) {
537 throw new IndexOutOfBoundsException("srcIndex: " + srcIndex);
538 }
539
540 if (length != 0) {
541 if (src.hasMemoryAddress()) {
542 PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr, length);
543 } else if (src.hasArray()) {
544 PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr, length);
545 } else {
546 src.getBytes(srcIndex, buf, index, length);
547 }
548 }
549 }
550
551 static void setBytes(AbstractByteBuf buf, long addr, int index, byte[] src, int srcIndex, int length) {
552 buf.checkIndex(index, length);
553
554
555 checkNotNull(src, "src");
556 if (isOutOfBounds(srcIndex, length, src.length)) {
557 throw new IndexOutOfBoundsException("srcIndex: " + srcIndex);
558 }
559
560 if (length != 0) {
561 PlatformDependent.copyMemory(src, srcIndex, addr, length);
562 }
563 }
564
565 static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer src) {
566 final int length = src.remaining();
567 if (length == 0) {
568 return;
569 }
570
571 if (src.isDirect()) {
572 buf.checkIndex(index, length);
573
574 long srcAddress = PlatformDependent.directBufferAddress(src);
575 PlatformDependent.copyMemory(srcAddress + src.position(), addr, length);
576 src.position(src.position() + length);
577 } else if (src.hasArray()) {
578 buf.checkIndex(index, length);
579
580 PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr, length);
581 src.position(src.position() + length);
582 } else {
583 if (length < 8) {
584 setSingleBytes(buf, addr, index, src, length);
585 } else {
586
587 assert buf.nioBufferCount() == 1;
588 final ByteBuffer internalBuffer = buf.internalNioBuffer(index, length);
589 internalBuffer.put(src);
590 }
591 }
592 }
593
594 private static void setSingleBytes(final AbstractByteBuf buf, final long addr, final int index,
595 final ByteBuffer src, final int length) {
596 buf.checkIndex(index, length);
597 final int srcPosition = src.position();
598 final int srcLimit = src.limit();
599 long dstAddr = addr;
600 for (int srcIndex = srcPosition; srcIndex < srcLimit; srcIndex++) {
601 final byte value = src.get(srcIndex);
602 PlatformDependent.putByte(dstAddr, value);
603 dstAddr++;
604 }
605 src.position(srcLimit);
606 }
607
608 static void getBytes(AbstractByteBuf buf, long addr, int index, OutputStream out, int length) throws IOException {
609 buf.checkIndex(index, length);
610 if (length != 0) {
611 int len = Math.min(length, ByteBufUtil.WRITE_CHUNK_SIZE);
612 if (len <= ByteBufUtil.MAX_TL_ARRAY_LEN || !buf.alloc().isDirectBufferPooled()) {
613 getBytes(addr, ByteBufUtil.threadLocalTempArray(len), 0, len, out, length);
614 } else {
615
616 ByteBuf tmpBuf = buf.alloc().heapBuffer(len);
617 try {
618 byte[] tmp = tmpBuf.array();
619 int offset = tmpBuf.arrayOffset();
620 getBytes(addr, tmp, offset, len, out, length);
621 } finally {
622 tmpBuf.release();
623 }
624 }
625 }
626 }
627
628 private static void getBytes(long inAddr, byte[] in, int inOffset, int inLen, OutputStream out, int outLen)
629 throws IOException {
630 do {
631 int len = Math.min(inLen, outLen);
632 PlatformDependent.copyMemory(inAddr, in, inOffset, len);
633 out.write(in, inOffset, len);
634 outLen -= len;
635 inAddr += len;
636 } while (outLen > 0);
637 }
638
639 private static void batchSetZero(long addr, int length) {
640 int longBatches = length / 8;
641 for (int i = 0; i < longBatches; i++) {
642 PlatformDependent.putLong(addr, ZERO);
643 addr += 8;
644 }
645 final int remaining = length % 8;
646 for (int i = 0; i < remaining; i++) {
647 PlatformDependent.putByte(addr + i, ZERO);
648 }
649 }
650
651 static void setZero(long addr, int length) {
652 if (length == 0) {
653 return;
654 }
655
656 if (length <= MAX_HAND_ROLLED_SET_ZERO_BYTES) {
657 if (!UNALIGNED) {
658
659 int bytesToGetAligned = zeroTillAligned(addr, length);
660 addr += bytesToGetAligned;
661 length -= bytesToGetAligned;
662 if (length == 0) {
663 return;
664 }
665 assert addr % 8 == 0;
666 }
667 batchSetZero(addr, length);
668 } else {
669 PlatformDependent.setMemory(addr, length, ZERO);
670 }
671 }
672
673 private static int zeroTillAligned(long addr, int length) {
674
675 int bytesToGetAligned = Math.min((int) (addr % 8), length);
676 for (int i = 0; i < bytesToGetAligned; i++) {
677 PlatformDependent.putByte(addr + i, ZERO);
678 }
679 return bytesToGetAligned;
680 }
681
682 static UnpooledUnsafeDirectByteBuf newUnsafeDirectByteBuf(
683 ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
684 if (PlatformDependent.useDirectBufferNoCleaner()) {
685 return new UnpooledUnsafeNoCleanerDirectByteBuf(alloc, initialCapacity, maxCapacity);
686 }
687 return new UnpooledUnsafeDirectByteBuf(alloc, initialCapacity, maxCapacity);
688 }
689
690 private UnsafeByteBufUtil() { }
691 }