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