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