blob: 6873117ae59f61ce2ac0741bde680d8870354f2d [file] [log] [blame]
package org.bouncycastle.util;
import java.math.BigInteger;
import java.util.NoSuchElementException;
/**
* General array utilities.
*/
public final class Arrays
{
private Arrays()
{
// static class, hide constructor
}
public static boolean areEqual(
boolean[] a,
boolean[] b)
{
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
if (a.length != b.length)
{
return false;
}
for (int i = 0; i != a.length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public static boolean areEqual(
char[] a,
char[] b)
{
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
if (a.length != b.length)
{
return false;
}
for (int i = 0; i != a.length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public static boolean areEqual(
byte[] a,
byte[] b)
{
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
if (a.length != b.length)
{
return false;
}
for (int i = 0; i != a.length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public static boolean areEqual(
short[] a,
short[] b)
{
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
if (a.length != b.length)
{
return false;
}
for (int i = 0; i != a.length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
/**
* A constant time equals comparison - does not terminate early if
* test will fail.
*
* @param a first array
* @param b second array
* @return true if arrays equal, false otherwise.
*/
public static boolean constantTimeAreEqual(
byte[] a,
byte[] b)
{
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
if (a.length != b.length)
{
return false;
}
int nonEqual = 0;
for (int i = 0; i != a.length; i++)
{
nonEqual |= (a[i] ^ b[i]);
}
return nonEqual == 0;
}
public static boolean areEqual(
int[] a,
int[] b)
{
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
if (a.length != b.length)
{
return false;
}
for (int i = 0; i != a.length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public static boolean areEqual(
long[] a,
long[] b)
{
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
if (a.length != b.length)
{
return false;
}
for (int i = 0; i != a.length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public static boolean areEqual(Object[] a, Object[] b)
{
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
if (a.length != b.length)
{
return false;
}
for (int i = 0; i != a.length; i++)
{
Object objA = a[i], objB = b[i];
if (objA == null)
{
if (objB != null)
{
return false;
}
}
else if (!objA.equals(objB))
{
return false;
}
}
return true;
}
public static int compareUnsigned(byte[] a, byte[] b)
{
if (a == b)
{
return 0;
}
if (a == null)
{
return -1;
}
if (b == null)
{
return 1;
}
int minLen = Math.min(a.length, b.length);
for (int i = 0; i < minLen; ++i)
{
int aVal = a[i] & 0xFF, bVal = b[i] & 0xFF;
if (aVal < bVal)
{
return -1;
}
if (aVal > bVal)
{
return 1;
}
}
if (a.length < b.length)
{
return -1;
}
if (a.length > b.length)
{
return 1;
}
return 0;
}
public static boolean contains(short[] a, short n)
{
for (int i = 0; i < a.length; ++i)
{
if (a[i] == n)
{
return true;
}
}
return false;
}
public static boolean contains(int[] a, int n)
{
for (int i = 0; i < a.length; ++i)
{
if (a[i] == n)
{
return true;
}
}
return false;
}
public static void fill(
byte[] array,
byte value)
{
for (int i = 0; i < array.length; i++)
{
array[i] = value;
}
}
public static void fill(
char[] array,
char value)
{
for (int i = 0; i < array.length; i++)
{
array[i] = value;
}
}
public static void fill(
long[] array,
long value)
{
for (int i = 0; i < array.length; i++)
{
array[i] = value;
}
}
public static void fill(
short[] array,
short value)
{
for (int i = 0; i < array.length; i++)
{
array[i] = value;
}
}
public static void fill(
int[] array,
int value)
{
for (int i = 0; i < array.length; i++)
{
array[i] = value;
}
}
public static int hashCode(byte[] data)
{
if (data == null)
{
return 0;
}
int i = data.length;
int hc = i + 1;
while (--i >= 0)
{
hc *= 257;
hc ^= data[i];
}
return hc;
}
public static int hashCode(byte[] data, int off, int len)
{
if (data == null)
{
return 0;
}
int i = len;
int hc = i + 1;
while (--i >= 0)
{
hc *= 257;
hc ^= data[off + i];
}
return hc;
}
public static int hashCode(char[] data)
{
if (data == null)
{
return 0;
}
int i = data.length;
int hc = i + 1;
while (--i >= 0)
{
hc *= 257;
hc ^= data[i];
}
return hc;
}
public static int hashCode(int[][] ints)
{
int hc = 0;
for (int i = 0; i != ints.length; i++)
{
hc = hc * 257 + hashCode(ints[i]);
}
return hc;
}
public static int hashCode(int[] data)
{
if (data == null)
{
return 0;
}
int i = data.length;
int hc = i + 1;
while (--i >= 0)
{
hc *= 257;
hc ^= data[i];
}
return hc;
}
public static int hashCode(int[] data, int off, int len)
{
if (data == null)
{
return 0;
}
int i = len;
int hc = i + 1;
while (--i >= 0)
{
hc *= 257;
hc ^= data[off + i];
}
return hc;
}
public static int hashCode(long[] data)
{
if (data == null)
{
return 0;
}
int i = data.length;
int hc = i + 1;
while (--i >= 0)
{
long di = data[i];
hc *= 257;
hc ^= (int)di;
hc *= 257;
hc ^= (int)(di >>> 32);
}
return hc;
}
public static int hashCode(long[] data, int off, int len)
{
if (data == null)
{
return 0;
}
int i = len;
int hc = i + 1;
while (--i >= 0)
{
long di = data[off + i];
hc *= 257;
hc ^= (int)di;
hc *= 257;
hc ^= (int)(di >>> 32);
}
return hc;
}
public static int hashCode(short[][][] shorts)
{
int hc = 0;
for (int i = 0; i != shorts.length; i++)
{
hc = hc * 257 + hashCode(shorts[i]);
}
return hc;
}
public static int hashCode(short[][] shorts)
{
int hc = 0;
for (int i = 0; i != shorts.length; i++)
{
hc = hc * 257 + hashCode(shorts[i]);
}
return hc;
}
public static int hashCode(short[] data)
{
if (data == null)
{
return 0;
}
int i = data.length;
int hc = i + 1;
while (--i >= 0)
{
hc *= 257;
hc ^= (data[i] & 0xff);
}
return hc;
}
public static int hashCode(Object[] data)
{
if (data == null)
{
return 0;
}
int i = data.length;
int hc = i + 1;
while (--i >= 0)
{
hc *= 257;
hc ^= data[i].hashCode();
}
return hc;
}
public static byte[] clone(byte[] data)
{
if (data == null)
{
return null;
}
byte[] copy = new byte[data.length];
System.arraycopy(data, 0, copy, 0, data.length);
return copy;
}
public static char[] clone(char[] data)
{
if (data == null)
{
return null;
}
char[] copy = new char[data.length];
System.arraycopy(data, 0, copy, 0, data.length);
return copy;
}
public static byte[] clone(byte[] data, byte[] existing)
{
if (data == null)
{
return null;
}
if ((existing == null) || (existing.length != data.length))
{
return clone(data);
}
System.arraycopy(data, 0, existing, 0, existing.length);
return existing;
}
public static byte[][] clone(byte[][] data)
{
if (data == null)
{
return null;
}
byte[][] copy = new byte[data.length][];
for (int i = 0; i != copy.length; i++)
{
copy[i] = clone(data[i]);
}
return copy;
}
public static byte[][][] clone(byte[][][] data)
{
if (data == null)
{
return null;
}
byte[][][] copy = new byte[data.length][][];
for (int i = 0; i != copy.length; i++)
{
copy[i] = clone(data[i]);
}
return copy;
}
public static int[] clone(int[] data)
{
if (data == null)
{
return null;
}
int[] copy = new int[data.length];
System.arraycopy(data, 0, copy, 0, data.length);
return copy;
}
public static long[] clone(long[] data)
{
if (data == null)
{
return null;
}
long[] copy = new long[data.length];
System.arraycopy(data, 0, copy, 0, data.length);
return copy;
}
public static long[] clone(long[] data, long[] existing)
{
if (data == null)
{
return null;
}
if ((existing == null) || (existing.length != data.length))
{
return clone(data);
}
System.arraycopy(data, 0, existing, 0, existing.length);
return existing;
}
public static short[] clone(short[] data)
{
if (data == null)
{
return null;
}
short[] copy = new short[data.length];
System.arraycopy(data, 0, copy, 0, data.length);
return copy;
}
public static BigInteger[] clone(BigInteger[] data)
{
if (data == null)
{
return null;
}
BigInteger[] copy = new BigInteger[data.length];
System.arraycopy(data, 0, copy, 0, data.length);
return copy;
}
public static byte[] copyOf(byte[] data, int newLength)
{
byte[] tmp = new byte[newLength];
if (newLength < data.length)
{
System.arraycopy(data, 0, tmp, 0, newLength);
}
else
{
System.arraycopy(data, 0, tmp, 0, data.length);
}
return tmp;
}
public static char[] copyOf(char[] data, int newLength)
{
char[] tmp = new char[newLength];
if (newLength < data.length)
{
System.arraycopy(data, 0, tmp, 0, newLength);
}
else
{
System.arraycopy(data, 0, tmp, 0, data.length);
}
return tmp;
}
public static int[] copyOf(int[] data, int newLength)
{
int[] tmp = new int[newLength];
if (newLength < data.length)
{
System.arraycopy(data, 0, tmp, 0, newLength);
}
else
{
System.arraycopy(data, 0, tmp, 0, data.length);
}
return tmp;
}
public static long[] copyOf(long[] data, int newLength)
{
long[] tmp = new long[newLength];
if (newLength < data.length)
{
System.arraycopy(data, 0, tmp, 0, newLength);
}
else
{
System.arraycopy(data, 0, tmp, 0, data.length);
}
return tmp;
}
public static BigInteger[] copyOf(BigInteger[] data, int newLength)
{
BigInteger[] tmp = new BigInteger[newLength];
if (newLength < data.length)
{
System.arraycopy(data, 0, tmp, 0, newLength);
}
else
{
System.arraycopy(data, 0, tmp, 0, data.length);
}
return tmp;
}
/**
* Make a copy of a range of bytes from the passed in data array. The range can
* extend beyond the end of the input array, in which case the return array will
* be padded with zeroes.
*
* @param data the array from which the data is to be copied.
* @param from the start index at which the copying should take place.
* @param to the final index of the range (exclusive).
*
* @return a new byte array containing the range given.
*/
public static byte[] copyOfRange(byte[] data, int from, int to)
{
int newLength = getLength(from, to);
byte[] tmp = new byte[newLength];
if (data.length - from < newLength)
{
System.arraycopy(data, from, tmp, 0, data.length - from);
}
else
{
System.arraycopy(data, from, tmp, 0, newLength);
}
return tmp;
}
public static int[] copyOfRange(int[] data, int from, int to)
{
int newLength = getLength(from, to);
int[] tmp = new int[newLength];
if (data.length - from < newLength)
{
System.arraycopy(data, from, tmp, 0, data.length - from);
}
else
{
System.arraycopy(data, from, tmp, 0, newLength);
}
return tmp;
}
public static long[] copyOfRange(long[] data, int from, int to)
{
int newLength = getLength(from, to);
long[] tmp = new long[newLength];
if (data.length - from < newLength)
{
System.arraycopy(data, from, tmp, 0, data.length - from);
}
else
{
System.arraycopy(data, from, tmp, 0, newLength);
}
return tmp;
}
public static BigInteger[] copyOfRange(BigInteger[] data, int from, int to)
{
int newLength = getLength(from, to);
BigInteger[] tmp = new BigInteger[newLength];
if (data.length - from < newLength)
{
System.arraycopy(data, from, tmp, 0, data.length - from);
}
else
{
System.arraycopy(data, from, tmp, 0, newLength);
}
return tmp;
}
private static int getLength(int from, int to)
{
int newLength = to - from;
if (newLength < 0)
{
StringBuffer sb = new StringBuffer(from);
sb.append(" > ").append(to);
throw new IllegalArgumentException(sb.toString());
}
return newLength;
}
public static byte[] append(byte[] a, byte b)
{
if (a == null)
{
return new byte[]{ b };
}
int length = a.length;
byte[] result = new byte[length + 1];
System.arraycopy(a, 0, result, 0, length);
result[length] = b;
return result;
}
public static short[] append(short[] a, short b)
{
if (a == null)
{
return new short[]{ b };
}
int length = a.length;
short[] result = new short[length + 1];
System.arraycopy(a, 0, result, 0, length);
result[length] = b;
return result;
}
public static int[] append(int[] a, int b)
{
if (a == null)
{
return new int[]{ b };
}
int length = a.length;
int[] result = new int[length + 1];
System.arraycopy(a, 0, result, 0, length);
result[length] = b;
return result;
}
public static String[] append(String[] a, String b)
{
if (a == null)
{
return new String[]{ b };
}
int length = a.length;
String[] result = new String[length + 1];
System.arraycopy(a, 0, result, 0, length);
result[length] = b;
return result;
}
public static byte[] concatenate(byte[] a, byte[] b)
{
if (a != null && b != null)
{
byte[] rv = new byte[a.length + b.length];
System.arraycopy(a, 0, rv, 0, a.length);
System.arraycopy(b, 0, rv, a.length, b.length);
return rv;
}
else if (b != null)
{
return clone(b);
}
else
{
return clone(a);
}
}
public static byte[] concatenate(byte[] a, byte[] b, byte[] c)
{
if (a != null && b != null && c != null)
{
byte[] rv = new byte[a.length + b.length + c.length];
System.arraycopy(a, 0, rv, 0, a.length);
System.arraycopy(b, 0, rv, a.length, b.length);
System.arraycopy(c, 0, rv, a.length + b.length, c.length);
return rv;
}
else if (a == null)
{
return concatenate(b, c);
}
else if (b == null)
{
return concatenate(a, c);
}
else
{
return concatenate(a, b);
}
}
public static byte[] concatenate(byte[] a, byte[] b, byte[] c, byte[] d)
{
if (a != null && b != null && c != null && d != null)
{
byte[] rv = new byte[a.length + b.length + c.length + d.length];
System.arraycopy(a, 0, rv, 0, a.length);
System.arraycopy(b, 0, rv, a.length, b.length);
System.arraycopy(c, 0, rv, a.length + b.length, c.length);
System.arraycopy(d, 0, rv, a.length + b.length + c.length, d.length);
return rv;
}
else if (d == null)
{
return concatenate(a, b, c);
}
else if (c == null)
{
return concatenate(a, b, d);
}
else if (b == null)
{
return concatenate(a, c, d);
}
else
{
return concatenate(b, c, d);
}
}
public static byte[] concatenate(byte[][] arrays)
{
int size = 0;
for (int i = 0; i != arrays.length; i++)
{
size += arrays[i].length;
}
byte[] rv = new byte[size];
int offSet = 0;
for (int i = 0; i != arrays.length; i++)
{
System.arraycopy(arrays[i], 0, rv, offSet, arrays[i].length);
offSet += arrays[i].length;
}
return rv;
}
public static int[] concatenate(int[] a, int[] b)
{
if (a == null)
{
return clone(b);
}
if (b == null)
{
return clone(a);
}
int[] c = new int[a.length + b.length];
System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(b, 0, c, a.length, b.length);
return c;
}
public static byte[] prepend(byte[] a, byte b)
{
if (a == null)
{
return new byte[]{ b };
}
int length = a.length;
byte[] result = new byte[length + 1];
System.arraycopy(a, 0, result, 1, length);
result[0] = b;
return result;
}
public static short[] prepend(short[] a, short b)
{
if (a == null)
{
return new short[]{ b };
}
int length = a.length;
short[] result = new short[length + 1];
System.arraycopy(a, 0, result, 1, length);
result[0] = b;
return result;
}
public static int[] prepend(int[] a, int b)
{
if (a == null)
{
return new int[]{ b };
}
int length = a.length;
int[] result = new int[length + 1];
System.arraycopy(a, 0, result, 1, length);
result[0] = b;
return result;
}
public static byte[] reverse(byte[] a)
{
if (a == null)
{
return null;
}
int p1 = 0, p2 = a.length;
byte[] result = new byte[p2];
while (--p2 >= 0)
{
result[p2] = a[p1++];
}
return result;
}
public static int[] reverse(int[] a)
{
if (a == null)
{
return null;
}
int p1 = 0, p2 = a.length;
int[] result = new int[p2];
while (--p2 >= 0)
{
result[p2] = a[p1++];
}
return result;
}
/**
* Iterator backed by a specific array.
*/
public static class Iterator<T>
implements java.util.Iterator<T>
{
private final T[] dataArray;
private int position = 0;
/**
* Base constructor.
* <p>
* Note: the array is not cloned, changes to it will affect the values returned by next().
* </p>
*
* @param dataArray array backing the iterator.
*/
public Iterator(T[] dataArray)
{
this.dataArray = dataArray;
}
public boolean hasNext()
{
return position < dataArray.length;
}
public T next()
{
if (position == dataArray.length)
{
throw new NoSuchElementException("Out of elements: " + position);
}
return dataArray[position++];
}
public void remove()
{
throw new UnsupportedOperationException("Cannot remove element from an Array.");
}
}
}