19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.util;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1959d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkeyimport android.annotation.NonNull;
2059d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkeyimport android.annotation.Nullable;
21da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkeyimport android.util.ArraySet;
22da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey
23776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinskiimport dalvik.system.VMRuntime;
24da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey
25776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinskiimport libcore.util.EmptyArray;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinskiimport java.lang.reflect.Array;
28da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkeyimport java.util.ArrayList;
2959d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkeyimport java.util.Objects;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ArrayUtils contains some methods that you can call to find out
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the most efficient increments by which to grow arrays.
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3559d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkeypublic class ArrayUtils {
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int CACHE_SIZE = 73;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static Object[] sCache = new Object[CACHE_SIZE];
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayUtils() { /* cannot be instantiated */ }
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
41776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    public static byte[] newUnpaddedByteArray(int minLen) {
42776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        return (byte[])VMRuntime.getRuntime().newUnpaddedArray(byte.class, minLen);
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
45776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    public static char[] newUnpaddedCharArray(int minLen) {
46776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        return (char[])VMRuntime.getRuntime().newUnpaddedArray(char.class, minLen);
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
49776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    public static int[] newUnpaddedIntArray(int minLen) {
50776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        return (int[])VMRuntime.getRuntime().newUnpaddedArray(int.class, minLen);
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
53776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    public static boolean[] newUnpaddedBooleanArray(int minLen) {
54776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        return (boolean[])VMRuntime.getRuntime().newUnpaddedArray(boolean.class, minLen);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
57776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    public static long[] newUnpaddedLongArray(int minLen) {
58776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        return (long[])VMRuntime.getRuntime().newUnpaddedArray(long.class, minLen);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
61776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    public static float[] newUnpaddedFloatArray(int minLen) {
62776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        return (float[])VMRuntime.getRuntime().newUnpaddedArray(float.class, minLen);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
65776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    public static Object[] newUnpaddedObjectArray(int minLen) {
66776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        return (Object[])VMRuntime.getRuntime().newUnpaddedArray(Object.class, minLen);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
69776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    @SuppressWarnings("unchecked")
70776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    public static <T> T[] newUnpaddedArray(Class<T> clazz, int minLen) {
71776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski        return (T[])VMRuntime.getRuntime().newUnpaddedArray(clazz, minLen);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Checks if the beginnings of two byte arrays are equal.
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param array1 the first byte array
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param array2 the second byte array
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param length the number of bytes to check
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if they're equal, false otherwise
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean equals(byte[] array1, byte[] array2, int length) {
83fc054349089563699349c161011f378c67d15587Christopher Tate        if (length < 0) {
84fc054349089563699349c161011f378c67d15587Christopher Tate            throw new IllegalArgumentException();
85fc054349089563699349c161011f378c67d15587Christopher Tate        }
86fc054349089563699349c161011f378c67d15587Christopher Tate
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (array1 == array2) {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (array1 == null || array2 == null || array1.length < length || array2.length < length) {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < length; i++) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (array1[i] != array2[i]) {
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns an empty array of the specified type.  The intent is that
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it will return the same empty array every time to avoid reallocation,
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * although this is not guaranteed.
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
106776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski    @SuppressWarnings("unchecked")
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static <T> T[] emptyArray(Class<T> kind) {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (kind == Object.class) {
109776abc24cdd18610232a50b997cce3cffa74609bAdam Lesinski            return (T[]) EmptyArray.OBJECT;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
112b4e5061fd6e0b665e025713643378ec31188cff2Mathieu Chartier        int bucket = (kind.hashCode() & 0x7FFFFFFF) % CACHE_SIZE;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Object cache = sCache[bucket];
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cache == null || cache.getClass().getComponentType() != kind) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cache = Array.newInstance(kind, 0);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sCache[bucket] = cache;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Log.e("cache", "new empty " + kind.getName() + " at " + bucket);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (T[]) cache;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1263a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey     * Checks if given array is null or has zero elements.
1273a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey     */
1283a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey    public static <T> boolean isEmpty(T[] array) {
1293a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey        return array == null || array.length == 0;
1303a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey    }
1313a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey
1323a44f3f1b446315ef894e01d2ab9b5388c2bd8c4Jeff Sharkey    /**
1333256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * Checks if given array is null or has zero elements.
1343256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     */
1353256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    public static boolean isEmpty(int[] array) {
1363256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        return array == null || array.length == 0;
1373256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    }
1383256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
1393256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    /**
1403256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * Checks if given array is null or has zero elements.
1413256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     */
1423256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    public static boolean isEmpty(long[] array) {
1433256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        return array == null || array.length == 0;
1443256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    }
1453256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
1463256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    /**
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Checks that value is present as at least one of the elements of the array.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param array the array to check in
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param value the value to check for
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the value is present in the array
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static <T> boolean contains(T[] array, T value) {
15394c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey        return indexOf(array, value) != -1;
15494c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey    }
15594c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey
15694c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey    /**
15794c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey     * Return first index of {@code value} in {@code array}, or {@code -1} if
15894c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey     * not found.
15994c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey     */
16094c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey    public static <T> int indexOf(T[] array, T value) {
16157dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey        if (array == null) return -1;
16294c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey        for (int i = 0; i < array.length; i++) {
16359d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey            if (Objects.equals(array[i], value)) return i;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16594c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey        return -1;
16694c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey    }
16794c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey
16894c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey    /**
16994c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey     * Test if all {@code check} items are contained in {@code array}.
17094c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey     */
17194c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey    public static <T> boolean containsAll(T[] array, T[] check) {
1723256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        if (check == null) return true;
17394c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey        for (T checkItem : check) {
17494c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey            if (!contains(array, checkItem)) {
17594c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey                return false;
17694c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey            }
17794c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey        }
17894c91dca55de9ffdbe072fcc5dd6dbf1efe5e4c1Jeff Sharkey        return true;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
180630a1712168f402653039e368259cb9480454fa8Jeff Sharkey
181630a1712168f402653039e368259cb9480454fa8Jeff Sharkey    public static boolean contains(int[] array, int value) {
18257dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey        if (array == null) return false;
183630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        for (int element : array) {
184630a1712168f402653039e368259cb9480454fa8Jeff Sharkey            if (element == value) {
185630a1712168f402653039e368259cb9480454fa8Jeff Sharkey                return true;
186630a1712168f402653039e368259cb9480454fa8Jeff Sharkey            }
187630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        }
188630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        return false;
189630a1712168f402653039e368259cb9480454fa8Jeff Sharkey    }
19096e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown
191874d0d4032dc940327a81359f144d38d3cb580a3dcashman    public static boolean contains(long[] array, long value) {
19257dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey        if (array == null) return false;
193874d0d4032dc940327a81359f144d38d3cb580a3dcashman        for (long element : array) {
194874d0d4032dc940327a81359f144d38d3cb580a3dcashman            if (element == value) {
195874d0d4032dc940327a81359f144d38d3cb580a3dcashman                return true;
196874d0d4032dc940327a81359f144d38d3cb580a3dcashman            }
197874d0d4032dc940327a81359f144d38d3cb580a3dcashman        }
198874d0d4032dc940327a81359f144d38d3cb580a3dcashman        return false;
199874d0d4032dc940327a81359f144d38d3cb580a3dcashman    }
200874d0d4032dc940327a81359f144d38d3cb580a3dcashman
20163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    public static long total(long[] array) {
20263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        long total = 0;
20363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        for (long value : array) {
20463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            total += value;
20563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        }
20663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return total;
20763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    }
20863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
20996e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown    /**
21059d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * Adds value to given array if not already present, providing set-like
21159d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * behavior.
21296e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown     */
21396e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown    @SuppressWarnings("unchecked")
21459d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey    public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
21596e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        final T[] result;
21696e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        final int end;
21796e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        if (array != null) {
21859d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey            if (contains(array, element)) return array;
21996e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown            end = array.length;
22096e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown            result = (T[])Array.newInstance(kind, end + 1);
22196e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown            System.arraycopy(array, 0, result, 0, end);
22296e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        } else {
22396e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown            end = 0;
22496e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown            result = (T[])Array.newInstance(kind, 1);
22596e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        }
22696e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        result[end] = element;
22796e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        return result;
22896e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown    }
22996e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown
23096e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown    /**
23159d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * Removes value from given array if present, providing set-like behavior.
23296e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown     */
23396e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown    @SuppressWarnings("unchecked")
23459d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey    public static @Nullable <T> T[] removeElement(Class<T> kind, @Nullable T[] array, T element) {
23596e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        if (array != null) {
23659d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey            if (!contains(array, element)) return array;
23796e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown            final int length = array.length;
23896e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown            for (int i = 0; i < length; i++) {
23959d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey                if (Objects.equals(array[i], element)) {
24096e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown                    if (length == 1) {
24196e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown                        return null;
24296e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown                    }
24396e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown                    T[] result = (T[])Array.newInstance(kind, length - 1);
24496e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown                    System.arraycopy(array, 0, result, 0, i);
24596e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown                    System.arraycopy(array, i + 1, result, i, length - i - 1);
24696e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown                    return result;
24796e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown                }
24896e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown            }
24996e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        }
25096e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown        return array;
25196e942dabeeaaa9ab6df3a870668c6fe53d930daJeff Brown    }
252854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey
253874d0d4032dc940327a81359f144d38d3cb580a3dcashman    /**
25459d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * Adds value to given array if not already present, providing set-like
25559d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * behavior.
256874d0d4032dc940327a81359f144d38d3cb580a3dcashman     */
25759d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey    public static @NonNull int[] appendInt(@Nullable int[] cur, int val) {
258854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        if (cur == null) {
259854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey            return new int[] { val };
260854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        }
261854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        final int N = cur.length;
262854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        for (int i = 0; i < N; i++) {
263854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey            if (cur[i] == val) {
264854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                return cur;
265854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey            }
266854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        }
267854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        int[] ret = new int[N + 1];
268854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        System.arraycopy(cur, 0, ret, 0, N);
269854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        ret[N] = val;
270854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        return ret;
271854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey    }
272854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey
27359d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey    /**
27459d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * Removes value from given array if present, providing set-like behavior.
27559d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     */
27659d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey    public static @Nullable int[] removeInt(@Nullable int[] cur, int val) {
277854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        if (cur == null) {
278854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey            return null;
279854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        }
280854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        final int N = cur.length;
281854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        for (int i = 0; i < N; i++) {
282854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey            if (cur[i] == val) {
283854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                int[] ret = new int[N - 1];
284854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                if (i > 0) {
285854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                    System.arraycopy(cur, 0, ret, 0, i);
286854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                }
287854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                if (i < (N - 1)) {
288854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                    System.arraycopy(cur, i + 1, ret, i, N - i - 1);
289854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                }
290854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                return ret;
291854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey            }
292854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        }
293854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        return cur;
294854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey    }
295874d0d4032dc940327a81359f144d38d3cb580a3dcashman
296874d0d4032dc940327a81359f144d38d3cb580a3dcashman    /**
29752153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov     * Removes value from given array if present, providing set-like behavior.
29852153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov     */
29952153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov    public static @Nullable String[] removeString(@Nullable String[] cur, String val) {
30052153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov        if (cur == null) {
30152153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov            return null;
30252153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov        }
30352153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov        final int N = cur.length;
30452153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov        for (int i = 0; i < N; i++) {
30552153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov            if (Objects.equals(cur[i], val)) {
30652153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov                String[] ret = new String[N - 1];
30752153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov                if (i > 0) {
30852153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov                    System.arraycopy(cur, 0, ret, 0, i);
30952153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov                }
31052153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov                if (i < (N - 1)) {
31152153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov                    System.arraycopy(cur, i + 1, ret, i, N - i - 1);
31252153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov                }
31352153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov                return ret;
31452153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov            }
31552153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov        }
31652153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov        return cur;
31752153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov    }
31852153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov
31952153f4c0540a991b5b7214f4f14b5a891479a3cSvet Ganov    /**
32059d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * Adds value to given array if not already present, providing set-like
32159d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * behavior.
322874d0d4032dc940327a81359f144d38d3cb580a3dcashman     */
32359d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey    public static @NonNull long[] appendLong(@Nullable long[] cur, long val) {
324874d0d4032dc940327a81359f144d38d3cb580a3dcashman        if (cur == null) {
325874d0d4032dc940327a81359f144d38d3cb580a3dcashman            return new long[] { val };
326874d0d4032dc940327a81359f144d38d3cb580a3dcashman        }
327874d0d4032dc940327a81359f144d38d3cb580a3dcashman        final int N = cur.length;
328874d0d4032dc940327a81359f144d38d3cb580a3dcashman        for (int i = 0; i < N; i++) {
329874d0d4032dc940327a81359f144d38d3cb580a3dcashman            if (cur[i] == val) {
330874d0d4032dc940327a81359f144d38d3cb580a3dcashman                return cur;
331874d0d4032dc940327a81359f144d38d3cb580a3dcashman            }
332874d0d4032dc940327a81359f144d38d3cb580a3dcashman        }
333874d0d4032dc940327a81359f144d38d3cb580a3dcashman        long[] ret = new long[N + 1];
334874d0d4032dc940327a81359f144d38d3cb580a3dcashman        System.arraycopy(cur, 0, ret, 0, N);
335874d0d4032dc940327a81359f144d38d3cb580a3dcashman        ret[N] = val;
336874d0d4032dc940327a81359f144d38d3cb580a3dcashman        return ret;
337874d0d4032dc940327a81359f144d38d3cb580a3dcashman    }
338874d0d4032dc940327a81359f144d38d3cb580a3dcashman
33959d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey    /**
34059d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     * Removes value from given array if present, providing set-like behavior.
34159d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey     */
34259d577a518333f4b4514315b6d10e8dba160abcdJeff Sharkey    public static @Nullable long[] removeLong(@Nullable long[] cur, long val) {
343874d0d4032dc940327a81359f144d38d3cb580a3dcashman        if (cur == null) {
344874d0d4032dc940327a81359f144d38d3cb580a3dcashman            return null;
345874d0d4032dc940327a81359f144d38d3cb580a3dcashman        }
346874d0d4032dc940327a81359f144d38d3cb580a3dcashman        final int N = cur.length;
347874d0d4032dc940327a81359f144d38d3cb580a3dcashman        for (int i = 0; i < N; i++) {
348874d0d4032dc940327a81359f144d38d3cb580a3dcashman            if (cur[i] == val) {
349874d0d4032dc940327a81359f144d38d3cb580a3dcashman                long[] ret = new long[N - 1];
350874d0d4032dc940327a81359f144d38d3cb580a3dcashman                if (i > 0) {
351874d0d4032dc940327a81359f144d38d3cb580a3dcashman                    System.arraycopy(cur, 0, ret, 0, i);
352874d0d4032dc940327a81359f144d38d3cb580a3dcashman                }
353874d0d4032dc940327a81359f144d38d3cb580a3dcashman                if (i < (N - 1)) {
354874d0d4032dc940327a81359f144d38d3cb580a3dcashman                    System.arraycopy(cur, i + 1, ret, i, N - i - 1);
355874d0d4032dc940327a81359f144d38d3cb580a3dcashman                }
356874d0d4032dc940327a81359f144d38d3cb580a3dcashman                return ret;
357874d0d4032dc940327a81359f144d38d3cb580a3dcashman            }
358874d0d4032dc940327a81359f144d38d3cb580a3dcashman        }
359874d0d4032dc940327a81359f144d38d3cb580a3dcashman        return cur;
360874d0d4032dc940327a81359f144d38d3cb580a3dcashman    }
36157dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey
36257dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey    public static long[] cloneOrNull(long[] array) {
36357dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey        return (array != null) ? array.clone() : null;
36457dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey    }
365da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey
366da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    public static <T> ArraySet<T> add(ArraySet<T> cur, T val) {
367da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        if (cur == null) {
368da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey            cur = new ArraySet<>();
369da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        }
370da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        cur.add(val);
371da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        return cur;
372da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    }
373da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey
374da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    public static <T> ArraySet<T> remove(ArraySet<T> cur, T val) {
375da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        if (cur == null) {
376da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey            return null;
377da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        }
378da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        cur.remove(val);
379da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        if (cur.isEmpty()) {
380da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey            return null;
381da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        } else {
382da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey            return cur;
383da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        }
384da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    }
385da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey
386da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    public static <T> boolean contains(ArraySet<T> cur, T val) {
387da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        return (cur != null) ? cur.contains(val) : false;
388da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    }
389da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey
390da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    public static <T> ArrayList<T> add(ArrayList<T> cur, T val) {
391da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        if (cur == null) {
392da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey            cur = new ArrayList<>();
393da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        }
394da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        cur.add(val);
395da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        return cur;
396da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    }
397da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey
398da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    public static <T> ArrayList<T> remove(ArrayList<T> cur, T val) {
399da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        if (cur == null) {
400da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey            return null;
401da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        }
402da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        cur.remove(val);
403da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        if (cur.isEmpty()) {
404da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey            return null;
405da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        } else {
406da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey            return cur;
407da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        }
408da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    }
409da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey
410da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    public static <T> boolean contains(ArrayList<T> cur, T val) {
411da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey        return (cur != null) ? cur.contains(val) : false;
412da96e137bcc8191c584ada7b5de31eaae92f244fJeff Sharkey    }
41372478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski
41472478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski    /**
41572478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski     * Returns true if the two ArrayLists are equal with respect to the objects they contain.
41672478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski     * The objects must be in the same order and be reference equal (== not .equals()).
41772478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski     */
41872478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski    public static <T> boolean referenceEquals(ArrayList<T> a, ArrayList<T> b) {
41972478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        if (a == b) {
42072478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski            return true;
42172478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        }
42272478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski
42372478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        final int sizeA = a.size();
42472478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        final int sizeB = b.size();
42572478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        if (a == null || b == null || sizeA != sizeB) {
42672478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski            return false;
42772478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        }
42872478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski
42972478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        boolean diff = false;
43072478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        for (int i = 0; i < sizeA && !diff; i++) {
43172478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski            diff |= a.get(i) != b.get(i);
43272478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        }
43372478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski        return !diff;
43472478f053f403e29223dba6cc7be9e5bf115f670Adam Lesinski    }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
436