From 43510a529117b03de3dd983c1baaa241d6cf2b57 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 29 Jul 2022 17:57:52 +0000 Subject: [PATCH] ArrayUtils: add concat() for byte arrays Concatenating byte arrays is a common thing that needs to be done, especially in the locksettings package, so add a utility method for it. Test: atest com.android.internal.util.ArrayUtilsTest Merged-In: I099c83155456139729f4d73f5873a172590ee7e9 Change-Id: I099c83155456139729f4d73f5873a172590ee7e9 (cherry picked from commit 4dd9540f0e1d157b233a4c0d27c7f350b93f18c0) --- .../com/android/internal/util/ArrayUtils.java | 31 ++++++++++-- .../android/internal/util/ArrayUtilsTest.java | 50 +++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 19228bc290e5a..d192ad932a623 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -39,8 +39,7 @@ import java.util.Set; import java.util.function.IntFunction; /** - * ArrayUtils contains some methods that you can call to find out - * the most efficient increments by which to grow arrays. + * Static utility methods for arrays that aren't already included in {@link java.util.Arrays}. */ public class ArrayUtils { private static final int CACHE_SIZE = 73; @@ -341,10 +340,11 @@ public class ArrayUtils { } /** - * Combine multiple arrays into a single array. + * Returns the concatenation of the given arrays. Only works for object arrays, not for + * primitive arrays. See {@link #concat(byte[]...)} for a variant that works on byte arrays. * * @param kind The class of the array elements - * @param arrays The arrays to combine + * @param arrays The arrays to concatenate. Null arrays are treated as empty. * @param The class of the array elements (inferred from kind). * @return A single array containing all the elements of the parameter arrays. */ @@ -390,6 +390,29 @@ public class ArrayUtils { return (T[]) Array.newInstance(kind, 0); } + /** + * Returns the concatenation of the given byte arrays. Null arrays are treated as empty. + */ + public static @NonNull byte[] concat(@Nullable byte[]... arrays) { + if (arrays == null) { + return new byte[0]; + } + int totalLength = 0; + for (byte[] a : arrays) { + if (a != null) { + totalLength += a.length; + } + } + final byte[] result = new byte[totalLength]; + int pos = 0; + for (byte[] a : arrays) { + if (a != null) { + System.arraycopy(a, 0, result, pos, a.length); + pos += a.length; + } + } + return result; + } /** * Adds value to given array if not already present, providing set-like diff --git a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java index 61f06bd515174..c66a743d8f530 100644 --- a/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/ArrayUtilsTest.java @@ -207,4 +207,54 @@ public class ArrayUtilsTest extends TestCase { assertArrayEquals(expectation, ArrayUtils.concat(String.class, array1, array2, array3)); } + + public void testConcat_zeroByteArrays() { + // empty varargs array + assertArrayEquals(new byte[] {}, ArrayUtils.concat()); + // null varargs array + assertArrayEquals(new byte[] {}, ArrayUtils.concat((byte[][]) null)); + } + + public void testConcat_oneByteArray() { + assertArrayEquals(new byte[] { 1, 2 }, ArrayUtils.concat(new byte[] { 1, 2 })); + } + + public void testConcat_oneEmptyByteArray() { + assertArrayEquals(new byte[] {}, ArrayUtils.concat((byte[]) null)); + assertArrayEquals(new byte[] {}, ArrayUtils.concat(new byte[] {})); + } + + public void testConcat_twoByteArrays() { + assertArrayEquals(new byte[] { 1 }, ArrayUtils.concat(new byte[] { 1 }, new byte[] {})); + assertArrayEquals(new byte[] { 1 }, ArrayUtils.concat(new byte[] {}, new byte[] { 1 })); + assertArrayEquals(new byte[] { 1, 2 }, + ArrayUtils.concat(new byte[] { 1 }, new byte[] { 2 })); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, + ArrayUtils.concat(new byte[] { 1, 2 }, new byte[] { 3, 4 })); + } + + public void testConcat_twoEmptyByteArrays() { + assertArrayEquals(new byte[] {}, ArrayUtils.concat((byte[]) null, null)); + assertArrayEquals(new byte[] {}, ArrayUtils.concat(new byte[] {}, null)); + assertArrayEquals(new byte[] {}, ArrayUtils.concat((byte[]) null, new byte[] {})); + assertArrayEquals(new byte[] {}, ArrayUtils.concat(new byte[] {}, new byte[] {})); + } + + public void testConcat_threeByteArrays() { + byte[] array1 = { 1, 2 }; + byte[] array2 = { 3, 4 }; + byte[] array3 = { 5, 6 }; + byte[] expectation = { 1, 2, 3, 4, 5, 6 }; + + assertArrayEquals(expectation, ArrayUtils.concat(array1, array2, array3)); + } + + public void testConcat_threeByteArraysWithNull() { + byte[] array1 = { 1, 2 }; + byte[] array2 = null; + byte[] array3 = { 5, 6 }; + byte[] expectation = { 1, 2, 5, 6 }; + + assertArrayEquals(expectation, ArrayUtils.concat(array1, array2, array3)); + } }