blob: 0688dfaf52a51209d4a604339016b7d365fbf15e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.remoting.internal;
/**
* Copy from Bouncy Castle Crypto APIs
*
* This class is a utility class for manipulating byte arrays.
*/
public final class ByteUtils {
private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* Default constructor (private)
*/
private ByteUtils() {
// empty
}
/**
* Compare two two-dimensional byte arrays. No null checks are performed.
*
* @param left the first byte array
* @param right the second byte array
* @return the result of the comparison
*/
public static boolean equals(byte[][] left, byte[][] right) {
if (left.length != right.length) {
return false;
}
boolean result = true;
for (int i = left.length - 1; i >= 0; i--) {
result &= ByteUtils.equals(left[i], right[i]);
}
return result;
}
/**
* Compare two byte arrays (perform null checks beforehand).
*
* @param left the first byte array
* @param right the second byte array
* @return the result of the comparison
*/
public static boolean equals(byte[] left, byte[] right) {
if (left == null) {
return right == null;
}
if (right == null) {
return false;
}
if (left.length != right.length) {
return false;
}
boolean result = true;
for (int i = left.length - 1; i >= 0; i--) {
result &= left[i] == right[i];
}
return result;
}
/**
* Compare two three-dimensional byte arrays. No null checks are performed.
*
* @param left the first byte array
* @param right the second byte array
* @return the result of the comparison
*/
public static boolean equals(byte[][][] left, byte[][][] right) {
if (left.length != right.length) {
return false;
}
boolean result = true;
for (int i = left.length - 1; i >= 0; i--) {
if (left[i].length != right[i].length) {
return false;
}
for (int j = left[i].length - 1; j >= 0; j--) {
result &= ByteUtils.equals(left[i][j], right[i][j]);
}
}
return result;
}
/**
* Computes a hashcode based on the contents of a three-dimensional byte
* array rather than its identity.
*
* @param array the array to compute the hashcode of
* @return the hashcode
*/
public static int deepHashCode(byte[][][] array) {
int result = 1;
for (int i = 0; i < array.length; i++) {
result = 31 * result + deepHashCode(array[i]);
}
return result;
}
/**
* Computes a hashcode based on the contents of a two-dimensional byte array
* rather than its identity.
*
* @param array the array to compute the hashcode of
* @return the hashcode
*/
public static int deepHashCode(byte[][] array) {
int result = 1;
for (int i = 0; i < array.length; i++) {
result = 31 * result + deepHashCode(array[i]);
}
return result;
}
/**
* Computes a hashcode based on the contents of a one-dimensional byte array
* rather than its identity.
*
* @param array the array to compute the hashcode of
* @return the hashcode
*/
public static int deepHashCode(byte[] array) {
int result = 1;
for (int i = 0; i < array.length; i++) {
result = 31 * result + array[i];
}
return result;
}
/**
* Return a clone of the given byte array (performs null check beforehand).
*
* @param array the array to clone
* @return the clone of the given array, or <tt>null</tt> if the array is
* <tt>null</tt>
*/
public static byte[] clone(byte[] array) {
if (array == null) {
return null;
}
byte[] result = new byte[array.length];
System.arraycopy(array, 0, result, 0, array.length);
return result;
}
/**
* Convert a string containing hexadecimal characters to a byte-array.
*
* @param s a hex string
* @return a byte array with the corresponding value
*/
public static byte[] fromHexString(String s) {
char[] rawChars = s.toUpperCase().toCharArray();
int hexChars = 0;
for (int i = 0; i < rawChars.length; i++) {
if ((rawChars[i] >= '0' && rawChars[i] <= '9')
|| (rawChars[i] >= 'A' && rawChars[i] <= 'F')) {
hexChars++;
}
}
byte[] byteString = new byte[(hexChars + 1) >> 1];
int pos = hexChars & 1;
for (int i = 0; i < rawChars.length; i++) {
if (rawChars[i] >= '0' && rawChars[i] <= '9') {
byteString[pos >> 1] <<= 4;
byteString[pos >> 1] |= rawChars[i] - '0';
} else if (rawChars[i] >= 'A' && rawChars[i] <= 'F') {
byteString[pos >> 1] <<= 4;
byteString[pos >> 1] |= rawChars[i] - 'A' + 10;
} else {
continue;
}
pos++;
}
return byteString;
}
/**
* Convert a byte array to the corresponding hexstring.
*
* @param input the byte array to be converted
* @return the corresponding hexstring
*/
public static String toHexString(byte[] input) {
String result = "";
for (int i = 0; i < input.length; i++) {
result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
result += HEX_CHARS[(input[i]) & 0x0f];
}
return result;
}
/**
* Convert a byte array to the corresponding hex string.
*
* @param input the byte array to be converted
* @param prefix the prefix to put at the beginning of the hex string
* @param seperator a separator string
* @return the corresponding hex string
*/
public static String toHexString(byte[] input, String prefix,
String seperator) {
String result = new String(prefix);
for (int i = 0; i < input.length; i++) {
result += HEX_CHARS[(input[i] >>> 4) & 0x0f];
result += HEX_CHARS[(input[i]) & 0x0f];
if (i < input.length - 1) {
result += seperator;
}
}
return result;
}
/**
* Convert a byte array to the corresponding bit string.
*
* @param input the byte array to be converted
* @return the corresponding bit string
*/
public static String toBinaryString(byte[] input) {
String result = "";
int i;
for (i = 0; i < input.length; i++) {
int e = input[i];
for (int ii = 0; ii < 8; ii++) {
int b = (e >>> ii) & 1;
result += b;
}
if (i != input.length - 1) {
result += " ";
}
}
return result;
}
/**
* Compute the bitwise XOR of two arrays of bytes. The arrays have to be of
* same length. No length checking is performed.
*
* @param x1 the first array
* @param x2 the second array
* @return x1 XOR x2
*/
public static byte[] xor(byte[] x1, byte[] x2) {
byte[] out = new byte[x1.length];
for (int i = x1.length - 1; i >= 0; i--) {
out[i] = (byte) (x1[i] ^ x2[i]);
}
return out;
}
/**
* Concatenate two byte arrays. No null checks are performed.
*
* @param x1 the first array
* @param x2 the second array
* @return (x2 | | x1) (little-endian order, i.e. x1 is at lower memory
* addresses)
*/
public static byte[] concatenate(byte[] x1, byte[] x2) {
byte[] result = new byte[x1.length + x2.length];
System.arraycopy(x1, 0, result, 0, x1.length);
System.arraycopy(x2, 0, result, x1.length, x2.length);
return result;
}
/**
* Convert a 2-dimensional byte array into a 1-dimensional byte array by
* concatenating all entries.
*
* @param array a 2-dimensional byte array
* @return the concatenated input array
*/
public static byte[] concatenate(byte[][] array) {
int rowLength = array[0].length;
byte[] result = new byte[array.length * rowLength];
int index = 0;
for (int i = 0; i < array.length; i++) {
System.arraycopy(array[i], 0, result, index, rowLength);
index += rowLength;
}
return result;
}
/**
* Split a byte array <tt>input</tt> into two arrays at <tt>index</tt>,
* i.e. the first array will have the lower <tt>index</tt> bytes, the
* second one the higher <tt>input.length - index</tt> bytes.
*
* @param input the byte array to be split
* @param index the index where the byte array is split
* @return the splitted input array as an array of two byte arrays
* @throws ArrayIndexOutOfBoundsException if <tt>index</tt> is out of bounds
*/
public static byte[][] split(byte[] input, int index)
throws ArrayIndexOutOfBoundsException {
if (index > input.length) {
throw new ArrayIndexOutOfBoundsException();
}
byte[][] result = new byte[2][];
result[0] = new byte[index];
result[1] = new byte[input.length - index];
System.arraycopy(input, 0, result[0], 0, index);
System.arraycopy(input, index, result[1], 0, input.length - index);
return result;
}
/**
* Generate a subarray of a given byte array.
*
* @param input the input byte array
* @param start the start index
* @return a subarray of <tt>input</tt>, ranging from <tt>start</tt> to
* the end of the array
*/
public static byte[] subArray(byte[] input, int start) {
return subArray(input, start, input.length);
}
/**
* Generate a subarray of a given byte array.
*
* @param input the input byte array
* @param start the start index
* @param end the end index
* @return a subarray of <tt>input</tt>, ranging from <tt>start</tt>
* (inclusively) to <tt>end</tt> (exclusively)
*/
public static byte[] subArray(byte[] input, int start, int end) {
byte[] result = new byte[end - start];
System.arraycopy(input, start, result, 0, end - start);
return result;
}
/**
* Rewrite a byte array as a char array
*
* @param input -
* the byte array
* @return char array
*/
public static char[] toCharArray(byte[] input) {
char[] result = new char[input.length];
for (int i = 0; i < input.length; i++) {
result[i] = (char) input[i];
}
return result;
}
}