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 if given array is null or has zero elements.
    132      */
    133     public static boolean isEmpty(int[] array) {
    134         return array == null || array.length == 0;
    135     }
    136 
    137     /**
    138      * Checks if given array is null or has zero elements.
    139      */
    140     public static boolean isEmpty(long[] array) {
    141         return array == null || array.length == 0;
    142     }
    143 
    144     /**
    145      * Checks that value is present as at least one of the elements of the array.
    146      * @param array the array to check in
    147      * @param value the value to check for
    148      * @return true if the value is present in the array
    149      */
    150     public static <T> boolean contains(T[] array, T value) {
    151         return indexOf(array, value) != -1;
    152     }
    153 
    154     /**
    155      * Return first index of {@code value} in {@code array}, or {@code -1} if
    156      * not found.
    157      */
    158     public static <T> int indexOf(T[] array, T value) {
    159         if (array == null) return -1;
    160         for (int i = 0; i < array.length; i++) {
    161             if (array[i] == null) {
    162                 if (value == null) return i;
    163             } else {
    164                 if (value != null && array[i].equals(value)) return i;
    165             }
    166         }
    167         return -1;
    168     }
    169 
    170     /**
    171      * Test if all {@code check} items are contained in {@code array}.
    172      */
    173     public static <T> boolean containsAll(T[] array, T[] check) {
    174         if (check == null) return true;
    175         for (T checkItem : check) {
    176             if (!contains(array, checkItem)) {
    177                 return false;
    178             }
    179         }
    180         return true;
    181     }
    182 
    183     public static boolean contains(int[] array, int value) {
    184         if (array == null) return false;
    185         for (int element : array) {
    186             if (element == value) {
    187                 return true;
    188             }
    189         }
    190         return false;
    191     }
    192 
    193     public static boolean contains(long[] array, long value) {
    194         if (array == null) return false;
    195         for (long element : array) {
    196             if (element == value) {
    197                 return true;
    198             }
    199         }
    200         return false;
    201     }
    202 
    203     public static long total(long[] array) {
    204         long total = 0;
    205         for (long value : array) {
    206             total += value;
    207         }
    208         return total;
    209     }
    210 
    211     /**
    212      * Appends an element to a copy of the array and returns the copy.
    213      * @param array The original array, or null to represent an empty array.
    214      * @param element The element to add.
    215      * @return A new array that contains all of the elements of the original array
    216      * with the specified element added at the end.
    217      */
    218     @SuppressWarnings("unchecked")
    219     public static <T> T[] appendElement(Class<T> kind, T[] array, T element) {
    220         final T[] result;
    221         final int end;
    222         if (array != null) {
    223             end = array.length;
    224             result = (T[])Array.newInstance(kind, end + 1);
    225             System.arraycopy(array, 0, result, 0, end);
    226         } else {
    227             end = 0;
    228             result = (T[])Array.newInstance(kind, 1);
    229         }
    230         result[end] = element;
    231         return result;
    232     }
    233 
    234     /**
    235      * Removes an element from a copy of the array and returns the copy.
    236      * If the element is not present, then the original array is returned unmodified.
    237      * @param array The original array, or null to represent an empty array.
    238      * @param element The element to remove.
    239      * @return A new array that contains all of the elements of the original array
    240      * except the first copy of the specified element removed.  If the specified element
    241      * was not present, then returns the original array.  Returns null if the result
    242      * would be an empty array.
    243      */
    244     @SuppressWarnings("unchecked")
    245     public static <T> T[] removeElement(Class<T> kind, T[] array, T element) {
    246         if (array != null) {
    247             final int length = array.length;
    248             for (int i = 0; i < length; i++) {
    249                 if (array[i] == element) {
    250                     if (length == 1) {
    251                         return null;
    252                     }
    253                     T[] result = (T[])Array.newInstance(kind, length - 1);
    254                     System.arraycopy(array, 0, result, 0, i);
    255                     System.arraycopy(array, i + 1, result, i, length - i - 1);
    256                     return result;
    257                 }
    258             }
    259         }
    260         return array;
    261     }
    262 
    263     /**
    264      * Appends a new value to a copy of the array and returns the copy.  If
    265      * the value is already present, the original array is returned
    266      * @param cur The original array, or null to represent an empty array.
    267      * @param val The value to add.
    268      * @return A new array that contains all of the values of the original array
    269      * with the new value added, or the original array.
    270      */
    271     public static int[] appendInt(int[] cur, int val) {
    272         if (cur == null) {
    273             return new int[] { val };
    274         }
    275         final int N = cur.length;
    276         for (int i = 0; i < N; i++) {
    277             if (cur[i] == val) {
    278                 return cur;
    279             }
    280         }
    281         int[] ret = new int[N + 1];
    282         System.arraycopy(cur, 0, ret, 0, N);
    283         ret[N] = val;
    284         return ret;
    285     }
    286 
    287     public static int[] removeInt(int[] cur, int val) {
    288         if (cur == null) {
    289             return null;
    290         }
    291         final int N = cur.length;
    292         for (int i = 0; i < N; i++) {
    293             if (cur[i] == val) {
    294                 int[] ret = new int[N - 1];
    295                 if (i > 0) {
    296                     System.arraycopy(cur, 0, ret, 0, i);
    297                 }
    298                 if (i < (N - 1)) {
    299                     System.arraycopy(cur, i + 1, ret, i, N - i - 1);
    300                 }
    301                 return ret;
    302             }
    303         }
    304         return cur;
    305     }
    306 
    307     /**
    308      * Appends a new value to a copy of the array and returns the copy.  If
    309      * the value is already present, the original array is returned
    310      * @param cur The original array, or null to represent an empty array.
    311      * @param val The value to add.
    312      * @return A new array that contains all of the values of the original array
    313      * with the new value added, or the original array.
    314      */
    315     public static long[] appendLong(long[] cur, long val) {
    316         if (cur == null) {
    317             return new long[] { val };
    318         }
    319         final int N = cur.length;
    320         for (int i = 0; i < N; i++) {
    321             if (cur[i] == val) {
    322                 return cur;
    323             }
    324         }
    325         long[] ret = new long[N + 1];
    326         System.arraycopy(cur, 0, ret, 0, N);
    327         ret[N] = val;
    328         return ret;
    329     }
    330 
    331     public static long[] removeLong(long[] cur, long val) {
    332         if (cur == null) {
    333             return null;
    334         }
    335         final int N = cur.length;
    336         for (int i = 0; i < N; i++) {
    337             if (cur[i] == val) {
    338                 long[] ret = new long[N - 1];
    339                 if (i > 0) {
    340                     System.arraycopy(cur, 0, ret, 0, i);
    341                 }
    342                 if (i < (N - 1)) {
    343                     System.arraycopy(cur, i + 1, ret, i, N - i - 1);
    344                 }
    345                 return ret;
    346             }
    347         }
    348         return cur;
    349     }
    350 
    351     public static long[] cloneOrNull(long[] array) {
    352         return (array != null) ? array.clone() : null;
    353     }
    354 
    355     public static <T> ArraySet<T> add(ArraySet<T> cur, T val) {
    356         if (cur == null) {
    357             cur = new ArraySet<>();
    358         }
    359         cur.add(val);
    360         return cur;
    361     }
    362 
    363     public static <T> ArraySet<T> remove(ArraySet<T> cur, T val) {
    364         if (cur == null) {
    365             return null;
    366         }
    367         cur.remove(val);
    368         if (cur.isEmpty()) {
    369             return null;
    370         } else {
    371             return cur;
    372         }
    373     }
    374 
    375     public static <T> boolean contains(ArraySet<T> cur, T val) {
    376         return (cur != null) ? cur.contains(val) : false;
    377     }
    378 
    379     public static <T> ArrayList<T> add(ArrayList<T> cur, T val) {
    380         if (cur == null) {
    381             cur = new ArrayList<>();
    382         }
    383         cur.add(val);
    384         return cur;
    385     }
    386 
    387     public static <T> ArrayList<T> remove(ArrayList<T> cur, T val) {
    388         if (cur == null) {
    389             return null;
    390         }
    391         cur.remove(val);
    392         if (cur.isEmpty()) {
    393             return null;
    394         } else {
    395             return cur;
    396         }
    397     }
    398 
    399     public static <T> boolean contains(ArrayList<T> cur, T val) {
    400         return (cur != null) ? cur.contains(val) : false;
    401     }
    402 }
    403