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
30
31
32
33 final class UnsafeByteBufUtil {
34
35 static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
36 private static final boolean UNALIGNED = PlatformDependent.isUnaligned();
37 private static final byte ZERO = 0;
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 int getUnsignedMedium(long address) {
52 if (UNALIGNED) {
53 return (PlatformDependent.getByte(address) & 0xff) << 16 |
54 (BIG_ENDIAN_NATIVE_ORDER ? PlatformDependent.getShort(address + 1)
55 : Short.reverseBytes(PlatformDependent.getShort(address + 1))) & 0xffff;
56 }
57 return (PlatformDependent.getByte(address) & 0xff) << 16 |
58 (PlatformDependent.getByte(address + 1) & 0xff) << 8 |
59 PlatformDependent.getByte(address + 2) & 0xff;
60 }
61
62 static int getInt(long address) {
63 if (UNALIGNED) {
64 int v = PlatformDependent.getInt(address);
65 return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
66 }
67 return PlatformDependent.getByte(address) << 24 |
68 (PlatformDependent.getByte(address + 1) & 0xff) << 16 |
69 (PlatformDependent.getByte(address + 2) & 0xff) << 8 |
70 PlatformDependent.getByte(address + 3) & 0xff;
71 }
72
73 static long getLong(long address) {
74 if (UNALIGNED) {
75 long v = PlatformDependent.getLong(address);
76 return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
77 }
78 return ((long) PlatformDependent.getByte(address)) << 56 |
79 (PlatformDependent.getByte(address + 1) & 0xffL) << 48 |
80 (PlatformDependent.getByte(address + 2) & 0xffL) << 40 |
81 (PlatformDependent.getByte(address + 3) & 0xffL) << 32 |
82 (PlatformDependent.getByte(address + 4) & 0xffL) << 24 |
83 (PlatformDependent.getByte(address + 5) & 0xffL) << 16 |
84 (PlatformDependent.getByte(address + 6) & 0xffL) << 8 |
85 (PlatformDependent.getByte(address + 7)) & 0xffL;
86 }
87
88 static void setByte(long address, int value) {
89 PlatformDependent.putByte(address, (byte) value);
90 }
91
92 static void setShort(long address, int value) {
93 if (UNALIGNED) {
94 PlatformDependent.putShort(
95 address, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
96 } else {
97 PlatformDependent.putByte(address, (byte) (value >>> 8));
98 PlatformDependent.putByte(address + 1, (byte) value);
99 }
100 }
101
102 static void setMedium(long address, int value) {
103 PlatformDependent.putByte(address, (byte) (value >>> 16));
104 if (UNALIGNED) {
105 PlatformDependent.putShort(address + 1, BIG_ENDIAN_NATIVE_ORDER ? (short) value
106 : Short.reverseBytes((short) value));
107 } else {
108 PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
109 PlatformDependent.putByte(address + 2, (byte) value);
110 }
111 }
112
113 static void setInt(long address, int value) {
114 if (UNALIGNED) {
115 PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
116 } else {
117 PlatformDependent.putByte(address, (byte) (value >>> 24));
118 PlatformDependent.putByte(address + 1, (byte) (value >>> 16));
119 PlatformDependent.putByte(address + 2, (byte) (value >>> 8));
120 PlatformDependent.putByte(address + 3, (byte) value);
121 }
122 }
123
124 static void setLong(long address, long value) {
125 if (UNALIGNED) {
126 PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
127 } else {
128 PlatformDependent.putByte(address, (byte) (value >>> 56));
129 PlatformDependent.putByte(address + 1, (byte) (value >>> 48));
130 PlatformDependent.putByte(address + 2, (byte) (value >>> 40));
131 PlatformDependent.putByte(address + 3, (byte) (value >>> 32));
132 PlatformDependent.putByte(address + 4, (byte) (value >>> 24));
133 PlatformDependent.putByte(address + 5, (byte) (value >>> 16));
134 PlatformDependent.putByte(address + 6, (byte) (value >>> 8));
135 PlatformDependent.putByte(address + 7, (byte) value);
136 }
137 }
138
139 static byte getByte(byte[] array, int index) {
140 return PlatformDependent.getByte(array, index);
141 }
142
143 static short getShort(byte[] array, int index) {
144 if (UNALIGNED) {
145 short v = PlatformDependent.getShort(array, index);
146 return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
147 }
148 return (short) (PlatformDependent.getByte(array, index) << 8 |
149 PlatformDependent.getByte(array, index + 1) & 0xff);
150 }
151
152 static int getUnsignedMedium(byte[] array, int index) {
153 if (UNALIGNED) {
154 return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
155 (BIG_ENDIAN_NATIVE_ORDER ? PlatformDependent.getShort(array, index + 1)
156 : Short.reverseBytes(PlatformDependent.getShort(array, index + 1)))
157 & 0xffff;
158 }
159 return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
160 (PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
161 PlatformDependent.getByte(array, index + 2) & 0xff;
162 }
163
164 static int getInt(byte[] array, int index) {
165 if (UNALIGNED) {
166 int v = PlatformDependent.getInt(array, index);
167 return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
168 }
169 return PlatformDependent.getByte(array, index) << 24 |
170 (PlatformDependent.getByte(array, index + 1) & 0xff) << 16 |
171 (PlatformDependent.getByte(array, index + 2) & 0xff) << 8 |
172 PlatformDependent.getByte(array, index + 3) & 0xff;
173 }
174
175 static long getLong(byte[] array, int index) {
176 if (UNALIGNED) {
177 long v = PlatformDependent.getLong(array, index);
178 return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
179 }
180 return ((long) PlatformDependent.getByte(array, index)) << 56 |
181 (PlatformDependent.getByte(array, index + 1) & 0xffL) << 48 |
182 (PlatformDependent.getByte(array, index + 2) & 0xffL) << 40 |
183 (PlatformDependent.getByte(array, index + 3) & 0xffL) << 32 |
184 (PlatformDependent.getByte(array, index + 4) & 0xffL) << 24 |
185 (PlatformDependent.getByte(array, index + 5) & 0xffL) << 16 |
186 (PlatformDependent.getByte(array, index + 6) & 0xffL) << 8 |
187 (PlatformDependent.getByte(array, index + 7)) & 0xffL;
188 }
189
190 static void setByte(byte[] array, int index, int value) {
191 PlatformDependent.putByte(array, index, (byte) value);
192 }
193
194 static void setShort(byte[] array, int index, int value) {
195 if (UNALIGNED) {
196 PlatformDependent.putShort(array, index,
197 BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
198 } else {
199 PlatformDependent.putByte(array, index, (byte) (value >>> 8));
200 PlatformDependent.putByte(array, index + 1, (byte) value);
201 }
202 }
203
204 static void setMedium(byte[] array, int index, int value) {
205 PlatformDependent.putByte(array, index, (byte) (value >>> 16));
206 if (UNALIGNED) {
207 PlatformDependent.putShort(array, index + 1,
208 BIG_ENDIAN_NATIVE_ORDER ? (short) value
209 : Short.reverseBytes((short) value));
210 } else {
211 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
212 PlatformDependent.putByte(array, index + 2, (byte) value);
213 }
214 }
215
216 static void setInt(byte[] array, int index, int value) {
217 if (UNALIGNED) {
218 PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
219 } else {
220 PlatformDependent.putByte(array, index, (byte) (value >>> 24));
221 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 16));
222 PlatformDependent.putByte(array, index + 2, (byte) (value >>> 8));
223 PlatformDependent.putByte(array, index + 3, (byte) value);
224 }
225 }
226
227 static void setLong(byte[] array, int index, long value) {
228 if (UNALIGNED) {
229 PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
230 } else {
231 PlatformDependent.putByte(array, index, (byte) (value >>> 56));
232 PlatformDependent.putByte(array, index + 1, (byte) (value >>> 48));
233 PlatformDependent.putByte(array, index + 2, (byte) (value >>> 40));
234 PlatformDependent.putByte(array, index + 3, (byte) (value >>> 32));
235 PlatformDependent.putByte(array, index + 4, (byte) (value >>> 24));
236 PlatformDependent.putByte(array, index + 5, (byte) (value >>> 16));
237 PlatformDependent.putByte(array, index + 6, (byte) (value >>> 8));
238 PlatformDependent.putByte(array, index + 7, (byte) value);
239 }
240 }
241
242 static void setZero(byte[] array, int index, int length) {
243 if (length == 0) {
244 return;
245 }
246 PlatformDependent.setMemory(array, index, length, ZERO);
247 }
248
249 static ByteBuf copy(AbstractByteBuf buf, long addr, int index, int length) {
250 buf.checkIndex(index, length);
251 ByteBuf copy = buf.alloc().directBuffer(length, buf.maxCapacity());
252 if (length != 0) {
253 if (copy.hasMemoryAddress()) {
254 PlatformDependent.copyMemory(addr, copy.memoryAddress(), length);
255 copy.setIndex(0, length);
256 } else {
257 copy.writeBytes(buf, index, length);
258 }
259 }
260 return copy;
261 }
262
263 static int setBytes(AbstractByteBuf buf, long addr, int index, InputStream in, int length) throws IOException {
264 buf.checkIndex(index, length);
265 ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
266 try {
267 byte[] tmp = tmpBuf.array();
268 int offset = tmpBuf.arrayOffset();
269 int readBytes = in.read(tmp, offset, length);
270 if (readBytes > 0) {
271 PlatformDependent.copyMemory(tmp, offset, addr, readBytes);
272 }
273 return readBytes;
274 } finally {
275 tmpBuf.release();
276 }
277 }
278
279 static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuf dst, int dstIndex, int length) {
280 buf.checkIndex(index, length);
281 checkNotNull(dst, "dst");
282 if (isOutOfBounds(dstIndex, length, dst.capacity())) {
283 throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
284 }
285
286 if (dst.hasMemoryAddress()) {
287 PlatformDependent.copyMemory(addr, dst.memoryAddress() + dstIndex, length);
288 } else if (dst.hasArray()) {
289 PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dstIndex, length);
290 } else {
291 dst.setBytes(dstIndex, buf, index, length);
292 }
293 }
294
295 static void getBytes(AbstractByteBuf buf, long addr, int index, byte[] dst, int dstIndex, int length) {
296 buf.checkIndex(index, length);
297 checkNotNull(dst, "dst");
298 if (isOutOfBounds(dstIndex, length, dst.length)) {
299 throw new IndexOutOfBoundsException("dstIndex: " + dstIndex);
300 }
301 if (length != 0) {
302 PlatformDependent.copyMemory(addr, dst, dstIndex, length);
303 }
304 }
305
306 static void getBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer dst) {
307 buf.checkIndex(index, dst.remaining());
308 if (dst.remaining() == 0) {
309 return;
310 }
311
312 if (dst.isDirect()) {
313 if (dst.isReadOnly()) {
314
315 throw new ReadOnlyBufferException();
316 }
317
318 long dstAddress = PlatformDependent.directBufferAddress(dst);
319 PlatformDependent.copyMemory(addr, dstAddress + dst.position(), dst.remaining());
320 dst.position(dst.position() + dst.remaining());
321 } else if (dst.hasArray()) {
322
323 PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dst.position(), dst.remaining());
324 dst.position(dst.position() + dst.remaining());
325 } else {
326 dst.put(buf.nioBuffer());
327 }
328 }
329
330 static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuf src, int srcIndex, int length) {
331 buf.checkIndex(index, length);
332 checkNotNull(src, "src");
333 if (isOutOfBounds(srcIndex, length, src.capacity())) {
334 throw new IndexOutOfBoundsException("srcIndex: " + srcIndex);
335 }
336
337 if (length != 0) {
338 if (src.hasMemoryAddress()) {
339 PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, addr, length);
340 } else if (src.hasArray()) {
341 PlatformDependent.copyMemory(src.array(), src.arrayOffset() + srcIndex, addr, length);
342 } else {
343 src.getBytes(srcIndex, buf, index, length);
344 }
345 }
346 }
347
348 static void setBytes(AbstractByteBuf buf, long addr, int index, byte[] src, int srcIndex, int length) {
349 buf.checkIndex(index, length);
350 if (length != 0) {
351 PlatformDependent.copyMemory(src, srcIndex, addr, length);
352 }
353 }
354
355 static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuffer src) {
356 buf.checkIndex(index, src.remaining());
357
358 int length = src.remaining();
359 if (length == 0) {
360 return;
361 }
362
363 if (src.isDirect()) {
364
365 long srcAddress = PlatformDependent.directBufferAddress(src);
366 PlatformDependent.copyMemory(srcAddress + src.position(), addr, src.remaining());
367 src.position(src.position() + length);
368 } else if (src.hasArray()) {
369
370 PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr, length);
371 src.position(src.position() + length);
372 } else {
373 ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
374 try {
375 byte[] tmp = tmpBuf.array();
376 src.get(tmp, tmpBuf.arrayOffset(), length);
377 PlatformDependent.copyMemory(tmp, tmpBuf.arrayOffset(), addr, length);
378 } finally {
379 tmpBuf.release();
380 }
381 }
382 }
383
384 static void getBytes(AbstractByteBuf buf, long addr, int index, OutputStream out, int length) throws IOException {
385 buf.checkIndex(index, length);
386 if (length != 0) {
387 ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
388 try {
389 byte[] tmp = tmpBuf.array();
390 int offset = tmpBuf.arrayOffset();
391 PlatformDependent.copyMemory(addr, tmp, offset, length);
392 out.write(tmp, offset, length);
393 } finally {
394 tmpBuf.release();
395 }
396 }
397 }
398
399 static void setZero(long addr, int length) {
400 if (length == 0) {
401 return;
402 }
403
404 PlatformDependent.setMemory(addr, length, ZERO);
405 }
406
407 static UnpooledUnsafeDirectByteBuf newUnsafeDirectByteBuf(
408 ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
409 if (PlatformDependent.useDirectBufferNoCleaner()) {
410 return new UnpooledUnsafeNoCleanerDirectByteBuf(alloc, initialCapacity, maxCapacity);
411 }
412 return new UnpooledUnsafeDirectByteBuf(alloc, initialCapacity, maxCapacity);
413 }
414
415 private UnsafeByteBufUtil() { }
416 }