Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2014 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 /**
     20  * A helper class that aims to provide comparable growth performance to ArrayList, but on primitive
     21  * arrays. Common array operations are implemented for efficient use in dynamic containers.
     22  *
     23  * All methods in this class assume that the length of an array is equivalent to its capacity and
     24  * NOT the number of elements in the array. The current size of the array is always passed in as a
     25  * parameter.
     26  *
     27  * @hide
     28  */
     29 public final class GrowingArrayUtils {
     30 
     31     /**
     32      * Appends an element to the end of the array, growing the array if there is no more room.
     33      * @param array The array to which to append the element. This must NOT be null.
     34      * @param currentSize The number of elements in the array. Must be less than or equal to
     35      *                    array.length.
     36      * @param element The element to append.
     37      * @return the array to which the element was appended. This may be different than the given
     38      *         array.
     39      */
     40     public static <T> T[] append(T[] array, int currentSize, T element) {
     41         assert currentSize <= array.length;
     42 
     43         if (currentSize + 1 > array.length) {
     44             @SuppressWarnings("unchecked")
     45             T[] newArray = ArrayUtils.newUnpaddedArray(
     46                     (Class<T>) array.getClass().getComponentType(), growSize(currentSize));
     47             System.arraycopy(array, 0, newArray, 0, currentSize);
     48             array = newArray;
     49         }
     50         array[currentSize] = element;
     51         return array;
     52     }
     53 
     54     /**
     55      * Primitive int version of {@link #append(Object[], int, Object)}.
     56      */
     57     public static int[] append(int[] array, int currentSize, int element) {
     58         assert currentSize <= array.length;
     59 
     60         if (currentSize + 1 > array.length) {
     61             int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
     62             System.arraycopy(array, 0, newArray, 0, currentSize);
     63             array = newArray;
     64         }
     65         array[currentSize] = element;
     66         return array;
     67     }
     68 
     69     /**
     70      * Primitive long version of {@link #append(Object[], int, Object)}.
     71      */
     72     public static long[] append(long[] array, int currentSize, long element) {
     73         assert currentSize <= array.length;
     74 
     75         if (currentSize + 1 > array.length) {
     76             long[] newArray = ArrayUtils.newUnpaddedLongArray(growSize(currentSize));
     77             System.arraycopy(array, 0, newArray, 0, currentSize);
     78             array = newArray;
     79         }
     80         array[currentSize] = element;
     81         return array;
     82     }
     83 
     84     /**
     85      * Primitive boolean version of {@link #append(Object[], int, Object)}.
     86      */
     87     public static boolean[] append(boolean[] array, int currentSize, boolean element) {
     88         assert currentSize <= array.length;
     89 
     90         if (currentSize + 1 > array.length) {
     91             boolean[] newArray = ArrayUtils.newUnpaddedBooleanArray(growSize(currentSize));
     92             System.arraycopy(array, 0, newArray, 0, currentSize);
     93             array = newArray;
     94         }
     95         array[currentSize] = element;
     96         return array;
     97     }
     98 
     99     /**
    100      * Inserts an element into the array at the specified index, growing the array if there is no
    101      * more room.
    102      *
    103      * @param array The array to which to append the element. Must NOT be null.
    104      * @param currentSize The number of elements in the array. Must be less than or equal to
    105      *                    array.length.
    106      * @param element The element to insert.
    107      * @return the array to which the element was appended. This may be different than the given
    108      *         array.
    109      */
    110     public static <T> T[] insert(T[] array, int currentSize, int index, T element) {
    111         assert currentSize <= array.length;
    112 
    113         if (currentSize + 1 <= array.length) {
    114             System.arraycopy(array, index, array, index + 1, currentSize - index);
    115             array[index] = element;
    116             return array;
    117         }
    118 
    119         @SuppressWarnings("unchecked")
    120         T[] newArray = ArrayUtils.newUnpaddedArray((Class<T>)array.getClass().getComponentType(),
    121                 growSize(currentSize));
    122         System.arraycopy(array, 0, newArray, 0, index);
    123         newArray[index] = element;
    124         System.arraycopy(array, index, newArray, index + 1, array.length - index);
    125         return newArray;
    126     }
    127 
    128     /**
    129      * Primitive int version of {@link #insert(Object[], int, int, Object)}.
    130      */
    131     public static int[] insert(int[] array, int currentSize, int index, int element) {
    132         assert currentSize <= array.length;
    133 
    134         if (currentSize + 1 <= array.length) {
    135             System.arraycopy(array, index, array, index + 1, currentSize - index);
    136             array[index] = element;
    137             return array;
    138         }
    139 
    140         int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
    141         System.arraycopy(array, 0, newArray, 0, index);
    142         newArray[index] = element;
    143         System.arraycopy(array, index, newArray, index + 1, array.length - index);
    144         return newArray;
    145     }
    146 
    147     /**
    148      * Primitive long version of {@link #insert(Object[], int, int, Object)}.
    149      */
    150     public static long[] insert(long[] array, int currentSize, int index, long element) {
    151         assert currentSize <= array.length;
    152 
    153         if (currentSize + 1 <= array.length) {
    154             System.arraycopy(array, index, array, index + 1, currentSize - index);
    155             array[index] = element;
    156             return array;
    157         }
    158 
    159         long[] newArray = ArrayUtils.newUnpaddedLongArray(growSize(currentSize));
    160         System.arraycopy(array, 0, newArray, 0, index);
    161         newArray[index] = element;
    162         System.arraycopy(array, index, newArray, index + 1, array.length - index);
    163         return newArray;
    164     }
    165 
    166     /**
    167      * Primitive boolean version of {@link #insert(Object[], int, int, Object)}.
    168      */
    169     public static boolean[] insert(boolean[] array, int currentSize, int index, boolean element) {
    170         assert currentSize <= array.length;
    171 
    172         if (currentSize + 1 <= array.length) {
    173             System.arraycopy(array, index, array, index + 1, currentSize - index);
    174             array[index] = element;
    175             return array;
    176         }
    177 
    178         boolean[] newArray = ArrayUtils.newUnpaddedBooleanArray(growSize(currentSize));
    179         System.arraycopy(array, 0, newArray, 0, index);
    180         newArray[index] = element;
    181         System.arraycopy(array, index, newArray, index + 1, array.length - index);
    182         return newArray;
    183     }
    184 
    185     /**
    186      * Given the current size of an array, returns an ideal size to which the array should grow.
    187      * This is typically double the given size, but should not be relied upon to do so in the
    188      * future.
    189      */
    190     public static int growSize(int currentSize) {
    191         return currentSize <= 4 ? 8 : currentSize * 2;
    192     }
    193 
    194     // Uninstantiable
    195     private GrowingArrayUtils() {}
    196 }
    197