// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.util;

import java.util.NoSuchElementException;
import java.util.Iterator;
import java.math.BigInteger;

public final class Arrays
{
    private Arrays() {
    }
    
    public static boolean areAllZeroes(final byte[] array, final int n, final int n2) {
        int n3 = 0;
        for (int i = 0; i < n2; ++i) {
            n3 |= array[n + i];
        }
        return n3 == 0;
    }
    
    public static boolean areEqual(final boolean[] a, final boolean[] a2) {
        return java.util.Arrays.equals(a, a2);
    }
    
    public static boolean areEqual(final byte[] a, final byte[] a2) {
        return java.util.Arrays.equals(a, a2);
    }
    
    public static boolean areEqual(final byte[] array, final int n, final int n2, final byte[] array2, final int n3, final int n4) {
        final int n5 = n2 - n;
        if (n5 != n4 - n3) {
            return false;
        }
        for (int i = 0; i < n5; ++i) {
            if (array[n + i] != array2[n3 + i]) {
                return false;
            }
        }
        return true;
    }
    
    public static boolean areEqual(final char[] a, final char[] a2) {
        return java.util.Arrays.equals(a, a2);
    }
    
    public static boolean areEqual(final int[] a, final int[] a2) {
        return java.util.Arrays.equals(a, a2);
    }
    
    public static boolean areEqual(final long[] a, final long[] a2) {
        return java.util.Arrays.equals(a, a2);
    }
    
    public static boolean areEqual(final Object[] a, final Object[] a2) {
        return java.util.Arrays.equals(a, a2);
    }
    
    public static boolean areEqual(final short[] a, final short[] a2) {
        return java.util.Arrays.equals(a, a2);
    }
    
    public static boolean constantTimeAreEqual(final byte[] array, final byte[] array2) {
        if (array == null || array2 == null) {
            return false;
        }
        if (array == array2) {
            return true;
        }
        final int n = (array.length < array2.length) ? array.length : array2.length;
        int n2 = array.length ^ array2.length;
        for (int i = 0; i != n; ++i) {
            n2 |= (array[i] ^ array2[i]);
        }
        for (int j = n; j < array2.length; ++j) {
            n2 |= (array2[j] ^ ~array2[j]);
        }
        return n2 == 0;
    }
    
    public static boolean constantTimeAreEqual(final int n, final byte[] array, final int n2, final byte[] array2, final int n3) {
        if (null == array) {
            throw new NullPointerException("'a' cannot be null");
        }
        if (null == array2) {
            throw new NullPointerException("'b' cannot be null");
        }
        if (n < 0) {
            throw new IllegalArgumentException("'len' cannot be negative");
        }
        if (n2 > array.length - n) {
            throw new IndexOutOfBoundsException("'aOff' value invalid for specified length");
        }
        if (n3 > array2.length - n) {
            throw new IndexOutOfBoundsException("'bOff' value invalid for specified length");
        }
        int n4 = 0;
        for (int i = 0; i < n; ++i) {
            n4 |= (array[n2 + i] ^ array2[n3 + i]);
        }
        return n4 == 0;
    }
    
    public static boolean constantTimeAreEqual(final int n, final long[] array, final int n2, final long[] array2, final int n3) {
        if (null == array) {
            throw new NullPointerException("'a' cannot be null");
        }
        if (null == array2) {
            throw new NullPointerException("'b' cannot be null");
        }
        if (n < 0) {
            throw new IllegalArgumentException("'len' cannot be negative");
        }
        if (n2 > array.length - n) {
            throw new IndexOutOfBoundsException("'aOff' value invalid for specified length");
        }
        if (n3 > array2.length - n) {
            throw new IndexOutOfBoundsException("'bOff' value invalid for specified length");
        }
        long n4 = 0L;
        for (int i = 0; i < n; ++i) {
            n4 |= (array[n2 + i] ^ array2[n3 + i]);
        }
        return 0L == n4;
    }
    
    public static boolean constantTimeAreEqual(final char[] array, final char[] array2) {
        if (array == null || array2 == null) {
            return false;
        }
        if (array == array2) {
            return true;
        }
        final int min = Math.min(array.length, array2.length);
        int n = array.length ^ array2.length;
        for (int i = 0; i != min; ++i) {
            n |= (array[i] ^ array2[i]);
        }
        for (int j = min; j < array2.length; ++j) {
            n |= ((byte)array2[j] ^ (byte)~array2[j]);
        }
        return n == 0;
    }
    
    public static boolean constantTimeAreEqual(final long[] array, final long[] array2) {
        if (array == null || array2 == null) {
            return false;
        }
        if (array == array2) {
            return true;
        }
        final int n = (array.length < array2.length) ? array.length : array2.length;
        long n2 = array.length ^ array2.length;
        for (int i = 0; i != n; ++i) {
            n2 |= (array[i] ^ array2[i]);
        }
        for (int j = n; j < array2.length; ++j) {
            n2 |= (array2[j] ^ ~array2[j]);
        }
        return n2 == 0L;
    }
    
    public static int compareUnsigned(final byte[] array, final byte[] array2) {
        if (array == array2) {
            return 0;
        }
        if (array == null) {
            return -1;
        }
        if (array2 == null) {
            return 1;
        }
        for (int min = Math.min(array.length, array2.length), i = 0; i < min; ++i) {
            final int n = array[i] & 0xFF;
            final int n2 = array2[i] & 0xFF;
            if (n < n2) {
                return -1;
            }
            if (n > n2) {
                return 1;
            }
        }
        if (array.length < array2.length) {
            return -1;
        }
        if (array.length > array2.length) {
            return 1;
        }
        return 0;
    }
    
    public static boolean contains(final boolean[] array, final boolean b) {
        for (int i = 0; i < array.length; ++i) {
            if (array[i] == b) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean contains(final byte[] array, final byte b) {
        for (int i = 0; i < array.length; ++i) {
            if (array[i] == b) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean contains(final char[] array, final char c) {
        for (int i = 0; i < array.length; ++i) {
            if (array[i] == c) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean contains(final int[] array, final int n) {
        for (int i = 0; i < array.length; ++i) {
            if (array[i] == n) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean contains(final long[] array, final long n) {
        for (int i = 0; i < array.length; ++i) {
            if (array[i] == n) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean contains(final short[] array, final short n) {
        for (int i = 0; i < array.length; ++i) {
            if (array[i] == n) {
                return true;
            }
        }
        return false;
    }
    
    public static void fill(final boolean[] a, final boolean val) {
        java.util.Arrays.fill(a, val);
    }
    
    public static void fill(final boolean[] a, final int fromIndex, final int toIndex, final boolean val) {
        java.util.Arrays.fill(a, fromIndex, toIndex, val);
    }
    
    public static void fill(final byte[] a, final byte val) {
        java.util.Arrays.fill(a, val);
    }
    
    public static void fill(final byte[] a, final int fromIndex, final int toIndex, final byte val) {
        java.util.Arrays.fill(a, fromIndex, toIndex, val);
    }
    
    public static void fill(final char[] a, final char val) {
        java.util.Arrays.fill(a, val);
    }
    
    public static void fill(final char[] a, final int fromIndex, final int toIndex, final char val) {
        java.util.Arrays.fill(a, fromIndex, toIndex, val);
    }
    
    public static void fill(final int[] a, final int val) {
        java.util.Arrays.fill(a, val);
    }
    
    public static void fill(final int[] a, final int fromIndex, final int toIndex, final int val) {
        java.util.Arrays.fill(a, fromIndex, toIndex, val);
    }
    
    public static void fill(final long[] a, final long val) {
        java.util.Arrays.fill(a, val);
    }
    
    public static void fill(final long[] a, final int fromIndex, final int toIndex, final long val) {
        java.util.Arrays.fill(a, fromIndex, toIndex, val);
    }
    
    public static void fill(final Object[] a, final Object val) {
        java.util.Arrays.fill(a, val);
    }
    
    public static void fill(final Object[] a, final int fromIndex, final int toIndex, final Object val) {
        java.util.Arrays.fill(a, fromIndex, toIndex, val);
    }
    
    public static void fill(final short[] a, final short val) {
        java.util.Arrays.fill(a, val);
    }
    
    public static void fill(final short[] a, final int fromIndex, final int toIndex, final short val) {
        java.util.Arrays.fill(a, fromIndex, toIndex, val);
    }
    
    public static int hashCode(final byte[] array) {
        if (array == null) {
            return 0;
        }
        int length = array.length;
        int n = length + 1;
        while (--length >= 0) {
            n = (n * 257 ^ array[length]);
        }
        return n;
    }
    
    public static int hashCode(final byte[] array, final int n, final int n2) {
        if (array == null) {
            return 0;
        }
        int n3 = n2;
        int n4 = n3 + 1;
        while (--n3 >= 0) {
            n4 = (n4 * 257 ^ array[n + n3]);
        }
        return n4;
    }
    
    public static int hashCode(final char[] array) {
        if (array == null) {
            return 0;
        }
        int length = array.length;
        int n = length + 1;
        while (--length >= 0) {
            n = (n * 257 ^ array[length]);
        }
        return n;
    }
    
    public static int hashCode(final int[][] array) {
        int n = 0;
        for (int i = 0; i != array.length; ++i) {
            n = n * 257 + hashCode(array[i]);
        }
        return n;
    }
    
    public static int hashCode(final int[] array) {
        if (array == null) {
            return 0;
        }
        int length = array.length;
        int n = length + 1;
        while (--length >= 0) {
            n = (n * 257 ^ array[length]);
        }
        return n;
    }
    
    public static int hashCode(final int[] array, final int n, final int n2) {
        if (array == null) {
            return 0;
        }
        int n3 = n2;
        int n4 = n3 + 1;
        while (--n3 >= 0) {
            n4 = (n4 * 257 ^ array[n + n3]);
        }
        return n4;
    }
    
    public static int hashCode(final long[] array) {
        if (array == null) {
            return 0;
        }
        int length = array.length;
        int n = length + 1;
        while (--length >= 0) {
            final long n2 = array[length];
            n = ((n * 257 ^ (int)n2) * 257 ^ (int)(n2 >>> 32));
        }
        return n;
    }
    
    public static int hashCode(final long[] array, final int n, final int n2) {
        if (array == null) {
            return 0;
        }
        int n3 = n2;
        int n4 = n3 + 1;
        while (--n3 >= 0) {
            final long n5 = array[n + n3];
            n4 = ((n4 * 257 ^ (int)n5) * 257 ^ (int)(n5 >>> 32));
        }
        return n4;
    }
    
    public static int hashCode(final short[][][] array) {
        int n = 0;
        for (int i = 0; i != array.length; ++i) {
            n = n * 257 + hashCode(array[i]);
        }
        return n;
    }
    
    public static int hashCode(final short[][] array) {
        int n = 0;
        for (int i = 0; i != array.length; ++i) {
            n = n * 257 + hashCode(array[i]);
        }
        return n;
    }
    
    public static int hashCode(final short[] array) {
        if (array == null) {
            return 0;
        }
        int length = array.length;
        int n = length + 1;
        while (--length >= 0) {
            n = (n * 257 ^ (array[length] & 0xFF));
        }
        return n;
    }
    
    public static int hashCode(final Object[] array) {
        if (array == null) {
            return 0;
        }
        int length = array.length;
        int n = length + 1;
        while (--length >= 0) {
            n = (n * 257 ^ Objects.hashCode(array[length]));
        }
        return n;
    }
    
    public static boolean[] clone(final boolean[] array) {
        return (boolean[])((null == array) ? null : ((boolean[])array.clone()));
    }
    
    public static byte[] clone(final byte[] array) {
        return (byte[])((null == array) ? null : ((byte[])array.clone()));
    }
    
    public static char[] clone(final char[] array) {
        return (char[])((null == array) ? null : ((char[])array.clone()));
    }
    
    public static int[] clone(final int[] array) {
        return (int[])((null == array) ? null : ((int[])array.clone()));
    }
    
    public static long[] clone(final long[] array) {
        return (long[])((null == array) ? null : ((long[])array.clone()));
    }
    
    public static short[] clone(final short[] array) {
        return (short[])((null == array) ? null : ((short[])array.clone()));
    }
    
    public static BigInteger[] clone(final BigInteger[] array) {
        return (BigInteger[])((null == array) ? null : ((BigInteger[])array.clone()));
    }
    
    public static byte[] clone(final byte[] array, final byte[] array2) {
        if (array == null) {
            return null;
        }
        if (array2 == null || array2.length != array.length) {
            return clone(array);
        }
        System.arraycopy(array, 0, array2, 0, array2.length);
        return array2;
    }
    
    public static long[] clone(final long[] array, final long[] array2) {
        if (array == null) {
            return null;
        }
        if (array2 == null || array2.length != array.length) {
            return clone(array);
        }
        System.arraycopy(array, 0, array2, 0, array2.length);
        return array2;
    }
    
    public static byte[][] clone(final byte[][] array) {
        if (array == null) {
            return null;
        }
        final byte[][] array2 = new byte[array.length][];
        for (int i = 0; i != array2.length; ++i) {
            array2[i] = clone(array[i]);
        }
        return array2;
    }
    
    public static byte[][][] clone(final byte[][][] array) {
        if (array == null) {
            return null;
        }
        final byte[][][] array2 = new byte[array.length][][];
        for (int i = 0; i != array2.length; ++i) {
            array2[i] = clone(array[i]);
        }
        return array2;
    }
    
    public static boolean[] copyOf(final boolean[] array, final int b) {
        final boolean[] array2 = new boolean[b];
        System.arraycopy(array, 0, array2, 0, Math.min(array.length, b));
        return array2;
    }
    
    public static byte[] copyOf(final byte[] array, final int b) {
        final byte[] array2 = new byte[b];
        System.arraycopy(array, 0, array2, 0, Math.min(array.length, b));
        return array2;
    }
    
    public static char[] copyOf(final char[] array, final int b) {
        final char[] array2 = new char[b];
        System.arraycopy(array, 0, array2, 0, Math.min(array.length, b));
        return array2;
    }
    
    public static int[] copyOf(final int[] array, final int b) {
        final int[] array2 = new int[b];
        System.arraycopy(array, 0, array2, 0, Math.min(array.length, b));
        return array2;
    }
    
    public static long[] copyOf(final long[] array, final int b) {
        final long[] array2 = new long[b];
        System.arraycopy(array, 0, array2, 0, Math.min(array.length, b));
        return array2;
    }
    
    public static short[] copyOf(final short[] array, final int b) {
        final short[] array2 = new short[b];
        System.arraycopy(array, 0, array2, 0, Math.min(array.length, b));
        return array2;
    }
    
    public static BigInteger[] copyOf(final BigInteger[] array, final int b) {
        final BigInteger[] array2 = new BigInteger[b];
        System.arraycopy(array, 0, array2, 0, Math.min(array.length, b));
        return array2;
    }
    
    public static boolean[] copyOfRange(final boolean[] array, final int n, final int n2) {
        final int length = getLength(n, n2);
        final boolean[] array2 = new boolean[length];
        System.arraycopy(array, n, array2, 0, Math.min(array.length - n, length));
        return array2;
    }
    
    public static byte[] copyOfRange(final byte[] array, final int n, final int n2) {
        final int length = getLength(n, n2);
        final byte[] array2 = new byte[length];
        System.arraycopy(array, n, array2, 0, Math.min(array.length - n, length));
        return array2;
    }
    
    public static char[] copyOfRange(final char[] array, final int n, final int n2) {
        final int length = getLength(n, n2);
        final char[] array2 = new char[length];
        System.arraycopy(array, n, array2, 0, Math.min(array.length - n, length));
        return array2;
    }
    
    public static int[] copyOfRange(final int[] array, final int n, final int n2) {
        final int length = getLength(n, n2);
        final int[] array2 = new int[length];
        System.arraycopy(array, n, array2, 0, Math.min(array.length - n, length));
        return array2;
    }
    
    public static long[] copyOfRange(final long[] array, final int n, final int n2) {
        final int length = getLength(n, n2);
        final long[] array2 = new long[length];
        System.arraycopy(array, n, array2, 0, Math.min(array.length - n, length));
        return array2;
    }
    
    public static short[] copyOfRange(final short[] array, final int n, final int n2) {
        final int length = getLength(n, n2);
        final short[] array2 = new short[length];
        System.arraycopy(array, n, array2, 0, Math.min(array.length - n, length));
        return array2;
    }
    
    public static BigInteger[] copyOfRange(final BigInteger[] array, final int n, final int n2) {
        final int length = getLength(n, n2);
        final BigInteger[] array2 = new BigInteger[length];
        System.arraycopy(array, n, array2, 0, Math.min(array.length - n, length));
        return array2;
    }
    
    private static int getLength(final int i, final int j) {
        final int n = j - i;
        if (n < 0) {
            throw new IllegalArgumentException(i + " > " + j);
        }
        return n;
    }
    
    public static byte[] append(final byte[] array, final byte b) {
        if (array == null) {
            return new byte[] { b };
        }
        final int length = array.length;
        final byte[] array2 = new byte[length + 1];
        System.arraycopy(array, 0, array2, 0, length);
        array2[length] = b;
        return array2;
    }
    
    public static short[] append(final short[] array, final short n) {
        if (array == null) {
            return new short[] { n };
        }
        final int length = array.length;
        final short[] array2 = new short[length + 1];
        System.arraycopy(array, 0, array2, 0, length);
        array2[length] = n;
        return array2;
    }
    
    public static int[] append(final int[] array, final int n) {
        if (array == null) {
            return new int[] { n };
        }
        final int length = array.length;
        final int[] array2 = new int[length + 1];
        System.arraycopy(array, 0, array2, 0, length);
        array2[length] = n;
        return array2;
    }
    
    public static String[] append(final String[] array, final String s) {
        if (array == null) {
            return new String[] { s };
        }
        final int length = array.length;
        final String[] array2 = new String[length + 1];
        System.arraycopy(array, 0, array2, 0, length);
        array2[length] = s;
        return array2;
    }
    
    public static byte[] concatenate(final byte[] array, final byte[] array2) {
        if (null == array) {
            return clone(array2);
        }
        if (null == array2) {
            return clone(array);
        }
        final byte[] array3 = new byte[array.length + array2.length];
        System.arraycopy(array, 0, array3, 0, array.length);
        System.arraycopy(array2, 0, array3, array.length, array2.length);
        return array3;
    }
    
    public static short[] concatenate(final short[] array, final short[] array2) {
        if (null == array) {
            return clone(array2);
        }
        if (null == array2) {
            return clone(array);
        }
        final short[] array3 = new short[array.length + array2.length];
        System.arraycopy(array, 0, array3, 0, array.length);
        System.arraycopy(array2, 0, array3, array.length, array2.length);
        return array3;
    }
    
    public static byte[] concatenate(final byte[] array, final byte[] array2, final byte[] array3) {
        if (null == array) {
            return concatenate(array2, array3);
        }
        if (null == array2) {
            return concatenate(array, array3);
        }
        if (null == array3) {
            return concatenate(array, array2);
        }
        final byte[] array4 = new byte[array.length + array2.length + array3.length];
        final int n = 0;
        System.arraycopy(array, 0, array4, n, array.length);
        final int n2 = n + array.length;
        System.arraycopy(array2, 0, array4, n2, array2.length);
        System.arraycopy(array3, 0, array4, n2 + array2.length, array3.length);
        return array4;
    }
    
    public static byte[] concatenate(final byte[] array, final byte[] array2, final byte[] array3, final byte[] array4) {
        if (null == array) {
            return concatenate(array2, array3, array4);
        }
        if (null == array2) {
            return concatenate(array, array3, array4);
        }
        if (null == array3) {
            return concatenate(array, array2, array4);
        }
        if (null == array4) {
            return concatenate(array, array2, array3);
        }
        final byte[] array5 = new byte[array.length + array2.length + array3.length + array4.length];
        final int n = 0;
        System.arraycopy(array, 0, array5, n, array.length);
        final int n2 = n + array.length;
        System.arraycopy(array2, 0, array5, n2, array2.length);
        final int n3 = n2 + array2.length;
        System.arraycopy(array3, 0, array5, n3, array3.length);
        System.arraycopy(array4, 0, array5, n3 + array3.length, array4.length);
        return array5;
    }
    
    public static byte[] concatenate(final byte[][] array) {
        int n = 0;
        for (int i = 0; i != array.length; ++i) {
            n += array[i].length;
        }
        final byte[] array2 = new byte[n];
        int n2 = 0;
        for (int j = 0; j != array.length; ++j) {
            System.arraycopy(array[j], 0, array2, n2, array[j].length);
            n2 += array[j].length;
        }
        return array2;
    }
    
    public static int[] concatenate(final int[] array, final int[] array2) {
        if (null == array) {
            return clone(array2);
        }
        if (null == array2) {
            return clone(array);
        }
        final int[] array3 = new int[array.length + array2.length];
        System.arraycopy(array, 0, array3, 0, array.length);
        System.arraycopy(array2, 0, array3, array.length, array2.length);
        return array3;
    }
    
    public static byte[] prepend(final byte[] array, final byte b) {
        if (array == null) {
            return new byte[] { b };
        }
        final int length = array.length;
        final byte[] array2 = new byte[length + 1];
        System.arraycopy(array, 0, array2, 1, length);
        array2[0] = b;
        return array2;
    }
    
    public static short[] prepend(final short[] array, final short n) {
        if (array == null) {
            return new short[] { n };
        }
        final int length = array.length;
        final short[] array2 = new short[length + 1];
        System.arraycopy(array, 0, array2, 1, length);
        array2[0] = n;
        return array2;
    }
    
    public static int[] prepend(final int[] array, final int n) {
        if (array == null) {
            return new int[] { n };
        }
        final int length = array.length;
        final int[] array2 = new int[length + 1];
        System.arraycopy(array, 0, array2, 1, length);
        array2[0] = n;
        return array2;
    }
    
    public static byte[] reverse(final byte[] array) {
        if (array == null) {
            return null;
        }
        int n = 0;
        int length = array.length;
        final byte[] array2 = new byte[length];
        while (--length >= 0) {
            array2[length] = array[n++];
        }
        return array2;
    }
    
    public static int[] reverse(final int[] array) {
        if (array == null) {
            return null;
        }
        int n = 0;
        int length = array.length;
        final int[] array2 = new int[length];
        while (--length >= 0) {
            array2[length] = array[n++];
        }
        return array2;
    }
    
    public static void reverse(final byte[] array, final byte[] array2) {
        for (int n = array.length - 1, i = 0; i <= n; ++i) {
            array2[i] = array[n - i];
        }
    }
    
    public static byte[] reverseInPlace(final byte[] array) {
        if (null == array) {
            return null;
        }
        byte b;
        for (int i = 0, n = array.length - 1; i < n; array[i++] = array[n], array[n--] = b) {
            b = array[i];
        }
        return array;
    }
    
    public static void reverseInPlace(final byte[] array, final int n, final int n2) {
        byte b;
        for (int i = n, n3 = n + n2 - 1; i < n3; array[i++] = array[n3], array[n3--] = b) {
            b = array[i];
        }
    }
    
    public static short[] reverseInPlace(final short[] array) {
        if (null == array) {
            return null;
        }
        short n2;
        for (int i = 0, n = array.length - 1; i < n; array[i++] = array[n], array[n--] = n2) {
            n2 = array[i];
        }
        return array;
    }
    
    public static int[] reverseInPlace(final int[] array) {
        if (null == array) {
            return null;
        }
        int n2;
        for (int i = 0, n = array.length - 1; i < n; array[i++] = array[n], array[n--] = n2) {
            n2 = array[i];
        }
        return array;
    }
    
    public static void clear(final byte[] a) {
        if (null != a) {
            java.util.Arrays.fill(a, (byte)0);
        }
    }
    
    public static void clear(final int[] a) {
        if (null != a) {
            java.util.Arrays.fill(a, 0);
        }
    }
    
    public static void clear(final long[] a) {
        if (null != a) {
            java.util.Arrays.fill(a, 0L);
        }
    }
    
    public static void clear(final char[] a) {
        if (null != a) {
            java.util.Arrays.fill(a, '\0');
        }
    }
    
    public static boolean isNullOrContainsNull(final Object[] array) {
        if (null == array) {
            return true;
        }
        for (int length = array.length, i = 0; i < length; ++i) {
            if (null == array[i]) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean isNullOrEmpty(final byte[] array) {
        return null == array || array.length < 1;
    }
    
    public static boolean isNullOrEmpty(final int[] array) {
        return null == array || array.length < 1;
    }
    
    public static boolean isNullOrEmpty(final Object[] array) {
        return null == array || array.length < 1;
    }
    
    public static boolean segmentsOverlap(final int n, final int n2, final int n3, final int n4) {
        return n2 > 0 && n4 > 0 && n - n3 < n4 && n3 - n < n2;
    }
    
    public static void validateRange(final byte[] array, final int i, final int j) {
        if (array == null) {
            throw new NullPointerException("'buf' cannot be null");
        }
        if ((i | array.length - i | j - i | array.length - j) < 0) {
            throw new IndexOutOfBoundsException("buf.length: " + array.length + ", from: " + i + ", to: " + j);
        }
    }
    
    public static void validateSegment(final byte[] array, final int i, final int j) {
        if (array == null) {
            throw new NullPointerException("'buf' cannot be null");
        }
        final int n = array.length - i;
        if ((i | j | n | n - j) < 0) {
            throw new IndexOutOfBoundsException("buf.length: " + array.length + ", off: " + i + ", len: " + j);
        }
    }
    
    public static class Iterator<T> implements java.util.Iterator<T>
    {
        private final T[] dataArray;
        private int position;
        
        public Iterator(final T[] dataArray) {
            this.position = 0;
            this.dataArray = dataArray;
        }
        
        @Override
        public boolean hasNext() {
            return this.position < this.dataArray.length;
        }
        
        @Override
        public T next() {
            if (this.position == this.dataArray.length) {
                throw new NoSuchElementException("Out of elements: " + this.position);
            }
            return this.dataArray[this.position++];
        }
        
        @Override
        public void remove() {
            throw new UnsupportedOperationException("Cannot remove element from an Array.");
        }
    }
}
