/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.util; import java.lang.reflect.Array; import java.nio.ByteBuffer; public class ArrayUtil { /* * verify an array copy before copying * * @param source * @param srcOffset * @param dest * @param destOffset * @param count * @return true if array can be copied */ public static boolean blockCopy(byte[] source, int srcOffset, byte[] dest, int destOffset, int count) { if ((source == null) || (dest == null)) return false; if ((srcOffset < 0) || (destOffset < 0) || (count <= 0)) return false; if ((source.length - srcOffset) < count) return false; if ((dest.length - destOffset) < count) return false; System.arraycopy(source, srcOffset, dest, destOffset, count); return true; } /* * verify and assist a byte buffer to byte array copy * * @param source * @param srcOffset * @param dest * @param destOffset * @param count * @return true if copy allowed */ public static boolean blockCopy(ByteBuffer source, int srcOffset, byte[] dest, int destOffset, int count) { if ((source == null) || (dest == null)) return false; if ((srcOffset < 0) || (destOffset < 0) || (count <= 0)) return false; if ((source.limit() - srcOffset) < count) return false; if ((dest.length - destOffset) < count) return false; source.position(srcOffset); source.get(dest,destOffset, count); return true; } /* * verify and assist a byte array to byte buffer copy * * @param source * @param srcOffset * @param dest * @param destOffset * @param count * @return true if copy allowed */ public static boolean blockCopy(byte[] source, int srcOffset, ByteBuffer dest, int destOffset, int count) { if ((source == null) || (dest == null)) return false; if ((srcOffset < 0) || (destOffset < 0) || (count <= 0)) return false; if ((source.length - srcOffset) < count) return false; if ((dest.limit() - destOffset) < count) return false; dest.position(destOffset); dest.put(source, srcOffset, count); return true; } /* * verify and assist a byte buffer to byte buffer copy * * @param source * @param srcOffset * @param dest * @param destOffset * @param count * @return true if copy allowed */ public static boolean blockCopy(ByteBuffer source, int srcOffset, ByteBuffer dest, int destOffset, int count) { if ((source == null) || (dest == null)) return false; if ((srcOffset < 0) || (destOffset < 0) || (count <= 0)) return false; if ((source.limit() - srcOffset) < count) return false; if ((dest.limit() - destOffset) < count) return false; int sl = source.limit(); source.limit(srcOffset + count); dest.position(destOffset); dest.put(source); source.limit(sl); return true; } @SuppressWarnings("unchecked") // OK, because array is of type T public static <T> T[] addAll(final T[] array1, final T... array2) { if ((array1 == null) && (array2 == null)) return null; if (array1 == null) return array2.clone(); if (array2 == null) return array1.clone(); final Class<?> type1 = array1.getClass().getComponentType(); final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length); System.arraycopy(array1, 0, joinedArray, 0, array1.length); try { System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); } catch (final ArrayStoreException ase) { // Check if problem was due to incompatible types /* * We do this here, rather than before the copy because: * - it would be a wasted check most of the time * - safer, in case check turns out to be too strict */ final Class<?> type2 = array2.getClass().getComponentType(); if (!type1.isAssignableFrom(type2)){ throw new IllegalArgumentException("Cannot store "+type2.getName()+" in an array of " +type1.getName(), ase); } throw ase; // No, so rethrow original } return joinedArray; } public static void reverse(final Object[] array) { if (array == null) { return; } reverse(array, 0, array.length); } public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) { if (array == null) return; int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; int j = Math.min(array.length, endIndexExclusive) - 1; Object tmp; while (j > i) { tmp = array[j]; array[j] = array[i]; array[i] = tmp; j--; i++; } } public static void increment(byte[] array) { for (int i = (array.length - 1); i >= 0; i--) { array[i]++; if (array[i] != 0) return; } throw new IndexOutOfBoundsException("Unable to increment array. Length: " + array.length); } }