| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.util; |
| |
| import android.annotation.Nullable; |
| import android.compat.annotation.UnsupportedAppUsage; |
| import android.os.Build; |
| |
| import com.android.internal.util.ArrayUtils; |
| import com.android.internal.util.Preconditions; |
| |
| import libcore.util.EmptyArray; |
| |
| import java.util.Arrays; |
| |
| /** |
| * Implements a growing array of long primitives. |
| * |
| * @hide |
| */ |
| public class LongArray implements Cloneable { |
| private static final int MIN_CAPACITY_INCREMENT = 12; |
| |
| private long[] mValues; |
| private int mSize; |
| |
| private LongArray(long[] array, int size) { |
| mValues = array; |
| mSize = Preconditions.checkArgumentInRange(size, 0, array.length, "size"); |
| } |
| |
| /** |
| * Creates an empty LongArray with the default initial capacity. |
| */ |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public LongArray() { |
| this(0); |
| } |
| |
| /** |
| * Creates an empty LongArray with the specified initial capacity. |
| */ |
| public LongArray(int initialCapacity) { |
| if (initialCapacity == 0) { |
| mValues = EmptyArray.LONG; |
| } else { |
| mValues = ArrayUtils.newUnpaddedLongArray(initialCapacity); |
| } |
| mSize = 0; |
| } |
| |
| /** |
| * Creates an LongArray wrapping the given primitive long array. |
| */ |
| public static LongArray wrap(long[] array) { |
| return new LongArray(array, array.length); |
| } |
| |
| /** |
| * Creates an LongArray from the given primitive long array, copying it. |
| */ |
| public static LongArray fromArray(long[] array, int size) { |
| return wrap(Arrays.copyOf(array, size)); |
| } |
| |
| /** |
| * Changes the size of this LongArray. If this LongArray is shrinked, the backing array capacity |
| * is unchanged. If the new size is larger than backing array capacity, a new backing array is |
| * created from the current content of this LongArray padded with 0s. |
| */ |
| public void resize(int newSize) { |
| Preconditions.checkArgumentNonnegative(newSize); |
| if (newSize <= mValues.length) { |
| Arrays.fill(mValues, newSize, mValues.length, 0); |
| } else { |
| ensureCapacity(newSize - mSize); |
| } |
| mSize = newSize; |
| } |
| |
| /** |
| * Appends the specified value to the end of this array. |
| */ |
| public void add(long value) { |
| add(mSize, value); |
| } |
| |
| /** |
| * Inserts a value at the specified position in this array. If the specified index is equal to |
| * the length of the array, the value is added at the end. |
| * |
| * @throws IndexOutOfBoundsException when index < 0 || index > size() |
| */ |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public void add(int index, long value) { |
| ensureCapacity(1); |
| int rightSegment = mSize - index; |
| mSize++; |
| ArrayUtils.checkBounds(mSize, index); |
| |
| if (rightSegment != 0) { |
| // Move by 1 all values from the right of 'index' |
| System.arraycopy(mValues, index, mValues, index + 1, rightSegment); |
| } |
| |
| mValues[index] = value; |
| } |
| |
| /** |
| * Adds the values in the specified array to this array. |
| */ |
| public void addAll(LongArray values) { |
| final int count = values.mSize; |
| ensureCapacity(count); |
| |
| System.arraycopy(values.mValues, 0, mValues, mSize, count); |
| mSize += count; |
| } |
| |
| /** |
| * Ensures capacity to append at least <code>count</code> values. |
| */ |
| private void ensureCapacity(int count) { |
| final int currentSize = mSize; |
| final int minCapacity = currentSize + count; |
| if (minCapacity >= mValues.length) { |
| final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ? |
| MIN_CAPACITY_INCREMENT : currentSize >> 1); |
| final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity; |
| final long[] newValues = ArrayUtils.newUnpaddedLongArray(newCapacity); |
| System.arraycopy(mValues, 0, newValues, 0, currentSize); |
| mValues = newValues; |
| } |
| } |
| |
| /** |
| * Removes all values from this array. |
| */ |
| public void clear() { |
| mSize = 0; |
| } |
| |
| @Override |
| public LongArray clone() { |
| LongArray clone = null; |
| try { |
| clone = (LongArray) super.clone(); |
| clone.mValues = mValues.clone(); |
| } catch (CloneNotSupportedException cnse) { |
| /* ignore */ |
| } |
| return clone; |
| } |
| |
| /** |
| * Returns the value at the specified position in this array. |
| */ |
| @UnsupportedAppUsage |
| public long get(int index) { |
| ArrayUtils.checkBounds(mSize, index); |
| return mValues[index]; |
| } |
| |
| /** |
| * Sets the value at the specified position in this array. |
| */ |
| public void set(int index, long value) { |
| ArrayUtils.checkBounds(mSize, index); |
| mValues[index] = value; |
| } |
| |
| /** |
| * Returns the index of the first occurrence of the specified value in this |
| * array, or -1 if this array does not contain the value. |
| */ |
| public int indexOf(long value) { |
| final int n = mSize; |
| for (int i = 0; i < n; i++) { |
| if (mValues[i] == value) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Removes the value at the specified index from this array. |
| */ |
| public void remove(int index) { |
| ArrayUtils.checkBounds(mSize, index); |
| System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1); |
| mSize--; |
| } |
| |
| /** |
| * Returns the number of values in this array. |
| */ |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public int size() { |
| return mSize; |
| } |
| |
| /** |
| * Returns a new array with the contents of this LongArray. |
| */ |
| public long[] toArray() { |
| return Arrays.copyOf(mValues, mSize); |
| } |
| |
| /** |
| * Test if each element of {@code a} equals corresponding element from {@code b} |
| */ |
| public static boolean elementsEqual(@Nullable LongArray a, @Nullable LongArray b) { |
| if (a == null || b == null) return a == b; |
| if (a.mSize != b.mSize) return false; |
| for (int i = 0; i < a.mSize; i++) { |
| if (a.get(i) != b.get(i)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| } |