1 /* 2 * Copyright (C) 2013 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 android.util; 18 19 import android.annotation.Nullable; 20 import android.compat.annotation.UnsupportedAppUsage; 21 22 import com.android.internal.util.ArrayUtils; 23 import com.android.internal.util.Preconditions; 24 25 import libcore.util.EmptyArray; 26 27 import java.util.Arrays; 28 29 /** 30 * Implements a growing array of long primitives. 31 * 32 * @hide 33 */ 34 public class LongArray implements Cloneable { 35 private static final int MIN_CAPACITY_INCREMENT = 12; 36 37 private long[] mValues; 38 private int mSize; 39 LongArray(long[] array, int size)40 private LongArray(long[] array, int size) { 41 mValues = array; 42 mSize = Preconditions.checkArgumentInRange(size, 0, array.length, "size"); 43 } 44 45 /** 46 * Creates an empty LongArray with the default initial capacity. 47 */ 48 @UnsupportedAppUsage LongArray()49 public LongArray() { 50 this(10); 51 } 52 53 /** 54 * Creates an empty LongArray with the specified initial capacity. 55 */ LongArray(int initialCapacity)56 public LongArray(int initialCapacity) { 57 if (initialCapacity == 0) { 58 mValues = EmptyArray.LONG; 59 } else { 60 mValues = ArrayUtils.newUnpaddedLongArray(initialCapacity); 61 } 62 mSize = 0; 63 } 64 65 /** 66 * Creates an LongArray wrapping the given primitive long array. 67 */ wrap(long[] array)68 public static LongArray wrap(long[] array) { 69 return new LongArray(array, array.length); 70 } 71 72 /** 73 * Creates an LongArray from the given primitive long array, copying it. 74 */ fromArray(long[] array, int size)75 public static LongArray fromArray(long[] array, int size) { 76 return wrap(Arrays.copyOf(array, size)); 77 } 78 79 /** 80 * Changes the size of this LongArray. If this LongArray is shrinked, the backing array capacity 81 * is unchanged. If the new size is larger than backing array capacity, a new backing array is 82 * created from the current content of this LongArray padded with 0s. 83 */ resize(int newSize)84 public void resize(int newSize) { 85 Preconditions.checkArgumentNonnegative(newSize); 86 if (newSize <= mValues.length) { 87 Arrays.fill(mValues, newSize, mValues.length, 0); 88 } else { 89 ensureCapacity(newSize - mSize); 90 } 91 mSize = newSize; 92 } 93 94 /** 95 * Appends the specified value to the end of this array. 96 */ add(long value)97 public void add(long value) { 98 add(mSize, value); 99 } 100 101 /** 102 * Inserts a value at the specified position in this array. If the specified index is equal to 103 * the length of the array, the value is added at the end. 104 * 105 * @throws IndexOutOfBoundsException when index < 0 || index > size() 106 */ 107 @UnsupportedAppUsage add(int index, long value)108 public void add(int index, long value) { 109 ensureCapacity(1); 110 int rightSegment = mSize - index; 111 mSize++; 112 ArrayUtils.checkBounds(mSize, index); 113 114 if (rightSegment != 0) { 115 // Move by 1 all values from the right of 'index' 116 System.arraycopy(mValues, index, mValues, index + 1, rightSegment); 117 } 118 119 mValues[index] = value; 120 } 121 122 /** 123 * Adds the values in the specified array to this array. 124 */ addAll(LongArray values)125 public void addAll(LongArray values) { 126 final int count = values.mSize; 127 ensureCapacity(count); 128 129 System.arraycopy(values.mValues, 0, mValues, mSize, count); 130 mSize += count; 131 } 132 133 /** 134 * Ensures capacity to append at least <code>count</code> values. 135 */ ensureCapacity(int count)136 private void ensureCapacity(int count) { 137 final int currentSize = mSize; 138 final int minCapacity = currentSize + count; 139 if (minCapacity >= mValues.length) { 140 final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ? 141 MIN_CAPACITY_INCREMENT : currentSize >> 1); 142 final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity; 143 final long[] newValues = ArrayUtils.newUnpaddedLongArray(newCapacity); 144 System.arraycopy(mValues, 0, newValues, 0, currentSize); 145 mValues = newValues; 146 } 147 } 148 149 /** 150 * Removes all values from this array. 151 */ clear()152 public void clear() { 153 mSize = 0; 154 } 155 156 @Override clone()157 public LongArray clone() { 158 LongArray clone = null; 159 try { 160 clone = (LongArray) super.clone(); 161 clone.mValues = mValues.clone(); 162 } catch (CloneNotSupportedException cnse) { 163 /* ignore */ 164 } 165 return clone; 166 } 167 168 /** 169 * Returns the value at the specified position in this array. 170 */ 171 @UnsupportedAppUsage get(int index)172 public long get(int index) { 173 ArrayUtils.checkBounds(mSize, index); 174 return mValues[index]; 175 } 176 177 /** 178 * Sets the value at the specified position in this array. 179 */ set(int index, long value)180 public void set(int index, long value) { 181 ArrayUtils.checkBounds(mSize, index); 182 mValues[index] = value; 183 } 184 185 /** 186 * Returns the index of the first occurrence of the specified value in this 187 * array, or -1 if this array does not contain the value. 188 */ indexOf(long value)189 public int indexOf(long value) { 190 final int n = mSize; 191 for (int i = 0; i < n; i++) { 192 if (mValues[i] == value) { 193 return i; 194 } 195 } 196 return -1; 197 } 198 199 /** 200 * Removes the value at the specified index from this array. 201 */ remove(int index)202 public void remove(int index) { 203 ArrayUtils.checkBounds(mSize, index); 204 System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1); 205 mSize--; 206 } 207 208 /** 209 * Returns the number of values in this array. 210 */ 211 @UnsupportedAppUsage size()212 public int size() { 213 return mSize; 214 } 215 216 /** 217 * Returns a new array with the contents of this LongArray. 218 */ toArray()219 public long[] toArray() { 220 return Arrays.copyOf(mValues, mSize); 221 } 222 223 /** 224 * Test if each element of {@code a} equals corresponding element from {@code b} 225 */ elementsEqual(@ullable LongArray a, @Nullable LongArray b)226 public static boolean elementsEqual(@Nullable LongArray a, @Nullable LongArray b) { 227 if (a == null || b == null) return a == b; 228 if (a.mSize != b.mSize) return false; 229 for (int i = 0; i < a.mSize; i++) { 230 if (a.get(i) != b.get(i)) { 231 return false; 232 } 233 } 234 return true; 235 } 236 } 237