Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.util;
     18 
     19 import android.util.ArraySet;
     20 
     21 import dalvik.system.VMRuntime;
     22 
     23 import libcore.util.EmptyArray;
     24 
     25 import java.lang.reflect.Array;
     26 import java.util.ArrayList;
     27 
     28 /**
     29  * ArrayUtils contains some methods that you can call to find out
     30  * the most efficient increments by which to grow arrays.
     31  */
     32 public class ArrayUtils
     33 {
     34     private static final int CACHE_SIZE = 73;
     35     private static Object[] sCache = new Object[CACHE_SIZE];
     36 
     37     private ArrayUtils() { /* cannot be instantiated */ }
     38 
     39     public static byte[] newUnpaddedByteArray(int minLen) {
     40         return (byte[])VMRuntime.getRuntime().newUnpaddedArray(byte.class, minLen);
     41     }
     42 
     43     public static char[] newUnpaddedCharArray(int minLen) {
     44         return (char[])VMRuntime.getRuntime().newUnpaddedArray(char.class, minLen);
     45     }
     46 
     47     public static int[] newUnpaddedIntArray(int minLen) {
     48         return (int[])VMRuntime.getRuntime().newUnpaddedArray(int.class, minLen);
     49     }
     50 
     51     public static boolean[] newUnpaddedBooleanArray(int minLen) {
     52         return (boolean[])VMRuntime.getRuntime().newUnpaddedArray(boolean.class, minLen);
     53     }
     54 
     55     public static long[] newUnpaddedLongArray(int minLen) {
     56         return (long[])VMRuntime.getRuntime().newUnpaddedArray(long.class, minLen);
     57     }
     58 
     59     public static float[] newUnpaddedFloatArray(int minLen) {
     60         return (float[])VMRuntime.getRuntime().newUnpaddedArray(float.class, minLen);
     61     }
     62 
     63     public static Object[] newUnpaddedObjectArray(int minLen) {
     64         return (Object[])VMRuntime.getRuntime().newUnpaddedArray(Object.class, minLen);
     65     }
     66 
     67     @SuppressWarnings("unchecked")
     68     public static <T> T[] newUnpaddedArray(Class<T> clazz, int minLen) {
     69         return (T[])VMRuntime.getRuntime().newUnpaddedArray(clazz, minLen);
     70     }
     71 
     72     /**
     73      * Checks if the beginnings of two byte arrays are equal.
     74      *
     75      * @param array1 the first byte array
     76      * @param array2 the second byte array
     77      * @param length the number of bytes to check
     78      * @return true if they're equal, false otherwise
     79      */
     80     public static boolean equals(byte[] array1, byte[] array2, int length) {
     81         if (length < 0) {
     82             throw new IllegalArgumentException();
     83         }
     84 
     85         if (array1 == array2) {
     86             return true;
     87         }
     88         if (array1 == null || array2 == null || array1.length < length || array2.length < length) {
     89             return false;
     90         }
     91         for (int i = 0; i < length; i++) {
     92             if (array1[i] != array2[i]) {
     93                 return false;
     94             }
     95         }
     96         return true;
     97     }
     98 
     99     /**
    100      * Returns an empty array of the specified type.  The intent is that
    101      * it will return the same empty array every time to avoid reallocation,
    102      * although this is not guaranteed.
    103      */
    104     @SuppressWarnings("unchecked")
    105     public static <T> T[] emptyArray(Class<T> kind) {
    106         if (kind == Object.class) {
    107             return (T[]) EmptyArray.OBJECT;
    108         }
    109 
    110         int bucket = (kind.hashCode() & 0x7FFFFFFF) % CACHE_SIZE;
    111         Object cache = sCache[bucket];
    112 
    113         if (cache == null || cache.getClass().getComponentType() != kind) {
    114             cache = Array.newInstance(kind, 0);
    115             sCache[bucket] = cache;
    116 
    117             // Log.e("cache", "new empty " + kind.getName() + " at " + bucket);
    118         }
    119 
    120         return (T[]) cache;
    121     }
    122 
    123     /**
    124      * Checks if given array is null or has zero elements.
    125      */
    126     public static <T> boolean isEmpty(T[] array) {
    127         return array == null || array.length == 0;
    128     }
    129 
    130     /**
    131      * Checks that value is present as at least one of the elements of the array.
    132      * @param array the array to check in
    133      * @param value the value to check for
    134      * @return true if the value is present in the array
    135      */
    136     public static <T> boolean contains(T[] array, T value) {
    137         return indexOf(array, value) != -1;
    138     }
    139 
    140     /**
    141      * Return first index of {@code value} in {@code array}, or {@code -1} if
    142      * not found.
    143      */
    144     public static <T> int indexOf(T[] array, T value) {
    145         if (array == null) return -1;
    146         for (int i = 0; i < array.length; i++) {
    147             if (array[i] == null) {
    148                 if (value == null) return i;
    149             } else {
    150                 if (value != null && array[i].equals(value)) return i;
    151             }
    152         }
    153         return -1;
    154     }
    155 
    156     /**
    157      * Test if all {@code check} items are contained in {@code array}.
    158      */
    159     public static <T> boolean containsAll(T[] array, T[] check) {
    160         for (T checkItem : check) {
    161             if (!contains(array, checkItem)) {
    162                 return false;
    163             }
    164         }
    165         return true;
    166     }
    167 
    168     public static boolean contains(int[] array, int value) {
    169         if (array == null) return false;
    170         for (int element : array) {
    171             if (element == value) {
    172                 return true;
    173             }
    174         }
    175         return false;
    176     }
    177 
    178     public static boolean contains(long[] array, long value) {
    179         if (array == null) return false;
    180         for (long element : array) {
    181             if (element == value) {
    182                 return true;
    183             }
    184         }
    185         return false;
    186     }
    187 
    188     public static long total(long[] array) {
    189         long total = 0;
    190         for (long value : array) {
    191             total += value;
    192         }
    193         return total;
    194     }
    195 
    196     /**
    197      * Appends an element to a copy of the array and returns the copy.
    198      * @param array The original array, or null to represent an empty array.
    199      * @param element The element to add.
    200      * @return A new array that contains all of the elements of the original array
    201      * with the specified element added at the end.
    202      */
    203     @SuppressWarnings("unchecked")
    204     public static <T> T[] appendElement(Class<T> kind, T[] array, T element) {
    205         final T[] result;
    206         final int end;
    207         if (array != null) {
    208             end = array.length;
    209             result = (T[])Array.newInstance(kind, end + 1);
    210             System.arraycopy(array, 0, result, 0, end);
    211         } else {
    212             end = 0;
    213             result = (T[])Array.newInstance(kind, 1);
    214         }
    215         result[end] = element;
    216         return result;
    217     }
    218 
    219     /**
    220      * Removes an element from a copy of the array and returns the copy.
    221      * If the element is not present, then the original array is returned unmodified.
    222      * @param array The original array, or null to represent an empty array.
    223      * @param element The element to remove.
    224      * @return A new array that contains all of the elements of the original array
    225      * except the first copy of the specified element removed.  If the specified element
    226      * was not present, then returns the original array.  Returns null if the result
    227      * would be an empty array.
    228      */
    229     @SuppressWarnings("unchecked")
    230     public static <T> T[] removeElement(Class<T> kind, T[] array, T element) {
    231         if (array != null) {
    232             final int length = array.length;
    233             for (int i = 0; i < length; i++) {
    234                 if (array[i] == element) {
    235                     if (length == 1) {
    236                         return null;
    237                     }
    238                     T[] result = (T[])Array.newInstance(kind, length - 1);
    239                     System.arraycopy(array, 0, result, 0, i);
    240                     System.arraycopy(array, i + 1, result, i, length - i - 1);
    241                     return result;
    242                 }
    243             }
    244         }
    245         return array;
    246     }
    247 
    248     /**
    249      * Appends a new value to a copy of the array and returns the copy.  If
    250      * the value is already present, the original array is returned
    251      * @param cur The original array, or null to represent an empty array.
    252      * @param val The value to add.
    253      * @return A new array that contains all of the values of the original array
    254      * with the new value added, or the original array.
    255      */
    256     public static int[] appendInt(int[] cur, int val) {
    257         if (cur == null) {
    258             return new int[] { val };
    259         }
    260         final int N = cur.length;
    261         for (int i = 0; i < N; i++) {
    262             if (cur[i] == val) {
    263                 return cur;
    264             }
    265         }
    266         int[] ret = new int[N + 1];
    267         System.arraycopy(cur, 0, ret, 0, N);
    268         ret[N] = val;
    269         return ret;
    270     }
    271 
    272     public static int[] removeInt(int[] cur, int val) {
    273         if (cur == null) {
    274             return null;
    275         }
    276         final int N = cur.length;
    277         for (int i = 0; i < N; i++) {
    278             if (cur[i] == val) {
    279                 int[] ret = new int[N - 1];
    280                 if (i > 0) {
    281                     System.arraycopy(cur, 0, ret, 0, i);
    282                 }
    283                 if (i < (N - 1)) {
    284                     System.arraycopy(cur, i + 1, ret, i, N - i - 1);
    285                 }
    286                 return ret;
    287             }
    288         }
    289         return cur;
    290     }
    291 
    292     /**
    293      * Appends a new value to a copy of the array and returns the copy.  If
    294      * the value is already present, the original array is returned
    295      * @param cur The original array, or null to represent an empty array.
    296      * @param val The value to add.
    297      * @return A new array that contains all of the values of the original array
    298      * with the new value added, or the original array.
    299      */
    300     public static long[] appendLong(long[] cur, long val) {
    301         if (cur == null) {
    302             return new long[] { val };
    303         }
    304         final int N = cur.length;
    305         for (int i = 0; i < N; i++) {
    306             if (cur[i] == val) {
    307                 return cur;
    308             }
    309         }
    310         long[] ret = new long[N + 1];
    311         System.arraycopy(cur, 0, ret, 0, N);
    312         ret[N] = val;
    313         return ret;
    314     }
    315 
    316     public static long[] removeLong(long[] cur, long val) {
    317         if (cur == null) {
    318             return null;
    319         }
    320         final int N = cur.length;
    321         for (int i = 0; i < N; i++) {
    322             if (cur[i] == val) {
    323                 long[] ret = new long[N - 1];
    324                 if (i > 0) {
    325                     System.arraycopy(cur, 0, ret, 0, i);
    326                 }
    327                 if (i < (N - 1)) {
    328                     System.arraycopy(cur, i + 1, ret, i, N - i - 1);
    329                 }
    330                 return ret;
    331             }
    332         }
    333         return cur;
    334     }
    335 
    336     public static long[] cloneOrNull(long[] array) {
    337         return (array != null) ? array.clone() : null;
    338     }
    339 
    340     public static <T> ArraySet<T> add(ArraySet<T> cur, T val) {
    341         if (cur == null) {
    342             cur = new ArraySet<>();
    343         }
    344         cur.add(val);
    345         return cur;
    346     }
    347 
    348     public static <T> ArraySet<T> remove(ArraySet<T> cur, T val) {
    349         if (cur == null) {
    350             return null;
    351         }
    352         cur.remove(val);
    353         if (cur.isEmpty()) {
    354             return null;
    355         } else {
    356             return cur;
    357         }
    358     }
    359 
    360     public static <T> boolean contains(ArraySet<T> cur, T val) {
    361         return (cur != null) ? cur.contains(val) : false;
    362     }
    363 
    364     public static <T> ArrayList<T> add(ArrayList<T> cur, T val) {
    365         if (cur == null) {
    366             cur = new ArrayList<>();
    367         }
    368         cur.add(val);
    369         return cur;
    370     }
    371 
    372     public static <T> ArrayList<T> remove(ArrayList<T> cur, T val) {
    373         if (cur == null) {
    374             return null;
    375         }
    376         cur.remove(val);
    377         if (cur.isEmpty()) {
    378             return null;
    379         } else {
    380             return cur;
    381         }
    382     }
    383 
    384     public static <T> boolean contains(ArrayList<T> cur, T val) {
    385         return (cur != null) ? cur.contains(val) : false;
    386     }
    387 }
    388