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