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