org.pcap4j.util.ByteArrays Maven / Gradle / Ivy
/*_##########################################################################
_##
_## Copyright (C) 2011-2019 Pcap4J.org
_##
_##########################################################################
*/
package org.pcap4j.util;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteOrder;
import java.util.List;
import java.util.regex.Pattern;
import java.util.zip.Adler32;
import java.util.zip.CRC32;
import org.pcap4j.core.LengthZeroException;
/**
* @author Kaito Yamada
* @since pcap4j 0.9.1
*/
public final class ByteArrays {
/** */
public static final int BYTE_SIZE_IN_BYTES = 1;
/** */
public static final int SHORT_SIZE_IN_BYTES = 2;
/** */
public static final int INT_SIZE_IN_BYTES = 4;
/** */
public static final int LONG_SIZE_IN_BYTES = 8;
/** */
public static final int INET4_ADDRESS_SIZE_IN_BYTES = 4;
/** */
public static final int INET6_ADDRESS_SIZE_IN_BYTES = 16;
/** */
public static final int BYTE_SIZE_IN_BITS = 8;
private static final Pattern NO_SEPARATOR_HEX_STRING_PATTERN =
Pattern.compile("\\A([0-9a-fA-F][0-9a-fA-F])+\\z");
private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
private static final int[] CRC32C_TABLE =
new int[] {
0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, 0x26a1e7e8,
0xd4ca64eb,
0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, 0x4d43cfd0, 0xbf284cd3, 0xac78bf27,
0x5e133c24,
0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087,
0xc494a384,
0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, 0xbc267848,
0x4e4dfb4b,
0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, 0xe72719c1, 0x154c9ac2, 0x061c6936,
0xf477ea35,
0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9,
0x7eaeb2fa,
0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, 0x1642ae59,
0xe4292d5a,
0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, 0x7da08661, 0x8fcb0562, 0x9c9bf696,
0x6ef07595,
0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54,
0x95b17957,
0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, 0xed03a29b,
0x1f682198,
0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, 0x96bf4dcc, 0x64d4cecf, 0x77843d3b,
0x85efbe38,
0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4,
0x0f36e6f7,
0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, 0x4767748a,
0xb50cf789,
0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45,
0x3fd5af46,
0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5,
0xa55230e6,
0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a,
0x2f8b6829,
0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, 0x456cac67, 0xb7072f64, 0xa457dc90,
0x563c5f93,
0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f,
0xdce5075c,
0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, 0xb4091bff,
0x466298fc,
0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330,
0xccbbc033,
0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e,
0x7681d14d,
0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, 0x0e330a81,
0xfc588982,
0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, 0x758fe5d6, 0x87e466d5, 0x94b49521,
0x66df1622,
0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee,
0xec064eed,
0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, 0xe52cc12c,
0x1747422f,
0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, 0x8ecee914, 0x7ca56a17, 0x6ff599e3,
0x9d9e1ae0,
0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643,
0x07198540,
0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c,
0x8dc0dd8f,
0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2,
0x37faccf1,
0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d,
0xbd23943e,
0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, 0xd5cf889d,
0x27a40b9e,
0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, 0xbe2da0a5, 0x4c4623a6, 0x5f16d052,
0xad7d5351,
};
private ByteArrays() {
throw new AssertionError();
}
/**
* @param array array
* @return a new array containing specified array's elements in reverse order.
*/
public static byte[] reverse(byte[] array) {
byte[] rarray = new byte[array.length];
for (int i = 0; i < array.length; i++) {
rarray[i] = array[array.length - i - 1];
}
return rarray;
}
/**
* @param array array
* @param offset offset
* @return byte value.
*/
public static byte getByte(byte[] array, int offset) {
validateBounds(array, offset, BYTE_SIZE_IN_BYTES);
return array[offset];
}
/**
* @param value value
* @return byte array
*/
public static byte[] toByteArray(byte value) {
return new byte[] {value};
}
/**
* @param value value
* @param separator separator
* @return hex string
*/
public static String toHexString(byte value, String separator) {
return toHexString(toByteArray(value), separator);
}
/**
* @param array array
* @param offset offset
* @return short value
*/
public static short getShort(byte[] array, int offset) {
return getShort(array, offset, ByteOrder.BIG_ENDIAN);
}
/**
* @param array array
* @param offset offset
* @param bo bo
* @return short value
*/
public static short getShort(byte[] array, int offset, ByteOrder bo) {
validateBounds(array, offset, SHORT_SIZE_IN_BYTES);
if (bo == null) {
throw new NullPointerException(" bo: " + bo);
}
if (bo.equals(LITTLE_ENDIAN)) {
return (short) (((array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1)) | ((0xFF & array[offset])));
} else {
return (short) (((array[offset]) << (BYTE_SIZE_IN_BITS * 1)) | ((0xFF & array[offset + 1])));
}
}
/**
* @param value value
* @return byte array
*/
public static byte[] toByteArray(short value) {
return toByteArray(value, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param bo bo
* @return byte array
*/
public static byte[] toByteArray(short value, ByteOrder bo) {
if (bo.equals(LITTLE_ENDIAN)) {
return new byte[] {(byte) (value), (byte) (value >> BYTE_SIZE_IN_BITS * 1)};
} else {
return new byte[] {(byte) (value >> BYTE_SIZE_IN_BITS * 1), (byte) (value)};
}
}
/**
* @param value value
* @param separator separator
* @return hex string
*/
public static String toHexString(short value, String separator) {
return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param separator separator
* @param bo bo
* @return hex string
*/
public static String toHexString(short value, String separator, ByteOrder bo) {
return toHexString(toByteArray(value, bo), separator);
}
/**
* @param array array
* @param offset offset
* @return int value.
*/
public static int getInt(byte[] array, int offset) {
return getInt(array, offset, ByteOrder.BIG_ENDIAN);
}
/**
* @param array array
* @param offset offset
* @param bo bo
* @return int value.
*/
public static int getInt(byte[] array, int offset, ByteOrder bo) {
validateBounds(array, offset, INT_SIZE_IN_BYTES);
if (bo == null) {
throw new NullPointerException(" bo: " + bo);
}
if (bo.equals(LITTLE_ENDIAN)) {
return ((array[offset + 3]) << (BYTE_SIZE_IN_BITS * 3))
| ((0xFF & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 2))
| ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1))
| ((0xFF & array[offset]));
} else {
return ((array[offset]) << (BYTE_SIZE_IN_BITS * 3))
| ((0xFF & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 2))
| ((0xFF & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 1))
| ((0xFF & array[offset + 3]));
}
}
/**
* @param array array
* @param offset offset
* @param length length
* @return int value.
*/
public static int getInt(byte[] array, int offset, int length) {
return getInt(array, offset, length, ByteOrder.BIG_ENDIAN);
}
/**
* @param array array
* @param offset offset
* @param length length
* @param bo bo
* @return int value.
*/
public static int getInt(byte[] array, int offset, int length, ByteOrder bo) {
validateBounds(array, offset, length);
if (length > INT_SIZE_IN_BYTES) {
StringBuilder sb =
new StringBuilder(30)
.append("length must be equal or less than ")
.append(INT_SIZE_IN_BYTES)
.append(", but is: ")
.append(length);
throw new IllegalArgumentException(sb.toString());
}
if (bo == null) {
throw new NullPointerException(" bo: " + bo);
}
int value = 0;
if (bo.equals(LITTLE_ENDIAN)) {
for (int i = offset + length - 1; i >= offset; i--) {
value <<= BYTE_SIZE_IN_BITS;
value |= 0xFF & array[i];
}
} else {
for (int i = offset; i < offset + length; i++) {
value <<= BYTE_SIZE_IN_BITS;
value |= 0xFF & array[i];
}
}
return value;
}
/**
* @param value value
* @return byte array
*/
public static byte[] toByteArray(int value) {
return toByteArray(value, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param bo bo
* @return byte array
*/
public static byte[] toByteArray(int value, ByteOrder bo) {
if (bo.equals(LITTLE_ENDIAN)) {
return new byte[] {
(byte) (value),
(byte) (value >> BYTE_SIZE_IN_BITS * 1),
(byte) (value >> BYTE_SIZE_IN_BITS * 2),
(byte) (value >> BYTE_SIZE_IN_BITS * 3),
};
} else {
return new byte[] {
(byte) (value >> BYTE_SIZE_IN_BITS * 3),
(byte) (value >> BYTE_SIZE_IN_BITS * 2),
(byte) (value >> BYTE_SIZE_IN_BITS * 1),
(byte) (value)
};
}
}
/**
* @param value value
* @param length length
* @return byte array
*/
public static byte[] toByteArray(int value, int length) {
return toByteArray(value, length, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param length length
* @param bo bo
* @return byte array
*/
public static byte[] toByteArray(int value, int length, ByteOrder bo) {
if (length > INT_SIZE_IN_BYTES) {
StringBuilder sb =
new StringBuilder(30)
.append("length must be equal or less than ")
.append(INT_SIZE_IN_BYTES)
.append(", but is: ")
.append(length);
throw new IllegalArgumentException(sb.toString());
}
byte[] arr = new byte[length];
if (bo.equals(LITTLE_ENDIAN)) {
for (int i = 0; i < length; i++) {
arr[length - i - 1] = (byte) (value >> BYTE_SIZE_IN_BITS * i);
}
} else {
for (int i = 0; i < length; i++) {
arr[i] = (byte) (value >> BYTE_SIZE_IN_BITS * i);
}
}
return arr;
}
/**
* @param value value
* @param separator separator
* @return hex string
*/
public static String toHexString(int value, String separator) {
return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param separator separator
* @param bo bo
* @return hex string
*/
public static String toHexString(int value, String separator, ByteOrder bo) {
return toHexString(toByteArray(value, bo), separator);
}
/**
* @param array array
* @param offset offset
* @return long value
*/
public static long getLong(byte[] array, int offset) {
return getLong(array, offset, ByteOrder.BIG_ENDIAN);
}
/**
* @param array array
* @param offset offset
* @param bo bo
* @return long value
*/
public static long getLong(byte[] array, int offset, ByteOrder bo) {
validateBounds(array, offset, LONG_SIZE_IN_BYTES);
if (bo == null) {
throw new NullPointerException(" bo: " + bo);
}
if (bo.equals(LITTLE_ENDIAN)) {
return (((long) array[offset + 7]) << (BYTE_SIZE_IN_BITS * 7))
| ((0xFFL & array[offset + 6]) << (BYTE_SIZE_IN_BITS * 6))
| ((0xFFL & array[offset + 5]) << (BYTE_SIZE_IN_BITS * 5))
| ((0xFFL & array[offset + 4]) << (BYTE_SIZE_IN_BITS * 4))
| ((0xFFL & array[offset + 3]) << (BYTE_SIZE_IN_BITS * 3))
| ((0xFFL & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 2))
| ((0xFFL & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 1))
| ((0xFFL & array[offset]));
} else {
return (((long) array[offset]) << (BYTE_SIZE_IN_BITS * 7))
| ((0xFFL & array[offset + 1]) << (BYTE_SIZE_IN_BITS * 6))
| ((0xFFL & array[offset + 2]) << (BYTE_SIZE_IN_BITS * 5))
| ((0xFFL & array[offset + 3]) << (BYTE_SIZE_IN_BITS * 4))
| ((0xFFL & array[offset + 4]) << (BYTE_SIZE_IN_BITS * 3))
| ((0xFFL & array[offset + 5]) << (BYTE_SIZE_IN_BITS * 2))
| ((0xFFL & array[offset + 6]) << (BYTE_SIZE_IN_BITS * 1))
| ((0xFFL & array[offset + 7]));
}
}
/**
* @param value value
* @return byte array
*/
public static byte[] toByteArray(long value) {
return toByteArray(value, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param bo bo
* @return byte array
*/
public static byte[] toByteArray(long value, ByteOrder bo) {
if (bo.equals(LITTLE_ENDIAN)) {
return new byte[] {
(byte) (value),
(byte) (value >> BYTE_SIZE_IN_BITS * 1),
(byte) (value >> BYTE_SIZE_IN_BITS * 2),
(byte) (value >> BYTE_SIZE_IN_BITS * 3),
(byte) (value >> BYTE_SIZE_IN_BITS * 4),
(byte) (value >> BYTE_SIZE_IN_BITS * 5),
(byte) (value >> BYTE_SIZE_IN_BITS * 6),
(byte) (value >> BYTE_SIZE_IN_BITS * 7)
};
} else {
return new byte[] {
(byte) (value >> BYTE_SIZE_IN_BITS * 7),
(byte) (value >> BYTE_SIZE_IN_BITS * 6),
(byte) (value >> BYTE_SIZE_IN_BITS * 5),
(byte) (value >> BYTE_SIZE_IN_BITS * 4),
(byte) (value >> BYTE_SIZE_IN_BITS * 3),
(byte) (value >> BYTE_SIZE_IN_BITS * 2),
(byte) (value >> BYTE_SIZE_IN_BITS * 1),
(byte) (value)
};
}
}
/**
* @param value value
* @param separator separator
* @return hex string
*/
public static String toHexString(long value, String separator) {
return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param separator separator
* @param bo bo
* @return hex string
*/
public static String toHexString(long value, String separator, ByteOrder bo) {
return toHexString(toByteArray(value, bo), separator);
}
/**
* @param array array
* @param offset offset
* @return a new MacAddress object.
*/
public static MacAddress getMacAddress(byte[] array, int offset) {
return getMacAddress(array, offset, ByteOrder.BIG_ENDIAN);
}
/**
* @param array array
* @param offset offset
* @param bo bo
* @return a new MacAddress object.
*/
public static MacAddress getMacAddress(byte[] array, int offset, ByteOrder bo) {
validateBounds(array, offset, MacAddress.SIZE_IN_BYTES);
if (bo == null) {
throw new NullPointerException(" bo: " + bo);
}
if (bo.equals(LITTLE_ENDIAN)) {
return MacAddress.getByAddress(reverse(getSubArray(array, offset, MacAddress.SIZE_IN_BYTES)));
} else {
return MacAddress.getByAddress(getSubArray(array, offset, MacAddress.SIZE_IN_BYTES));
}
}
/**
* @param value value
* @return byte array
*/
public static byte[] toByteArray(MacAddress value) {
return toByteArray(value, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param bo bo
* @return byte array
*/
public static byte[] toByteArray(MacAddress value, ByteOrder bo) {
if (bo.equals(LITTLE_ENDIAN)) {
return reverse(value.getAddress());
} else {
return value.getAddress();
}
}
/**
* @param array array
* @param offset offset
* @param length length
* @return a new LinkLayerAddress object.
*/
public static LinkLayerAddress getLinkLayerAddress(byte[] array, int offset, int length) {
return getLinkLayerAddress(array, offset, length, ByteOrder.BIG_ENDIAN);
}
/**
* @param array array
* @param offset offset
* @param length length
* @param bo bo
* @return a new LinkLayerAddress object.
*/
public static LinkLayerAddress getLinkLayerAddress(
byte[] array, int offset, int length, ByteOrder bo) {
validateBounds(array, offset, length);
if (bo == null) {
throw new NullPointerException(" bo: " + bo);
}
if (bo.equals(LITTLE_ENDIAN)) {
return LinkLayerAddress.getByAddress(reverse(getSubArray(array, offset, length)));
} else {
return LinkLayerAddress.getByAddress(getSubArray(array, offset, length));
}
}
/**
* @param value value
* @return byte array
*/
public static byte[] toByteArray(LinkLayerAddress value) {
return toByteArray(value, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param bo bo
* @return byte array
*/
public static byte[] toByteArray(LinkLayerAddress value, ByteOrder bo) {
if (bo.equals(LITTLE_ENDIAN)) {
return reverse(value.getAddress());
} else {
return value.getAddress();
}
}
/**
* @param array array
* @param offset offset
* @return a new Inet4Address object.
*/
public static Inet4Address getInet4Address(byte[] array, int offset) {
return getInet4Address(array, offset, ByteOrder.BIG_ENDIAN);
}
/**
* @param array array
* @param offset offset
* @param bo bo
* @return a new Inet4Address object.
*/
public static Inet4Address getInet4Address(byte[] array, int offset, ByteOrder bo) {
validateBounds(array, offset, INET4_ADDRESS_SIZE_IN_BYTES);
if (bo == null) {
throw new NullPointerException(" bo: " + bo);
}
try {
if (bo.equals(LITTLE_ENDIAN)) {
return (Inet4Address)
InetAddress.getByAddress(
reverse(getSubArray(array, offset, INET4_ADDRESS_SIZE_IN_BYTES)));
} else {
return (Inet4Address)
InetAddress.getByAddress(getSubArray(array, offset, INET4_ADDRESS_SIZE_IN_BYTES));
}
} catch (UnknownHostException e) {
throw new AssertionError(e);
}
}
/**
* @param addr a string representation of an IPv4 address. (e.g. "192.168.0.100")
* @return a byte array representation of the IPv4 address.
* @throws IllegalArgumentException if failed to parse addr.
*/
public static byte[] parseInet4Address(String addr) {
String[] octetStrs = addr.split("\\.", 4);
if (octetStrs.length != INET4_ADDRESS_SIZE_IN_BYTES) {
throw new IllegalArgumentException("Couldn't get an Inet4Address from " + addr);
}
byte[] octets = new byte[4];
for (int i = 0; i < octets.length; i++) {
String octetStr = octetStrs[i];
try {
int octet = Integer.parseInt(octetStr);
if (octet < 0 || octet > 255) {
throw new IllegalArgumentException("Couldn't get an Inet4Address from " + addr);
}
octets[i] = (byte) octet;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Couldn't get an Inet4Address from " + addr);
}
}
return octets;
}
/**
* @param array array
* @param offset offset
* @return a new Inet6Address object.
*/
public static Inet6Address getInet6Address(byte[] array, int offset) {
return getInet6Address(array, offset, ByteOrder.BIG_ENDIAN);
}
/**
* @param array array
* @param offset offset
* @param bo bo
* @return a new Inet6Address object.
*/
public static Inet6Address getInet6Address(byte[] array, int offset, ByteOrder bo) {
validateBounds(array, offset, INET6_ADDRESS_SIZE_IN_BYTES);
if (bo == null) {
throw new NullPointerException(" bo: " + bo);
}
try {
if (bo.equals(LITTLE_ENDIAN)) {
return Inet6Address.getByAddress(
null, reverse(getSubArray(array, offset, INET6_ADDRESS_SIZE_IN_BYTES)), -1);
} else {
return Inet6Address.getByAddress(
null, getSubArray(array, offset, INET6_ADDRESS_SIZE_IN_BYTES), -1);
}
} catch (UnknownHostException e) {
throw new AssertionError(e);
}
}
/**
* @param value value
* @return byte array
*/
public static byte[] toByteArray(InetAddress value) {
return toByteArray(value, ByteOrder.BIG_ENDIAN);
}
/**
* @param value value
* @param bo bo
* @return byte array
*/
public static byte[] toByteArray(InetAddress value, ByteOrder bo) {
if (bo.equals(LITTLE_ENDIAN)) {
return reverse(value.getAddress());
} else {
return value.getAddress();
}
}
/**
* @param array array
* @param offset offset
* @param length length
* @return sub array
*/
public static byte[] getSubArray(byte[] array, int offset, int length) {
validateBounds(array, offset, length);
byte[] subArray = new byte[length];
System.arraycopy(array, offset, subArray, 0, length);
return subArray;
}
/**
* @param array array
* @param offset offset
* @return sub array
*/
public static byte[] getSubArray(byte[] array, int offset) {
return getSubArray(array, offset, array.length - offset);
}
/**
* @param array array
* @param separator separator
* @return hex string
*/
public static String toHexString(byte[] array, String separator) {
return toHexString(array, separator, 0, array.length);
}
/**
* @param array array
* @param separator separator
* @param offset offset
* @param length length
* @return hex string
*/
public static String toHexString(byte[] array, String separator, int offset, int length) {
validateBounds(array, offset, length);
char[] hexChars;
if (separator.length() != 0) {
char[] sepChars = separator.toCharArray();
hexChars = new char[length * 2 + sepChars.length * (length - 1)];
int cur = 0;
int i = 0;
for (; i < length - 1; i++) {
int v = array[offset + i] & 0xFF;
hexChars[cur] = HEX_CHARS[v >>> 4];
cur++;
hexChars[cur] = HEX_CHARS[v & 0x0F];
cur++;
for (int j = 0; j < sepChars.length; j++) {
hexChars[cur] = sepChars[j];
cur++;
}
}
int v = array[offset + i] & 0xFF;
hexChars[cur] = HEX_CHARS[v >>> 4];
hexChars[cur + 1] = HEX_CHARS[v & 0x0F];
} else {
hexChars = new char[length * 2];
int cur = 0;
for (int i = 0; i < length; i++) {
int v = array[offset + i] & 0xFF;
hexChars[cur] = HEX_CHARS[v >>> 4];
cur++;
hexChars[cur] = HEX_CHARS[v & 0x0F];
cur++;
}
}
return new String(hexChars);
}
/**
* A utility method to calculate the Internet checksum.
*
* @see RFC 1071
* @param data data
* @return checksum
*/
public static short calcChecksum(byte[] data) {
long sum = 0;
for (int i = 1; i < data.length; i += SHORT_SIZE_IN_BYTES) {
sum += 0xFFFFL & getShort(data, i - 1);
}
if (data.length % 2 != 0) {
sum += 0xFFFFL & (data[data.length - 1] << BYTE_SIZE_IN_BITS);
}
while ((sum >> (BYTE_SIZE_IN_BITS * SHORT_SIZE_IN_BYTES)) != 0) {
sum = (0xFFFFL & sum) + (sum >>> (BYTE_SIZE_IN_BITS * SHORT_SIZE_IN_BYTES));
}
return (short) ~sum;
}
/**
* A utility method to calculate CRC-32 checksum.
*
* @param data data
* @return checksum
*/
public static int calcCrc32Checksum(byte[] data) {
CRC32 crc32 = new CRC32();
crc32.update(data);
return (int) crc32.getValue();
}
/**
* A utility method to calculate CRC-32C checksum.
*
* @param data data
* @return checksum
*/
public static int calcCrc32cChecksum(byte[] data) {
int c = 0xFFFFFFFF;
for (int i = 0; i < data.length; i++) {
c = CRC32C_TABLE[(c ^ data[i]) & 0xFF] ^ (c >>> 8);
}
return c ^ 0xFFFFFFFF;
}
/**
* A utility method to calculate Adler-32 checksum.
*
* @param data data
* @return checksum
*/
public static int calcAdler32Checksum(byte[] data) {
Adler32 adler32 = new Adler32();
adler32.update(data);
return (int) adler32.getValue();
}
/**
* @param hexString hexString
* @param separator separator
* @return a new byte array.
*/
public static byte[] parseByteArray(String hexString, String separator) {
if (hexString == null || separator == null) {
StringBuilder sb = new StringBuilder();
sb.append("hexString: ").append(hexString).append(" separator: ").append(separator);
throw new NullPointerException(sb.toString());
}
if (hexString.startsWith("0x")) {
hexString = hexString.substring(2);
}
String noSeparatorHexString;
if (separator.length() == 0) {
if (!NO_SEPARATOR_HEX_STRING_PATTERN.matcher(hexString).matches()) {
StringBuilder sb = new StringBuilder(100);
sb.append("invalid hex string(")
.append(hexString)
.append("), not match pattern(")
.append(NO_SEPARATOR_HEX_STRING_PATTERN.pattern())
.append(")");
throw new IllegalArgumentException(sb.toString());
}
noSeparatorHexString = hexString;
} else {
StringBuilder patternSb = new StringBuilder(60);
patternSb
.append("\\A[0-9a-fA-F][0-9a-fA-F](")
.append(Pattern.quote(separator))
.append("[0-9a-fA-F][0-9a-fA-F])*\\z");
String patternString = patternSb.toString();
Pattern pattern = Pattern.compile(patternString);
if (!pattern.matcher(hexString).matches()) {
StringBuilder sb = new StringBuilder(150);
sb.append("invalid hex string(")
.append(hexString)
.append("), not match pattern(")
.append(patternString)
.append(")");
throw new IllegalArgumentException(sb.toString());
}
noSeparatorHexString = hexString.replaceAll(Pattern.quote(separator), "");
}
int arrayLength = noSeparatorHexString.length() / 2;
byte[] array = new byte[arrayLength];
for (int i = 0; i < arrayLength; i++) {
array[i] = (byte) Integer.parseInt(noSeparatorHexString.substring(i * 2, i * 2 + 2), 16);
}
return array;
}
/**
* @param array array
* @return a clone of array
*/
public static byte[] clone(byte[] array) {
byte[] clone = new byte[array.length];
System.arraycopy(array, 0, clone, 0, array.length);
return clone;
}
/**
* A utility method to validate arguments which indicate a part of an array.
*
* @param arr arr
* @param offset offset
* @param len len
* @throws NullPointerException if the {@code arr} is null.
* @throws IllegalArgumentException if {@code arr} is empty.
* @throws LengthZeroException if {@code len} is zero.
* @throws ArrayIndexOutOfBoundsException if {@code offset} or {@code len} is negative, or ({@code
* offset} + {@code len}) is greater than or equal to {@code arr.length}.
*/
public static void validateBounds(byte[] arr, int offset, int len) {
if (arr == null) {
throw new NullPointerException("arr must not be null.");
}
if (arr.length == 0) {
throw new IllegalArgumentException("arr is empty.");
}
if (len == 0) {
StringBuilder sb = new StringBuilder(100);
sb.append("length is zero. offset: ")
.append(offset)
.append(", arr: ")
.append(toHexString(arr, ""));
throw new LengthZeroException(sb.toString());
}
if (offset < 0 || len < 0 || offset + len > arr.length) {
StringBuilder sb = new StringBuilder(100);
sb.append("arr.length: ")
.append(arr.length)
.append(", offset: ")
.append(offset)
.append(", len: ")
.append(len)
.append(", arr: ")
.append(toHexString(arr, ""));
throw new ArrayIndexOutOfBoundsException(sb.toString());
}
}
/**
* @param arr1 arr1
* @param arr2 arr2
* @return arr1 xor arr2
*/
public static byte[] xor(byte[] arr1, byte[] arr2) {
if (arr1 == null) {
throw new NullPointerException("arr1 must not be null.");
}
if (arr2 == null) {
throw new NullPointerException("arr2 must not be null.");
}
if (arr1.length != arr2.length) {
throw new IllegalArgumentException("arr1.length must equal to arr2.length.");
}
byte[] result = new byte[arr1.length];
for (int i = 0; i < arr1.length; i++) {
result[i] = (byte) (arr1[i] ^ arr2[i]);
}
return result;
}
/**
* @param arr1 arr1
* @param arr2 arr2
* @return arr1 + arr2
*/
public static byte[] concatenate(byte[] arr1, byte[] arr2) {
byte[] result = new byte[arr1.length + arr2.length];
System.arraycopy(arr1, 0, result, 0, arr1.length);
System.arraycopy(arr2, 0, result, arr1.length, arr2.length);
return result;
}
/**
* @param arrs arrays
* @return the concatenated array.
*/
public static byte[] concatenate(List arrs) {
int length = 0;
for (byte[] arr : arrs) {
length += arr.length;
}
byte[] result = new byte[length];
int destPos = 0;
for (byte[] arr : arrs) {
System.arraycopy(arr, 0, result, destPos, arr.length);
destPos += arr.length;
}
return result;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy