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