| /* |
| * Copyright (C) 2017 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.text; |
| |
| import android.annotation.IntRange; |
| import android.annotation.NonNull; |
| |
| import com.android.internal.util.ArrayUtils; |
| |
| import libcore.util.EmptyArray; |
| |
| /** |
| * Implements a growing array of int primitives. |
| * |
| * These arrays are NOT thread safe. |
| * |
| * @hide |
| */ |
| public final class AutoGrowArray { |
| private static final int MIN_CAPACITY_INCREMENT = 12; |
| private static final int MAX_CAPACITY_TO_BE_KEPT = 10000; |
| |
| /** |
| * Returns next capacity size. |
| * |
| * The returned capacity is larger than requested capacity. |
| */ |
| private static int computeNewCapacity(int currentSize, int requested) { |
| final int targetCapacity = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) |
| ? MIN_CAPACITY_INCREMENT : currentSize >> 1); |
| return targetCapacity > requested ? targetCapacity : requested; |
| } |
| |
| /** |
| * An auto growing byte array. |
| */ |
| public static class ByteArray { |
| |
| private @NonNull byte[] mValues; |
| private @IntRange(from = 0) int mSize; |
| |
| /** |
| * Creates an empty ByteArray with the default initial capacity. |
| */ |
| public ByteArray() { |
| this(10); |
| } |
| |
| /** |
| * Creates an empty ByteArray with the specified initial capacity. |
| */ |
| public ByteArray(@IntRange(from = 0) int initialCapacity) { |
| if (initialCapacity == 0) { |
| mValues = EmptyArray.BYTE; |
| } else { |
| mValues = ArrayUtils.newUnpaddedByteArray(initialCapacity); |
| } |
| mSize = 0; |
| } |
| |
| /** |
| * Changes the size of this ByteArray. If this ByteArray is shrinked, the backing array |
| * capacity is unchanged. |
| */ |
| public void resize(@IntRange(from = 0) int newSize) { |
| if (newSize > mValues.length) { |
| ensureCapacity(newSize - mSize); |
| } |
| mSize = newSize; |
| } |
| |
| /** |
| * Appends the specified value to the end of this array. |
| */ |
| public void append(byte value) { |
| ensureCapacity(1); |
| mValues[mSize++] = value; |
| } |
| |
| /** |
| * Ensures capacity to append at least <code>count</code> values. |
| */ |
| private void ensureCapacity(@IntRange int count) { |
| final int requestedSize = mSize + count; |
| if (requestedSize >= mValues.length) { |
| final int newCapacity = computeNewCapacity(mSize, requestedSize); |
| final byte[] newValues = ArrayUtils.newUnpaddedByteArray(newCapacity); |
| System.arraycopy(mValues, 0, newValues, 0, mSize); |
| mValues = newValues; |
| } |
| } |
| |
| /** |
| * Removes all values from this array. |
| */ |
| public void clear() { |
| mSize = 0; |
| } |
| |
| /** |
| * Removes all values from this array and release the internal array object if it is too |
| * large. |
| */ |
| public void clearWithReleasingLargeArray() { |
| clear(); |
| if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) { |
| mValues = EmptyArray.BYTE; |
| } |
| } |
| |
| /** |
| * Returns the value at the specified position in this array. |
| */ |
| public byte get(@IntRange(from = 0) int index) { |
| return mValues[index]; |
| } |
| |
| /** |
| * Sets the value at the specified position in this array. |
| */ |
| public void set(@IntRange(from = 0) int index, byte value) { |
| mValues[index] = value; |
| } |
| |
| /** |
| * Returns the number of values in this array. |
| */ |
| public @IntRange(from = 0) int size() { |
| return mSize; |
| } |
| |
| /** |
| * Returns internal raw array. |
| * |
| * Note that this array may have larger size than you requested. |
| * Use size() instead for getting the actual array size. |
| */ |
| public @NonNull byte[] getRawArray() { |
| return mValues; |
| } |
| } |
| |
| /** |
| * An auto growing int array. |
| */ |
| public static class IntArray { |
| |
| private @NonNull int[] mValues; |
| private @IntRange(from = 0) int mSize; |
| |
| /** |
| * Creates an empty IntArray with the default initial capacity. |
| */ |
| public IntArray() { |
| this(10); |
| } |
| |
| /** |
| * Creates an empty IntArray with the specified initial capacity. |
| */ |
| public IntArray(@IntRange(from = 0) int initialCapacity) { |
| if (initialCapacity == 0) { |
| mValues = EmptyArray.INT; |
| } else { |
| mValues = ArrayUtils.newUnpaddedIntArray(initialCapacity); |
| } |
| mSize = 0; |
| } |
| |
| /** |
| * Changes the size of this IntArray. If this IntArray is shrinked, the backing array |
| * capacity is unchanged. |
| */ |
| public void resize(@IntRange(from = 0) int newSize) { |
| if (newSize > mValues.length) { |
| ensureCapacity(newSize - mSize); |
| } |
| mSize = newSize; |
| } |
| |
| /** |
| * Appends the specified value to the end of this array. |
| */ |
| public void append(int value) { |
| ensureCapacity(1); |
| mValues[mSize++] = value; |
| } |
| |
| /** |
| * Ensures capacity to append at least <code>count</code> values. |
| */ |
| private void ensureCapacity(@IntRange(from = 0) int count) { |
| final int requestedSize = mSize + count; |
| if (requestedSize >= mValues.length) { |
| final int newCapacity = computeNewCapacity(mSize, requestedSize); |
| final int[] newValues = ArrayUtils.newUnpaddedIntArray(newCapacity); |
| System.arraycopy(mValues, 0, newValues, 0, mSize); |
| mValues = newValues; |
| } |
| } |
| |
| /** |
| * Removes all values from this array. |
| */ |
| public void clear() { |
| mSize = 0; |
| } |
| |
| /** |
| * Removes all values from this array and release the internal array object if it is too |
| * large. |
| */ |
| public void clearWithReleasingLargeArray() { |
| clear(); |
| if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) { |
| mValues = EmptyArray.INT; |
| } |
| } |
| |
| /** |
| * Returns the value at the specified position in this array. |
| */ |
| public int get(@IntRange(from = 0) int index) { |
| return mValues[index]; |
| } |
| |
| /** |
| * Sets the value at the specified position in this array. |
| */ |
| public void set(@IntRange(from = 0) int index, int value) { |
| mValues[index] = value; |
| } |
| |
| /** |
| * Returns the number of values in this array. |
| */ |
| public @IntRange(from = 0) int size() { |
| return mSize; |
| } |
| |
| /** |
| * Returns internal raw array. |
| * |
| * Note that this array may have larger size than you requested. |
| * Use size() instead for getting the actual array size. |
| */ |
| public @NonNull int[] getRawArray() { |
| return mValues; |
| } |
| } |
| |
| /** |
| * An auto growing float array. |
| */ |
| public static class FloatArray { |
| |
| private @NonNull float[] mValues; |
| private @IntRange(from = 0) int mSize; |
| |
| /** |
| * Creates an empty FloatArray with the default initial capacity. |
| */ |
| public FloatArray() { |
| this(10); |
| } |
| |
| /** |
| * Creates an empty FloatArray with the specified initial capacity. |
| */ |
| public FloatArray(@IntRange(from = 0) int initialCapacity) { |
| if (initialCapacity == 0) { |
| mValues = EmptyArray.FLOAT; |
| } else { |
| mValues = ArrayUtils.newUnpaddedFloatArray(initialCapacity); |
| } |
| mSize = 0; |
| } |
| |
| /** |
| * Changes the size of this FloatArray. If this FloatArray is shrinked, the backing array |
| * capacity is unchanged. |
| */ |
| public void resize(@IntRange(from = 0) int newSize) { |
| if (newSize > mValues.length) { |
| ensureCapacity(newSize - mSize); |
| } |
| mSize = newSize; |
| } |
| |
| /** |
| * Appends the specified value to the end of this array. |
| */ |
| public void append(float value) { |
| ensureCapacity(1); |
| mValues[mSize++] = value; |
| } |
| |
| /** |
| * Ensures capacity to append at least <code>count</code> values. |
| */ |
| private void ensureCapacity(int count) { |
| final int requestedSize = mSize + count; |
| if (requestedSize >= mValues.length) { |
| final int newCapacity = computeNewCapacity(mSize, requestedSize); |
| final float[] newValues = ArrayUtils.newUnpaddedFloatArray(newCapacity); |
| System.arraycopy(mValues, 0, newValues, 0, mSize); |
| mValues = newValues; |
| } |
| } |
| |
| /** |
| * Removes all values from this array. |
| */ |
| public void clear() { |
| mSize = 0; |
| } |
| |
| /** |
| * Removes all values from this array and release the internal array object if it is too |
| * large. |
| */ |
| public void clearWithReleasingLargeArray() { |
| clear(); |
| if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) { |
| mValues = EmptyArray.FLOAT; |
| } |
| } |
| |
| /** |
| * Returns the value at the specified position in this array. |
| */ |
| public float get(@IntRange(from = 0) int index) { |
| return mValues[index]; |
| } |
| |
| /** |
| * Sets the value at the specified position in this array. |
| */ |
| public void set(@IntRange(from = 0) int index, float value) { |
| mValues[index] = value; |
| } |
| |
| /** |
| * Returns the number of values in this array. |
| */ |
| public @IntRange(from = 0) int size() { |
| return mSize; |
| } |
| |
| /** |
| * Returns internal raw array. |
| * |
| * Note that this array may have larger size than you requested. |
| * Use size() instead for getting the actual array size. |
| */ |
| public @NonNull float[] getRawArray() { |
| return mValues; |
| } |
| } |
| } |