1 /* 2 * Copyright (C) 2018 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.launcher3.util; 18 19 import java.util.Arrays; 20 21 /** 22 * Copy of the platform hidden implementation of android.util.IntArray. 23 * Implements a growing array of int primitives. 24 */ 25 public class IntArray implements Cloneable { 26 private static final int MIN_CAPACITY_INCREMENT = 12; 27 28 private static final int[] EMPTY_INT = new int[0]; 29 30 /* package private */ int[] mValues; 31 /* package private */ int mSize; 32 IntArray(int[] array, int size)33 private IntArray(int[] array, int size) { 34 mValues = array; 35 mSize = size; 36 } 37 38 /** 39 * Creates an empty IntArray with the default initial capacity. 40 */ IntArray()41 public IntArray() { 42 this(10); 43 } 44 45 /** 46 * Creates an empty IntArray with the specified initial capacity. 47 */ IntArray(int initialCapacity)48 public IntArray(int initialCapacity) { 49 if (initialCapacity == 0) { 50 mValues = EMPTY_INT; 51 } else { 52 mValues = new int[initialCapacity]; 53 } 54 mSize = 0; 55 } 56 57 /** 58 * Creates an IntArray wrapping the given primitive int array. 59 */ wrap(int... array)60 public static IntArray wrap(int... array) { 61 return new IntArray(array, array.length); 62 } 63 64 /** 65 * Appends the specified value to the end of this array. 66 */ add(int value)67 public void add(int value) { 68 add(mSize, value); 69 } 70 71 /** 72 * Inserts a value at the specified position in this array. If the specified index is equal to 73 * the length of the array, the value is added at the end. 74 * 75 * @throws IndexOutOfBoundsException when index < 0 || index > size() 76 */ add(int index, int value)77 public void add(int index, int value) { 78 ensureCapacity(1); 79 int rightSegment = mSize - index; 80 mSize++; 81 checkBounds(mSize, index); 82 83 if (rightSegment != 0) { 84 // Move by 1 all values from the right of 'index' 85 System.arraycopy(mValues, index, mValues, index + 1, rightSegment); 86 } 87 88 mValues[index] = value; 89 } 90 91 /** 92 * Adds the values in the specified array to this array. 93 */ addAll(IntArray values)94 public void addAll(IntArray values) { 95 final int count = values.mSize; 96 ensureCapacity(count); 97 98 System.arraycopy(values.mValues, 0, mValues, mSize, count); 99 mSize += count; 100 } 101 102 /** 103 * Sets the array to be same as {@param other} 104 */ copyFrom(IntArray other)105 public void copyFrom(IntArray other) { 106 clear(); 107 addAll(other); 108 } 109 110 /** 111 * Ensures capacity to append at least <code>count</code> values. 112 */ ensureCapacity(int count)113 private void ensureCapacity(int count) { 114 final int currentSize = mSize; 115 final int minCapacity = currentSize + count; 116 if (minCapacity >= mValues.length) { 117 final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ? 118 MIN_CAPACITY_INCREMENT : currentSize >> 1); 119 final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity; 120 final int[] newValues = new int[newCapacity]; 121 System.arraycopy(mValues, 0, newValues, 0, currentSize); 122 mValues = newValues; 123 } 124 } 125 126 /** 127 * Removes all values from this array. 128 */ clear()129 public void clear() { 130 mSize = 0; 131 } 132 133 @Override clone()134 public IntArray clone() { 135 return wrap(toArray()); 136 } 137 138 @Override equals(Object obj)139 public boolean equals(Object obj) { 140 if (obj == this) { 141 return true; 142 } 143 if (obj instanceof IntArray) { 144 IntArray arr = (IntArray) obj; 145 if (mSize == arr.mSize) { 146 for (int i = 0; i < mSize; i++) { 147 if (arr.mValues[i] != mValues[i]) { 148 return false; 149 } 150 } 151 return true; 152 } 153 } 154 return false; 155 } 156 157 /** 158 * Returns the value at the specified position in this array. 159 */ get(int index)160 public int get(int index) { 161 checkBounds(mSize, index); 162 return mValues[index]; 163 } 164 165 /** 166 * Sets the value at the specified position in this array. 167 */ set(int index, int value)168 public void set(int index, int value) { 169 checkBounds(mSize, index); 170 mValues[index] = value; 171 } 172 173 /** 174 * Returns the index of the first occurrence of the specified value in this 175 * array, or -1 if this array does not contain the value. 176 */ indexOf(int value)177 public int indexOf(int value) { 178 final int n = mSize; 179 for (int i = 0; i < n; i++) { 180 if (mValues[i] == value) { 181 return i; 182 } 183 } 184 return -1; 185 } 186 contains(int value)187 public boolean contains(int value) { 188 return indexOf(value) >= 0; 189 } 190 isEmpty()191 public boolean isEmpty() { 192 return mSize == 0; 193 } 194 195 /** 196 * Removes the value at the specified index from this array. 197 */ removeIndex(int index)198 public void removeIndex(int index) { 199 checkBounds(mSize, index); 200 System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1); 201 mSize--; 202 } 203 204 /** 205 * Removes the values if it exists 206 */ removeValue(int value)207 public void removeValue(int value) { 208 int index = indexOf(value); 209 if (index >= 0) { 210 removeIndex(index); 211 } 212 } 213 214 /** 215 * Removes the values if it exists 216 */ removeAllValues(IntArray values)217 public void removeAllValues(IntArray values) { 218 for (int i = 0; i < values.mSize; i++) { 219 removeValue(values.mValues[i]); 220 } 221 } 222 223 /** 224 * Returns the number of values in this array. 225 */ size()226 public int size() { 227 return mSize; 228 } 229 230 /** 231 * Returns a new array with the contents of this IntArray. 232 */ toArray()233 public int[] toArray() { 234 return mSize == 0 ? EMPTY_INT : Arrays.copyOf(mValues, mSize); 235 } 236 237 /** 238 * Returns a comma separate list of all values. 239 */ toConcatString()240 public String toConcatString() { 241 StringBuilder b = new StringBuilder(); 242 for (int i = 0; i < mSize ; i++) { 243 if (i > 0) { 244 b.append(", "); 245 } 246 b.append(mValues[i]); 247 } 248 return b.toString(); 249 } 250 251 /** 252 * Throws {@link ArrayIndexOutOfBoundsException} if the index is out of bounds. 253 * 254 * @param len length of the array. Must be non-negative 255 * @param index the index to check 256 * @throws ArrayIndexOutOfBoundsException if the {@code index} is out of bounds of the array 257 */ checkBounds(int len, int index)258 private static void checkBounds(int len, int index) { 259 if (index < 0 || len <= index) { 260 throw new ArrayIndexOutOfBoundsException("length=" + len + "; index=" + index); 261 } 262 } 263 }